Fix the auto-composer to support supplementary chars
Change-Id: I61ff218ae2ca4eb443a370e581b677755258670amain
parent
8174373a0e
commit
9159b9953d
|
@ -90,11 +90,11 @@ public class WordComposer {
|
||||||
* @return the number of keystrokes
|
* @return the number of keystrokes
|
||||||
*/
|
*/
|
||||||
public final int size() {
|
public final int size() {
|
||||||
return mTypedWord.length();
|
return mCodes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isComposingWord() {
|
public final boolean isComposingWord() {
|
||||||
return size() > 0;
|
return mCodes.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,8 +125,8 @@ public class WordComposer {
|
||||||
* @param codes the array of unicode values
|
* @param codes the array of unicode values
|
||||||
*/
|
*/
|
||||||
public void add(int primaryCode, int[] codes, int x, int y) {
|
public void add(int primaryCode, int[] codes, int x, int y) {
|
||||||
final int newIndex = size();
|
final int newIndex = mCodes.size();
|
||||||
mTypedWord.append((char) primaryCode);
|
mTypedWord.appendCodePoint(primaryCode);
|
||||||
correctPrimaryJuxtapos(primaryCode, codes);
|
correctPrimaryJuxtapos(primaryCode, codes);
|
||||||
mCodes.add(codes);
|
mCodes.add(codes);
|
||||||
if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
|
if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
|
||||||
|
@ -171,8 +171,8 @@ public class WordComposer {
|
||||||
final KeyDetector keyDetector) {
|
final KeyDetector keyDetector) {
|
||||||
reset();
|
reset();
|
||||||
final int length = word.length();
|
final int length = word.length();
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) {
|
||||||
int codePoint = word.charAt(i);
|
int codePoint = Character.codePointAt(word, i);
|
||||||
addKeyInfo(codePoint, keyboard, keyDetector);
|
addKeyInfo(codePoint, keyboard, keyDetector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,16 +207,25 @@ public class WordComposer {
|
||||||
* Delete the last keystroke as a result of hitting backspace.
|
* Delete the last keystroke as a result of hitting backspace.
|
||||||
*/
|
*/
|
||||||
public void deleteLast() {
|
public void deleteLast() {
|
||||||
final int size = size();
|
final int size = mCodes.size();
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
final int lastPos = size - 1;
|
mCodes.remove(size - 1);
|
||||||
char lastChar = mTypedWord.charAt(lastPos);
|
// Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs
|
||||||
mCodes.remove(lastPos);
|
final int stringBuilderLength = mTypedWord.length();
|
||||||
// TODO: This crashes and catches fire if the code point doesn't fit a char
|
if (stringBuilderLength < size) {
|
||||||
mTypedWord.deleteCharAt(lastPos);
|
throw new RuntimeException(
|
||||||
|
"In WordComposer: mCodes and mTypedWords have non-matching lengths");
|
||||||
|
}
|
||||||
|
final int lastChar = mTypedWord.codePointBefore(stringBuilderLength);
|
||||||
|
if (Character.isSupplementaryCodePoint(lastChar)) {
|
||||||
|
mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength);
|
||||||
|
} else {
|
||||||
|
mTypedWord.deleteCharAt(stringBuilderLength - 1);
|
||||||
|
}
|
||||||
if (Character.isUpperCase(lastChar)) mCapsCount--;
|
if (Character.isUpperCase(lastChar)) mCapsCount--;
|
||||||
}
|
}
|
||||||
if (size() == 0) {
|
// We may have deleted the last one.
|
||||||
|
if (0 == mCodes.size()) {
|
||||||
mIsFirstCharCapitalized = false;
|
mIsFirstCharCapitalized = false;
|
||||||
}
|
}
|
||||||
if (mTrailingSingleQuotesCount > 0) {
|
if (mTrailingSingleQuotesCount > 0) {
|
||||||
|
|
|
@ -159,11 +159,26 @@ public class InputLogicTests extends ServiceTestCase<LatinIME> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPickSuggestionThenBackspace() {
|
public void testPickSuggestionThenBackspace() {
|
||||||
final String WORD_TO_TYPE = "tgis";
|
final String WORD_TO_TYPE = "this";
|
||||||
|
final String EXPECTED_RESULT = "this";
|
||||||
type(WORD_TO_TYPE);
|
type(WORD_TO_TYPE);
|
||||||
mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE);
|
mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE);
|
||||||
|
mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
|
||||||
type(Keyboard.CODE_DELETE);
|
type(Keyboard.CODE_DELETE);
|
||||||
assertEquals("press suggestion then backspace", WORD_TO_TYPE,
|
assertEquals("press suggestion then backspace", EXPECTED_RESULT,
|
||||||
|
mTextView.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPickTypedWordOverAutoCorrectionThenBackspace() {
|
||||||
|
final String WORD_TO_TYPE = "tgis";
|
||||||
|
final String EXPECTED_RESULT = "tgis";
|
||||||
|
type(WORD_TO_TYPE);
|
||||||
|
// Choose the typed word, which should be in position 1 (because position 0 should
|
||||||
|
// be occupied by the "this" auto-correction, as checked by testAutoCorrect())
|
||||||
|
mLatinIME.pickSuggestionManually(1, WORD_TO_TYPE);
|
||||||
|
mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
|
||||||
|
type(Keyboard.CODE_DELETE);
|
||||||
|
assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT,
|
||||||
mTextView.getText().toString());
|
mTextView.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,4 +394,6 @@ public class InputLogicTests extends ServiceTestCase<LatinIME> {
|
||||||
assertEquals("type word type dot then press the .com key",
|
assertEquals("type word type dot then press the .com key",
|
||||||
EXPECTED_RESULT, mTextView.getText().toString());
|
EXPECTED_RESULT, mTextView.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add some tests for non-BMP characters
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue