aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtil.java27
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java44
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java152
3 files changed, 143 insertions, 80 deletions
diff --git a/java/src/com/android/inputmethod/latin/EditingUtil.java b/java/src/com/android/inputmethod/latin/EditingUtil.java
index 0c87f8d58..be31cb787 100644
--- a/java/src/com/android/inputmethod/latin/EditingUtil.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtil.java
@@ -16,12 +16,12 @@
package com.android.inputmethod.latin;
-import java.util.regex.Pattern;
-
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
+import java.util.regex.Pattern;
+
/**
* Utility methods to deal with editing text through an InputConnection.
*/
@@ -203,4 +203,27 @@ public class EditingUtil {
return null;
}
}
+
+ /**
+ * Checks if the cursor is touching/inside a word or the selection is for a whole
+ * word and no more and no less.
+ * @param range the Range object that contains the bounds of the word around the cursor
+ * @param start the start of the selection
+ * @param end the end of the selection, which could be the same as the start, if text is not
+ * in selection mode
+ * @return false if the selection is a partial word or straddling multiple words, true if
+ * the selection is a full word or there is no selection.
+ */
+ public static boolean isFullWordOrInside(Range range, int start, int end) {
+ // Is the cursor inside or touching a word?
+ if (start == end) return true;
+
+ // Is it a selection? Then is the start of the selection the start of the word and
+ // the size of the selection the size of the word? Then return true
+ if (start < end
+ && (range.charsBefore == 0 && range.charsAfter == end - start)) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index b059b6cfe..b1bb84d27 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -752,10 +752,10 @@ public class LatinIME extends InputMethodService
mVoiceInputHighlighted = false;
} else if (!mPredicting && !mJustAccepted) {
switch (TextEntryState.getState()) {
- case TextEntryState.STATE_ACCEPTED_DEFAULT:
+ case ACCEPTED_DEFAULT:
TextEntryState.reset();
// fall through
- case TextEntryState.STATE_SPACE_AFTER_PICKED:
+ case SPACE_AFTER_PICKED:
mJustAddedAutoSpace = false; // The user moved the cursor.
break;
}
@@ -768,10 +768,10 @@ public class LatinIME extends InputMethodService
mLastSelectionEnd = newSelEnd;
- // TODO: Uncomment this block when we enable re-editing feature
- // If a word is selected
+ // Check if we should go in or out of correction mode.
if (isPredictionOn() && mJustRevertedSeparator == null
- && (candidatesStart == candidatesEnd || newSelStart != oldSelStart)
+ && (candidatesStart == candidatesEnd || newSelStart != oldSelStart
+ || TextEntryState.isCorrecting())
&& (newSelStart < newSelEnd - 1 || (!mPredicting))
&& !mVoiceInputHighlighted) {
if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) {
@@ -1207,7 +1207,7 @@ public class LatinIME extends InputMethodService
}
postUpdateShiftKeyState();
TextEntryState.backspace();
- if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) {
+ if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) {
revertLastWord(deleteChar);
ic.endBatchEdit();
return;
@@ -1358,13 +1358,13 @@ public class LatinIME extends InputMethodService
// Handle the case of ". ." -> " .." with auto-space if necessary
// before changing the TextEntryState.
- if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
+ if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED
&& primaryCode == KEYCODE_PERIOD) {
reswapPeriodAndSpace();
}
TextEntryState.typedCharacter((char) primaryCode, true);
- if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
+ if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED
&& primaryCode != KEYCODE_ENTER) {
swapPunctuationAndSpace();
} else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) {
@@ -1790,8 +1790,16 @@ public class LatinIME extends InputMethodService
mJustAddedAutoSpace = true;
}
- // Fool the state watcher so that a subsequent backspace will not do a revert
- TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
+ // Fool the state watcher so that a subsequent backspace will not do a revert, unless
+ // we just did a correction, in which case we need to stay in
+ // TextEntryState.State.PICKED_SUGGESTION state.
+ if (!correcting) {
+ TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
+ setNextSuggestions();
+ } else {
+ // In case the cursor position doesn't change, make sure we show the suggestions again.
+ postUpdateOldSuggestions();
+ }
if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)
&& !mSuggest.isValidWord(suggestion.toString().toLowerCase())) {
mCandidateView.showAddToDictionaryHint(suggestion);
@@ -1820,7 +1828,6 @@ public class LatinIME extends InputMethodService
mWordToSuggestions.put(suggestion.toString(), suggestions);
}
}
- // TODO: implement rememberReplacedWord for typed words
}
/**
@@ -1860,7 +1867,10 @@ public class LatinIME extends InputMethodService
mPredicting = false;
mCommittedLength = suggestion.length();
((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(null);
- setNextSuggestions();
+ // If we just corrected a word, then don't show punctuations
+ if (!correcting) {
+ setNextSuggestions();
+ }
updateShiftKeyState(getCurrentInputEditorInfo());
}
@@ -1880,13 +1890,16 @@ public class LatinIME extends InputMethodService
EditingUtil.Range range = new EditingUtil.Range();
CharSequence touching = EditingUtil.getWordAtCursor(getCurrentInputConnection(),
mWordSeparators, range);
- if (touching != null && touching.length() > 1) {
+ // If it's a selection, check if it's an entire word and no more, no less.
+ boolean fullword = EditingUtil.isFullWordOrInside(range, mLastSelectionStart,
+ mLastSelectionEnd);
+ if (fullword && touching != null && touching.length() > 1) {
+ // Strip out any trailing word separator
if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) {
touching = touching.toString().substring(0, touching.length() - 1);
}
// Search for result in spoken word alternatives
- // TODO: possibly combine the spoken suggestions with the typed suggestions.
String selectedWord = touching.toString().trim();
if (!mWordToSuggestions.containsKey(selectedWord)){
selectedWord = selectedWord.toLowerCase();
@@ -1911,7 +1924,8 @@ public class LatinIME extends InputMethodService
ic.endBatchEdit();
return;
}
- // If we didn't find a match, search for result in word history
+
+ // If we didn't find a match, search for result in typed word history
WordComposer foundWord = null;
WordAlternatives alternatives = null;
for (WordAlternatives entry : mWordHistory) {
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index bc7bf3f71..9011191f1 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -17,19 +17,22 @@
package com.android.inputmethod.latin;
import android.content.Context;
+import android.inputmethodservice.Keyboard.Key;
import android.text.format.DateFormat;
import android.util.Log;
-import android.inputmethodservice.Keyboard.Key;
-
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
public class TextEntryState {
+ private static final boolean DBG = false;
+
+ private static final String TAG = "TextEntryState";
+
private static boolean LOGGING = false;
-
+
private static int sBackspaceCount = 0;
private static int sAutoSuggestCount = 0;
@@ -46,20 +49,22 @@ public class TextEntryState {
private static int sActualChars;
- public static final int STATE_UNKNOWN = 0;
- public static final int STATE_START = 1;
- public static final int STATE_IN_WORD = 2;
- public static final int STATE_ACCEPTED_DEFAULT = 3;
- public static final int STATE_PICKED_SUGGESTION = 4;
- public static final int STATE_PUNCTUATION_AFTER_WORD = 5;
- public static final int STATE_PUNCTUATION_AFTER_ACCEPTED = 6;
- public static final int STATE_SPACE_AFTER_ACCEPTED = 7;
- public static final int STATE_SPACE_AFTER_PICKED = 8;
- public static final int STATE_UNDO_COMMIT = 9;
- public static final int STATE_CORRECTING = 10;
- public static final int STATE_PICKED_CORRECTION = 11;
-
- private static int sState = STATE_UNKNOWN;
+ public enum State {
+ UNKNOWN,
+ START,
+ IN_WORD,
+ ACCEPTED_DEFAULT,
+ PICKED_SUGGESTION,
+ PUNCTUATION_AFTER_WORD,
+ PUNCTUATION_AFTER_ACCEPTED,
+ SPACE_AFTER_ACCEPTED,
+ SPACE_AFTER_PICKED,
+ UNDO_COMMIT,
+ CORRECTING,
+ PICKED_CORRECTION;
+ }
+
+ private static State sState = State.UNKNOWN;
private static FileOutputStream sKeyLocationFile;
private static FileOutputStream sUserActionFile;
@@ -73,7 +78,7 @@ public class TextEntryState {
sWordNotInDictionaryCount = 0;
sTypedChars = 0;
sActualChars = 0;
- sState = STATE_START;
+ sState = State.START;
if (LOGGING) {
try {
@@ -118,118 +123,133 @@ public class TextEntryState {
}
sTypedChars += typedWord.length();
sActualChars += actualWord.length();
- sState = STATE_ACCEPTED_DEFAULT;
+ sState = State.ACCEPTED_DEFAULT;
LatinImeLogger.logOnAutoSuggestion(typedWord.toString(), actualWord.toString());
+ displayState();
}
- // STATE_ACCEPTED_DEFAULT will be changed to other sub-states
- // (see "case STATE_ACCEPTED_DEFAULT" in typedCharacter() below),
- // and should be restored back to STATE_ACCEPTED_DEFAULT after processing for each sub-state.
+ // State.ACCEPTED_DEFAULT will be changed to other sub-states
+ // (see "case ACCEPTED_DEFAULT" in typedCharacter() below),
+ // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state.
public static void backToAcceptedDefault(CharSequence typedWord) {
if (typedWord == null) return;
switch (sState) {
- case STATE_SPACE_AFTER_ACCEPTED:
- case STATE_PUNCTUATION_AFTER_ACCEPTED:
- case STATE_IN_WORD:
- sState = STATE_ACCEPTED_DEFAULT;
+ case SPACE_AFTER_ACCEPTED:
+ case PUNCTUATION_AFTER_ACCEPTED:
+ case IN_WORD:
+ sState = State.ACCEPTED_DEFAULT;
break;
}
+ displayState();
}
public static void acceptedTyped(CharSequence typedWord) {
sWordNotInDictionaryCount++;
- sState = STATE_PICKED_SUGGESTION;
+ sState = State.PICKED_SUGGESTION;
+ displayState();
}
public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
sManualSuggestCount++;
- int oldState = sState;
+ State oldState = sState;
if (typedWord.equals(actualWord)) {
acceptedTyped(typedWord);
}
- sState = oldState == STATE_CORRECTING ? STATE_PICKED_CORRECTION : STATE_PICKED_SUGGESTION;
+ if (oldState == State.CORRECTING || oldState == State.PICKED_CORRECTION) {
+ sState = State.PICKED_CORRECTION;
+ } else {
+ sState = State.PICKED_SUGGESTION;
+ }
+ displayState();
}
public static void selectedForCorrection() {
- sState = STATE_CORRECTING;
+ sState = State.CORRECTING;
+ displayState();
}
public static void typedCharacter(char c, boolean isSeparator) {
boolean isSpace = c == ' ';
switch (sState) {
- case STATE_IN_WORD:
+ case IN_WORD:
if (isSpace || isSeparator) {
- sState = STATE_START;
+ sState = State.START;
} else {
// State hasn't changed.
}
break;
- case STATE_ACCEPTED_DEFAULT:
- case STATE_SPACE_AFTER_PICKED:
+ case ACCEPTED_DEFAULT:
+ case SPACE_AFTER_PICKED:
if (isSpace) {
- sState = STATE_SPACE_AFTER_ACCEPTED;
+ sState = State.SPACE_AFTER_ACCEPTED;
} else if (isSeparator) {
- sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
+ sState = State.PUNCTUATION_AFTER_ACCEPTED;
} else {
- sState = STATE_IN_WORD;
+ sState = State.IN_WORD;
}
break;
- case STATE_PICKED_SUGGESTION:
- case STATE_PICKED_CORRECTION:
+ case PICKED_SUGGESTION:
+ case PICKED_CORRECTION:
if (isSpace) {
- sState = STATE_SPACE_AFTER_PICKED;
+ sState = State.SPACE_AFTER_PICKED;
} else if (isSeparator) {
// Swap
- sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
+ sState = State.PUNCTUATION_AFTER_ACCEPTED;
} else {
- sState = STATE_IN_WORD;
+ sState = State.IN_WORD;
}
break;
- case STATE_START:
- case STATE_UNKNOWN:
- case STATE_SPACE_AFTER_ACCEPTED:
- case STATE_PUNCTUATION_AFTER_ACCEPTED:
- case STATE_PUNCTUATION_AFTER_WORD:
+ case START:
+ case UNKNOWN:
+ case SPACE_AFTER_ACCEPTED:
+ case PUNCTUATION_AFTER_ACCEPTED:
+ case PUNCTUATION_AFTER_WORD:
if (!isSpace && !isSeparator) {
- sState = STATE_IN_WORD;
+ sState = State.IN_WORD;
} else {
- sState = STATE_START;
+ sState = State.START;
}
break;
- case STATE_UNDO_COMMIT:
+ case UNDO_COMMIT:
if (isSpace || isSeparator) {
- sState = STATE_ACCEPTED_DEFAULT;
+ sState = State.ACCEPTED_DEFAULT;
} else {
- sState = STATE_IN_WORD;
+ sState = State.IN_WORD;
}
break;
- case STATE_CORRECTING:
- sState = STATE_START;
+ case CORRECTING:
+ sState = State.START;
break;
}
+ displayState();
}
public static void backspace() {
- if (sState == STATE_ACCEPTED_DEFAULT) {
- sState = STATE_UNDO_COMMIT;
+ if (sState == State.ACCEPTED_DEFAULT) {
+ sState = State.UNDO_COMMIT;
sAutoSuggestUndoneCount++;
LatinImeLogger.logOnAutoSuggestionCanceled();
- } else if (sState == STATE_UNDO_COMMIT) {
- sState = STATE_IN_WORD;
+ } else if (sState == State.UNDO_COMMIT) {
+ sState = State.IN_WORD;
}
sBackspaceCount++;
+ displayState();
}
-
+
public static void reset() {
- sState = STATE_START;
+ sState = State.START;
+ displayState();
}
-
- public static int getState() {
+
+ public static State getState() {
+ if (DBG) {
+ Log.d(TAG, "Returning state = " + sState);
+ }
return sState;
}
public static boolean isCorrecting() {
- return sState == STATE_CORRECTING || sState == STATE_PICKED_CORRECTION;
+ return sState == State.CORRECTING || sState == State.PICKED_CORRECTION;
}
public static void keyPressedAt(Key key, int x, int y) {
@@ -248,5 +268,11 @@ public class TextEntryState {
}
}
}
+
+ private static void displayState() {
+ if (DBG) {
+ Log.d(TAG, "State = " + sState);
+ }
+ }
}