aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
authorsatok <satok@google.com>2010-07-01 05:11:23 +0900
committersatok <satok@google.com>2010-07-01 05:11:23 +0900
commit9d2e059f835e7d845c3bbbe473f388b878e44fd2 (patch)
tree8b4d0251ccc0431770a28ed4871572cdabb9faeb /java/src
parent67607ea8b12a149f95a5d74b94ff550eac4bd0ff (diff)
parent57691a35743e3705abe60db4902f9ad3c0e722d8 (diff)
downloadlatinime-9d2e059f835e7d845c3bbbe473f388b878e44fd2.tar.gz
latinime-9d2e059f835e7d845c3bbbe473f388b878e44fd2.tar.xz
latinime-9d2e059f835e7d845c3bbbe473f388b878e44fd2.zip
Merge commit 'goog/master'
Conflicts: java/src/com/android/inputmethod/latin/LatinIME.java
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtil.java (renamed from java/src/com/android/inputmethod/voice/EditingUtil.java)48
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java306
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java26
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java7
-rw-r--r--java/src/com/android/inputmethod/voice/VoiceInput.java4
5 files changed, 332 insertions, 59 deletions
diff --git a/java/src/com/android/inputmethod/voice/EditingUtil.java b/java/src/com/android/inputmethod/latin/EditingUtil.java
index 6316d8ccf..7571f1daf 100644
--- a/java/src/com/android/inputmethod/voice/EditingUtil.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtil.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.android.inputmethod.voice;
+package com.android.inputmethod.latin;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -75,9 +75,21 @@ public class EditingUtil {
* represents the cursor, then "hello " will be returned.
*/
public static String getWordAtCursor(
- InputConnection connection, String separators) {
- Range range = getWordRangeAtCursor(connection, separators);
- return (range == null) ? null : range.word;
+ InputConnection connection, String separators) {
+ return getWordAtCursor(connection, separators, null);
+ }
+
+ /**
+ * @param connection connection to the current text field.
+ * @param sep characters which may separate words
+ * @return the word that surrounds the cursor, including up to one trailing
+ * separator. For example, if the field contains "he|llo world", where |
+ * represents the cursor, then "hello " will be returned.
+ */
+ public static String getWordAtCursor(
+ InputConnection connection, String separators, Range range) {
+ Range r = getWordRangeAtCursor(connection, separators, range);
+ return (r == null) ? null : r.word;
}
/**
@@ -87,7 +99,7 @@ public class EditingUtil {
public static void deleteWordAtCursor(
InputConnection connection, String separators) {
- Range range = getWordRangeAtCursor(connection, separators);
+ Range range = getWordRangeAtCursor(connection, separators, null);
if (range == null) return;
connection.finishComposingText();
@@ -101,18 +113,20 @@ public class EditingUtil {
/**
* Represents a range of text, relative to the current cursor position.
*/
- private static class Range {
+ public static class Range {
/** Characters before selection start */
- int charsBefore;
+ public int charsBefore;
/**
* Characters after selection start, including one trailing word
* separator.
*/
- int charsAfter;
+ public int charsAfter;
/** The actual characters that make up a word */
- String word;
+ public String word;
+
+ public Range() {}
public Range(int charsBefore, int charsAfter, String word) {
if (charsBefore < 0 || charsAfter < 0) {
@@ -125,7 +139,7 @@ public class EditingUtil {
}
private static Range getWordRangeAtCursor(
- InputConnection connection, String sep) {
+ InputConnection connection, String sep, Range range) {
if (connection == null || sep == null) {
return null;
}
@@ -137,20 +151,22 @@ public class EditingUtil {
// Find first word separator before the cursor
int start = before.length();
- while (--start > 0 && !isWhitespace(before.charAt(start - 1), sep));
+ while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--;
// Find last word separator after the cursor
int end = -1;
while (++end < after.length() && !isWhitespace(after.charAt(end), sep));
- if (end < after.length() - 1) {
- end++; // Include trailing space, if it exists, in word
- }
int cursor = getCursorPosition(connection);
if (start >= 0 && cursor + end <= after.length() + before.length()) {
String word = before.toString().substring(start, before.length())
- + after.toString().substring(0, end);
- return new Range(before.length() - start, end, word);
+ + after.toString().substring(0, end);
+
+ Range returnRange = range != null? range : new Range();
+ returnRange.charsBefore = before.length() - start;
+ returnRange.charsAfter = end;
+ returnRange.word = word;
+ return returnRange;
}
return null;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6af8c4f22..756cd2327 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.voice.EditingUtil;
import com.android.inputmethod.voice.FieldContext;
import com.android.inputmethod.voice.SettingsUtil;
import com.android.inputmethod.voice.VoiceInput;
@@ -127,6 +126,7 @@ public class LatinIME extends InputMethodService
private static final int MSG_UPDATE_SHIFT_STATE = 2;
private static final int MSG_VOICE_RESULTS = 3;
private static final int MSG_START_LISTENING_AFTER_SWIPE = 4;
+ private static final int MSG_UPDATE_OLD_SUGGESTIONS = 5;
// If we detect a swipe gesture within N ms of typing, then swipe is
// ignored, since it may in fact be two key presses in quick succession.
@@ -204,6 +204,12 @@ public class LatinIME extends InputMethodService
private boolean mVoiceOnPrimary;
private int mOrientation;
private List<CharSequence> mSuggestPuncList;
+ // Keep track of the last selection range to decide if we need to show word alternatives
+ private int mLastSelectionStart;
+ private int mLastSelectionEnd;
+
+ // Input type is such that we should not auto-correct
+ private boolean mInputTypeNoAutoCorrect;
// Indicates whether the suggestion strip is to be on in landscape
private boolean mJustAccepted;
@@ -228,17 +234,66 @@ public class LatinIME extends InputMethodService
// Keeps track of most recently inserted text (multi-character key) for reverting
private CharSequence mEnteredText;
+ private boolean mRefreshKeyboardRequired;
// For each word, a list of potential replacements, usually from voice.
private Map<String, List<CharSequence>> mWordToSuggestions =
new HashMap<String, List<CharSequence>>();
+ private ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>();
+
private class VoiceResults {
List<String> candidates;
Map<String, List<CharSequence>> alternatives;
}
+
+ public abstract static class WordAlternatives {
+ protected CharSequence mChosenWord;
- private boolean mRefreshKeyboardRequired;
+ public WordAlternatives() {
+ // Nothing
+ }
+
+ public WordAlternatives(CharSequence chosenWord) {
+ mChosenWord = chosenWord;
+ }
+
+ @Override
+ public int hashCode() {
+ return mChosenWord.hashCode();
+ }
+
+ public abstract CharSequence getOriginalWord();
+
+ public CharSequence getChosenWord() {
+ return mChosenWord;
+ }
+
+ public abstract List<CharSequence> getAlternatives();
+ }
+
+ public class TypedWordAlternatives extends WordAlternatives {
+ private WordComposer word;
+
+ public TypedWordAlternatives() {
+ // Nothing
+ }
+
+ public TypedWordAlternatives(CharSequence chosenWord, WordComposer wordComposer) {
+ super(chosenWord);
+ word = wordComposer;
+ }
+
+ @Override
+ public CharSequence getOriginalWord() {
+ return word.getTypedWord();
+ }
+
+ @Override
+ public List<CharSequence> getAlternatives() {
+ return getTypedSuggestions(word);
+ }
+ }
Handler mHandler = new Handler() {
@Override
@@ -247,6 +302,9 @@ public class LatinIME extends InputMethodService
case MSG_UPDATE_SUGGESTIONS:
updateSuggestions();
break;
+ case MSG_UPDATE_OLD_SUGGESTIONS:
+ setOldSuggestions();
+ break;
case MSG_START_TUTORIAL:
if (mTutorial == null) {
if (mKeyboardSwitcher.getInputView().isShown()) {
@@ -467,7 +525,6 @@ public class LatinIME extends InputMethodService
mShowingVoiceSuggestions = false;
mImmediatelyAfterVoiceSuggestions = false;
mVoiceInputHighlighted = false;
- mWordToSuggestions.clear();
mInputTypeNoAutoCorrect = false;
mPredictionOn = false;
mCompletionOn = false;
@@ -625,10 +682,11 @@ public class LatinIME extends InputMethodService
// clear whatever candidate text we have.
if ((((mComposing.length() > 0 && mPredicting) || mVoiceInputHighlighted)
&& (newSelStart != candidatesEnd
- || newSelEnd != candidatesEnd))) {
+ || newSelEnd != candidatesEnd)
+ && mLastSelectionStart != newSelStart)) {
mComposing.setLength(0);
mPredicting = false;
- updateSuggestions();
+ postUpdateSuggestions();
TextEntryState.reset();
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
@@ -648,26 +706,18 @@ public class LatinIME extends InputMethodService
mJustAccepted = false;
postUpdateShiftKeyState();
- if (VOICE_INSTALLED) {
- if (mShowingVoiceSuggestions) {
- if (mImmediatelyAfterVoiceSuggestions) {
- mImmediatelyAfterVoiceSuggestions = false;
- } else {
- updateSuggestions();
- mShowingVoiceSuggestions = false;
- }
- }
- if (VoiceInput.ENABLE_WORD_CORRECTIONS) {
- // If we have alternatives for the current word, then show them.
- String word = EditingUtil.getWordAtCursor(
- getCurrentInputConnection(), getWordSeparators());
- if (word != null && mWordToSuggestions.containsKey(word.trim())) {
- mSuggestionShouldReplaceCurrentWord = true;
- final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim());
+ // Make a note of the cursor position
+ mLastSelectionStart = newSelStart;
+ mLastSelectionEnd = newSelEnd;
- setSuggestions(suggestions, false, true, true);
- setCandidatesViewShown(true);
- }
+
+ // If a word is selected
+ if ((candidatesStart == candidatesEnd || newSelStart != oldSelStart)
+ && (newSelStart < newSelEnd - 1 || (!mPredicting))
+ && !mVoiceInputHighlighted) {
+ abortCorrection(false);
+ if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) {
+ postUpdateOldSuggestions();
}
}
}
@@ -692,6 +742,8 @@ public class LatinIME extends InputMethodService
mVoiceInput.cancel();
}
}
+ mWordToSuggestions.clear();
+ mWordHistory.clear();
super.hideWindow();
TextEntryState.endSession();
}
@@ -1035,6 +1087,7 @@ public class LatinIME extends InputMethodService
}
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
+ abortCorrection(false);
ic.beginBatchEdit();
if (mPredicting) {
commitTyped(ic);
@@ -1115,6 +1168,13 @@ public class LatinIME extends InputMethodService
}
}
+ private void abortCorrection(boolean force) {
+ if (force || TextEntryState.isCorrecting()) {
+ getCurrentInputConnection().finishComposingText();
+ setSuggestions(null, false, false, false);
+ }
+ }
+
private void handleCharacter(int primaryCode, int[] keyCodes) {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
commitVoiceInput();
@@ -1124,11 +1184,13 @@ public class LatinIME extends InputMethodService
// Assume input length is 1. This assumption fails for smiley face insertions.
mVoiceInput.incrementTextModificationInsertCount(1);
}
+ abortCorrection(false);
if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) {
if (!mPredicting) {
mPredicting = true;
mComposing.setLength(0);
+ saveWordInHistory(mBestWord);
mWord.reset();
}
}
@@ -1184,6 +1246,7 @@ public class LatinIME extends InputMethodService
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.beginBatchEdit();
+ abortCorrection(false);
}
if (mPredicting) {
// In certain languages where single quote is a separator, it's better
@@ -1222,7 +1285,6 @@ public class LatinIME extends InputMethodService
&& primaryCode != KEYCODE_ENTER) {
swapPunctuationAndSpace();
} else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) {
- //else if (TextEntryState.STATE_SPACE_AFTER_ACCEPTED) {
doubleSpace();
}
if (pickedDefault) {
@@ -1244,6 +1306,17 @@ public class LatinIME extends InputMethodService
TextEntryState.endSession();
}
+ private void saveWordInHistory(CharSequence result) {
+ if (mWord.size() <= 1) {
+ mWord.reset();
+ return;
+ }
+ TypedWordAlternatives entry = new TypedWordAlternatives(result, mWord);
+ // Create a new WordComposer as the old one is being saved for later use
+ mWord = new WordComposer(mWord);
+ mWordHistory.add(entry);
+ }
+
private void checkToggleCapsLock() {
if (mKeyboardSwitcher.getInputView().getKeyboard().isShifted()) {
toggleCapsLock();
@@ -1263,6 +1336,11 @@ public class LatinIME extends InputMethodService
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SUGGESTIONS), 100);
}
+ private void postUpdateOldSuggestions() {
+ mHandler.removeMessages(MSG_UPDATE_OLD_SUGGESTIONS);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 300);
+ }
+
private boolean isPredictionOn() {
boolean predictionOn = mPredictionOn;
return predictionOn;
@@ -1447,9 +1525,6 @@ public class LatinIME extends InputMethodService
// Show N-Best alternates, if there is more than one choice.
if (nBest.size() > 1) {
mImmediatelyAfterVoiceSuggestions = true;
- mShowingVoiceSuggestions = true;
- setSuggestions(nBest.subList(1, nBest.size()), false, true, true);
- setCandidatesViewShown(true);
}
mVoiceInputHighlighted = true;
mWordToSuggestions.putAll(mVoiceResults.alternatives);
@@ -1489,17 +1564,32 @@ public class LatinIME extends InputMethodService
setNextSuggestions();
return;
}
+ showSuggestions(mWord);
+ }
+
+ private List<CharSequence> getTypedSuggestions(WordComposer word) {
+ List<CharSequence> stringList = mSuggest.getSuggestions(
+ mKeyboardSwitcher.getInputView(), word, false);
+ return stringList;
+ }
- List<CharSequence> stringList = mSuggest.getSuggestions(inputView,
- mWord, false);
+ private void showCorrections(WordAlternatives alternatives) {
+ List<CharSequence> stringList = alternatives.getAlternatives();
+ ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).setPreferredLetters(null);
+ showSuggestions(stringList, alternatives.getOriginalWord(), false, false);
+ }
+
+ private void showSuggestions(WordComposer word) {
+ List<CharSequence> stringList = mSuggest.getSuggestions(
+ mKeyboardSwitcher.getInputView(), word, false);
int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
- ((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(
+ ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).setPreferredLetters(
nextLettersFrequencies);
boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasMinimalCorrection();
//|| mCorrectionMode == mSuggest.CORRECTION_FULL;
- CharSequence typedWord = mWord.getTypedWord();
+ CharSequence typedWord = word.getTypedWord();
// If we're in basic correct
boolean typedWordValid = mSuggest.isValidWord(typedWord) ||
(preferCapitalization()
@@ -1508,8 +1598,14 @@ public class LatinIME extends InputMethodService
correctionAvailable |= typedWordValid;
}
// Don't auto-correct words with multiple capital letter
- correctionAvailable &= !mWord.isMostlyCaps();
+ correctionAvailable &= !word.isMostlyCaps();
+ correctionAvailable &= !TextEntryState.isCorrecting();
+
+ showSuggestions(stringList, typedWord, typedWordValid, correctionAvailable);
+ }
+ private void showSuggestions(List<CharSequence> stringList, CharSequence typedWord,
+ boolean typedWordValid, boolean correctionAvailable) {
setSuggestions(stringList, false, typedWordValid, correctionAvailable);
if (stringList.size() > 0) {
if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
@@ -1550,6 +1646,7 @@ public class LatinIME extends InputMethodService
mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.length());
}
+ final boolean correcting = TextEntryState.isCorrecting();
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.beginBatchEdit();
@@ -1594,10 +1691,11 @@ public class LatinIME extends InputMethodService
index, suggestions);
TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
// Follow it with a space
- if (mAutoSpace) {
+ if (mAutoSpace && !correcting) {
sendSpace();
mJustAddedAutoSpace = true;
}
+
// Fool the state watcher so that a subsequent backspace will not do a revert
TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)) {
@@ -1608,6 +1706,29 @@ public class LatinIME extends InputMethodService
}
}
+ private void rememberReplacedWord(CharSequence suggestion) {
+ if (mShowingVoiceSuggestions) {
+ // Retain the replaced word in the alternatives array.
+ InputConnection ic = getCurrentInputConnection();
+ EditingUtil.Range range = new EditingUtil.Range();
+ String wordToBeReplaced = EditingUtil.getWordAtCursor(getCurrentInputConnection(),
+ mWordSeparators, range).trim();
+ if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
+ wordToBeReplaced = wordToBeReplaced.toLowerCase();
+ }
+ if (mWordToSuggestions.containsKey(wordToBeReplaced)) {
+ List<CharSequence> suggestions = mWordToSuggestions.get(wordToBeReplaced);
+ if (suggestions.contains(suggestion)) {
+ suggestions.remove(suggestion);
+ }
+ suggestions.add(wordToBeReplaced);
+ mWordToSuggestions.remove(wordToBeReplaced);
+ mWordToSuggestions.put(suggestion.toString(), suggestions);
+ }
+ }
+ // TODO: implement rememberReplacedWord for typed words
+ }
+
private void pickSuggestion(CharSequence suggestion) {
LatinKeyboardView inputView = mKeyboardSwitcher.getInputView();
if (mCapsLock) {
@@ -1620,6 +1741,7 @@ public class LatinIME extends InputMethodService
}
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
+ rememberReplacedWord(suggestion);
if (mSuggestionShouldReplaceCurrentWord) {
EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
}
@@ -1627,6 +1749,7 @@ public class LatinIME extends InputMethodService
ic.commitText(suggestion, 1);
}
}
+ saveWordInHistory(suggestion);
mPredicting = false;
mCommittedLength = suggestion.length();
((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(null);
@@ -1634,16 +1757,128 @@ public class LatinIME extends InputMethodService
updateShiftKeyState(getCurrentInputEditorInfo());
}
+ private void setOldSuggestions() {
+ // TODO: Inefficient to check if touching word and then get the touching word. Do it
+ // in one go.
+ mShowingVoiceSuggestions = false;
+ InputConnection ic = getCurrentInputConnection();
+ if (ic == null) return;
+ ic.beginBatchEdit();
+ // If there is a selection, then undo the selection first. Unfortunately this causes
+ // a flicker. TODO: Add getSelectionText() to InputConnection API.
+ if (mLastSelectionStart < mLastSelectionEnd) {
+ ic.setSelection(mLastSelectionStart, mLastSelectionStart);
+ }
+ if (!mPredicting && isCursorTouchingWord()) {
+ EditingUtil.Range range = new EditingUtil.Range();
+ CharSequence touching =
+ EditingUtil.getWordAtCursor(getCurrentInputConnection(), mWordSeparators,
+ range);
+ if (touching != null && touching.length() > 1) {
+ 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();
+ }
+ if (mWordToSuggestions.containsKey(selectedWord)){
+ mShowingVoiceSuggestions = true;
+ mSuggestionShouldReplaceCurrentWord = true;
+ underlineWord(touching, range.charsBefore, range.charsAfter);
+ List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
+ // If the first letter of touching is capitalized, make all the suggestions
+ // start with a capital letter.
+ if (Character.isUpperCase((char) touching.charAt(0))) {
+ for (int i=0; i< suggestions.size(); i++) {
+ String origSugg = (String) suggestions.get(i);
+ String capsSugg = origSugg.toUpperCase().charAt(0)
+ + origSugg.subSequence(1, origSugg.length()).toString();
+ suggestions.set(i,capsSugg);
+ }
+ }
+ setSuggestions(suggestions, false, true, true);
+ setCandidatesViewShown(true);
+ TextEntryState.selectedForCorrection();
+ ic.endBatchEdit();
+ return;
+ }
+ // If we didn't find a match, search for result in word history
+ WordComposer foundWord = null;
+ WordAlternatives alternatives = null;
+ for (WordAlternatives entry : mWordHistory) {
+ if (TextUtils.equals(entry.getChosenWord(), touching)) {
+ if (entry instanceof TypedWordAlternatives) {
+ foundWord = ((TypedWordAlternatives)entry).word;
+ }
+ alternatives = entry;
+ break;
+ }
+ }
+ // If we didn't find a match, at least suggest completions
+ if (foundWord == null && mSuggest.isValidWord(touching)) {
+ foundWord = new WordComposer();
+ for (int i = 0; i < touching.length(); i++) {
+ foundWord.add(touching.charAt(i), new int[] { touching.charAt(i) });
+ }
+ }
+ // Found a match, show suggestions
+ if (foundWord != null || alternatives != null) {
+ mSuggestionShouldReplaceCurrentWord = true;
+ underlineWord(touching, range.charsBefore, range.charsAfter);
+ TextEntryState.selectedForCorrection();
+ if (alternatives == null) alternatives = new TypedWordAlternatives(touching,
+ foundWord);
+ showCorrections(alternatives);
+ if (foundWord != null) {
+ mWord = foundWord;
+ } else {
+ mWord.reset();
+ }
+ // Revert the selection
+ if (mLastSelectionStart < mLastSelectionEnd) {
+ ic.setSelection(mLastSelectionStart, mLastSelectionEnd);
+ }
+ ic.endBatchEdit();
+ return;
+ }
+ abortCorrection(true);
+ } else {
+ abortCorrection(true);
+ setNextSuggestions();
+ }
+ } else {
+ abortCorrection(true);
+ }
+ // Revert the selection
+ if (mLastSelectionStart < mLastSelectionEnd) {
+ ic.setSelection(mLastSelectionStart, mLastSelectionEnd);
+ }
+ ic.endBatchEdit();
+ }
+
private void setNextSuggestions() {
setSuggestions(mSuggestPuncList, false, false, false);
}
+ private void underlineWord(CharSequence word, int left, int right) {
+ InputConnection ic = getCurrentInputConnection();
+ if (ic == null) return;
+ ic.deleteSurroundingText(left, right);
+ ic.setComposingText(word, 1);
+ ic.setSelection(mLastSelectionStart, mLastSelectionStart);
+ }
+
private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta) {
+ if (suggestion == null || suggestion.length() < 1) return;
// Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be
// adding words in situations where the user or application really didn't
// want corrections enabled or learned.
if (!(mCorrectionMode == Suggest.CORRECTION_FULL)) return;
- if (mAutoDictionary.isValidWord(suggestion)
+ if (suggestion != null && mAutoDictionary.isValidWord(suggestion)
|| (!mSuggest.isValidWord(suggestion.toString())
&& !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) {
mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
@@ -2065,7 +2300,6 @@ public class LatinIME extends InputMethodService
private static final int CPS_BUFFER_SIZE = 16;
private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
private int mCpsIndex;
- private boolean mInputTypeNoAutoCorrect;
private void measureCps() {
long now = System.currentTimeMillis();
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index e2f949e4b..1a3bb877a 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -69,9 +69,11 @@ public class TextEntryState {
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;
-
+
private static FileOutputStream sKeyLocationFile;
private static FileOutputStream sUserActionFile;
@@ -153,12 +155,17 @@ public class TextEntryState {
public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
sManualSuggestCount++;
+ int oldState = sState;
if (typedWord.equals(actualWord)) {
acceptedTyped(typedWord);
}
- sState = STATE_PICKED_SUGGESTION;
+ sState = oldState == STATE_CORRECTING ? STATE_PICKED_CORRECTION : STATE_PICKED_SUGGESTION;
}
-
+
+ public static void selectedForCorrection() {
+ sState = STATE_CORRECTING;
+ }
+
public static void typedCharacter(char c, boolean isSeparator) {
boolean isSpace = c == ' ';
switch (sState) {
@@ -180,6 +187,7 @@ public class TextEntryState {
}
break;
case STATE_PICKED_SUGGESTION:
+ case STATE_PICKED_CORRECTION:
if (isSpace) {
sState = STATE_SPACE_AFTER_PICKED;
} else if (isSeparator) {
@@ -206,6 +214,10 @@ public class TextEntryState {
} else {
sState = STATE_IN_WORD;
}
+ break;
+ case STATE_CORRECTING:
+ sState = STATE_START;
+ break;
}
}
@@ -227,7 +239,11 @@ public class TextEntryState {
public static int getState() {
return sState;
}
-
+
+ public static boolean isCorrecting() {
+ return sState == STATE_CORRECTING || sState == STATE_PICKED_CORRECTION;
+ }
+
public static void keyPressedAt(Key key, int x, int y) {
if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) {
String out =
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 2547aa133..e2573a0a9 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -49,6 +49,13 @@ public class WordComposer {
mTypedWord = new StringBuilder(20);
}
+ WordComposer(WordComposer copy) {
+ mCodes = (ArrayList<int[]>) copy.mCodes.clone();
+ mPreferredWord = copy.mPreferredWord;
+ mTypedWord = new StringBuilder(copy.mTypedWord);
+ mCapsCount = copy.mCapsCount;
+ mAutoCapitalized = copy.mAutoCapitalized;
+ }
/**
* Clear out the keys registered so far.
*/
diff --git a/java/src/com/android/inputmethod/voice/VoiceInput.java b/java/src/com/android/inputmethod/voice/VoiceInput.java
index ac06ab50d..354670969 100644
--- a/java/src/com/android/inputmethod/voice/VoiceInput.java
+++ b/java/src/com/android/inputmethod/voice/VoiceInput.java
@@ -63,7 +63,7 @@ public class VoiceInput implements OnClickListener {
// WARNING! Before enabling this, fix the problem with calling getExtractedText() in
// landscape view. It causes Extracted text updates to be rejected due to a token mismatch
- public static boolean ENABLE_WORD_CORRECTIONS = false;
+ public static boolean ENABLE_WORD_CORRECTIONS = true;
// Dummy word suggestion which means "delete current word"
public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
@@ -308,7 +308,7 @@ public class VoiceInput implements OnClickListener {
SettingsUtil.getSettingsInt(
mContext.getContentResolver(),
SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
- 1));
+ 10));
// Get endpointer params from Gservices.
// TODO: Consider caching these values for improved performance on slower devices.