[IL6] Move handleSeparator to InputLogic

Also move swapSwapperAndSpace, maybeDoubleSpacePeriod,
maybeStripSpace, promotePhantomSpace and canBeFollowedByDoubleSpacePeriod

Bug: 8636060
Change-Id: I864053d21c4b3d51ee7a3cd79053ca602337f6f8
This commit is contained in:
Jean Chalard 2013-12-19 17:14:11 +09:00
parent c8dfaab783
commit 40b42b7d84
2 changed files with 219 additions and 201 deletions

View file

@ -1306,71 +1306,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return WordComposer.CAPS_MODE_OFF; return WordComposer.CAPS_MODE_OFF;
} }
private void swapSwapperAndSpace() {
final CharSequence lastTwo = mInputLogic.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) {
mInputLogic.mConnection.deleteSurroundingText(2, 0);
final String text = lastTwo.charAt(1) + " ";
mInputLogic.mConnection.commitText(text, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_swapSwapperAndSpace(lastTwo, text);
}
mKeyboardSwitcher.updateShiftState();
}
}
private boolean maybeDoubleSpacePeriod() {
final SettingsValues currentSettingsValues = mSettings.getCurrent();
if (!currentSettingsValues.mUseDoubleSpacePeriod) return false;
if (!mHandler.isAcceptingDoubleSpacePeriod()) 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 = mInputLogic.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.
final int firstCodePoint =
Character.isSurrogatePair(lastThree.charAt(0), lastThree.charAt(1)) ?
Character.codePointAt(lastThree, 0) : lastThree.charAt(length - 3);
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
mHandler.cancelDoubleSpacePeriodTimer();
mInputLogic.mConnection.deleteSurroundingText(2, 0);
final String textToInsert = new String(
new int[] { currentSettingsValues.mSentenceSeparator, Constants.CODE_SPACE },
0, 2);
mInputLogic.mConnection.commitText(textToInsert, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert,
false /* isBatchMode */);
}
mInputLogic.mWordComposer.discardPreviousWordForSuggestion();
mKeyboardSwitcher.updateShiftState();
return true;
}
return false;
}
private static boolean canBeFollowedByDoubleSpacePeriod(final int codePoint) {
// TODO: Check again whether there really ain't a better way to check this.
// TODO: This should probably be language-dependant...
return Character.isLetterOrDigit(codePoint)
|| codePoint == Constants.CODE_SINGLE_QUOTE
|| codePoint == Constants.CODE_DOUBLE_QUOTE
|| codePoint == Constants.CODE_CLOSING_PARENTHESIS
|| codePoint == Constants.CODE_CLOSING_SQUARE_BRACKET
|| codePoint == Constants.CODE_CLOSING_CURLY_BRACKET
|| codePoint == Constants.CODE_CLOSING_ANGLE_BRACKET
|| codePoint == Constants.CODE_PLUS
|| codePoint == Constants.CODE_PERCENT
|| Character.getType(codePoint) == Character.OTHER_SYMBOL;
}
// Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
// pressed. // pressed.
@Override @Override
@ -1430,6 +1365,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
// Called from PointerTracker through the KeyboardActionListener interface // Called from PointerTracker through the KeyboardActionListener interface
// TODO[IL]: Move this to InputLogic
@Override @Override
public void onTextInput(final String rawText) { public void onTextInput(final String rawText) {
mInputLogic.mConnection.beginBatchEdit(); mInputLogic.mConnection.beginBatchEdit();
@ -1446,7 +1382,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
final String text = specificTldProcessingOnTextInput(rawText); final String text = specificTldProcessingOnTextInput(rawText);
if (SpaceState.PHANTOM == mInputLogic.mSpaceState) { if (SpaceState.PHANTOM == mInputLogic.mSpaceState) {
promotePhantomSpace(); mInputLogic.promotePhantomSpace(mSettings.getCurrent());
} }
mInputLogic.mConnection.commitText(text, 1); mInputLogic.mConnection.commitText(text, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@ -1684,7 +1620,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (candidate.mSourceDict.shouldAutoCommit(candidate)) { if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
final String[] commitParts = candidate.mWord.split(" ", 2); final String[] commitParts = candidate.mWord.split(" ", 2);
batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord); batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
promotePhantomSpace(); mInputLogic.promotePhantomSpace(mSettings.getCurrent());
mInputLogic.mConnection.commitText(commitParts[0], 0); mInputLogic.mConnection.commitText(commitParts[0], 0);
mInputLogic.mSpaceState = SpaceState.PHANTOM; mInputLogic.mSpaceState = SpaceState.PHANTOM;
mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
@ -1706,7 +1642,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
mInputLogic.mConnection.beginBatchEdit(); mInputLogic.mConnection.beginBatchEdit();
if (SpaceState.PHANTOM == mInputLogic.mSpaceState) { if (SpaceState.PHANTOM == mInputLogic.mSpaceState) {
promotePhantomSpace(); mInputLogic.promotePhantomSpace(mSettings.getCurrent());
} }
if (mSettings.getCurrent().mPhraseGestureEnabled) { if (mSettings.getCurrent().mPhraseGestureEnabled) {
// Find the last space // Find the last space
@ -1775,25 +1711,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputUpdater.onCancelBatchInput(); mInputUpdater.onCancelBatchInput();
} }
/*
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
*/
private boolean maybeStripSpace(final int code, final int spaceState,
final boolean isFromSuggestionStrip) {
if (Constants.CODE_ENTER == code && SpaceState.SWAP_PUNCTUATION == spaceState) {
mInputLogic.mConnection.removeTrailingSpace();
return false;
}
if ((SpaceState.WEAK == spaceState || SpaceState.SWAP_PUNCTUATION == spaceState)
&& isFromSuggestionStrip) {
final SettingsValues currentSettings = mSettings.getCurrent();
if (currentSettings.isUsuallyPrecededBySpace(code)) return false;
if (currentSettings.isUsuallyFollowedBySpace(code)) return true;
mInputLogic.mConnection.removeTrailingSpace();
}
return false;
}
// TODO[IL]: Move to InputLogic and make private again. // TODO[IL]: Move to InputLogic and make private again.
public void handleCharacter(final int primaryCode, final int x, final int y, public void handleCharacter(final int primaryCode, final int x, final int y,
final int spaceState) { final int spaceState) {
@ -1810,7 +1727,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Sanity check // Sanity check
throw new RuntimeException("Should not be composing here"); throw new RuntimeException("Should not be composing here");
} }
promotePhantomSpace(); mInputLogic.promotePhantomSpace(currentSettings);
} }
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
@ -1864,13 +1781,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.mConnection.setComposingText(mInputLogic.getTextWithUnderline( mInputLogic.mConnection.setComposingText(mInputLogic.getTextWithUnderline(
mInputLogic.mWordComposer.getTypedWord()), 1); mInputLogic.mWordComposer.getTypedWord()), 1);
} else { } else {
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState, final boolean swapWeakSpace = mInputLogic.maybeStripSpace(currentSettings,
Constants.SUGGESTION_STRIP_COORDINATE == x); primaryCode, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x);
mInputLogic.sendKeyCodePoint(primaryCode); mInputLogic.sendKeyCodePoint(primaryCode);
if (swapWeakSpace) { if (swapWeakSpace) {
swapSwapperAndSpace(); mInputLogic.swapSwapperAndSpace(mKeyboardSwitcher);
mInputLogic.mSpaceState = SpaceState.WEAK; mInputLogic.mSpaceState = SpaceState.WEAK;
} }
// In case the "add to dictionary" hint was still displayed. // In case the "add to dictionary" hint was still displayed.
@ -1929,92 +1846,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
} }
// Returns true if we do an autocorrection, false otherwise. // TODO[IL]: Rename this to avoid using handle*
// TODO[IL]: Move to InputLogic and make private again
public boolean handleSeparator(final int primaryCode, final int x, final int y,
final int spaceState) {
boolean didAutoCorrect = false;
final SettingsValues currentSettings = mSettings.getCurrent();
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == primaryCode
&& !currentSettings.mCurrentLanguageHasSpaces
&& mInputLogic.mWordComposer.isComposingWord();
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the separator at the current cursor position.
mInputLogic.resetEntireInputState(currentSettings, mInputLogic.mLastSelectionStart,
mInputLogic.mLastSelectionEnd);
}
// isComposingWord() may have changed since we stored wasComposing
if (mInputLogic.mWordComposer.isComposingWord()) {
if (currentSettings.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(primaryCode);
commitCurrentAutoCorrection(separator);
didAutoCorrect = true;
} else {
mInputLogic.commitTyped(StringUtils.newSingleCodePointString(primaryCode));
}
}
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
Constants.SUGGESTION_STRIP_COORDINATE == x);
if (SpaceState.PHANTOM == spaceState &&
currentSettings.isUsuallyPrecededBySpace(primaryCode)) {
promotePhantomSpace();
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleSeparator(primaryCode,
mInputLogic.mWordComposer.isComposingWord());
}
if (!shouldAvoidSendingCode) {
mInputLogic.sendKeyCodePoint(primaryCode);
}
if (Constants.CODE_SPACE == primaryCode) {
if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
if (maybeDoubleSpacePeriod()) {
mInputLogic.mSpaceState = SpaceState.DOUBLE;
} else if (!isShowingPunctuationList()) {
mInputLogic.mSpaceState = SpaceState.WEAK;
}
}
mHandler.startDoubleSpacePeriodTimer();
mHandler.postUpdateSuggestionStrip();
} else {
if (swapWeakSpace) {
swapSwapperAndSpace();
mInputLogic.mSpaceState = SpaceState.SWAP_PUNCTUATION;
} else if (SpaceState.PHANTOM == spaceState
&& currentSettings.isUsuallyFollowedBySpace(primaryCode)) {
// 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.
// The case is a little different if the separator is a space stripper. Such a
// separator does not normally need a space on the right (that's the difference
// between swappers and strippers), so we should not stay in phantom space state if
// the separator is a stripper. Hence the additional test above.
mInputLogic.mSpaceState = SpaceState.PHANTOM;
}
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
setPunctuationSuggestions();
}
if (currentSettings.mIsInternal) {
LatinImeLoggerUtils.onSeparator((char)primaryCode, x, y);
}
mKeyboardSwitcher.updateShiftState();
return didAutoCorrect;
}
private void handleClose() { private void handleClose() {
// TODO: Verify that words are logged properly when IME is closed. // TODO: Verify that words are logged properly when IME is closed.
mInputLogic.commitTyped(LastComposedWord.NOT_A_SEPARATOR); mInputLogic.commitTyped(LastComposedWord.NOT_A_SEPARATOR);
@ -2025,10 +1857,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
} }
// TODO: make this private // TODO[IL]: Move this to InputLogic and make it private
// Outside LatinIME, only used by the test suite. // Outside LatinIME, only used by the test suite.
@UsedForTesting @UsedForTesting
boolean isShowingPunctuationList() { public boolean isShowingPunctuationList() {
if (mInputLogic.mSuggestedWords == null) return false; if (mInputLogic.mSuggestedWords == null) return false;
return mSettings.getCurrent().mSuggestPuncList == mInputLogic.mSuggestedWords; return mSettings.getCurrent().mSuggestPuncList == mInputLogic.mSuggestedWords;
} }
@ -2261,7 +2093,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD)); suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD));
} }
private void commitCurrentAutoCorrection(final String separator) { // TODO[IL]: Move this to InputLogic and make private again
public void commitCurrentAutoCorrection(final String separator) {
// Complete any pending suggestions query first // Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) { if (mHandler.hasPendingUpdateSuggestions()) {
updateSuggestionStrip(); updateSuggestionStrip();
@ -2331,7 +2164,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int firstChar = Character.codePointAt(suggestion, 0); final int firstChar = Character.codePointAt(suggestion, 0);
if (!currentSettings.isWordSeparator(firstChar) if (!currentSettings.isWordSeparator(firstChar)
|| currentSettings.isUsuallyPrecededBySpace(firstChar)) { || currentSettings.isUsuallyPrecededBySpace(firstChar)) {
promotePhantomSpace(); mInputLogic.promotePhantomSpace(currentSettings);
} }
} }
@ -2425,7 +2258,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
} }
private void setPunctuationSuggestions() { // TODO[IL]: Define a clean interface for this
public void setPunctuationSuggestions() {
final SettingsValues currentSettings = mSettings.getCurrent(); final SettingsValues currentSettings = mSettings.getCurrent();
if (currentSettings.mBigramPredictionEnabled) { if (currentSettings.mBigramPredictionEnabled) {
clearSuggestionStrip(); clearSuggestionStrip();
@ -2700,19 +2534,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestionStrip(); mHandler.postUpdateSuggestionStrip();
} }
// This essentially inserts a space, and that's it.
public void promotePhantomSpace() {
final SettingsValues currentSettings = mSettings.getCurrent();
if (currentSettings.shouldInsertSpacesAutomatically()
&& currentSettings.mCurrentLanguageHasSpaces
&& !mInputLogic.mConnection.textBeforeCursorLooksLikeURL()) {
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_promotePhantomSpace();
}
mInputLogic.sendKeyCodePoint(Constants.CODE_SPACE);
}
}
// TODO: Make this private // TODO: Make this private
// Outside LatinIME, only used by the {@link InputTestsBase} test suite. // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
@UsedForTesting @UsedForTesting

View file

@ -195,16 +195,16 @@ public final class InputLogic {
// No action label, and the action from imeOptions is NONE: this is a regular // No action label, and the action from imeOptions is NONE: this is a regular
// enter key that should input a carriage return. // enter key that should input a carriage return.
didAutoCorrect = handleNonSpecialCharacter(settingsValues, didAutoCorrect = handleNonSpecialCharacter(settingsValues,
Constants.CODE_ENTER, x, y, spaceState, keyboardSwitcher); Constants.CODE_ENTER, x, y, spaceState, keyboardSwitcher, handler);
} }
break; break;
case Constants.CODE_SHIFT_ENTER: case Constants.CODE_SHIFT_ENTER:
didAutoCorrect = handleNonSpecialCharacter(settingsValues, didAutoCorrect = handleNonSpecialCharacter(settingsValues,
Constants.CODE_ENTER, x, y, spaceState, keyboardSwitcher); Constants.CODE_ENTER, x, y, spaceState, keyboardSwitcher, handler);
break; break;
default: default:
didAutoCorrect = handleNonSpecialCharacter(settingsValues, didAutoCorrect = handleNonSpecialCharacter(settingsValues,
codePoint, x, y, spaceState, keyboardSwitcher); codePoint, x, y, spaceState, keyboardSwitcher, handler);
break; break;
} }
switcher.onCodeInput(codePoint); switcher.onCodeInput(codePoint);
@ -235,13 +235,14 @@ public final class InputLogic {
*/ */
private boolean handleNonSpecialCharacter(final SettingsValues settingsValues, private boolean handleNonSpecialCharacter(final SettingsValues settingsValues,
final int codePoint, final int x, final int y, final int spaceState, final int codePoint, final int x, final int y, final int spaceState,
// TODO: remove this argument. // TODO: remove these arguments
final KeyboardSwitcher keyboardSwitcher) { final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
mSpaceState = SpaceState.NONE; mSpaceState = SpaceState.NONE;
final boolean didAutoCorrect; final boolean didAutoCorrect;
if (settingsValues.isWordSeparator(codePoint) if (settingsValues.isWordSeparator(codePoint)
|| Character.getType(codePoint) == Character.OTHER_SYMBOL) { || Character.getType(codePoint) == Character.OTHER_SYMBOL) {
didAutoCorrect = mLatinIME.handleSeparator(codePoint, x, y, spaceState); didAutoCorrect = handleSeparator(settingsValues, codePoint, x, y, spaceState,
keyboardSwitcher, handler);
} else { } else {
didAutoCorrect = false; didAutoCorrect = false;
if (SpaceState.PHANTOM == spaceState) { if (SpaceState.PHANTOM == spaceState) {
@ -273,6 +274,98 @@ public final class InputLogic {
return didAutoCorrect; return didAutoCorrect;
} }
/**
* Handle input of a separator code point.
* @param settingsValues The current settings values.
* @param codePoint the code point associated with the key.
* @param x the x-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable.
* @param y the y-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable.
* @param spaceState the space state at start of the batch input.
* @return whether this caused an auto-correction to happen.
*/
private boolean handleSeparator(final SettingsValues settingsValues,
final int codePoint, final int x, final int y, final int spaceState,
// TODO: remove these arguments
final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
boolean didAutoCorrect = false;
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint
&& !settingsValues.mCurrentLanguageHasSpaces
&& mWordComposer.isComposingWord();
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the separator at the current cursor position.
resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
if (settingsValues.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
mLatinIME.commitCurrentAutoCorrection(separator);
didAutoCorrect = true;
} else {
commitTyped(StringUtils.newSingleCodePointString(codePoint));
}
}
final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState,
Constants.SUGGESTION_STRIP_COORDINATE == x);
if (SpaceState.PHANTOM == spaceState &&
settingsValues.isUsuallyPrecededBySpace(codePoint)) {
promotePhantomSpace(settingsValues);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord());
}
if (!shouldAvoidSendingCode) {
sendKeyCodePoint(codePoint);
}
if (Constants.CODE_SPACE == codePoint) {
if (settingsValues.isSuggestionsRequested(mLatinIME.mDisplayOrientation)) {
if (maybeDoubleSpacePeriod(settingsValues, keyboardSwitcher, handler)) {
mSpaceState = SpaceState.DOUBLE;
} else if (!mLatinIME.isShowingPunctuationList()) {
mSpaceState = SpaceState.WEAK;
}
}
handler.startDoubleSpacePeriodTimer();
handler.postUpdateSuggestionStrip();
} else {
if (swapWeakSpace) {
swapSwapperAndSpace(keyboardSwitcher);
mSpaceState = SpaceState.SWAP_PUNCTUATION;
} else if (SpaceState.PHANTOM == spaceState
&& settingsValues.isUsuallyFollowedBySpace(codePoint)) {
// 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.
// The case is a little different if the separator is a space stripper. Such a
// separator does not normally need a space on the right (that's the difference
// between swappers and strippers), so we should not stay in phantom space state if
// the separator is a stripper. Hence the additional test above.
mSpaceState = SpaceState.PHANTOM;
}
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
mLatinIME.setPunctuationSuggestions();
}
if (settingsValues.mIsInternal) {
LatinImeLoggerUtils.onSeparator((char)codePoint, x, y);
}
keyboardSwitcher.updateShiftState();
return didAutoCorrect;
}
/** /**
* Handle a press on the backspace key. * Handle a press on the backspace key.
* @param settingsValues The current settings values. * @param settingsValues The current settings values.
@ -429,6 +522,97 @@ public final class InputLogic {
mLatinIME.handleLanguageSwitchKey(); mLatinIME.handleLanguageSwitchKey();
} }
// TODO: Make this private
// TODO: Remove this argument
public void swapSwapperAndSpace(final KeyboardSwitcher keyboardSwitcher) {
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);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_swapSwapperAndSpace(lastTwo, text);
}
keyboardSwitcher.updateShiftState();
}
}
/*
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
* @param settingsValues The current settings values.
* @param codePoint The code point that is about to be inserted.
* @param spaceState The space state at start of this batch edit.
* @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip.
* @return whether we should swap the space instead of removing it.
*/
// TODO: Make this private
public boolean maybeStripSpace(final SettingsValues settingsValues,
final int code, final int spaceState, final boolean isFromSuggestionStrip) {
if (Constants.CODE_ENTER == code && SpaceState.SWAP_PUNCTUATION == spaceState) {
mConnection.removeTrailingSpace();
return false;
}
if ((SpaceState.WEAK == spaceState || SpaceState.SWAP_PUNCTUATION == spaceState)
&& isFromSuggestionStrip) {
if (settingsValues.isUsuallyPrecededBySpace(code)) return false;
if (settingsValues.isUsuallyFollowedBySpace(code)) return true;
mConnection.removeTrailingSpace();
}
return false;
}
private boolean maybeDoubleSpacePeriod(final SettingsValues settingsValues,
// TODO: remove these arguments
final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
if (!settingsValues.mUseDoubleSpacePeriod) return false;
if (!handler.isAcceptingDoubleSpacePeriod()) 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.
final int firstCodePoint =
Character.isSurrogatePair(lastThree.charAt(0), lastThree.charAt(1)) ?
Character.codePointAt(lastThree, 0) : lastThree.charAt(length - 3);
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
handler.cancelDoubleSpacePeriodTimer();
mConnection.deleteSurroundingText(2, 0);
final String textToInsert = new String(
new int[] { settingsValues.mSentenceSeparator, Constants.CODE_SPACE }, 0, 2);
mConnection.commitText(textToInsert, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert,
false /* isBatchMode */);
}
mWordComposer.discardPreviousWordForSuggestion();
keyboardSwitcher.updateShiftState();
return true;
}
return false;
}
private static boolean canBeFollowedByDoubleSpacePeriod(final int codePoint) {
// TODO: Check again whether there really ain't a better way to check this.
// TODO: This should probably be language-dependant...
return Character.isLetterOrDigit(codePoint)
|| codePoint == Constants.CODE_SINGLE_QUOTE
|| codePoint == Constants.CODE_DOUBLE_QUOTE
|| codePoint == Constants.CODE_CLOSING_PARENTHESIS
|| codePoint == Constants.CODE_CLOSING_SQUARE_BRACKET
|| codePoint == Constants.CODE_CLOSING_CURLY_BRACKET
|| codePoint == Constants.CODE_CLOSING_ANGLE_BRACKET
|| codePoint == Constants.CODE_PLUS
|| codePoint == Constants.CODE_PERCENT
|| Character.getType(codePoint) == Character.OTHER_SYMBOL;
}
/** /**
* Processes a recapitalize event. * Processes a recapitalize event.
*/ */
@ -522,6 +706,19 @@ public final class InputLogic {
} }
} }
// This essentially inserts a space, and that's it.
// TODO: Make this private.
public void promotePhantomSpace(final SettingsValues settingsValues) {
if (settingsValues.shouldInsertSpacesAutomatically()
&& settingsValues.mCurrentLanguageHasSpaces
&& !mConnection.textBeforeCursorLooksLikeURL()) {
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_promotePhantomSpace();
}
sendKeyCodePoint(Constants.CODE_SPACE);
}
}
// TODO: Make this private // TODO: Make this private
public void commitTyped(final String separatorString) { public void commitTyped(final String separatorString) {
if (!mWordComposer.isComposingWord()) return; if (!mWordComposer.isComposingWord()) return;