diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
8 files changed, 119 insertions, 103 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index b333e4873..79441c557 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -75,7 +75,8 @@ class BinaryDictionaryGetter { // This assumes '%' is fully available as a non-separator, normal // character in a file name. This is probably true for all file systems. final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < name.length(); ++i) { + final int nameLength = name.length(); + for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) { final int codePoint = name.codePointAt(i); if (isFileNameCharacter(codePoint)) { sb.appendCodePoint(codePoint); @@ -92,7 +93,8 @@ class BinaryDictionaryGetter { */ private static String getWordListIdFromFileName(final String fname) { final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < fname.length(); ++i) { + final int fnameLength = fname.length(); + for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) { final int codePoint = fname.codePointAt(i); if ('%' != codePoint) { sb.appendCodePoint(codePoint); diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index f5cf953c4..3de5c1d48 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -28,7 +28,6 @@ import com.android.inputmethod.compat.InputTypeCompatUtils; public class InputAttributes { private final String TAG = InputAttributes.class.getSimpleName(); - final public boolean mInsertSpaceOnPickSuggestionManually; final public boolean mInputTypeNoAutoCorrect; final public boolean mIsSettingsSuggestionStripOn; final public boolean mApplicationSpecifiedCompletionOn; @@ -52,7 +51,6 @@ public class InputAttributes { + " imeOptions=0x%08x", inputType, editorInfo.imeOptions)); } - mInsertSpaceOnPickSuggestionManually = false; mIsSettingsSuggestionStripOn = false; mInputTypeNoAutoCorrect = false; mApplicationSpecifiedCompletionOn = false; @@ -80,15 +78,6 @@ public class InputAttributes { mIsSettingsSuggestionStripOn = true; } - if (InputTypeCompatUtils.isEmailVariation(variation) - || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { - // The point in turning this off is that we don't want to insert a space after - // a name when filling a form: we can't delete trailing spaces when changing fields - mInsertSpaceOnPickSuggestionManually = false; - } else { - mInsertSpaceOnPickSuggestionManually = true; - } - // If it's a browser edit field and auto correct is not ON explicitly, then // disable auto correction, but keep suggestions on. // If NO_SUGGESTIONS is set, don't do prediction. @@ -109,8 +98,7 @@ public class InputAttributes { // Pretty print @Override public String toString() { - return "\n mInsertSpaceOnPickSuggestionManually = " + mInsertSpaceOnPickSuggestionManually - + "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect + return "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect + "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn + "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn; } diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java index 0c8c88f50..f34cb5ff9 100644 --- a/java/src/com/android/inputmethod/latin/LastComposedWord.java +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -51,6 +51,8 @@ public class LastComposedWord { public static final LastComposedWord NOT_A_COMPOSED_WORD = new LastComposedWord(null, null, null, "", ""); + // Warning: this is using the passed objects as is and fully expects them to be + // immutable. Do not fiddle with their contents after you passed them to this constructor. public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates, final int[] yCoordinates, final String typedWord, final String autoCorrection) { mCodes = codes; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1bc55a583..e4339318b 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -160,18 +160,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar SUGGESTION_VISIBILILTY_HIDE_VALUE }; - // Magic space: a space that should disappear on space/apostrophe insertion, move after the - // punctuation on punctuation insertion, and become a real space on alpha char insertion. - // Weak space: a space that should be swapped only by suggestion strip punctuation. + private static final int SPACE_STATE_NONE = 0; // Double space: the state where the user pressed space twice quickly, which LatinIME // resolved as period-space. Undoing this converts the period to a space. + private static final int SPACE_STATE_DOUBLE = 1; // Swap punctuation: the state where a (weak or magic) space and a punctuation from the // suggestion strip have just been swapped. Undoing this swaps them back. - private static final int SPACE_STATE_NONE = 0; - private static final int SPACE_STATE_DOUBLE = 1; private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; - private static final int SPACE_STATE_MAGIC = 3; - private static final int SPACE_STATE_WEAK = 4; + // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak + // spaces happen when the user presses space, accepting the current suggestion (whether + // it's an auto-correction or not). + private static final int SPACE_STATE_WEAK = 3; + // Phantom space: a not-yet-inserted space that should get inserted on the next input, + // character provided it's not a separator. If it's a separator, the phantom space is dropped. + // Phantom spaces happen when a user chooses a word from the suggestion strip. + private static final int SPACE_STATE_PHANTOM = 4; // Current space state of the input method. This can be any of the above constants. private int mSpaceState; @@ -1162,18 +1165,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return false; } - // "ic" must not be null - private static void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) { - // When the text's first character is '.', remove the previous period - // if there is one. - final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); - if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == Keyboard.CODE_PERIOD - && text.charAt(0) == Keyboard.CODE_PERIOD) { - ic.deleteSurroundingText(1, 0); - } - } - // "ic" may be null private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { if (ic == null) return; @@ -1234,26 +1225,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } private void insertPunctuationFromSuggestionStrip(final InputConnection ic, final int code) { - final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : null; - final int toLeft = TextUtils.isEmpty(beforeText) ? 0 : beforeText.charAt(0); - final boolean shouldRegisterSwapPunctuation; - // If we have a space left of the cursor and it's a weak or a magic space, then we should - // swap it, and override the space state with SPACESTATE_SWAP_PUNCTUATION. - // To swap it, we fool handleSeparator to think the previous space state was a - // magic space. - if (Keyboard.CODE_SPACE == toLeft && mSpaceState == SPACE_STATE_WEAK - && mSettingsValues.isMagicSpaceSwapper(code)) { - mSpaceState = SPACE_STATE_MAGIC; - shouldRegisterSwapPunctuation = true; - } else { - shouldRegisterSwapPunctuation = false; - } onCodeInput(code, new int[] { code }, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE); - if (shouldRegisterSwapPunctuation) { - mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; - } + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); } // Implementation of {@link KeyboardActionListener}. @@ -1331,7 +1305,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (ic == null) return; ic.beginBatchEdit(); commitTyped(ic); - maybeRemovePreviousPeriod(ic, text); + text = specificTldProcessingOnTextInput(ic, text); + if (SPACE_STATE_PHANTOM == mSpaceState) { + sendKeyChar((char)Keyboard.CODE_SPACE); + } ic.commitText(text, 1); ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); @@ -1341,6 +1318,24 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar resetComposingState(true /* alsoResetLastComposedWord */); } + // ic may not be null + private CharSequence specificTldProcessingOnTextInput(final InputConnection ic, + final CharSequence text) { + if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD + || !Character.isLetter(text.charAt(1))) { + // Not a tld: do nothing. + return text; + } + final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); + if (lastOne != null && lastOne.length() == 1 + && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { + mSpaceState = SPACE_STATE_NONE; + return text.subSequence(1, text.length()); + } else { + return text; + } + } + @Override public void onCancelInput() { // User released a finger outside any key @@ -1492,13 +1487,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // "ic" may be null without this crashing, but the behavior will be really strange private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes, final int x, final int y, final int spaceState, final InputConnection ic) { - if (SPACE_STATE_MAGIC == spaceState - && mSettingsValues.isMagicSpaceStripper(primaryCode)) { - if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic); - } - boolean isComposingWord = mWordComposer.isComposingWord(); int code = primaryCode; + + if (SPACE_STATE_PHANTOM == spaceState && + !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) { + if (isComposingWord) { + // Sanity check + throw new RuntimeException("Should not be composing here"); + } + sendKeyChar((char)Keyboard.CODE_SPACE); + } + if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code)) && isSuggestionsRequested() && !isCursorTouchingWord()) { if (!isComposingWord) { @@ -1530,10 +1530,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { sendKeyChar((char)code); } - if (SPACE_STATE_MAGIC == spaceState - && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { - if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic); - } if (mSettingsValues.isWordSeparator(code)) { Utils.Stats.onSeparator((char)code, x, y); @@ -1575,24 +1571,28 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } - final boolean swapMagicSpace; - if (Keyboard.CODE_ENTER == primaryCode && (SPACE_STATE_MAGIC == spaceState - || SPACE_STATE_SWAP_PUNCTUATION == spaceState)) { + final boolean swapWeakSpace; + if (Keyboard.CODE_ENTER == primaryCode && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { removeTrailingSpaceWhileInBatchEdit(ic); - swapMagicSpace = false; - } else if (SPACE_STATE_MAGIC == spaceState) { + swapWeakSpace = false; + } else if ((SPACE_STATE_WEAK == spaceState || SPACE_STATE_SWAP_PUNCTUATION == spaceState) + && KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x) { if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { - swapMagicSpace = true; + swapWeakSpace = true; } else { - swapMagicSpace = false; + swapWeakSpace = false; if (mSettingsValues.isMagicSpaceStripper(primaryCode)) { removeTrailingSpaceWhileInBatchEdit(ic); } } } else { - swapMagicSpace = false; + swapWeakSpace = false; } + // TODO: rethink interactions of sendKeyChar, commitText("\n") and actions. sendKeyChar + // with a CODE_ENTER parameter will have the default InputMethodService implementation + // possibly redirect on the keyboard action. That may be the right thing to do, but + // on Shift+Enter, it's generally not, so we may want to do the redirection right here. sendKeyChar((char)primaryCode); if (Keyboard.CODE_SPACE == primaryCode) { @@ -1610,9 +1610,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.postUpdateBigramPredictions(); } } else { - if (swapMagicSpace) { + if (swapWeakSpace) { swapSwapperAndSpaceWhileInBatchEdit(ic); - mSpaceState = SPACE_STATE_MAGIC; + mSpaceState = SPACE_STATE_WEAK; + } else if (SPACE_STATE_PHANTOM == spaceState) { + // If we are in phantom space state, and the user presses a separator, we want to + // stay in phantom space state so that the next keypress has a chance to add the + // space. For example, if I type "Good dat", pick "day" from the suggestion strip + // then insert a comma and go on to typing the next word, I want the space to be + // inserted automatically before the next word, the same way it is when I don't + // input the comma. + mSpaceState = SPACE_STATE_PHANTOM; } // Set punctuation right away. onUpdateSelection will fire but tests whether it is @@ -1921,10 +1929,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { addToOnlyBigramDictionary(suggestion, 1); } - // Follow it with a space - if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) { - sendMagicSpace(); - } + mSpaceState = SPACE_STATE_PHANTOM; + // TODO: is this necessary? + mKeyboardSwitcher.updateShiftState(); // We should show the "Touch again to save" hint if the user pressed the first entry // AND either: @@ -2194,9 +2201,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // new composing text. final int restartLength = mWordComposer.size(); if (DEBUG) { - final String wordBeforeCursor = - ic.getTextBeforeCursor(restartLength + 1, 0).subSequence(0, restartLength) - .toString(); + final String wordBeforeCursor = ic.getTextBeforeCursor(restartLength, 0).toString(); if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) { throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord " + "check failed: we thought we were reverting \"" @@ -2205,8 +2210,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar + wordBeforeCursor + "\""); } } - // Warning: this +1 takes into account the extra space added by the manual pick process. - ic.deleteSurroundingText(restartLength + 1, 0); + ic.deleteSurroundingText(restartLength, 0); ic.setComposingText(mWordComposer.getTypedWord(), 1); mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); @@ -2259,12 +2263,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return mSettingsValues.isWordSeparator(code); } - private void sendMagicSpace() { - sendKeyChar((char)Keyboard.CODE_SPACE); - mSpaceState = SPACE_STATE_MAGIC; - mKeyboardSwitcher.updateShiftState(); - } - public boolean preferCapitalization() { return mWordComposer.isFirstCharCapitalized(); } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 8e2f605c4..589cb6f86 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -93,7 +93,8 @@ public class SettingsValues { mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols); mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols); if (LatinImeLogger.sDBG) { - for (int i = 0; i < mMagicSpaceStrippers.length(); ++i) { + final int length = mMagicSpaceStrippers.length(); + for (int i = 0; i < length; i = mMagicSpaceStrippers.offsetByCodePoints(i, 1)) { if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) { throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i) + " is both a magic space swapper and stripper."); @@ -234,10 +235,12 @@ public class SettingsValues { } public boolean isMagicSpaceStripper(int code) { + // TODO: this does not work if the code does not fit in a char return mMagicSpaceStrippers.contains(String.valueOf((char)code)); } public boolean isMagicSpaceSwapper(int code) { + // TODO: this does not work if the code does not fit in a char return mMagicSpaceSwappers.contains(String.valueOf((char)code)); } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index bd244b913..f418968b5 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -212,6 +212,7 @@ public class WordComposer { final int lastPos = size - 1; char lastChar = mTypedWord.charAt(lastPos); mCodes.remove(lastPos); + // TODO: This crashes and catches fire if the code point doesn't fit a char mTypedWord.deleteCharAt(lastPos); if (Character.isUpperCase(lastChar)) mCapsCount--; } @@ -221,7 +222,9 @@ public class WordComposer { if (mTrailingSingleQuotesCount > 0) { --mTrailingSingleQuotesCount; } else { - for (int i = mTypedWord.length() - 1; i >= 0; --i) { + int i = mTypedWord.length(); + while (i > 0) { + i = mTypedWord.offsetByCodePoints(i, -1); if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; ++mTrailingSingleQuotesCount; } @@ -307,13 +310,18 @@ public class WordComposer { // LastComposedWord#didAutoCorrectToAnotherWord with #equals(). It would be marginally // cleaner to do it here, but it would be slower (since we would #equals() for each commit, // instead of only on cancel), and ultimately we want to figure it out even earlier anyway. - final LastComposedWord lastComposedWord = new LastComposedWord(mCodes, - mXCoordinates, mYCoordinates, mTypedWord.toString(), + final ArrayList<int[]> codes = mCodes; + final int[] xCoordinates = mXCoordinates; + final int[] yCoordinates = mYCoordinates; + mCodes = new ArrayList<int[]>(N); + mXCoordinates = new int[N]; + mYCoordinates = new int[N]; + final LastComposedWord lastComposedWord = new LastComposedWord(codes, + xCoordinates, yCoordinates, mTypedWord.toString(), null == mAutoCorrection ? null : mAutoCorrection.toString()); if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD) { lastComposedWord.deactivate(); } - mCodes.clear(); mTypedWord.setLength(0); mAutoCorrection = null; return lastComposedWord; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 88ac043ed..8ac82ee5b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -431,9 +431,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService // If the first char is not uppercase, then the word is either all lower case, // and in either case we return CAPITALIZE_NONE. if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE; - final int len = text.codePointCount(0, text.length()); + final int len = text.length(); int capsCount = 1; - for (int i = 1; i < len; ++i) { + for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) { if (1 != capsCount && i != capsCount) break; if (Character.isUpperCase(text.codePointAt(i))) ++capsCount; } @@ -522,13 +522,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService // Filter contents final int length = text.length(); int letterCount = 0; - for (int i = 0; i < length; ++i) { + for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { final int codePoint = text.codePointAt(i); // Any word containing a '@' is probably an e-mail address // Any word containing a '/' is probably either an ad-hoc combination of two // words or a URI - in either case we don't want to spell check that - if ('@' == codePoint - || '/' == codePoint) return true; + if ('@' == codePoint || '/' == codePoint) return true; if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount; } // Guestimate heuristic: perform spell checking if at least 3/4 of the characters @@ -570,7 +569,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService suggestionsLimit); final WordComposer composer = new WordComposer(); final int length = text.length(); - for (int i = 0; i < length; ++i) { + for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { final int character = text.codePointAt(i); final int proximityIndex = SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript); diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index f42b8e681..4ef5bd386 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -25,6 +25,7 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; @@ -199,6 +200,21 @@ public class MoreSuggestions extends Keyboard { return info; } + private static class Divider extends Key.Spacer { + private final Drawable mIcon; + + public Divider(Keyboard.Params params, Drawable icon, int x, int y, int width, + int height) { + super(params, x, y, width, height); + mIcon = icon; + } + + @Override + public Drawable getIcon(KeyboardIconsSet iconSet) { + return mIcon; + } + } + @Override public MoreSuggestions build() { final MoreSuggestionsParam params = mParams; @@ -210,16 +226,16 @@ public class MoreSuggestions extends Keyboard { final String info = getDebugInfo(mSuggestions, pos); final int index = pos + SUGGESTION_CODE_BASE; final Key key = new Key( - params, word, info, null, index, null, x, y, width, - params.mDefaultRowHeight); + params, word, info, KeyboardIconsSet.ICON_UNDEFINED, index, null, x, y, + width, params.mDefaultRowHeight); params.markAsEdgeKey(key, pos); params.onAddKey(key); final int columnNumber = params.getColumnNumber(pos); final int numColumnInRow = params.getNumColumnInRow(pos); if (columnNumber < numColumnInRow - 1) { - final Key.Spacer spacer = new Key.Spacer(params, params.mDivider, x + width, y, + final Divider divider = new Divider(params, params.mDivider, x + width, y, params.mDividerWidth, params.mDefaultRowHeight); - params.onAddKey(spacer); + params.onAddKey(divider); } } return new MoreSuggestions(params); |