aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java49
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java33
-rw-r--r--java/src/com/android/inputmethod/latin/RecapitalizeStatus.java68
-rw-r--r--native/jni/src/binary_format.h12
-rw-r--r--native/jni/src/defines.h5
-rw-r--r--native/jni/src/suggest/core/policy/weighting.cpp30
-rw-r--r--native/jni/src/suggest/core/policy/weighting.h6
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.cpp2
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.h13
-rw-r--r--native/jni/src/suggest/core/suggest.cpp24
-rw-r--r--native/jni/src/suggest/core/suggest.h15
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp4
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.h8
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.h15
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java5
-rw-r--r--tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java42
17 files changed, 201 insertions, 136 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index d15f14f88..4e41b77ce 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -207,7 +207,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
* Update keyboard shift state triggered by connected EditText status change.
*/
public void updateShiftState() {
- mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
+ mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState(),
+ mLatinIME.getCurrentRecapitalizeState());
}
// TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout
@@ -276,7 +277,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void requestUpdatingShiftState() {
- mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
+ mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState(),
+ mLatinIME.getCurrentRecapitalizeState());
}
// Implements {@link KeyboardState.SwitchActions}.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 95d9ccb58..b1d499702 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -20,6 +20,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.RecapitalizeStatus;
/**
* Keyboard state machine.
@@ -29,7 +30,7 @@ import com.android.inputmethod.latin.Constants;
* The input events are {@link #onLoadKeyboard()}, {@link #onSaveKeyboardState()},
* {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
* {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
- * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
+ * {@link #onUpdateShiftState(int, int)}, {@link #onLongPressTimeout(int)}.
*
* The actions are {@link SwitchActions}'s methods.
*/
@@ -48,7 +49,7 @@ public final class KeyboardState {
public void setSymbolsShiftedKeyboard();
/**
- * Request to call back {@link KeyboardState#onUpdateShiftState(int)}.
+ * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}.
*/
public void requestUpdatingShiftState();
@@ -80,6 +81,7 @@ public final class KeyboardState {
private boolean mIsSymbolShifted;
private boolean mPrevMainKeyboardWasShiftLocked;
private boolean mPrevSymbolsKeyboardWasShifted;
+ private int mRecapitalizeMode;
// For handling long press.
private boolean mLongPressShiftLockFired;
@@ -110,6 +112,7 @@ public final class KeyboardState {
public KeyboardState(final SwitchActions switchActions) {
mSwitchActions = switchActions;
+ mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
}
public void onLoadKeyboard() {
@@ -283,6 +286,7 @@ public final class KeyboardState {
mSwitchActions.setAlphabetKeyboard();
mIsAlphabetMode = true;
mIsSymbolShifted = false;
+ mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
mSwitchState = SWITCH_STATE_ALPHA;
mSwitchActions.requestUpdatingShiftState();
}
@@ -386,11 +390,13 @@ public final class KeyboardState {
}
}
- public void onUpdateShiftState(final int autoCaps) {
+ public void onUpdateShiftState(final int autoCaps, final int recapitalizeMode) {
if (DEBUG_EVENT) {
- Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
+ Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + ", recapitalizeMode="
+ + recapitalizeMode + " " + this);
}
- updateAlphabetShiftState(autoCaps);
+ mRecapitalizeMode = recapitalizeMode;
+ updateAlphabetShiftState(autoCaps, recapitalizeMode);
}
// TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout
@@ -402,8 +408,28 @@ public final class KeyboardState {
resetKeyboardStateToAlphabet();
}
- private void updateAlphabetShiftState(final int autoCaps) {
+ private void updateShiftStateForRecapitalize(final int recapitalizeMode) {
+ switch (recapitalizeMode) {
+ case RecapitalizeStatus.CAPS_MODE_ALL_UPPER:
+ setShifted(SHIFT_LOCK_SHIFTED);
+ break;
+ case RecapitalizeStatus.CAPS_MODE_FIRST_WORD_UPPER:
+ setShifted(AUTOMATIC_SHIFT);
+ break;
+ case RecapitalizeStatus.CAPS_MODE_ALL_LOWER:
+ case RecapitalizeStatus.CAPS_MODE_ORIGINAL_MIXED_CASE:
+ default:
+ setShifted(UNSHIFT);
+ }
+ }
+
+ private void updateAlphabetShiftState(final int autoCaps, final int recapitalizeMode) {
if (!mIsAlphabetMode) return;
+ if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != recapitalizeMode) {
+ // We are recapitalizing. Match the keyboard to the current recapitalize state.
+ updateShiftStateForRecapitalize(recapitalizeMode);
+ return;
+ }
if (!mShiftKeyState.isReleasing()) {
// Ignore update shift state event while the shift key is being pressed (including
// chording).
@@ -421,6 +447,9 @@ public final class KeyboardState {
private void onPressShift() {
mLongPressShiftLockFired = false;
+ // If we are recapitalizing, we don't do any of the normal processing, including
+ // importantly the double tap timer.
+ if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != mRecapitalizeMode) return;
if (mIsAlphabetMode) {
mIsInDoubleTapShiftKey = mSwitchActions.isInDoubleTapTimeout();
if (!mIsInDoubleTapShiftKey) {
@@ -467,7 +496,11 @@ public final class KeyboardState {
}
private void onReleaseShift(final boolean withSliding) {
- if (mIsAlphabetMode) {
+ if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != mRecapitalizeMode) {
+ // We are recapitalizing. We should match the keyboard state to the recapitalize
+ // state in priority.
+ updateShiftStateForRecapitalize(mRecapitalizeMode);
+ } else if (mIsAlphabetMode) {
final boolean isShiftLocked = mAlphabetShiftState.isShiftLocked();
mIsInAlphabetUnshiftedFromShifted = false;
if (mIsInDoubleTapShiftKey) {
@@ -597,7 +630,7 @@ public final class KeyboardState {
// If the code is a letter, update keyboard shift state.
if (Constants.isLetterCode(code)) {
- updateAlphabetShiftState(autoCaps);
+ updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index bf4c22d23..0a6f2ab00 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -161,7 +161,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mPositionalInfoForUserDictPendingAddition = null;
private final WordComposer mWordComposer = new WordComposer();
private final RichInputConnection mConnection = new RichInputConnection(this);
- private RecapitalizeStatus mRecapitalizeStatus = null;
+ private final RecapitalizeStatus mRecapitalizeStatus = new RecapitalizeStatus();
// Keep track of the last selection range to decide if we need to show word alternatives
private static final int NOT_A_CURSOR_POSITION = -1;
@@ -742,6 +742,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
mSpaceState = SPACE_STATE_NONE;
+ mRecapitalizeStatus.deactivate();
mCurrentlyPressedHardwareKeys.clear();
if (mSuggestionStripView != null) {
@@ -925,7 +926,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// We moved the cursor. If we are touching a word, we need to resume suggestion.
mHandler.postResumeSuggestions();
// Reset the last recapitalization.
- mRecapitalizeStatus = null;
+ mRecapitalizeStatus.deactivate();
mKeyboardSwitcher.updateShiftState();
}
mExpectingUpdateSelection = false;
@@ -995,8 +996,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
}
if (!mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()) return;
- mApplicationSpecifiedCompletions =
- CompletionInfoUtils.removeNulls(applicationSpecifiedCompletions);
if (applicationSpecifiedCompletions == null) {
clearSuggestionStrip();
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -1004,6 +1003,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
return;
}
+ mApplicationSpecifiedCompletions =
+ CompletionInfoUtils.removeNulls(applicationSpecifiedCompletions);
final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords =
SuggestedWords.getFromApplicationSpecifiedCompletions(
@@ -1179,6 +1180,15 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
SPACE_STATE_PHANTOM == mSpaceState);
}
+ public int getCurrentRecapitalizeState() {
+ if (!mRecapitalizeStatus.isActive()
+ || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
+ // Not recapitalizing at the moment
+ return RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
+ }
+ return mRecapitalizeStatus.getCurrentMode();
+ }
+
// Factor in auto-caps and manual caps and compute the current caps mode.
private int getActualCapsMode() {
final int keyboardShiftMode = mKeyboardSwitcher.getKeyboardShiftMode();
@@ -1391,7 +1401,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
case Constants.CODE_SHIFT:
// Note: calling back to the keyboard on Shift key is handled in onPressKey()
// and onReleaseKey().
- handleRecapitalize();
+ final Keyboard currentKeyboard = switcher.getKeyboard();
+ if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
+ // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
+ // alphabetic shift and shift while in symbol layout.
+ handleRecapitalize();
+ }
break;
case Constants.CODE_SWITCH_ALPHA_SYMBOL:
// Note: calling back to the keyboard on symbol key is handled in onPressKey()
@@ -1953,10 +1968,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private void handleRecapitalize() {
if (mLastSelectionStart == mLastSelectionEnd) return; // No selection
// If we have a recapitalize in progress, use it; otherwise, create a new one.
- if (null == mRecapitalizeStatus
+ if (!mRecapitalizeStatus.isActive()
|| !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
- mRecapitalizeStatus =
- new RecapitalizeStatus(mLastSelectionStart, mLastSelectionEnd,
+ mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd,
mConnection.getSelectedText(0 /* flags, 0 for no styles */).toString(),
mSettings.getCurrentLocale(), mSettings.getWordSeparators());
// We trim leading and trailing whitespace.
@@ -1979,6 +1993,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart();
mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd();
mConnection.setSelection(mLastSelectionStart, mLastSelectionEnd);
+ // Match the keyboard to the new state.
+ mKeyboardSwitcher.updateShiftState();
}
// Returns true if we did an autocorrection, false otherwise.
@@ -2413,6 +2429,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (!mConnection.isCursorTouchingWord(mSettings.getCurrent())) return;
final Range range = mConnection.getWordRangeAtCursor(mSettings.getWordSeparators(),
0 /* additionalPrecedingWordsCount */);
+ if (null == range) return; // Happens if we don't have an input connection at all
final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
final String typedWord = range.mWord.toString();
if (range.mWord instanceof SpannableString) {
diff --git a/java/src/com/android/inputmethod/latin/RecapitalizeStatus.java b/java/src/com/android/inputmethod/latin/RecapitalizeStatus.java
index 9edd3a160..8a704ab42 100644
--- a/java/src/com/android/inputmethod/latin/RecapitalizeStatus.java
+++ b/java/src/com/android/inputmethod/latin/RecapitalizeStatus.java
@@ -24,6 +24,7 @@ import java.util.Locale;
* The status of the current recapitalize process.
*/
public class RecapitalizeStatus {
+ public static final int NOT_A_RECAPITALIZE_MODE = -1;
public static final int CAPS_MODE_ORIGINAL_MIXED_CASE = 0;
public static final int CAPS_MODE_ALL_LOWER = 1;
public static final int CAPS_MODE_FIRST_WORD_UPPER = 2;
@@ -37,6 +38,7 @@ public class RecapitalizeStatus {
CAPS_MODE_FIRST_WORD_UPPER,
CAPS_MODE_ALL_UPPER
};
+
private static final int getStringMode(final String string, final String separators) {
if (StringUtils.isIdenticalAfterUpcase(string)) {
return CAPS_MODE_ALL_UPPER;
@@ -50,24 +52,29 @@ public class RecapitalizeStatus {
}
/**
- * We store the location of the cursor and the string that was there before the undoable
+ * We store the location of the cursor and the string that was there before the recapitalize
* action was done, and the location of the cursor and the string that was there after.
*/
private int mCursorStartBefore;
- private int mCursorEndBefore;
private String mStringBefore;
private int mCursorStartAfter;
private int mCursorEndAfter;
private int mRotationStyleCurrentIndex;
- private final boolean mSkipOriginalMixedCaseMode;
- private final Locale mLocale;
- private final String mSeparators;
+ private boolean mSkipOriginalMixedCaseMode;
+ private Locale mLocale;
+ private String mSeparators;
private String mStringAfter;
+ private boolean mIsActive;
+
+ public RecapitalizeStatus() {
+ // By default, initialize with dummy values that won't match any real recapitalize.
+ initialize(-1, -1, "", Locale.getDefault(), "");
+ deactivate();
+ }
- public RecapitalizeStatus(final int cursorStart, final int cursorEnd, final String string,
+ public void initialize(final int cursorStart, final int cursorEnd, final String string,
final Locale locale, final String separators) {
mCursorStartBefore = cursorStart;
- mCursorEndBefore = cursorEnd;
mStringBefore = string;
mCursorStartAfter = cursorStart;
mCursorEndAfter = cursorEnd;
@@ -89,6 +96,15 @@ public class RecapitalizeStatus {
mRotationStyleCurrentIndex = currentMode;
mSkipOriginalMixedCaseMode = true;
}
+ mIsActive = true;
+ }
+
+ public void deactivate() {
+ mIsActive = false;
+ }
+
+ public boolean isActive() {
+ return mIsActive;
}
public boolean isSetAt(final int cursorStart, final int cursorEnd) {
@@ -110,23 +126,23 @@ public class RecapitalizeStatus {
}
++count;
switch (ROTATION_STYLE[mRotationStyleCurrentIndex]) {
- case CAPS_MODE_ORIGINAL_MIXED_CASE:
- mStringAfter = mStringBefore;
- break;
- case CAPS_MODE_ALL_LOWER:
- mStringAfter = mStringBefore.toLowerCase(mLocale);
- break;
- case CAPS_MODE_FIRST_WORD_UPPER:
- mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSeparators,
- mLocale);
- break;
- case CAPS_MODE_ALL_UPPER:
- mStringAfter = mStringBefore.toUpperCase(mLocale);
- break;
- default:
- mStringAfter = mStringBefore;
+ case CAPS_MODE_ORIGINAL_MIXED_CASE:
+ mStringAfter = mStringBefore;
+ break;
+ case CAPS_MODE_ALL_LOWER:
+ mStringAfter = mStringBefore.toLowerCase(mLocale);
+ break;
+ case CAPS_MODE_FIRST_WORD_UPPER:
+ mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSeparators,
+ mLocale);
+ break;
+ case CAPS_MODE_ALL_UPPER:
+ mStringAfter = mStringBefore.toUpperCase(mLocale);
+ break;
+ default:
+ mStringAfter = mStringBefore;
}
- } while (mStringAfter.equals(oldResult) && count < 5);
+ } while (mStringAfter.equals(oldResult) && count < ROTATION_STYLE.length + 1);
mCursorEndAfter = mCursorStartAfter + mStringAfter.length();
}
@@ -148,7 +164,7 @@ public class RecapitalizeStatus {
if (!Character.isWhitespace(codePoint)) break;
}
if (0 != nonWhitespaceStart || len != nonWhitespaceEnd) {
- mCursorEndBefore = mCursorEndAfter = mCursorStartBefore + nonWhitespaceEnd;
+ mCursorEndAfter = mCursorStartBefore + nonWhitespaceEnd;
mCursorStartBefore = mCursorStartAfter = mCursorStartBefore + nonWhitespaceStart;
mStringAfter = mStringBefore =
mStringBefore.substring(nonWhitespaceStart, nonWhitespaceEnd);
@@ -166,4 +182,8 @@ public class RecapitalizeStatus {
public int getNewCursorEnd() {
return mCursorEndAfter;
}
+
+ public int getCurrentMode() {
+ return ROTATION_STYLE[mRotationStyleCurrentIndex];
+ }
}
diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h
index 1c4061fd8..2d2e19501 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/binary_format.h
@@ -92,6 +92,7 @@ class BinaryFormat {
const int unigramProbability, const int bigramProbability);
static int getProbability(const int position, const std::map<int, int> *bigramMap,
const uint8_t *bigramFilter, const int unigramProbability);
+ static float getMultiWordCostMultiplier(const uint8_t *const dict);
// Flags for special processing
// Those *must* match the flags in makedict (BinaryDictInputOutput#*_PROCESSING_FLAG) or
@@ -241,6 +242,17 @@ AK_FORCE_INLINE int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t *
return ((msb & 0x7F) << 8) | dict[(*pos)++];
}
+inline float BinaryFormat::getMultiWordCostMultiplier(const uint8_t *const dict) {
+ const int headerValue = readHeaderValueInt(dict, "MULTIPLE_WORDS_DEMOTION_RATE");
+ if (headerValue == S_INT_MIN) {
+ return 1.0f;
+ }
+ if (headerValue <= 0) {
+ return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
+ }
+ return 100.0f / static_cast<float>(headerValue);
+}
+
inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t *const dict, int *pos) {
return dict[(*pos)++];
}
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index a7b023a75..6ef9f414b 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -424,10 +424,9 @@ typedef enum {
CT_OMISSION,
CT_INSERTION,
CT_TRANSPOSITION,
- CT_SPACE_SUBSTITUTION,
- CT_SPACE_OMISSION,
CT_COMPLETION,
CT_TERMINAL,
- CT_NEW_WORD,
+ CT_NEW_WORD_SPACE_OMITTION,
+ CT_NEW_WORD_SPACE_SUBSTITUTION,
} CorrectionType;
#endif // LATINIME_DEFINES_H
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index e62b70423..b9c0b8129 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -38,7 +38,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
case CT_SUBSTITUTION:
PROF_SUBSTITUTION(node->mProfiler);
return;
- case CT_NEW_WORD:
+ case CT_NEW_WORD_SPACE_OMITTION:
PROF_NEW_WORD(node->mProfiler);
return;
case CT_MATCH:
@@ -50,7 +50,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
case CT_TERMINAL:
PROF_TERMINAL(node->mProfiler);
return;
- case CT_SPACE_SUBSTITUTION:
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
PROF_SPACE_SUBSTITUTION(node->mProfiler);
return;
case CT_INSERTION:
@@ -107,16 +107,16 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
case CT_SUBSTITUTION:
// only used for typing
return weighting->getSubstitutionCost();
- case CT_NEW_WORD:
- return weighting->getNewWordCost(dicNode);
+ case CT_NEW_WORD_SPACE_OMITTION:
+ return weighting->getNewWordCost(traverseSession, dicNode);
case CT_MATCH:
return weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
case CT_COMPLETION:
return weighting->getCompletionCost(traverseSession, dicNode);
case CT_TERMINAL:
return weighting->getTerminalSpatialCost(traverseSession, dicNode);
- case CT_SPACE_SUBSTITUTION:
- return weighting->getSpaceSubstitutionCost();
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
+ return weighting->getSpaceSubstitutionCost(traverseSession, dicNode);
case CT_INSERTION:
return weighting->getInsertionCost(traverseSession, parentDicNode, dicNode);
case CT_TRANSPOSITION:
@@ -135,7 +135,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return 0.0f;
case CT_SUBSTITUTION:
return 0.0f;
- case CT_NEW_WORD:
+ case CT_NEW_WORD_SPACE_OMITTION:
return weighting->getNewWordBigramCost(traverseSession, parentDicNode, bigramCacheMap);
case CT_MATCH:
return 0.0f;
@@ -147,8 +147,8 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
traverseSession->getOffsetDict(), dicNode, bigramCacheMap);
return weighting->getTerminalLanguageCost(traverseSession, dicNode, languageImprobability);
}
- case CT_SPACE_SUBSTITUTION:
- return 0.0f;
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
+ return weighting->getNewWordBigramCost(traverseSession, parentDicNode, bigramCacheMap);
case CT_INSERTION:
return 0.0f;
case CT_TRANSPOSITION:
@@ -168,7 +168,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
case CT_SUBSTITUTION:
// Should return true?
return false;
- case CT_NEW_WORD:
+ case CT_NEW_WORD_SPACE_OMITTION:
return false;
case CT_MATCH:
return false;
@@ -176,7 +176,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return false;
case CT_TERMINAL:
return false;
- case CT_SPACE_SUBSTITUTION:
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
return false;
case CT_INSERTION:
return true;
@@ -197,7 +197,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return false;
case CT_SUBSTITUTION:
return false;
- case CT_NEW_WORD:
+ case CT_NEW_WORD_SPACE_OMITTION:
return false;
case CT_MATCH:
return weighting->isProximityDicNode(traverseSession, dicNode);
@@ -205,7 +205,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return false;
case CT_TERMINAL:
return false;
- case CT_SPACE_SUBSTITUTION:
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
return false;
case CT_INSERTION:
return false;
@@ -224,7 +224,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return 0;
case CT_SUBSTITUTION:
return 0;
- case CT_NEW_WORD:
+ case CT_NEW_WORD_SPACE_OMITTION:
return 0;
case CT_MATCH:
return 1;
@@ -232,7 +232,7 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
return 0;
case CT_TERMINAL:
return 0;
- case CT_SPACE_SUBSTITUTION:
+ case CT_NEW_WORD_SPACE_SUBSTITUTION:
return 1;
case CT_INSERTION:
return 2;
diff --git a/native/jni/src/suggest/core/policy/weighting.h b/native/jni/src/suggest/core/policy/weighting.h
index b92dbe278..bce479c51 100644
--- a/native/jni/src/suggest/core/policy/weighting.h
+++ b/native/jni/src/suggest/core/policy/weighting.h
@@ -56,7 +56,8 @@ class Weighting {
const DicTraverseSession *const traverseSession,
const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
- virtual float getNewWordCost(const DicNode *const dicNode) const = 0;
+ virtual float getNewWordCost(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const = 0;
virtual float getNewWordBigramCost(
const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
@@ -76,7 +77,8 @@ class Weighting {
virtual float getSubstitutionCost() const = 0;
- virtual float getSpaceSubstitutionCost() const = 0;
+ virtual float getSpaceSubstitutionCost(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const = 0;
Weighting() {}
virtual ~Weighting() {}
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index 5b783a2ba..3c44db21c 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -16,6 +16,7 @@
#include "suggest/core/session/dic_traverse_session.h"
+#include "binary_format.h"
#include "defines.h"
#include "dictionary.h"
#include "dic_traverse_wrapper.h"
@@ -63,6 +64,7 @@ static TraverseSessionFactoryRegisterer traverseSessionFactoryRegisterer;
void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
int prevWordLength) {
mDictionary = dictionary;
+ mMultiWordCostMultiplier = BinaryFormat::getMultiWordCostMultiplier(mDictionary->getDict());
if (!prevWord) {
mPrevWordPos = NOT_VALID_WORD;
return;
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index fe0527639..d9c2a51d0 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -36,7 +36,8 @@ class DicTraverseSession {
AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
: mPrevWordPos(NOT_VALID_WORD), mProximityInfo(0),
mDictionary(0), mDicNodesCache(), mBigramCacheMap(),
- mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1) {
+ mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
+ mMultiWordCostMultiplier(1.0f) {
// NOTE: mProximityInfoStates is an array of instances.
// No need to initialize it explicitly here.
}
@@ -52,6 +53,7 @@ class DicTraverseSession {
const int maxPointerCount);
void resetCache(const int nextActiveCacheSize, const int maxWords);
+ // TODO: Remove
const uint8_t *getOffsetDict() const;
int getDictFlags() const;
@@ -150,6 +152,10 @@ class DicTraverseSession {
return mProximityInfoStates[0].touchPositionCorrectionEnabled();
}
+ float getMultiWordCostMultiplier() const {
+ return mMultiWordCostMultiplier;
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
// threshold to start caching
@@ -170,6 +176,11 @@ class DicTraverseSession {
int mInputSize;
bool mPartiallyCommited;
int mMaxPointerCount;
+
+ /////////////////////////////////
+ // Configuration per dictionary
+ float mMultiWordCostMultiplier;
+
};
} // namespace latinime
#endif // LATINIME_DIC_TRAVERSE_SESSION_H
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index 67d351fa1..9de2cd2e2 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -33,16 +33,9 @@
namespace latinime {
// Initialization of class constants.
-const int Suggest::LOOKAHEAD_DIC_NODES_CACHE_SIZE = 25;
const int Suggest::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16;
const int Suggest::MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE = 2;
const float Suggest::AUTOCORRECT_CLASSIFICATION_THRESHOLD = 0.33f;
-const float Suggest::AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD = 0.6f;
-
-const bool Suggest::CORRECT_SPACE_OMISSION = true;
-const bool Suggest::CORRECT_TRANSPOSITION = true;
-const bool Suggest::CORRECT_INSERTION = true;
-const bool Suggest::CORRECT_OMISSION_G = true;
/**
* Returns a set of suggestions for the given input touch points. The commitPoint argument indicates
@@ -270,12 +263,8 @@ void Suggest::expandCurrentDicNodes(DicTraverseSession *traverseSession) const {
// latest touch point yet. These are needed to apply look-ahead correction operations
// that require special handling of the latest touch point. For example, with insertions
// (e.g., "thiis" -> "this") the latest touch point should not be consumed at all.
- if (CORRECT_TRANSPOSITION) {
- processDicNodeAsTransposition(traverseSession, &dicNode);
- }
- if (CORRECT_INSERTION) {
- processDicNodeAsInsertion(traverseSession, &dicNode);
- }
+ processDicNodeAsTransposition(traverseSession, &dicNode);
+ processDicNodeAsInsertion(traverseSession, &dicNode);
} else { // !isLookAheadCorrection
// Only consider typing error corrections if the normalized compound distance is
// below a spatial distance threshold.
@@ -531,13 +520,10 @@ void Suggest::createNextWordDicNode(DicTraverseSession *traverseSession, DicNode
DicNode newDicNode;
DicNodeUtils::initAsRootWithPreviousWord(traverseSession->getDicRootPos(),
traverseSession->getOffsetDict(), dicNode, &newDicNode);
- Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_NEW_WORD, traverseSession, dicNode,
+ const CorrectionType correctionType = spaceSubstitution ?
+ CT_NEW_WORD_SPACE_SUBSTITUTION : CT_NEW_WORD_SPACE_OMITTION;
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, correctionType, traverseSession, dicNode,
&newDicNode, traverseSession->getBigramCacheMap());
- if (spaceSubstitution) {
- // Merge this with CT_NEW_WORD
- Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SPACE_SUBSTITUTION,
- traverseSession, 0, &newDicNode, 0 /* bigramCacheMap */);
- }
traverseSession->getDicTraverseCache()->copyPushNextActive(&newDicNode);
}
} // namespace latinime
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
index becd6c1de..875cbe4e0 100644
--- a/native/jni/src/suggest/core/suggest.h
+++ b/native/jni/src/suggest/core/suggest.h
@@ -76,31 +76,16 @@ class Suggest : public SuggestInterface {
void processDicNodeAsMatch(DicTraverseSession *traverseSession,
DicNode *childDicNode) const;
- // Dic nodes cache size for lookahead (autocompletion)
- static const int LOOKAHEAD_DIC_NODES_CACHE_SIZE;
- // Max characters to lookahead
- static const int MAX_LOOKAHEAD;
// Inputs longer than this will autocorrect if the suggestion is multi-word
static const int MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT;
static const int MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE;
- // Base value for converting costs into scores (low so will not autocorrect without classifier)
- static const float BASE_OUTPUT_SCORE;
// Threshold for autocorrection classifier
static const float AUTOCORRECT_CLASSIFICATION_THRESHOLD;
- // Threshold for computing the language model feature for autocorrect classification
- static const float AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD;
-
- // Typing error correction settings
- static const bool CORRECT_SPACE_OMISSION;
- static const bool CORRECT_TRANSPOSITION;
- static const bool CORRECT_INSERTION;
const Traversal *const TRAVERSAL;
const Scoring *const SCORING;
const Weighting *const WEIGHTING;
-
- static const bool CORRECT_OMISSION_G;
};
} // namespace latinime
#endif // LATINIME_SUGGEST_IMPL_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
index 66f8ba9fa..e7e40e34d 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
@@ -18,7 +18,7 @@
namespace latinime {
const bool TypingTraversal::CORRECT_OMISSION = true;
-const bool TypingTraversal::CORRECT_SPACE_SUBSTITUTION = true;
-const bool TypingTraversal::CORRECT_SPACE_OMISSION = true;
+const bool TypingTraversal::CORRECT_NEW_WORD_SPACE_SUBSTITUTION = true;
+const bool TypingTraversal::CORRECT_NEW_WORD_SPACE_OMISSION = true;
const TypingTraversal TypingTraversal::sInstance;
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index f22029a2c..9f8347452 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -66,7 +66,7 @@ class TypingTraversal : public Traversal {
AK_FORCE_INLINE bool isSpaceSubstitutionTerminal(
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
- if (!CORRECT_SPACE_SUBSTITUTION) {
+ if (!CORRECT_NEW_WORD_SPACE_SUBSTITUTION) {
return false;
}
if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
@@ -80,7 +80,7 @@ class TypingTraversal : public Traversal {
AK_FORCE_INLINE bool isSpaceOmissionTerminal(
const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
- if (!CORRECT_SPACE_OMISSION) {
+ if (!CORRECT_NEW_WORD_SPACE_OMISSION) {
return false;
}
const int inputSize = traverseSession->getInputSize();
@@ -173,8 +173,8 @@ class TypingTraversal : public Traversal {
private:
DISALLOW_COPY_AND_ASSIGN(TypingTraversal);
static const bool CORRECT_OMISSION;
- static const bool CORRECT_SPACE_SUBSTITUTION;
- static const bool CORRECT_SPACE_OMISSION;
+ static const bool CORRECT_NEW_WORD_SPACE_SUBSTITUTION;
+ static const bool CORRECT_NEW_WORD_SPACE_OMISSION;
static const TypingTraversal sInstance;
TypingTraversal() {}
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 2dcee343f..74e4e34e4 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -128,10 +128,12 @@ class TypingWeighting : public Weighting {
return cost + weightedDistance;
}
- float getNewWordCost(const DicNode *const dicNode) const {
+ float getNewWordCost(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const {
const bool isCapitalized = dicNode->isCapitalized();
- return isCapitalized ?
+ const float cost = isCapitalized ?
ScoringParams::COST_NEW_WORD_CAPITALIZED : ScoringParams::COST_NEW_WORD;
+ return cost * traverseSession->getMultiWordCostMultiplier();
}
float getNewWordBigramCost(
@@ -183,8 +185,13 @@ class TypingWeighting : public Weighting {
return ScoringParams::SUBSTITUTION_COST;
}
- AK_FORCE_INLINE float getSpaceSubstitutionCost() const {
- return ScoringParams::SPACE_SUBSTITUTION_COST;
+ AK_FORCE_INLINE float getSpaceSubstitutionCost(
+ const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const {
+ const bool isCapitalized = dicNode->isCapitalized();
+ const float cost = ScoringParams::SPACE_SUBSTITUTION_COST + (isCapitalized ?
+ ScoringParams::COST_NEW_WORD_CAPITALIZED : ScoringParams::COST_NEW_WORD);
+ return cost * traverseSession->getMultiWordCostMultiplier();
}
private:
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index eb484084e..74506d26a 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard.internal;
import android.text.TextUtils;
import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.RecapitalizeStatus;
public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
public interface MockConstants {
@@ -120,7 +121,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
@Override
public void requestUpdatingShiftState() {
- mState.onUpdateShiftState(mAutoCapsState);
+ mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
}
@Override
@@ -162,7 +163,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
}
public void updateShiftState() {
- mState.onUpdateShiftState(mAutoCapsState);
+ mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
}
public void loadKeyboard() {
diff --git a/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java b/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java
index 4dfae4c94..9d7203e5a 100644
--- a/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java
+++ b/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java
@@ -24,29 +24,26 @@ import java.util.Locale;
@SmallTest
public class RecapitalizeStatusTests extends AndroidTestCase {
public void testTrim() {
- RecapitalizeStatus status = new RecapitalizeStatus(30, 40, "abcdefghij",
- Locale.ENGLISH, " ");
+ final RecapitalizeStatus status = new RecapitalizeStatus();
+ status.initialize(30, 40, "abcdefghij", Locale.ENGLISH, " ");
status.trim();
assertEquals("abcdefghij", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(40, status.getNewCursorEnd());
- status = new RecapitalizeStatus(30, 44, " abcdefghij",
- Locale.ENGLISH, " ");
+ status.initialize(30, 44, " abcdefghij", Locale.ENGLISH, " ");
status.trim();
assertEquals("abcdefghij", status.getRecapitalizedString());
assertEquals(34, status.getNewCursorStart());
assertEquals(44, status.getNewCursorEnd());
- status = new RecapitalizeStatus(30, 40, "abcdefgh ",
- Locale.ENGLISH, " ");
+ status.initialize(30, 40, "abcdefgh ", Locale.ENGLISH, " ");
status.trim();
assertEquals("abcdefgh", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(38, status.getNewCursorEnd());
- status = new RecapitalizeStatus(30, 45, " abcdefghij ",
- Locale.ENGLISH, " ");
+ status.initialize(30, 45, " abcdefghij ", Locale.ENGLISH, " ");
status.trim();
assertEquals("abcdefghij", status.getRecapitalizedString());
assertEquals(33, status.getNewCursorStart());
@@ -54,8 +51,8 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
}
public void testRotate() {
- RecapitalizeStatus status = new RecapitalizeStatus(29, 40, "abcd efghij",
- Locale.ENGLISH, " ");
+ final RecapitalizeStatus status = new RecapitalizeStatus();
+ status.initialize(29, 40, "abcd efghij", Locale.ENGLISH, " ");
status.rotate();
assertEquals("Abcd Efghij", status.getRecapitalizedString());
assertEquals(29, status.getNewCursorStart());
@@ -67,8 +64,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
status.rotate();
assertEquals("Abcd Efghij", status.getRecapitalizedString());
- status = new RecapitalizeStatus(29, 40, "Abcd Efghij",
- Locale.ENGLISH, " ");
+ status.initialize(29, 40, "Abcd Efghij", Locale.ENGLISH, " ");
status.rotate();
assertEquals("ABCD EFGHIJ", status.getRecapitalizedString());
assertEquals(29, status.getNewCursorStart());
@@ -80,8 +76,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
status.rotate();
assertEquals("ABCD EFGHIJ", status.getRecapitalizedString());
- status = new RecapitalizeStatus(29, 40, "ABCD EFGHIJ",
- Locale.ENGLISH, " ");
+ status.initialize(29, 40, "ABCD EFGHIJ", Locale.ENGLISH, " ");
status.rotate();
assertEquals("abcd efghij", status.getRecapitalizedString());
assertEquals(29, status.getNewCursorStart());
@@ -93,8 +88,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
status.rotate();
assertEquals("abcd efghij", status.getRecapitalizedString());
- status = new RecapitalizeStatus(29, 39, "AbCDefghij",
- Locale.ENGLISH, " ");
+ status.initialize(29, 39, "AbCDefghij", Locale.ENGLISH, " ");
status.rotate();
assertEquals("abcdefghij", status.getRecapitalizedString());
assertEquals(29, status.getNewCursorStart());
@@ -108,8 +102,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
status.rotate();
assertEquals("abcdefghij", status.getRecapitalizedString());
- status = new RecapitalizeStatus(29, 40, "Abcd efghij",
- Locale.ENGLISH, " ");
+ status.initialize(29, 40, "Abcd efghij", Locale.ENGLISH, " ");
status.rotate();
assertEquals("abcd efghij", status.getRecapitalizedString());
assertEquals(29, status.getNewCursorStart());
@@ -123,8 +116,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
status.rotate();
assertEquals("abcd efghij", status.getRecapitalizedString());
- status = new RecapitalizeStatus(30, 34, "grüß", Locale.GERMAN, " ");
- status.rotate();
+ status.initialize(30, 34, "grüß", Locale.GERMAN, " "); status.rotate();
assertEquals("Grüß", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(34, status.getNewCursorEnd());
@@ -141,9 +133,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
assertEquals(30, status.getNewCursorStart());
assertEquals(34, status.getNewCursorEnd());
-
- status = new RecapitalizeStatus(30, 33, "œuf", Locale.FRENCH, " ");
- status.rotate();
+ status.initialize(30, 33, "œuf", Locale.FRENCH, " "); status.rotate();
assertEquals("Œuf", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(33, status.getNewCursorEnd());
@@ -160,8 +150,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
assertEquals(30, status.getNewCursorStart());
assertEquals(33, status.getNewCursorEnd());
- status = new RecapitalizeStatus(30, 33, "œUf", Locale.FRENCH, " ");
- status.rotate();
+ status.initialize(30, 33, "œUf", Locale.FRENCH, " "); status.rotate();
assertEquals("œuf", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(33, status.getNewCursorEnd());
@@ -182,8 +171,7 @@ public class RecapitalizeStatusTests extends AndroidTestCase {
assertEquals(30, status.getNewCursorStart());
assertEquals(33, status.getNewCursorEnd());
- status = new RecapitalizeStatus(30, 35, "école", Locale.FRENCH, " ");
- status.rotate();
+ status.initialize(30, 35, "école", Locale.FRENCH, " "); status.rotate();
assertEquals("École", status.getRecapitalizedString());
assertEquals(30, status.getNewCursorStart());
assertEquals(35, status.getNewCursorEnd());