From 9159b9953d857de83ae2f90a121fcd259f5ee01d Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 3 Feb 2012 16:05:48 +0900 Subject: [PATCH] Fix the auto-composer to support supplementary chars Change-Id: I61ff218ae2ca4eb443a370e581b677755258670a --- .../inputmethod/latin/WordComposer.java | 35 ++++++++++++------- .../inputmethod/latin/InputLogicTests.java | 21 +++++++++-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index f418968b5..a1a329a8d 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -90,11 +90,11 @@ public class WordComposer { * @return the number of keystrokes */ public final int size() { - return mTypedWord.length(); + return mCodes.size(); } 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 */ public void add(int primaryCode, int[] codes, int x, int y) { - final int newIndex = size(); - mTypedWord.append((char) primaryCode); + final int newIndex = mCodes.size(); + mTypedWord.appendCodePoint(primaryCode); correctPrimaryJuxtapos(primaryCode, codes); mCodes.add(codes); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { @@ -171,8 +171,8 @@ public class WordComposer { final KeyDetector keyDetector) { reset(); final int length = word.length(); - for (int i = 0; i < length; ++i) { - int codePoint = word.charAt(i); + for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) { + int codePoint = Character.codePointAt(word, i); addKeyInfo(codePoint, keyboard, keyDetector); } } @@ -207,16 +207,25 @@ public class WordComposer { * Delete the last keystroke as a result of hitting backspace. */ public void deleteLast() { - final int size = size(); + final int size = mCodes.size(); if (size > 0) { - final int lastPos = size - 1; - char lastChar = mTypedWord.charAt(lastPos); - mCodes.remove(lastPos); - // TODO: This crashes and catches fire if the code point doesn't fit a char - mTypedWord.deleteCharAt(lastPos); + mCodes.remove(size - 1); + // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs + final int stringBuilderLength = mTypedWord.length(); + if (stringBuilderLength < size) { + 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 (size() == 0) { + // We may have deleted the last one. + if (0 == mCodes.size()) { mIsFirstCharCapitalized = false; } if (mTrailingSingleQuotesCount > 0) { diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index 2cecc9d8d..9d886da3b 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -159,11 +159,26 @@ public class InputLogicTests extends ServiceTestCase { } public void testPickSuggestionThenBackspace() { - final String WORD_TO_TYPE = "tgis"; + final String WORD_TO_TYPE = "this"; + final String EXPECTED_RESULT = "this"; type(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); - 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()); } @@ -379,4 +394,6 @@ public class InputLogicTests extends ServiceTestCase { assertEquals("type word type dot then press the .com key", EXPECTED_RESULT, mTextView.getText().toString()); } + + // TODO: Add some tests for non-BMP characters }