aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java10
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java4
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java38
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java41
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java2
6 files changed, 73 insertions, 32 deletions
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index be807ab0c..0bde2c011 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -131,6 +131,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
private interface SubtypeDialogProxy {
public void onRemovePressed(SubtypePreference subtypePref);
+ public void onAddPressed(SubtypePreference subtypePref);
public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
}
@@ -241,6 +242,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
super.onClick(dialog, which);
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
+ final boolean addPressed = isIncomplete();
final SubtypeLocaleItem locale =
(SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
final KeyboardLayoutSetItem layout =
@@ -249,6 +251,9 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
locale.first, layout.first, ASCII_CAPABLE);
setSubtype(subtype);
notifyChanged();
+ if (addPressed) {
+ mProxy.onAddPressed(this);
+ }
break;
case DialogInterface.BUTTON_NEUTRAL:
// Nothing to do
@@ -391,6 +396,11 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
}
@Override
+ public void onAddPressed(SubtypePreference subtypePref) {
+ mIsAddingNewSubtype = false;
+ }
+
+ @Override
public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
return mSubtypeLocaleAdapter;
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 37deb0c5d..f3aa27a22 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -70,6 +70,10 @@ public class DictionaryCollection extends Dictionary {
return false;
}
+ public boolean isEmpty() {
+ return mDictionaries.isEmpty();
+ }
+
@Override
public void close() {
for (final Dictionary dict : mDictionaries)
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index f5dc7b34a..4cd1b3883 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -36,7 +36,7 @@ public class DictionaryFactory {
DictionaryFactory.class.getPackage().getName();
/**
- * Initializes a dictionary from a dictionary pack, with explicit flags.
+ * Initializes a main dictionary collection 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 the built-in dictionary - if any.
@@ -45,7 +45,7 @@ public class DictionaryFactory {
* @param useFullEditDistance whether to use the full edit distance in suggestions
* @return an initialized instance of DictionaryCollection
*/
- public static DictionaryCollection createDictionaryFromManager(final Context context,
+ public static DictionaryCollection createMainDictionaryFromManager(final Context context,
final Locale locale, final boolean useFullEditDistance) {
if (null == locale) {
Log.e(TAG, "No locale defined for dictionary");
@@ -73,7 +73,7 @@ public class DictionaryFactory {
}
/**
- * Initializes a dictionary from a dictionary pack, with default flags.
+ * Initializes a main dictionary collection 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 the built-in dictionary, if any.
@@ -81,9 +81,9 @@ public class DictionaryFactory {
* @param locale the locale for which to create the dictionary
* @return an initialized instance of DictionaryCollection
*/
- public static DictionaryCollection createDictionaryFromManager(final Context context,
+ public static DictionaryCollection createMainDictionaryFromManager(final Context context,
final Locale locale) {
- return createDictionaryFromManager(context, locale, false /* useFullEditDistance */);
+ return createMainDictionaryFromManager(context, locale, false /* useFullEditDistance */);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index a97f200fd..7832cb522 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -65,7 +65,7 @@ public class Suggest implements Dictionary.WordCallback {
private static final boolean DBG = LatinImeLogger.sDBG;
- private Dictionary mMainDict;
+ private boolean mHasMainDictionary;
private Dictionary mContactsDict;
private WhitelistDictionary mWhiteListDictionary;
private final HashMap<String, Dictionary> mUnigramDictionaries =
@@ -96,8 +96,12 @@ public class Suggest implements Dictionary.WordCallback {
/* package for test */ Suggest(final Context context, final File dictionary,
final long startOffset, final long length, final Locale locale) {
- initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary,
- startOffset, length /* useFullEditDistance */, false, locale), locale);
+ final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
+ startOffset, length /* useFullEditDistance */, false, locale);
+ mHasMainDictionary = null != mainDict;
+ addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
+ addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
+ initWhitelistAndAutocorrectAndPool(context, locale);
}
private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
@@ -113,14 +117,6 @@ public class Suggest implements Dictionary.WordCallback {
initWhitelistAndAutocorrectAndPool(context, locale);
}
- private void initSynchronously(final Context context, final Dictionary mainDict,
- final Locale locale) {
- mMainDict = mainDict;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
- initWhitelistAndAutocorrectAndPool(context, locale);
- }
-
private static void addOrReplaceDictionary(HashMap<String, Dictionary> dictionaries, String key,
Dictionary dict) {
final Dictionary oldDict = (dict == null)
@@ -132,13 +128,13 @@ public class Suggest implements Dictionary.WordCallback {
}
public void resetMainDict(final Context context, final Locale locale) {
- mMainDict = null;
+ mHasMainDictionary = false;
new Thread("InitializeBinaryDictionary") {
@Override
public void run() {
- final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager(
- context, locale);
- mMainDict = newMainDict;
+ final DictionaryCollection newMainDict =
+ DictionaryFactory.createMainDictionaryFromManager(context, locale);
+ mHasMainDictionary = null != newMainDict && !newMainDict.isEmpty();
addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
}
@@ -148,7 +144,7 @@ public class Suggest implements Dictionary.WordCallback {
// The main dictionary could have been loaded asynchronously. Don't cache the return value
// of this method.
public boolean hasMainDictionary() {
- return mMainDict != null;
+ return mHasMainDictionary;
}
public Dictionary getContactsDictionary() {
@@ -362,7 +358,13 @@ public class Suggest implements Dictionary.WordCallback {
// a boolean flag. Right now this is handled with a slight hack in
// WhitelistDictionary#shouldForciblyAutoCorrectFrom.
final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
- getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized());
+ getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized())
+ // If we don't have a main dictionary, we never want to auto-correct. The reason for this
+ // is, the user may have a contact whose name happens to match a valid word in their
+ // language, and it will unexpectedly auto-correct. For example, if the user types in
+ // English with no dictionary and has a "Will" in their contact list, "will" would
+ // always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct.
+ && mHasMainDictionary;
boolean autoCorrectionAvailable = hasAutoCorrection;
if (correctionMode == CORRECTION_FULL || correctionMode == CORRECTION_FULL_BIGRAM) {
@@ -530,7 +532,7 @@ public class Suggest implements Dictionary.WordCallback {
for (final Dictionary dictionary : dictionaries) {
dictionary.close();
}
- mMainDict = null;
+ mHasMainDictionary = false;
}
// TODO: Resolve the inconsistencies between the native auto correction algorithms and
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index 830fbf07e..563f8a99b 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -765,14 +765,39 @@ public class BinaryDictInputOutput {
bigramFrequency = unigramFrequency;
}
// We compute the difference between 255 (which means probability = 1) and the
- // unigram score. We split this into discrete 16 steps, and this is the value
- // we store into the 4 bits of the bigrams frequency.
- final float bigramRatio = (float)(bigramFrequency - unigramFrequency)
- / (MAX_TERMINAL_FREQUENCY - unigramFrequency);
- // TODO: if the bigram freq is very close to the unigram frequency, we don't want
- // to include the bigram in the binary dictionary at all.
- final int discretizedFrequency = Math.round(bigramRatio * MAX_BIGRAM_FREQUENCY);
- bigramFlags += discretizedFrequency & FLAG_ATTRIBUTE_FREQUENCY;
+ // unigram score. We split this into a number of discrete steps.
+ // Now, the steps are numbered 0~15; 0 represents an increase of 1 step while 15
+ // represents an increase of 16 steps: a value of 15 will be interpreted as the median
+ // value of the 16th step. In all justice, if the bigram frequency is low enough to be
+ // rounded below the first step (which means it is less than half a step higher than the
+ // unigram frequency) then the unigram frequency itself is the best approximation of the
+ // bigram freq that we could possibly supply, hence we should *not* include this bigram
+ // in the file at all.
+ // until this is done, we'll write 0 and slightly overestimate this case.
+ // In other words, 0 means "between 0.5 step and 1.5 step", 1 means "between 1.5 step
+ // and 2.5 steps", and 15 means "between 15.5 steps and 16.5 steps". So we want to
+ // divide our range [unigramFreq..MAX_TERMINAL_FREQUENCY] in 16.5 steps to get the
+ // step size. Then we compute the start of the first step (the one where value 0 starts)
+ // by adding half-a-step to the unigramFrequency. From there, we compute the integer
+ // number of steps to the bigramFrequency. One last thing: we want our steps to include
+ // their lower bound and exclude their higher bound so we need to have the first step
+ // start at exactly 1 unit higher than floor(unigramFreq + half a step).
+ // Note : to reconstruct the score, the dictionary reader will need to divide
+ // MAX_TERMINAL_FREQUENCY - unigramFreq by 16.5 likewise, and add
+ // (discretizedFrequency + 0.5) times this value to get the median value of the step,
+ // which is the best approximation. This is how we get the most precise result with
+ // only four bits.
+ final double stepSize =
+ (double)(MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5 + MAX_BIGRAM_FREQUENCY);
+ final double firstStepStart = 1 + unigramFrequency + (stepSize / 2.0);
+ final int discretizedFrequency = (int)((bigramFrequency - firstStepStart) / stepSize);
+ // If the bigram freq is less than half-a-step higher than the unigram freq, we get -1
+ // here. The best approximation would be the unigram freq itself, so we should not
+ // include this bigram in the dictionary. For now, register as 0, and live with the
+ // small over-estimation that we get in this case. TODO: actually remove this bigram
+ // if discretizedFrequency < 0.
+ final int finalBigramFrequency = discretizedFrequency > 0 ? discretizedFrequency : 0;
+ bigramFlags += finalBigramFrequency & FLAG_ATTRIBUTE_FREQUENCY;
return bigramFlags;
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 6f7f0c333..0c9f9fb27 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -398,7 +398,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH,
SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT);
final DictionaryCollection dictionaryCollection =
- DictionaryFactory.createDictionaryFromManager(this, locale,
+ DictionaryFactory.createMainDictionaryFromManager(this, locale,
true /* useFullEditDistance */);
final String localeStr = locale.toString();
Dictionary userDictionary = mUserDictionaries.get(localeStr);