aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod')
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java2
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java33
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java14
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java67
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java38
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java112
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/WordProperty.java6
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java8
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsFragment.java36
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java5
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java4
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SuggestionResults.java8
16 files changed, 190 insertions, 171 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 81825934f..702efb3d7 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -451,7 +451,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
locatePreviewPlacerView();
getLocationInWindow(mOriginCoords);
- mKeyPreviewChoreographer.placeKeyPreviewAndShow(key, keyboard.mIconsSet, mKeyDrawParams,
+ mKeyPreviewChoreographer.placeAndShowKeyPreview(key, keyboard.mIconsSet, mKeyDrawParams,
getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
}
@@ -554,11 +554,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// though there may be some chances that the value is zero. <code>width == 0</code>
// will cause zero-division error at
// {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}.
- final boolean singleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled()
+ final boolean isSingleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled()
&& !key.noKeyPreview() && moreKeys.length == 1
&& mKeyPreviewDrawParams.getVisibleWidth() > 0;
final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
- context, key, getKeyboard(), singleMoreKeyWithPreview,
+ context, key, getKeyboard(), isSingleMoreKeyWithPreview,
mKeyPreviewDrawParams.getVisibleWidth(),
mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
moreKeysKeyboard = builder.build();
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index 353e07cf7..e0184d7f1 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -261,13 +261,13 @@ public final class MoreKeysKeyboard extends Keyboard {
* @param context the context of {@link MoreKeysKeyboardView}.
* @param key the {@link Key} that invokes more keys keyboard.
* @param keyboard the {@link Keyboard} that contains the parentKey.
- * @param singleMoreKeyWithPreview true if the <code>key</code> has only one more key
- * and key popup preview is enabled.
+ * @param isSingleMoreKeyWithPreview true if the <code>key</code> has just a single
+ * "more key" and its key popup preview is enabled.
* @param keyPreviewDrawParams the parameter to place key preview.
- * @param paintToMeasure the {@link Paint} object to measure a more key width
+ * @param paintToMeasure the {@link Paint} object to measure a "more key" width
*/
public Builder(final Context context, final Key key, final Keyboard keyboard,
- final boolean singleMoreKeyWithPreview, final int keyPreviewVisibleWidth,
+ final boolean isSingleMoreKeyWithPreview, final int keyPreviewVisibleWidth,
final int keyPreviewVisibleHeight, final Paint paintToMeasure) {
super(context, new MoreKeysKeyboardParams());
load(keyboard.mMoreKeysTemplate, keyboard.mId);
@@ -275,10 +275,11 @@ public final class MoreKeysKeyboard extends Keyboard {
// TODO: More keys keyboard's vertical gap is currently calculated heuristically.
// Should revise the algorithm.
mParams.mVerticalGap = keyboard.mVerticalGap / 2;
+ // This {@link MoreKeysKeyboard} is invoked from the <code>key</code>.
mParentKey = key;
final int keyWidth, rowHeight;
- if (singleMoreKeyWithPreview) {
+ if (isSingleMoreKeyWithPreview) {
// Use pre-computed width and height if this more keys keyboard has only one key to
// mitigate visual flicker between key preview and more keys keyboard.
// Caveats for the visual assets: To achieve this effect, both the key preview
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index 6fc300beb..cd29c8d17 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -105,7 +105,7 @@ public final class KeyPreviewChoreographer {
mFreeKeyPreviewViews.add(keyPreviewView);
}
- public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet,
+ public void placeAndShowKeyPreview(final Key key, final KeyboardIconsSet iconsSet,
final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin,
final ViewGroup placerView, final boolean withAnimation) {
final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 0c196f2a3..95e1340ed 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -64,11 +64,12 @@ public final class BinaryDictionary extends Dictionary {
public static final int NOT_A_VALID_TIMESTAMP = -1;
// Format to get unigram flags from native side via getWordPropertyNative().
- private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 4;
+ private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5;
private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1;
private static final int FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX = 2;
private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+ private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
// Format to get probability and historical info from native side via getWordPropertyNative().
public static final int FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT = 4;
@@ -176,10 +177,12 @@ public final class BinaryDictionary extends Dictionary {
private static native int getNgramProbabilityNative(long dict, int[] word0,
boolean isBeginningOfSentence, int[] word1);
private static native void getWordPropertyNative(long dict, int[] word,
- int[] outCodePoints, boolean[] outFlags, int[] outProbabilityInfo,
- ArrayList<int[]> outBigramTargets, ArrayList<int[]> outBigramProbabilityInfo,
- ArrayList<int[]> outShortcutTargets, ArrayList<Integer> outShortcutProbabilities);
- private static native int getNextWordNative(long dict, int token, int[] outCodePoints);
+ boolean isBeginningOfSentence, int[] outCodePoints, boolean[] outFlags,
+ int[] outProbabilityInfo, ArrayList<int[]> outBigramTargets,
+ ArrayList<int[]> outBigramProbabilityInfo, ArrayList<int[]> outShortcutTargets,
+ ArrayList<Integer> outShortcutProbabilities);
+ private static native int getNextWordNative(long dict, int token, int[] outCodePoints,
+ boolean[] outIsBeginningOfSentence);
private static native void getSuggestionsNative(long dict, long proximityInfo,
long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times,
int[] pointerIds, int[] inputCodePoints, int inputSize, int[] suggestOptions,
@@ -360,8 +363,8 @@ public final class BinaryDictionary extends Dictionary {
isBeginningOfSentenceArray[0], wordCodePoints);
}
- public WordProperty getWordProperty(final String word) {
- if (TextUtils.isEmpty(word)) {
+ public WordProperty getWordProperty(final String word, final boolean isBeginningOfSentence) {
+ if (word == null) {
return null;
}
final int[] codePoints = StringUtils.toCodePointArray(word);
@@ -373,14 +376,15 @@ public final class BinaryDictionary extends Dictionary {
final ArrayList<int[]> outBigramProbabilityInfo = new ArrayList<>();
final ArrayList<int[]> outShortcutTargets = new ArrayList<>();
final ArrayList<Integer> outShortcutProbabilities = new ArrayList<>();
- getWordPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbabilityInfo,
- outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
- outShortcutProbabilities);
+ getWordPropertyNative(mNativeDict, codePoints, isBeginningOfSentence, outCodePoints,
+ outFlags, outProbabilityInfo, outBigramTargets, outBigramProbabilityInfo,
+ outShortcutTargets, outShortcutProbabilities);
return new WordProperty(codePoints,
outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX],
outFlags[FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX],
- outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX], outProbabilityInfo,
+ outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
+ outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
outShortcutProbabilities);
}
@@ -401,9 +405,12 @@ public final class BinaryDictionary extends Dictionary {
*/
public GetNextWordPropertyResult getNextWordProperty(final int token) {
final int[] codePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
- final int nextToken = getNextWordNative(mNativeDict, token, codePoints);
+ final boolean[] isBeginningOfSentence = new boolean[1];
+ final int nextToken = getNextWordNative(mNativeDict, token, codePoints,
+ isBeginningOfSentence);
final String word = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
- return new GetNextWordPropertyResult(getWordProperty(word), nextToken);
+ return new GetNextWordPropertyResult(
+ getWordProperty(word, isBeginningOfSentence[0]), nextToken);
}
// Add a unigram entry to binary dictionary with unigram attributes in native code.
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 2f1aca6a3..b8feb2278 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -487,7 +487,7 @@ public class DictionaryFacilitator {
public SuggestionResults getSuggestionResults(final WordComposer composer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId, final ArrayList<SuggestedWordInfo> rawSuggestions) {
+ final int sessionId) {
final Dictionaries dictionaries = mDictionaries;
final SuggestionResults suggestionResults =
new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
@@ -501,21 +501,13 @@ public class DictionaryFacilitator {
languageWeight);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
- if (null != rawSuggestions) {
- rawSuggestions.addAll(dictionarySuggestions);
+ if (null != suggestionResults.mRawSuggestions) {
+ suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
}
}
return suggestionResults;
}
- public boolean isValidMainDictWord(final String word) {
- final Dictionary mainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
- if (TextUtils.isEmpty(word) || mainDict == null) {
- return false;
- }
- return mainDict.isValidWord(word);
- }
-
public boolean isValidWord(final String word, final boolean ignoreCase) {
if (TextUtils.isEmpty(word)) {
return false;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 1884e41e4..37879cf68 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -122,12 +122,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
return mBinaryDictionary.isValidDictionary();
}
- // TODO: Remove and always enable beginning of sentence prediction. Currently, this is enabled
- // only for ContextualDictionary.
- protected boolean enableBeginningOfSentencePrediction() {
- return false;
- }
-
/**
* Creates a new expandable binary dictionary.
*
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 670d856e3..9d03e8a43 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -100,30 +100,43 @@ public final class Suggest {
? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
: typedWord;
- final ArrayList<SuggestedWordInfo> rawSuggestions;
- if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
- rawSuggestions = new ArrayList<>();
- } else {
- rawSuggestions = null;
- }
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, SESSION_TYPING, rawSuggestions);
+ additionalFeaturesOptions, SESSION_TYPING);
+ final boolean isPrediction = !wordComposer.isComposingWord();
+ final boolean shouldMakeSuggestionsAllUpperCase = wordComposer.isAllUpperCase()
+ && !wordComposer.isResumed();
final boolean isOnlyFirstCharCapitalized =
wordComposer.isOrWillBeOnlyFirstCharCapitalized();
+
+ final ArrayList<SuggestedWordInfo> suggestionsContainer =
+ new ArrayList<>(suggestionResults);
+ final int suggestionsCount = suggestionsContainer.size();
+ if (isOnlyFirstCharCapitalized || shouldMakeSuggestionsAllUpperCase
+ || 0 != trailingSingleQuotesCount) {
+ for (int i = 0; i < suggestionsCount; ++i) {
+ final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+ final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
+ wordInfo, suggestionResults.mLocale, shouldMakeSuggestionsAllUpperCase,
+ isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+ suggestionsContainer.set(i, transformedWordInfo);
+ }
+ }
+ SuggestedWordInfo.removeDups(typedWord, suggestionsContainer);
+
// If resumed, then we don't want to upcase everything: resuming on a fully-capitalized
// words is rarely done to switch to another fully-capitalized word, but usually to a
// normal, non-capitalized suggestion.
- final boolean isAllUpperCase = wordComposer.isAllUpperCase() && !wordComposer.isResumed();
final String firstSuggestion;
final String whitelistedWord;
if (suggestionResults.isEmpty()) {
whitelistedWord = firstSuggestion = null;
} else {
final SuggestedWordInfo firstSuggestedWordInfo = getTransformedSuggestedWordInfo(
- suggestionResults.first(), suggestionResults.mLocale, isAllUpperCase,
- isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+ suggestionResults.first(), suggestionResults.mLocale,
+ shouldMakeSuggestionsAllUpperCase, isOnlyFirstCharCapitalized,
+ trailingSingleQuotesCount);
firstSuggestion = firstSuggestedWordInfo.mWord;
if (!firstSuggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
whitelistedWord = null;
@@ -132,8 +145,6 @@ public final class Suggest {
}
}
- final boolean isPrediction = !wordComposer.isComposingWord();
-
// We allow auto-correction if we have a whitelisted word, or if the word is not a valid
// word of more than 1 char, except if the first suggestion is the same as the typed string
// because in this case if it's strong enough to auto-correct that will mistakenly designate
@@ -171,19 +182,6 @@ public final class Suggest {
suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
}
- final ArrayList<SuggestedWordInfo> suggestionsContainer =
- new ArrayList<>(suggestionResults);
- final int suggestionsCount = suggestionsContainer.size();
- if (isOnlyFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) {
- for (int i = 0; i < suggestionsCount; ++i) {
- final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
- final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
- wordInfo, suggestionResults.mLocale, isAllUpperCase,
- isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
- suggestionsContainer.set(i, transformedWordInfo);
- }
- }
-
if (!TextUtils.isEmpty(typedWord)) {
suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
@@ -191,7 +189,6 @@ public final class Suggest {
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
- SuggestedWordInfo.removeDups(suggestionsContainer);
final ArrayList<SuggestedWordInfo> suggestionsList;
if (DBG && !suggestionsContainer.isEmpty()) {
@@ -200,12 +197,13 @@ public final class Suggest {
suggestionsList = suggestionsContainer;
}
- callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, rawSuggestions,
+ callback.onGetSuggestedWords(new SuggestedWords(suggestionsList,
+ suggestionResults.mRawSuggestions,
// TODO: this first argument is lying. If this is a whitelisted word which is an
// actual word, it says typedWordValid = false, which looks wrong. We should either
// rename the attribute or change the value.
!isPrediction && !allowsToBeAutoCorrected /* typedWordValid */,
- hasAutoCorrection, /* willAutoCorrect */
+ hasAutoCorrection /* willAutoCorrect */,
false /* isObsoleteSuggestions */, isPrediction, sequenceNumber));
}
@@ -216,15 +214,9 @@ public final class Suggest {
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
- final ArrayList<SuggestedWordInfo> rawSuggestions;
- if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
- rawSuggestions = new ArrayList<>();
- } else {
- rawSuggestions = null;
- }
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, sessionId, rawSuggestions);
+ additionalFeaturesOptions, sessionId);
final ArrayList<SuggestedWordInfo> suggestionsContainer =
new ArrayList<>(suggestionResults);
final int suggestionsCount = suggestionsContainer.size();
@@ -245,7 +237,7 @@ public final class Suggest {
final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
suggestionsContainer.add(1, rejected);
}
- SuggestedWordInfo.removeDups(suggestionsContainer);
+ SuggestedWordInfo.removeDups(null /* typedWord */, suggestionsContainer);
// For some reason some suggestions with MIN_VALUE are making their way here.
// TODO: Find a more robust way to detect distractors.
@@ -257,7 +249,8 @@ public final class Suggest {
// In the batch input mode, the most relevant suggested word should act as a "typed word"
// (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false).
- callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer, rawSuggestions,
+ callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer,
+ suggestionResults.mRawSuggestions,
true /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 72461e17a..f22af7991 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -316,10 +316,6 @@ public class SuggestedWords {
return mDebugString;
}
- public int codePointCount() {
- return mCodePointCount;
- }
-
public int codePointAt(int i) {
return mWord.codePointAt(i);
}
@@ -333,23 +329,29 @@ public class SuggestedWords {
}
}
- // TODO: Consolidate this method and StringUtils.removeDupes() in the future.
- public static void removeDups(ArrayList<SuggestedWordInfo> candidates) {
- if (candidates.size() <= 1) {
+ // This will always remove the higher index if a duplicate is found.
+ public static void removeDups(final String typedWord,
+ ArrayList<SuggestedWordInfo> candidates) {
+ if (candidates.isEmpty()) {
return;
}
- int i = 1;
- while (i < candidates.size()) {
- final SuggestedWordInfo cur = candidates.get(i);
- for (int j = 0; j < i; ++j) {
- final SuggestedWordInfo previous = candidates.get(j);
- if (cur.mWord.equals(previous.mWord)) {
- candidates.remove(cur.mScore < previous.mScore ? i : j);
- --i;
- break;
- }
+ if (!TextUtils.isEmpty(typedWord)) {
+ removeSuggestedWordInfoFrom(typedWord, candidates, -1 /* startIndexExclusive */);
+ }
+ for (int i = 0; i < candidates.size(); ++i) {
+ removeSuggestedWordInfoFrom(candidates.get(i).mWord, candidates,
+ i /* startIndexExclusive */);
+ }
+ }
+
+ private static void removeSuggestedWordInfoFrom(final String word,
+ final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) {
+ for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) {
+ final SuggestedWordInfo previous = candidates.get(i);
+ if (word.equals(previous.mWord)) {
+ candidates.remove(i);
+ --i;
}
- ++i;
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 32c6942f7..c9d0dcf60 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -728,14 +728,13 @@ public final class InputLogic {
mConnection.setComposingText(getTextWithUnderline(
mWordComposer.getTypedWord()), 1);
} else {
- final boolean swapWeakSpace = maybeStripSpace(inputTransaction,
- inputTransaction.mEvent.isSuggestionStripPress());
+ final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ inputTransaction, inputTransaction.mEvent.isSuggestionStripPress());
- sendKeyCodePoint(settingsValues, codePoint);
-
- if (swapWeakSpace) {
- swapSwapperAndSpace(inputTransaction);
+ if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
mSpaceState = SpaceState.WEAK;
+ } else {
+ sendKeyCodePoint(settingsValues, codePoint);
}
// In case the "add to dictionary" hint was still displayed.
mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
@@ -780,7 +779,8 @@ public final class InputLogic {
}
}
- final boolean swapWeakSpace = maybeStripSpace(inputTransaction, isFromSuggestionStrip);
+ final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ inputTransaction, isFromSuggestionStrip);
final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
&& mConnection.isInsideDoubleQuoteOrAfterDigit();
@@ -804,16 +804,14 @@ public final class InputLogic {
promotePhantomSpace(settingsValues);
}
- if (!shouldAvoidSendingCode) {
- sendKeyCodePoint(settingsValues, codePoint);
- }
-
- if (Constants.CODE_SPACE == codePoint) {
- if (maybeDoubleSpacePeriod(inputTransaction)) {
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- inputTransaction.setRequiresUpdateSuggestions();
- mSpaceState = SpaceState.DOUBLE;
- } else if (!mSuggestedWords.isPunctuationSuggestions()) {
+ if (tryPerformDoubleSpacePeriod(inputTransaction)) {
+ mSpaceState = SpaceState.DOUBLE;
+ inputTransaction.setRequiresUpdateSuggestions();
+ } else if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
+ mSpaceState = SpaceState.SWAP_PUNCTUATION;
+ mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+ } else if (Constants.CODE_SPACE == codePoint) {
+ if (!mSuggestedWords.isPunctuationSuggestions()) {
mSpaceState = SpaceState.WEAK;
}
@@ -821,11 +819,12 @@ public final class InputLogic {
if (wasComposingWord || mSuggestedWords.isEmpty()) {
inputTransaction.setRequiresUpdateSuggestions();
}
+
+ if (!shouldAvoidSendingCode) {
+ sendKeyCodePoint(settingsValues, codePoint);
+ }
} else {
- if (swapWeakSpace) {
- swapSwapperAndSpace(inputTransaction);
- mSpaceState = SpaceState.SWAP_PUNCTUATION;
- } else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
+ if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
&& settingsValues.isUsuallyFollowedBySpace(codePoint))
|| (Constants.CODE_DOUBLE_QUOTE == codePoint
&& isInsideDoubleQuoteOrAfterDigit)) {
@@ -843,6 +842,8 @@ public final class InputLogic {
mSpaceState = SpaceState.PHANTOM;
}
+ sendKeyCodePoint(settingsValues, codePoint);
+
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
@@ -1008,16 +1009,18 @@ public final class InputLogic {
* This method will check that there are two characters before the cursor and that the first
* one is a space before it does the actual swapping.
* @param inputTransaction The transaction in progress.
+ * @return true if the swap has been performed, false if it was prevented by preliminary checks.
*/
- private void swapSwapperAndSpace(final InputTransaction inputTransaction) {
- final CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
- // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
- if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) {
- mConnection.deleteSurroundingText(2, 0);
- final String text = lastTwo.charAt(1) + " ";
- mConnection.commitText(text, 1);
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ private boolean trySwapSwapperAndSpace(final InputTransaction inputTransaction) {
+ final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+ if (Constants.CODE_SPACE != codePointBeforeCursor) {
+ return false;
}
+ mConnection.deleteSurroundingText(1, 0);
+ final String text = inputTransaction.mEvent.getTextToCommit() + " ";
+ mConnection.commitText(text, 1);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ return true;
}
/*
@@ -1026,8 +1029,8 @@ public final class InputLogic {
* @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip.
* @return whether we should swap the space instead of removing it.
*/
- private boolean maybeStripSpace(final InputTransaction inputTransaction,
- final boolean isFromSuggestionStrip) {
+ private boolean tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
if (Constants.CODE_ENTER == codePoint &&
SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
@@ -1068,37 +1071,42 @@ public final class InputLogic {
* period-space sequence of characters. This typically happens when the user presses space
* twice in a row quickly.
* This method will check that the double-space-to-period is active in settings, that the
- * two spaces have been input close enough together, and that the previous character allows
- * for the transformation to take place. If all of these conditions are fulfilled, this
- * method applies the transformation and returns true. Otherwise, it does nothing and
- * returns false.
+ * two spaces have been input close enough together, that the typed character is a space
+ * and that the previous character allows for the transformation to take place. If all of
+ * these conditions are fulfilled, this method applies the transformation and returns true.
+ * Otherwise, it does nothing and returns false.
*
* @param inputTransaction The transaction in progress.
* @return true if we applied the double-space-to-period transformation, false otherwise.
*/
- private boolean maybeDoubleSpacePeriod(final InputTransaction inputTransaction) {
- if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod) return false;
- if (!isDoubleSpacePeriodCountdownActive(inputTransaction)) return false;
- // We only do this when we see two spaces and an accepted code point before the cursor.
- // The code point may be a surrogate pair but the two spaces may not, so we need 4 chars.
- final CharSequence lastThree = mConnection.getTextBeforeCursor(4, 0);
- if (null == lastThree) return false;
- final int length = lastThree.length();
- if (length < 3) return false;
- if (lastThree.charAt(length - 1) != Constants.CODE_SPACE) return false;
- if (lastThree.charAt(length - 2) != Constants.CODE_SPACE) return false;
- // We know there are spaces in pos -1 and -2, and we have at least three chars.
- // If we have only three chars, isSurrogatePairs can't return true as charAt(1) is a space,
- // so this is fine.
+ private boolean tryPerformDoubleSpacePeriod(final InputTransaction inputTransaction) {
+ // Check the setting, the typed character and the countdown. If any of the conditions is
+ // not fulfilled, return false.
+ if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod
+ || Constants.CODE_SPACE != inputTransaction.mEvent.mCodePoint
+ || !isDoubleSpacePeriodCountdownActive(inputTransaction)) {
+ return false;
+ }
+ // We only do this when we see one space and an accepted code point before the cursor.
+ // The code point may be a surrogate pair but the space may not, so we need 3 chars.
+ final CharSequence lastTwo = mConnection.getTextBeforeCursor(3, 0);
+ if (null == lastTwo) return false;
+ final int length = lastTwo.length();
+ if (length < 2) return false;
+ if (lastTwo.charAt(length - 1) != Constants.CODE_SPACE) return false;
+ // We know there is a space in pos -1, and we have at least two chars. If we have only two
+ // chars, isSurrogatePairs can't return true as charAt(1) is a space, so this is fine.
final int firstCodePoint =
- Character.isSurrogatePair(lastThree.charAt(0), lastThree.charAt(1)) ?
- Character.codePointAt(lastThree, 0) : lastThree.charAt(length - 3);
+ Character.isSurrogatePair(lastTwo.charAt(0), lastTwo.charAt(1)) ?
+ Character.codePointAt(lastTwo, length - 3) : lastTwo.charAt(length - 2);
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
cancelDoubleSpacePeriodCountdown();
- mConnection.deleteSurroundingText(2, 0);
+ mConnection.deleteSurroundingText(1, 0);
final String textToInsert = inputTransaction.mSettingsValues.mSpacingAndPunctuations
.mSentenceSeparatorAndSpace;
mConnection.commitText(textToInsert, 1);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ inputTransaction.setRequiresUpdateSuggestions();
return true;
}
return false;
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index 31cb59756..cd78e2235 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -70,8 +70,8 @@ public final class WordProperty implements Comparable<WordProperty> {
// Construct word property using information from native code.
// This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
public WordProperty(final int[] codePoints, final boolean isNotAWord,
- final boolean isBlacklisted, final boolean hasBigram,
- final boolean hasShortcuts, final int[] probabilityInfo,
+ final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts,
+ final boolean isBeginningOfSentence, final int[] probabilityInfo,
final ArrayList<int[]> bigramTargets, final ArrayList<int[]> bigramProbabilityInfo,
final ArrayList<int[]> shortcutTargets,
final ArrayList<Integer> shortcutProbabilities) {
@@ -79,7 +79,7 @@ public final class WordProperty implements Comparable<WordProperty> {
mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
mShortcutTargets = new ArrayList<>();
mBigrams = new ArrayList<>();
- mIsBeginningOfSentence = false;
+ mIsBeginningOfSentence = isBeginningOfSentence;
mIsNotAWord = isNotAWord;
mIsBlacklistEntry = isBlacklisted;
mHasShortcuts = hasShortcuts;
diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
index a96018fe9..ac55b9333 100644
--- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
@@ -43,11 +43,6 @@ public class ContextualDictionary extends ExpandableBinaryDictionary {
}
@Override
- protected boolean enableBeginningOfSentencePrediction() {
- return true;
- }
-
- @Override
public boolean isValidWord(final String word) {
// Strings out of this dictionary should not be considered existing words.
return false;
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index aede003d4..a98b0f156 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -75,7 +75,13 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
return;
}
if (null != prevWord) {
- userHistoryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp);
+ if (prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence) {
+ // Beginning-of-Sentence n-gram entry is treated as a n-gram entry of invalid word.
+ userHistoryDictionary.addNgramEntry(prevWordsInfo, word,
+ FREQUENCY_FOR_WORDS_NOT_IN_DICTS, timestamp);
+ } else {
+ userHistoryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp);
+ }
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index 9d824121c..689f878be 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -126,9 +126,17 @@ public final class SettingsFragment extends InputMethodSettingsFragment
final PreferenceScreen inputScreen =
(PreferenceScreen) findPreference(Settings.SCREEN_INPUT);
+ final PreferenceScreen multiLingualScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL);
+ final PreferenceScreen gestureScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_GESTURE);
+ final PreferenceScreen correctionScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_CORRECTION);
final PreferenceScreen advancedScreen =
(PreferenceScreen) findPreference(Settings.SCREEN_ADVANCED);
- final Preference debugScreen = findPreference(Settings.SCREEN_DEBUG);
+ final PreferenceScreen debugScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_DEBUG);
+
if (Settings.isInternal(prefs)) {
final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
debugSettingsIntent.setClassName(
@@ -149,8 +157,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment
removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen);
}
if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
- final PreferenceScreen multiLingualScreen =
- (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL);
removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, multiLingualScreen);
removePreference(
Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, multiLingualScreen);
@@ -185,8 +191,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment
removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedScreen);
}
- final PreferenceScreen correctionScreen =
- (PreferenceScreen) findPreference(Settings.SCREEN_CORRECTION);
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
final Intent intent = dictionaryLink.getIntent();
@@ -221,7 +225,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
}
if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
- removePreference(Settings.SCREEN_GESTURE, getPreferenceScreen());
+ getPreferenceScreen().removePreference(gestureScreen);
}
AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this);
@@ -462,13 +466,14 @@ public final class SettingsFragment extends InputMethodSettingsFragment
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
- if (!FeedbackUtils.isFeedbackFormSupported()) {
- return;
+ if (FeedbackUtils.isFeedbackFormSupported()) {
+ menu.add(NO_MENU_GROUP, MENU_FEEDBACK /* itemId */, MENU_FEEDBACK /* order */,
+ R.string.send_feedback);
+ }
+ final int aboutResId = FeedbackUtils.getAboutKeyboardTitleResId();
+ if (aboutResId != 0) {
+ menu.add(NO_MENU_GROUP, MENU_ABOUT /* itemId */, MENU_ABOUT /* order */, aboutResId);
}
- menu.add(NO_MENU_GROUP, MENU_FEEDBACK /* itemId */, MENU_FEEDBACK /* order */,
- R.string.send_feedback);
- menu.add(NO_MENU_GROUP, MENU_ABOUT /* itemId */, MENU_ABOUT /* order */,
- FeedbackUtils.getAboutKeyboardTitleResId());
}
@Override
@@ -479,8 +484,11 @@ public final class SettingsFragment extends InputMethodSettingsFragment
return true;
}
if (itemId == MENU_ABOUT) {
- startActivity(FeedbackUtils.getAboutKeyboardIntent(getActivity()));
- return true;
+ final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(getActivity());
+ if (aboutIntent != null) {
+ startActivity(aboutIntent);
+ return true;
+ }
}
return super.onOptionsItemSelected(item);
}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 46f5cdee0..ad5aad747 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -49,6 +49,7 @@ import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.PunctuationSuggestions;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -250,8 +251,8 @@ final class SuggestionStripLayoutHelper {
final int positionInStrip =
getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords);
// Use identity for strings, not #equals : it's the typed word if it's the same object
- final boolean isTypedWord =
- suggestedWords.getWord(indexInSuggestedWords) == suggestedWords.mTypedWord;
+ final boolean isTypedWord = suggestedWords.getInfo(indexInSuggestedWords).isKindOf(
+ SuggestedWordInfo.KIND_TYPED);
final int color;
if (positionInStrip == mCenterPositionInStrip && suggestedWords.mWillAutoCorrect) {
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index c66007537..34f59e8bc 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -31,6 +31,7 @@ public class CombinedFormatUtils {
public static final String HISTORICAL_INFO_TAG = "historicalInfo";
public static final String HISTORICAL_INFO_SEPARATOR = ":";
public static final String WORD_TAG = "word";
+ public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence";
public static final String NOT_A_WORD_TAG = "not_a_word";
public static final String BLACKLISTED_TAG = "blacklisted";
@@ -56,6 +57,9 @@ public class CombinedFormatUtils {
builder.append(" " + WORD_TAG + "=" + wordProperty.mWord);
builder.append(",");
builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo));
+ if (wordProperty.mIsBeginningOfSentence) {
+ builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+ }
if (wordProperty.mIsNotAWord) {
builder.append("," + NOT_A_WORD_TAG + "=true");
}
diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
index 0b362c48a..5c109a68c 100644
--- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
+++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
@@ -17,7 +17,9 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.define.ProductionFlag;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Locale;
@@ -29,6 +31,7 @@ import java.util.TreeSet;
*/
public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
public final Locale mLocale;
+ public final ArrayList<SuggestedWordInfo> mRawSuggestions;
private final int mCapacity;
public SuggestionResults(final Locale locale, final int capacity) {
@@ -40,6 +43,11 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
super(comparator);
mLocale = locale;
mCapacity = capacity;
+ if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
+ mRawSuggestions = new ArrayList<>();
+ } else {
+ mRawSuggestions = null;
+ }
}
@Override