aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android')
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java19
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java8
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java66
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java46
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java42
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java6
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java30
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java84
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java6
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java16
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java51
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java3
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java204
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java3
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java9
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java10
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java33
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java1
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java19
20 files changed, 340 insertions, 322 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 383298de9..e3739eb3c 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -127,6 +127,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
private static final int MSG_TYPING_STATE_EXPIRED = 4;
private final KeyTimerParams mParams;
+ // TODO: Suppress layout changes in key repeat mode
+ // TODO: Remove this variable.
private boolean mInKeyRepeat;
public KeyTimerHandler(LatinKeyboardView outerInstance, KeyTimerParams params) {
@@ -140,8 +142,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
case MSG_REPEAT_KEY:
- tracker.onRegisterKey(tracker.getKey());
- startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+ final Key currentKey = tracker.getKey();
+ if (currentKey != null && currentKey.mCode == msg.arg1) {
+ tracker.onRegisterKey(currentKey);
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+ }
break;
case MSG_LONGPRESS_KEY:
if (tracker != null) {
@@ -158,12 +163,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
private void startKeyRepeatTimer(PointerTracker tracker, long delay) {
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
+ final Key key = tracker.getKey();
+ if (key == null) return;
+ mInKeyRepeat = true;
+ sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, key.mCode, 0, tracker), delay);
}
@Override
public void startKeyRepeatTimer(PointerTracker tracker) {
- mInKeyRepeat = true;
startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout);
}
@@ -451,8 +458,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
*/
@Override
public void setKeyboard(Keyboard keyboard) {
- // Remove any pending messages, except dismissing preview
- mKeyTimerHandler.cancelKeyTimers();
+ // Remove any pending messages, except dismissing preview and key repeat.
+ mKeyTimerHandler.cancelLongPressTimer();
super.setKeyboard(keyboard);
mKeyDetector.setKeyboard(
keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 34e428e82..8aac8d80c 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -148,6 +148,7 @@ public class PointerTracker {
// true if this pointer has been long-pressed and is showing a more keys panel.
private boolean mIsShowingMoreKeysPanel;
+ // TODO: Remove this variable.
// true if this pointer is repeatable key
private boolean mIsRepeatableKey;
@@ -319,6 +320,13 @@ public class PointerTracker {
private void setKeyDetectorInner(KeyDetector keyDetector) {
mKeyDetector = keyDetector;
mKeyboard = keyDetector.getKeyboard();
+ final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
+ if (newKey != mCurrentKey) {
+ if (mDrawingProxy != null) {
+ setReleasedKeyGraphics(mCurrentKey);
+ }
+ mCurrentKey = newKey;
+ }
final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index d0613bd72..f44e6328b 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -20,7 +20,9 @@ import android.content.Context;
import android.text.TextUtils;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@@ -40,6 +42,7 @@ public class BinaryDictionary extends Dictionary {
*/
public static final int MAX_WORD_LENGTH = 48;
public static final int MAX_WORDS = 18;
+ public static final int MAX_SPACES = 16;
private static final String TAG = "BinaryDictionary";
private static final int MAX_BIGRAMS = 60;
@@ -51,6 +54,7 @@ public class BinaryDictionary extends Dictionary {
private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
+ private final int[] mSpaceIndices = new int[MAX_SPACES];
private final int[] mScores = new int[MAX_WORDS];
private final int[] mBigramScores = new int[MAX_BIGRAMS];
@@ -65,14 +69,12 @@ public class BinaryDictionary extends Dictionary {
* @param offset the offset of the dictionary data within the file.
* @param length the length of the binary data.
* @param useFullEditDistance whether to use the full edit distance in suggestions
+ * @param dicTypeId the dictionary type id of the dictionary
*/
public BinaryDictionary(final Context context,
final String filename, final long offset, final long length,
- final boolean useFullEditDistance, final Locale locale) {
- // Note: at the moment a binary dictionary is always of the "main" type.
- // Initializing this here will help transitioning out of the scheme where
- // the Suggest class knows everything about every single dictionary.
- mDicTypeId = Suggest.DIC_MAIN;
+ final boolean useFullEditDistance, final Locale locale, final int dicTypeId) {
+ mDicTypeId = dicTypeId;
mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length);
}
@@ -87,8 +89,10 @@ public class BinaryDictionary extends Dictionary {
private native int getFrequencyNative(long dict, int[] word, int wordLength);
private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
- int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams,
- boolean useFullEditDistance, char[] outputChars, int[] scores);
+ int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize,
+ int commitPoint, boolean isGesture, int dicTypeId,
+ int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars,
+ int[] scores, int[] outputIndices);
private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength,
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
int maxWordLength, int maxBigrams);
@@ -103,9 +107,9 @@ public class BinaryDictionary extends Dictionary {
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- if (mNativeDict == 0) return;
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
+ if (mNativeDict == 0) return null;
int[] codePoints = StringUtils.toCodePointArray(previousWord.toString());
Arrays.fill(mOutputChars_bigrams, (char) 0);
@@ -123,6 +127,7 @@ public class BinaryDictionary extends Dictionary {
count = MAX_BIGRAMS;
}
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
for (int j = 0; j < count; ++j) {
if (codesSize > 0 && mBigramScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
@@ -131,19 +136,22 @@ public class BinaryDictionary extends Dictionary {
++len;
}
if (len > 0) {
- callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j],
- mDicTypeId, Dictionary.BIGRAM);
+ suggestions.add(new SuggestedWordInfo(
+ new String(mOutputChars_bigrams, start, len),
+ mBigramScores[j], SuggestedWordInfo.KIND_CORRECTION));
}
}
+ return suggestions;
}
// proximityInfo and/or prevWordForBigrams may not be null.
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
- mScores);
+ mScores, mSpaceIndices);
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
for (int j = 0; j < count; ++j) {
if (mScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
@@ -152,10 +160,13 @@ public class BinaryDictionary extends Dictionary {
++len;
}
if (len > 0) {
- callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId,
- Dictionary.UNIGRAM);
+ // TODO: actually get the kind from native code
+ suggestions.add(new SuggestedWordInfo(
+ new String(mOutputChars, start, len),
+ mScores[j], SuggestedWordInfo.KIND_CORRECTION));
}
}
+ return suggestions;
}
/* package for test */ boolean isValidDictionary() {
@@ -165,7 +176,7 @@ public class BinaryDictionary extends Dictionary {
// proximityInfo may not be null.
/* package for test */ int getSuggestions(final WordComposer codes,
final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo,
- char[] outputChars, int[] scores) {
+ char[] outputChars, int[] scores, int[] spaceIndices) {
if (!isValidDictionary()) return -1;
final int codesSize = codes.size();
@@ -179,14 +190,21 @@ public class BinaryDictionary extends Dictionary {
Arrays.fill(outputChars, (char) 0);
Arrays.fill(scores, 0);
- final int[] prevWordCodePointArray = null == prevWordForBigrams
+ // TODO: toLowerCase in the native code
+ final int[] prevWordCodePointArray = (null == prevWordForBigrams)
? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
- // TODO: pass the previous word to native code
- return getSuggestionsNative(
- mNativeDict, proximityInfo.getNativeProximityInfo(),
- codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize,
- prevWordCodePointArray, mUseFullEditDistance, outputChars, scores);
+ int[] emptyArray = new int[codesSize];
+ Arrays.fill(emptyArray, 0);
+
+ //final int commitPoint = codes.getCommitPoint();
+ //codes.clearCommitPoint();
+
+ return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
+ codes.getXCoordinates(), codes.getYCoordinates(), emptyArray, emptyArray, mInputCodes,
+ codesSize, 0 /* unused */, false, mDicTypeId,
+ prevWordCodePointArray, mUseFullEditDistance,
+ outputChars, scores, spaceIndices);
}
public static float calcNormalizedScore(String before, String after, int score) {
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 10e511eaf..2a02603ca 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -120,12 +120,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
}
}
- @Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- super.getBigrams(codes, previousWord, callback);
- }
-
private boolean useFirstLastBigramsForLocale(Locale locale) {
// TODO: Add firstname/lastname bigram rules for other languages.
if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 9c3d46e70..99a04da72 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,6 +17,9 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
/**
* Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
@@ -32,51 +35,26 @@ public abstract class Dictionary {
public static final int BIGRAM = 1;
public static final int NOT_A_PROBABILITY = -1;
- /**
- * Interface to be implemented by classes requesting words to be fetched from the dictionary.
- * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo)
- */
- public interface WordCallback {
- /**
- * Adds a word to a list of suggestions. The word is expected to be ordered based on
- * the provided score.
- * @param word the character array containing the word
- * @param wordOffset starting offset of the word in the character array
- * @param wordLength length of valid characters in the character array
- * @param score the score of occurrence. This is normalized between 1 and 255, but
- * can exceed those limits
- * @param dicTypeId of the dictionary where word was from
- * @param dataType tells type of this data, either UNIGRAM or BIGRAM
- * @return true if the word was added, false if no more words are required
- */
- boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId,
- int dataType);
- }
/**
* Searches for words in the dictionary that match the characters in the composer. Matched
- * words are added through the callback object.
- * @param composer the key sequence to match
+ * words are returned as an ArrayList.
+ * @param composer the key sequence to match with coordinate info, as a WordComposer
* @param prevWordForBigrams the previous word, or null if none
- * @param callback the callback object to send matched words to as possible candidates
* @param proximityInfo the object for key proximity. May be ignored by some implementations.
- * @see WordCallback#addWord(char[], int, int, int, int, int)
+ * @return the list of suggestions
*/
- abstract public void getWords(final WordComposer composer,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo);
+ abstract public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo);
/**
- * Searches for pairs in the bigram dictionary that matches the previous word and all the
- * possible words following are added through the callback object.
+ * Searches for pairs in the bigram dictionary that matches the previous word.
* @param composer the key sequence to match
* @param previousWord the word before
- * @param callback the callback object to send possible word following previous word
+ * @return the list of suggestions
*/
- public void getBigrams(final WordComposer composer, final CharSequence previousWord,
- final WordCallback callback) {
- // empty base implementation
- }
+ public abstract ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+ final CharSequence previousWord);
/**
* Checks if the given word occurs in the dictionary
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 26c2e637e..169e70745 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -17,9 +17,11 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -50,17 +52,41 @@ public class DictionaryCollection extends Dictionary {
}
@Override
- public void getWords(final WordComposer composer, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
- for (final Dictionary dict : mDictionaries)
- dict.getWords(composer, prevWordForBigrams, callback, proximityInfo);
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+ final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+ if (dictionaries.isEmpty()) return null;
+ // To avoid creating unnecessary objects, we get the list out of the first
+ // dictionary and add the rest to it if not null, hence the get(0)
+ ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getWords(composer,
+ prevWordForBigrams, proximityInfo);
+ if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+ final int length = dictionaries.size();
+ for (int i = 0; i < length; ++ i) {
+ final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getWords(composer,
+ prevWordForBigrams, proximityInfo);
+ if (null != sugg) suggestions.addAll(sugg);
+ }
+ return suggestions;
}
@Override
- public void getBigrams(final WordComposer composer, final CharSequence previousWord,
- final WordCallback callback) {
- for (final Dictionary dict : mDictionaries)
- dict.getBigrams(composer, previousWord, callback);
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+ final CharSequence previousWord) {
+ final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+ if (dictionaries.isEmpty()) return null;
+ // To avoid creating unnecessary objects, we get the list out of the first
+ // dictionary and add the rest to it if not null, hence the get(0)
+ ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getBigrams(composer,
+ previousWord);
+ if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+ final int length = dictionaries.size();
+ for (int i = 0; i < length; ++ i) {
+ final ArrayList<SuggestedWordInfo> sugg =
+ dictionaries.get(i).getBigrams(composer, previousWord);
+ if (null != sugg) suggestions.addAll(sugg);
+ }
+ return suggestions;
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index a22d73af7..6d77c4dd2 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -59,7 +59,7 @@ public class DictionaryFactory {
for (final AssetFileAddress f : assetFileList) {
final BinaryDictionary binaryDictionary =
new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength,
- useFullEditDistance, locale);
+ useFullEditDistance, locale, Suggest.DIC_MAIN);
if (binaryDictionary.isValidDictionary()) {
dictList.add(binaryDictionary);
}
@@ -112,7 +112,7 @@ public class DictionaryFactory {
return null;
}
return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(),
- false /* useFullEditDistance */, locale);
+ false /* useFullEditDistance */, locale, Suggest.DIC_MAIN);
} catch (android.content.res.Resources.NotFoundException e) {
Log.e(TAG, "Could not find the resource");
return null;
@@ -140,7 +140,7 @@ public class DictionaryFactory {
long startOffset, long length, final boolean useFullEditDistance, Locale locale) {
if (dictionary.isFile()) {
return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length,
- useFullEditDistance, locale);
+ useFullEditDistance, locale, Suggest.DIC_MAIN);
} else {
Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
return null;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c65404cbc..c076fa0f9 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -19,6 +19,7 @@ import android.os.SystemClock;
import android.util.Log;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
import com.android.inputmethod.latin.makedict.FusionDictionary;
import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
@@ -194,46 +195,47 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
asyncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
- protected final void getWordsInner(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
// Ensure that there are no concurrent calls to getWords. If there are, do nothing and
// return.
if (mLocalDictionaryController.tryLock()) {
try {
if (mBinaryDictionary != null) {
- mBinaryDictionary.getWords(codes, prevWordForBigrams, callback, proximityInfo);
+ return mBinaryDictionary.getWords(codes, prevWordForBigrams, proximityInfo);
}
} finally {
mLocalDictionaryController.unlock();
}
}
+ return null;
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
asyncReloadDictionaryIfRequired();
- getBigramsInner(codes, previousWord, callback);
+ return getBigramsInner(codes, previousWord);
}
- protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ protected ArrayList<SuggestedWordInfo> getBigramsInner(final WordComposer codes,
+ final CharSequence previousWord) {
if (mLocalDictionaryController.tryLock()) {
try {
if (mBinaryDictionary != null) {
- mBinaryDictionary.getBigrams(codes, previousWord, callback);
+ return mBinaryDictionary.getBigrams(codes, previousWord);
}
} finally {
mLocalDictionaryController.unlock();
}
}
+ return null;
}
@Override
@@ -306,7 +308,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
// Build the new binary dictionary
final BinaryDictionary newBinaryDictionary =
new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */,
- null);
+ null, mDicTypeId);
if (mBinaryDictionary != null) {
// Ensure all threads accessing the current dictionary have finished before swapping in
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 4a5471c85..f19d77be2 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -21,6 +21,7 @@ import android.content.Context;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams;
import java.util.ArrayList;
@@ -247,23 +248,25 @@ public class ExpandableDictionary extends Dictionary {
}
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
synchronized (mUpdatingLock) {
// If we need to update, start off a background task
if (mRequiresReload) startDictionaryLoadingTaskLocked();
// Currently updating contacts, don't return any results.
- if (mUpdatingDictionary) return;
+ if (mUpdatingDictionary) return null;
}
if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
- return;
+ return null;
}
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ final ArrayList<SuggestedWordInfo> suggestions =
+ getWordsInner(codes, prevWordForBigrams, proximityInfo);
+ return suggestions;
}
- protected final void getWordsInner(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
mInputLength = codes.size();
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
final int[] xCoordinates = codes.getXCoordinates();
@@ -281,10 +284,11 @@ public class ExpandableDictionary extends Dictionary {
proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]);
}
mMaxDepth = mInputLength * 3;
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, suggestions);
for (int i = 0; i < mInputLength; i++) {
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, suggestions);
}
+ return suggestions;
}
@Override
@@ -368,24 +372,27 @@ public class ExpandableDictionary extends Dictionary {
* @param word the word to insert, as an array of code points
* @param depth the depth of the node in the tree
* @param finalFreq the frequency for this word
+ * @param suggestions the suggestion collection to add the suggestions to
* @return whether there is still space for more words.
- * @see Dictionary.WordCallback#addWord(char[], int, int, int, int, int)
*/
private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth,
- final int finalFreq, final WordCallback callback) {
+ final int finalFreq, final ArrayList<SuggestedWordInfo> suggestions) {
if (finalFreq > 0 && !node.mShortcutOnly) {
- if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, Dictionary.UNIGRAM)) {
- return false;
- }
+ // Use KIND_CORRECTION always. This dictionary does not really have a notion of
+ // COMPLETION against CORRECTION; we could artificially add one by looking at
+ // the respective size of the typed word and the suggestion if it matters sometime
+ // in the future.
+ suggestions.add(new SuggestedWordInfo(new String(word, 0, depth + 1), finalFreq,
+ SuggestedWordInfo.KIND_CORRECTION));
+ if (suggestions.size() >= Suggest.MAX_SUGGESTIONS) return false;
}
if (null != node.mShortcutTargets) {
final int length = node.mShortcutTargets.size();
for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) {
final char[] shortcut = node.mShortcutTargets.get(shortcutIndex);
- if (!callback.addWord(shortcut, 0, shortcut.length, finalFreq, mDicTypeId,
- Dictionary.UNIGRAM)) {
- return false;
- }
+ suggestions.add(new SuggestedWordInfo(new String(shortcut, 0, shortcut.length),
+ finalFreq, SuggestedWordInfo.KIND_SHORTCUT));
+ if (suggestions.size() > Suggest.MAX_SUGGESTIONS) return false;
}
}
return true;
@@ -408,12 +415,12 @@ public class ExpandableDictionary extends Dictionary {
* case we skip over some punctuations such as apostrophe in the traversal. That is, if you type
* "wouldve", it could be matching "would've", so the depth will be one more than the
* inputIndex
- * @param callback the callback class for adding a word
+ * @param suggestions the list in which to add suggestions
*/
// TODO: Share this routine with the native code for BinaryDictionary
protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word,
final int depth, final boolean completion, int snr, int inputIndex, int skipPos,
- WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
final int count = roots.mLength;
final int codeSize = mInputLength;
// Optimization: Prune out words that are too long compared to how much was typed.
@@ -443,14 +450,14 @@ public class ExpandableDictionary extends Dictionary {
} else {
finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength);
}
- if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, callback)) {
+ if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, suggestions)) {
// No space left in the queue, bail out
return;
}
}
if (children != null) {
getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex,
- skipPos, callback);
+ skipPos, suggestions);
}
} else if ((c == Keyboard.CODE_SINGLE_QUOTE
&& currentChars[0] != Keyboard.CODE_SINGLE_QUOTE) || depth == skipPos) {
@@ -458,7 +465,7 @@ public class ExpandableDictionary extends Dictionary {
word[depth] = c;
if (children != null) {
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
- skipPos, callback);
+ skipPos, suggestions);
}
} else {
// Don't use alternatives if we're looking for missing characters
@@ -483,7 +490,7 @@ public class ExpandableDictionary extends Dictionary {
snr * addedAttenuation, mInputLength);
}
if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq,
- callback)) {
+ suggestions)) {
// No space left in the queue, bail out
return;
}
@@ -491,12 +498,12 @@ public class ExpandableDictionary extends Dictionary {
if (children != null) {
getWordsRec(children, codes, word, depth + 1,
true, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
+ skipPos, suggestions);
}
} else if (children != null) {
getWordsRec(children, codes, word, depth + 1,
false, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
+ skipPos, suggestions);
}
}
}
@@ -593,22 +600,25 @@ public class ExpandableDictionary extends Dictionary {
}
private void runBigramReverseLookUp(final CharSequence previousWord,
- final WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
// Search for the lowercase version of the word only, because that's where bigrams
// store their sons.
Node prevWord = searchNode(mRoots, previousWord.toString().toLowerCase(), 0,
previousWord.length());
if (prevWord != null && prevWord.mNGrams != null) {
- reverseLookUp(prevWord.mNGrams, callback);
+ reverseLookUp(prevWord.mNGrams, suggestions);
}
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
if (!reloadDictionaryIfRequired()) {
- runBigramReverseLookUp(previousWord, callback);
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
+ runBigramReverseLookUp(previousWord, suggestions);
+ return suggestions;
}
+ return null;
}
/**
@@ -635,11 +645,12 @@ public class ExpandableDictionary extends Dictionary {
/**
* reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
- * through callback.
+ * to the suggestions list passed as an argument.
* @param terminalNodes list of terminal nodes we want to add
+ * @param suggestions the suggestion collection to add the word to
*/
private void reverseLookUp(LinkedList<NextWord> terminalNodes,
- final WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
Node node;
int freq;
for (NextWord nextWord : terminalNodes) {
@@ -653,8 +664,9 @@ public class ExpandableDictionary extends Dictionary {
} while (node != null);
if (freq >= 0) {
- callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index,
- freq, mDicTypeId, Dictionary.BIGRAM);
+ suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index,
+ BinaryDictionary.MAX_WORD_LENGTH - index),
+ freq, SuggestedWordInfo.KIND_CORRECTION));
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 8a5fc495e..25b8fd566 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1710,7 +1710,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// getSuggestedWords handles gracefully a null value of prevWord
final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
- mCurrentSettings.mCorrectionEnabled);
+ mCurrentSettings.mCorrectionEnabled, false);
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1922,7 +1922,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mCurrentSettings.mCorrectionEnabled) {
final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
if (!TextUtils.isEmpty(prevWord)) {
- suggestedWords = mSuggest.getBigramPredictions(prevWord);
+ suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+ mCurrentSettings.mCorrectionEnabled, true);
} else {
suggestedWords = null;
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 0c19bed05..40d327ebb 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -340,13 +340,6 @@ public class RichInputConnection {
* Returns the word before the cursor if the cursor is at the end of a word, null otherwise
*/
public CharSequence getWordBeforeCursorIfAtEndOfWord(final SettingsValues settings) {
- // Bail out if the cursor is not at the end of a word (cursor must be preceded by
- // non-whitespace, non-separator, non-start-of-text)
- // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
- final CharSequence textBeforeCursor = getTextBeforeCursor(1, 0);
- if (TextUtils.isEmpty(textBeforeCursor)
- || settings.isWordSeparator(textBeforeCursor.charAt(0))) return null;
-
// Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
// separator or end of line/text)
// Example: "test|"<EOL> "te|st" get rejected here
@@ -363,6 +356,15 @@ public class RichInputConnection {
word = word.subSequence(1, word.length());
}
if (TextUtils.isEmpty(word)) return null;
+ // Find the last code point of the string
+ final int lastCodePoint = Character.codePointBefore(word, word.length());
+ // If for some reason the text field contains non-unicode binary data, or if the
+ // charsequence is exactly one char long and the contents is a low surrogate, return null.
+ if (!Character.isDefined(lastCodePoint)) return null;
+ // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+ // non-whitespace, non-separator, non-start-of-text)
+ // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+ if (settings.isWordSeparator(lastCodePoint)) return null;
final char firstChar = word.charAt(0); // we just tested that word is not empty
if (word.length() == 1 && !Character.isLetter(firstChar)) return null;
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4c67b4957..4c89a6e91 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -143,19 +143,39 @@ public class Settings extends InputMethodSettingsFragment
generalSettings.removePreference(mVoicePreference);
}
+ final PreferenceGroup advancedSettings =
+ (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
if (!VibratorUtils.getInstance(context).hasVibrator()) {
- final PreferenceGroup advancedSettings =
- (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
advancedSettings.removePreference(findPreference(PREF_VIBRATION_DURATION_SETTINGS));
}
}
- final boolean showPopupOption = res.getBoolean(
+ final boolean showKeyPreviewPopupOption = res.getBoolean(
R.bool.config_enable_show_popup_on_keypress_option);
- if (!showPopupOption) {
+ mKeyPreviewPopupDismissDelay =
+ (ListPreference) findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+ if (!showKeyPreviewPopupOption) {
generalSettings.removePreference(findPreference(PREF_POPUP_ON));
+ if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+ advancedSettings.removePreference(mKeyPreviewPopupDismissDelay);
+ }
+ } else {
+ final String[] entries = new String[] {
+ res.getString(R.string.key_preview_popup_dismiss_no_delay),
+ res.getString(R.string.key_preview_popup_dismiss_default_delay),
+ };
+ final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
+ R.integer.config_key_preview_linger_timeout));
+ mKeyPreviewPopupDismissDelay.setEntries(entries);
+ mKeyPreviewPopupDismissDelay.setEntryValues(
+ new String[] { "0", popupDismissDelayDefaultValue });
+ if (null == mKeyPreviewPopupDismissDelay.getValue()) {
+ mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
+ }
+ mKeyPreviewPopupDismissDelay.setEnabled(
+ SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
}
final CheckBoxPreference includeOtherImesInLanguageSwitchList =
@@ -163,23 +183,6 @@ public class Settings extends InputMethodSettingsFragment
includeOtherImesInLanguageSwitchList.setEnabled(
!SettingsValues.isLanguageSwitchKeySupressed(prefs));
- mKeyPreviewPopupDismissDelay =
- (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
- final String[] entries = new String[] {
- res.getString(R.string.key_preview_popup_dismiss_no_delay),
- res.getString(R.string.key_preview_popup_dismiss_default_delay),
- };
- final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
- R.integer.config_key_preview_linger_timeout));
- mKeyPreviewPopupDismissDelay.setEntries(entries);
- mKeyPreviewPopupDismissDelay.setEntryValues(
- new String[] { "0", popupDismissDelayDefaultValue });
- if (null == mKeyPreviewPopupDismissDelay.getValue()) {
- mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
- }
- mKeyPreviewPopupDismissDelay.setEnabled(
- SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
-
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
final Intent intent = dictionaryLink.getIntent();
@@ -305,13 +308,15 @@ public class Settings extends InputMethodSettingsFragment
private void updateKeyPreviewPopupDelaySummary() {
final ListPreference lp = mKeyPreviewPopupDismissDelay;
- lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
+ final CharSequence[] entries = lp.getEntries();
+ if (entries == null || entries.length <= 0) return;
+ lp.setSummary(entries[lp.findIndexOfValue(lp.getValue())]);
}
private void updateVoiceModeSummary() {
mVoicePreference.setSummary(
getResources().getStringArray(R.array.voice_input_modes_summary)
- [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
+ [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
}
private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index a43b90525..6e7d985d6 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -184,6 +184,9 @@ public class StringUtils {
final char[] characters = string.toCharArray();
final int length = characters.length;
final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+ if (length <= 0) {
+ return new int[0];
+ }
int codePoint = Character.codePointAt(characters, 0);
int dsti = 0;
for (int srci = Character.charCount(codePoint);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 892245402..03ed9d98c 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -26,6 +26,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
@@ -34,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
* This class loads a dictionary and provides a list of suggestions for a given sequence of
* characters. This includes corrections and completions.
*/
-public class Suggest implements Dictionary.WordCallback {
+public class Suggest {
public static final String TAG = Suggest.class.getSimpleName();
public static final int APPROX_MAX_WORD_LENGTH = 32;
@@ -58,30 +59,34 @@ public class Suggest implements Dictionary.WordCallback {
public static final String DICT_KEY_CONTACTS = "contacts";
// User dictionary, the system-managed one.
public static final String DICT_KEY_USER = "user";
- // User history dictionary for the unigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram";
- // User history dictionary for the bigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram";
+ // User history dictionary internal to LatinIME
+ public static final String DICT_KEY_USER_HISTORY = "history";
public static final String DICT_KEY_WHITELIST ="whitelist";
+ // TODO: remove this map. This only serves as backward compatibility with a feature
+ // that has never been used and has been broken for a while.
+ private static final HashMap<String, Integer> sDictKeyToDictIndex
+ = new HashMap<String, Integer>();
+ static {
+ sDictKeyToDictIndex.put(DICT_KEY_MAIN, DIC_MAIN);
+ sDictKeyToDictIndex.put(DICT_KEY_USER, DIC_USER);
+ sDictKeyToDictIndex.put(DICT_KEY_USER_HISTORY, DIC_USER_HISTORY);
+ sDictKeyToDictIndex.put(DICT_KEY_CONTACTS, DIC_CONTACTS);
+ sDictKeyToDictIndex.put(DICT_KEY_WHITELIST, DIC_WHITELIST);
+ }
private static final boolean DBG = LatinImeLogger.sDBG;
private Dictionary mMainDictionary;
private ContactsBinaryDictionary mContactsDict;
private WhitelistDictionary mWhiteListDictionary;
- private final ConcurrentHashMap<String, Dictionary> mUnigramDictionaries =
- new ConcurrentHashMap<String, Dictionary>();
- private final ConcurrentHashMap<String, Dictionary> mBigramDictionaries =
+ private final ConcurrentHashMap<String, Dictionary> mDictionaries =
new ConcurrentHashMap<String, Dictionary>();
public static final int MAX_SUGGESTIONS = 18;
- private static final int PREF_MAX_BIGRAMS = 60;
-
private float mAutoCorrectionThreshold;
private ArrayList<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>();
- private ArrayList<SuggestedWordInfo> mBigramSuggestions = new ArrayList<SuggestedWordInfo>();
private CharSequence mConsideredWord;
// TODO: Remove these member variables by passing more context to addWord() callback method
@@ -100,14 +105,13 @@ public class Suggest implements Dictionary.WordCallback {
final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
startOffset, length /* useFullEditDistance */, false, locale);
mMainDictionary = mainDict;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, mainDict);
initWhitelistAndAutocorrectAndPool(context, locale);
}
private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
mWhiteListDictionary = new WhitelistDictionary(context, locale);
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
}
private void initAsynchronously(final Context context, final Locale locale) {
@@ -136,8 +140,7 @@ public class Suggest implements Dictionary.WordCallback {
public void run() {
final DictionaryCollection newMainDict =
DictionaryFactory.createMainDictionaryFromManager(context, locale);
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, newMainDict);
mMainDictionary = newMainDict;
}
}.start();
@@ -158,7 +161,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
- return mUnigramDictionaries;
+ return mDictionaries;
}
public static int getApproxMaxWordLength() {
@@ -170,7 +173,7 @@ public class Suggest implements Dictionary.WordCallback {
* before the main dictionary, if set. This refers to the system-managed user dictionary.
*/
public void setUserDictionary(UserBinaryDictionary userDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER, userDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_USER, userDictionary);
}
/**
@@ -180,15 +183,11 @@ public class Suggest implements Dictionary.WordCallback {
*/
public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) {
mContactsDict = contactsDictionary;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
}
public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM,
- userHistoryDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM,
- userHistoryDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_USER_HISTORY, userHistoryDictionary);
}
public void setAutoCorrectionThreshold(float threshold) {
@@ -212,50 +211,14 @@ public class Suggest implements Dictionary.WordCallback {
return sb;
}
- protected void addBigramToSuggestions(SuggestedWordInfo bigram) {
- mSuggestions.add(bigram);
- }
-
- private static final WordComposer sEmptyWordComposer = new WordComposer();
- public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) {
- LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mIsFirstCharCapitalized = false;
- mIsAllUpperCase = false;
- mTrailingSingleQuotesCount = 0;
- mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
-
- // Treating USER_TYPED as UNIGRAM suggestion for logging now.
- LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
- mConsideredWord = "";
-
- mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
- getAllBigrams(prevWordForBigram, sEmptyWordComposer);
-
- // Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
- for (int i = 0; i < insertCount; ++i) {
- addBigramToSuggestions(mBigramSuggestions.get(i));
- }
-
- SuggestedWordInfo.removeDups(mSuggestions);
-
- return new SuggestedWords(mSuggestions,
- false /* typedWordValid */,
- false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
- false /* isPunctuationSuggestions */,
- false /* isObsoleteSuggestions */,
- true /* isPrediction */);
- }
-
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
public SuggestedWords getSuggestedWords(
final WordComposer wordComposer, CharSequence prevWordForBigram,
- final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
+ final ProximityInfo proximityInfo, final boolean isCorrectionEnabled,
+ final boolean isPrediction) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
- mIsAllUpperCase = wordComposer.isAllUpperCase();
+ mIsFirstCharCapitalized = !isPrediction && wordComposer.isFirstCharCapitalized();
+ mIsAllUpperCase = !isPrediction && wordComposer.isAllUpperCase();
mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
@@ -269,37 +232,29 @@ public class Suggest implements Dictionary.WordCallback {
if (wordComposer.size() <= 1 && isCorrectionEnabled) {
// At first character typed, search only the bigrams
- mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
if (!TextUtils.isEmpty(prevWordForBigram)) {
- getAllBigrams(prevWordForBigram, wordComposer);
- if (TextUtils.isEmpty(consideredWord)) {
- // Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
- for (int i = 0; i < insertCount; ++i) {
- addBigramToSuggestions(mBigramSuggestions.get(i));
- }
- } else {
- // Word entered: return only bigrams that match the first char of the typed word
- final char currentChar = consideredWord.charAt(0);
+ final CharSequence lowerPrevWord;
+ if (StringUtils.hasUpperCase(prevWordForBigram)) {
// TODO: Must pay attention to locale when changing case.
- // TODO: Use codepoint instead of char
- final char currentCharUpper = Character.toUpperCase(currentChar);
- int count = 0;
- final int bigramSuggestionSize = mBigramSuggestions.size();
- for (int i = 0; i < bigramSuggestionSize; i++) {
- final SuggestedWordInfo bigramSuggestion = mBigramSuggestions.get(i);
- final char bigramSuggestionFirstChar =
- (char)bigramSuggestion.codePointAt(0);
- if (bigramSuggestionFirstChar == currentChar
- || bigramSuggestionFirstChar == currentCharUpper) {
- addBigramToSuggestions(bigramSuggestion);
- if (++count > MAX_SUGGESTIONS) break;
- }
+ lowerPrevWord = prevWordForBigram.toString().toLowerCase();
+ } else {
+ lowerPrevWord = null;
+ }
+ for (final String key : mDictionaries.keySet()) {
+ final int dicTypeId = sDictKeyToDictIndex.get(key);
+ final Dictionary dictionary = mDictionaries.get(key);
+ final ArrayList<SuggestedWordInfo> suggestions =
+ dictionary.getBigrams(wordComposer, prevWordForBigram);
+ if (null != lowerPrevWord) {
+ suggestions.addAll(dictionary.getBigrams(wordComposer, lowerPrevWord));
+ }
+ for (final SuggestedWordInfo suggestion : suggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(),
+ suggestion.mScore, dicTypeId, Dictionary.BIGRAM, mSuggestions);
}
}
}
-
} else if (wordComposer.size() > 1) {
final WordComposer wordComposerForLookup;
if (mTrailingSingleQuotesCount > 0) {
@@ -311,12 +266,19 @@ public class Suggest implements Dictionary.WordCallback {
wordComposerForLookup = wordComposer;
}
// At second character typed, search the unigrams (scores being affected by bigrams)
- for (final String key : mUnigramDictionaries.keySet()) {
+ for (final String key : mDictionaries.keySet()) {
// Skip UserUnigramDictionary and WhitelistDictionary to lookup
- if (key.equals(DICT_KEY_USER_HISTORY_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
+ if (key.equals(DICT_KEY_USER_HISTORY) || key.equals(DICT_KEY_WHITELIST))
continue;
- final Dictionary dictionary = mUnigramDictionaries.get(key);
- dictionary.getWords(wordComposerForLookup, prevWordForBigram, this, proximityInfo);
+ final int dicTypeId = sDictKeyToDictIndex.get(key);
+ final Dictionary dictionary = mDictionaries.get(key);
+ final ArrayList<SuggestedWordInfo> suggestions = dictionary.getWords(
+ wordComposerForLookup, prevWordForBigram, proximityInfo);
+ for (final SuggestedWordInfo suggestion : suggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(),
+ suggestion.mScore, dicTypeId, Dictionary.UNIGRAM, mSuggestions);
+ }
}
}
@@ -326,7 +288,7 @@ public class Suggest implements Dictionary.WordCallback {
final boolean hasAutoCorrection;
if (isCorrectionEnabled) {
final CharSequence autoCorrection =
- AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer,
+ AutoCorrection.computeAutoCorrectionWord(mDictionaries, wordComposer,
mSuggestions, consideredWord, mAutoCorrectionThreshold,
whitelistedWord);
hasAutoCorrection = (null != autoCorrection);
@@ -348,12 +310,14 @@ public class Suggest implements Dictionary.WordCallback {
}
}
- mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
- SuggestedWordInfo.KIND_TYPED));
+ if (!isPrediction) {
+ mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_TYPED));
+ }
SuggestedWordInfo.removeDups(mSuggestions);
final ArrayList<SuggestedWordInfo> suggestionsList;
- if (DBG) {
+ if (DBG && !mSuggestions.isEmpty()) {
suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions);
} else {
suggestionsList = mSuggestions;
@@ -386,29 +350,12 @@ public class Suggest implements Dictionary.WordCallback {
autoCorrectionAvailable = false;
}
return new SuggestedWords(suggestionsList,
- !allowsToBeAutoCorrected /* typedWordValid */,
- autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
- allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
+ !isPrediction && !allowsToBeAutoCorrected /* typedWordValid */,
+ !isPrediction && autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
+ !isPrediction && allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
false /* isPunctuationSuggestions */,
false /* isObsoleteSuggestions */,
- false /* isPrediction */);
- }
-
- /**
- * Adds all bigram predictions for prevWord. Also checks the lower case version of prevWord if
- * it contains any upper case characters.
- */
- private void getAllBigrams(final CharSequence prevWord, final WordComposer wordComposer) {
- if (StringUtils.hasUpperCase(prevWord)) {
- // TODO: Must pay attention to locale when changing case.
- final CharSequence lowerPrevWord = prevWord.toString().toLowerCase();
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, lowerPrevWord, this);
- }
- }
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, prevWord, this);
- }
+ isPrediction);
}
private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
@@ -438,19 +385,11 @@ public class Suggest implements Dictionary.WordCallback {
}
// TODO: Use codepoint instead of char
- @Override
- public boolean addWord(final char[] word, final int offset, final int length, int score,
- final int dicTypeId, final int dataType) {
+ public boolean addWord(final char[] word, int[] indices, final int offset, final int length,
+ int score, final int dicTypeId, final int dataType,
+ final ArrayList<SuggestedWordInfo> suggestions) {
int dataTypeForLog = dataType;
- final ArrayList<SuggestedWordInfo> suggestions;
- final int prefMaxSuggestions;
- if (dataType == Dictionary.BIGRAM) {
- suggestions = mBigramSuggestions;
- prefMaxSuggestions = PREF_MAX_BIGRAMS;
- } else {
- suggestions = mSuggestions;
- prefMaxSuggestions = MAX_SUGGESTIONS;
- }
+ final int prefMaxSuggestions = MAX_SUGGESTIONS;
int pos = 0;
@@ -513,8 +452,7 @@ public class Suggest implements Dictionary.WordCallback {
public void close() {
final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>();
- dictionaries.addAll(mUnigramDictionaries.values());
- dictionaries.addAll(mBigramDictionaries.values());
+ dictionaries.addAll(mDictionaries.values());
for (final Dictionary dictionary : dictionaries) {
dictionary.close();
}
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 1ed91fe71..45ac9ff53 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -129,10 +129,11 @@ public class SuggestedWords {
public static final int KIND_BLACKLIST = 4; // Blacklisted word
public static final int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
public static final int KIND_APP_DEFINED = 6; // Suggested by the application
+ public static final int KIND_SHORTCUT = 7; // A shortcut
private final String mWordStr;
public final CharSequence mWord;
public final int mScore;
- public final int mKind;
+ public final int mKind; // one of the KIND_* constants above
public final int mCodePointCount;
private String mDebugString = "";
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 673b54500..74f27e3cc 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -19,7 +19,9 @@ package com.android.inputmethod.latin;
import android.content.Context;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import java.util.ArrayList;
import java.util.Locale;
public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
@@ -30,11 +32,10 @@ public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryD
}
@Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
syncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 1606a34e0..5b2a6edec 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -19,6 +19,9 @@ package com.android.inputmethod.latin;
import android.content.Context;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
@@ -32,11 +35,10 @@ public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionar
}
@Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
syncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 6fa1a25a1..5bcdb57b5 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -36,11 +36,22 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
// TODO: use Words.SHORTCUT when it's public in the SDK
final static String SHORTCUT = "shortcut";
- private static final String[] PROJECTION_QUERY = {
- Words.WORD,
- SHORTCUT,
- Words.FREQUENCY,
- };
+ private static final String[] PROJECTION_QUERY;
+ static {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ SHORTCUT,
+ Words.FREQUENCY,
+ };
+ } else {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ Words.FREQUENCY,
+ };
+ }
+ }
private static final String NAME = "userunigram";
@@ -136,7 +147,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
requestArguments = localeElements;
}
final Cursor cursor = mContext.getContentResolver().query(
- Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
+ Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
try {
addWords(cursor);
} finally {
@@ -182,16 +193,18 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
}
private void addWords(Cursor cursor) {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16;
clearFusionDictionary();
if (cursor == null) return;
if (cursor.moveToFirst()) {
final int indexWord = cursor.getColumnIndex(Words.WORD);
- final int indexShortcut = cursor.getColumnIndex(SHORTCUT);
+ final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(SHORTCUT) : 0;
final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
while (!cursor.isAfterLast()) {
- String word = cursor.getString(indexWord);
- String shortcut = cursor.getString(indexShortcut);
- int frequency = cursor.getInt(indexFrequency);
+ final String word = cursor.getString(indexWord);
+ final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
+ final int frequency = cursor.getInt(indexFrequency);
// Safeguard against adding really long words.
if (word.length() < MAX_WORD_LENGTH) {
super.addWord(word, null, frequency);
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index f2d21ab9b..8f71de0e7 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -44,6 +44,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 7fffc31c0..5f4d66091 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -32,12 +32,12 @@ import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.BinaryDictionary;
import com.android.inputmethod.latin.ContactsBinaryDictionary;
import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.Dictionary.WordCallback;
import com.android.inputmethod.latin.DictionaryCollection;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary;
import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary;
import com.android.inputmethod.latin.UserBinaryDictionary;
@@ -203,7 +203,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
EMPTY_STRING_ARRAY);
}
- private static class SuggestionsGatherer implements WordCallback {
+ // TODO: remove this class and replace it by storage local to the session.
+ private static class SuggestionsGatherer {
public static class Result {
public final String[] mSuggestions;
public final boolean mHasRecommendedSuggestions;
@@ -237,9 +238,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
mScores = new int[mMaxLength];
}
- @Override
- synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score,
- int dicTypeId, int dataType) {
+ synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset,
+ int wordLength, int score) {
final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score);
// binarySearch returns the index if the element exists, and -<insertion index> - 1
// if it doesn't. See documentation for binarySearch.
@@ -780,8 +780,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService
try {
dictInfo = mDictionaryPool.takeOrGetNull();
if (null == dictInfo) return getNotInDictEmptySuggestions();
- dictInfo.mDictionary.getWords(composer, prevWord, suggestionsGatherer,
- dictInfo.mProximityInfo);
+ final ArrayList<SuggestedWordInfo> suggestions = dictInfo.mDictionary.getWords(
+ composer, prevWord, dictInfo.mProximityInfo);
+ for (final SuggestedWordInfo suggestion : suggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0,
+ suggestionStr.length(), suggestion.mScore);
+ }
isInDict = dictInfo.mDictionary.isValidWord(text);
if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
// We want to test the word again if it's all caps or first caps only.