From 0ba6bcb16dfe8cc442f906f631ff543ad999f5c8 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Wed, 27 Aug 2014 15:07:28 +0000 Subject: [PATCH] Revert "Straighten the dead char implementation." This reverts commit 5ef447aeea97c755008785b36468715922b7ccc1. Reverting because this broke a bunch of unit tests -- https://sponge.corp.google.com/target?id=b6439742-099e-46cb-8f00-d0c602a4d9bb&target=com.google.android.inputmethod.latin.tests&searchFor=&show=FAILED&sortBy=STATUS Change-Id: Ibbd9e11372993f62e630fd9da37158ffcf47c17a --- .../inputmethod/event/DeadKeyCombiner.java | 265 ++---------------- .../android/inputmethod/latin/Constants.java | 3 - .../inputmethod/latin/utils/StringUtils.java | 4 +- .../latin/InputLogicTestsDeadKeys.java | 215 -------------- 4 files changed, 24 insertions(+), 463 deletions(-) delete mode 100644 tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java index 88c70630d..4f3f4d25f 100644 --- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java +++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java @@ -17,12 +17,10 @@ package com.android.inputmethod.event; import android.text.TextUtils; -import android.util.SparseIntArray; import android.view.KeyCharacterMap; import com.android.inputmethod.latin.Constants; -import java.text.Normalizer; import java.util.ArrayList; import javax.annotation.Nonnull; @@ -31,209 +29,9 @@ import javax.annotation.Nonnull; * A combiner that handles dead keys. */ public class DeadKeyCombiner implements Combiner { - - private static class Data { - // This class data taken from KeyCharacterMap.java. - - /* Characters used to display placeholders for dead keys. */ - private static final int ACCENT_ACUTE = '\u00B4'; - private static final int ACCENT_BREVE = '\u02D8'; - private static final int ACCENT_CARON = '\u02C7'; - private static final int ACCENT_CEDILLA = '\u00B8'; - private static final int ACCENT_CIRCUMFLEX = '\u02C6'; - private static final int ACCENT_COMMA_ABOVE = '\u1FBD'; - private static final int ACCENT_COMMA_ABOVE_RIGHT = '\u02BC'; - private static final int ACCENT_DOT_ABOVE = '\u02D9'; - private static final int ACCENT_DOT_BELOW = Constants.CODE_PERIOD; // approximate - private static final int ACCENT_DOUBLE_ACUTE = '\u02DD'; - private static final int ACCENT_GRAVE = '\u02CB'; - private static final int ACCENT_HOOK_ABOVE = '\u02C0'; - private static final int ACCENT_HORN = Constants.CODE_SINGLE_QUOTE; // approximate - private static final int ACCENT_MACRON = '\u00AF'; - private static final int ACCENT_MACRON_BELOW = '\u02CD'; - private static final int ACCENT_OGONEK = '\u02DB'; - private static final int ACCENT_REVERSED_COMMA_ABOVE = '\u02BD'; - private static final int ACCENT_RING_ABOVE = '\u02DA'; - private static final int ACCENT_STROKE = Constants.CODE_DASH; // approximate - private static final int ACCENT_TILDE = '\u02DC'; - private static final int ACCENT_TURNED_COMMA_ABOVE = '\u02BB'; - private static final int ACCENT_UMLAUT = '\u00A8'; - private static final int ACCENT_VERTICAL_LINE_ABOVE = '\u02C8'; - private static final int ACCENT_VERTICAL_LINE_BELOW = '\u02CC'; - - /* Legacy dead key display characters used in previous versions of the API (before L) - * We still support these characters by mapping them to their non-legacy version. */ - private static final int ACCENT_GRAVE_LEGACY = Constants.CODE_GRAVE_ACCENT; - private static final int ACCENT_CIRCUMFLEX_LEGACY = Constants.CODE_CIRCUMFLEX_ACCENT; - private static final int ACCENT_TILDE_LEGACY = Constants.CODE_TILDE; - - /** - * Maps Unicode combining diacritical to display-form dead key. - */ - private static final SparseIntArray sCombiningToAccent = new SparseIntArray(); - private static final SparseIntArray sAccentToCombining = new SparseIntArray(); - static { - // U+0300: COMBINING GRAVE ACCENT - addCombining('\u0300', ACCENT_GRAVE); - // U+0301: COMBINING ACUTE ACCENT - addCombining('\u0301', ACCENT_ACUTE); - // U+0302: COMBINING CIRCUMFLEX ACCENT - addCombining('\u0302', ACCENT_CIRCUMFLEX); - // U+0303: COMBINING TILDE - addCombining('\u0303', ACCENT_TILDE); - // U+0304: COMBINING MACRON - addCombining('\u0304', ACCENT_MACRON); - // U+0306: COMBINING BREVE - addCombining('\u0306', ACCENT_BREVE); - // U+0307: COMBINING DOT ABOVE - addCombining('\u0307', ACCENT_DOT_ABOVE); - // U+0308: COMBINING DIAERESIS - addCombining('\u0308', ACCENT_UMLAUT); - // U+0309: COMBINING HOOK ABOVE - addCombining('\u0309', ACCENT_HOOK_ABOVE); - // U+030A: COMBINING RING ABOVE - addCombining('\u030A', ACCENT_RING_ABOVE); - // U+030B: COMBINING DOUBLE ACUTE ACCENT - addCombining('\u030B', ACCENT_DOUBLE_ACUTE); - // U+030C: COMBINING CARON - addCombining('\u030C', ACCENT_CARON); - // U+030D: COMBINING VERTICAL LINE ABOVE - addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE); - // U+030E: COMBINING DOUBLE VERTICAL LINE ABOVE - //addCombining('\u030E', ACCENT_DOUBLE_VERTICAL_LINE_ABOVE); - // U+030F: COMBINING DOUBLE GRAVE ACCENT - //addCombining('\u030F', ACCENT_DOUBLE_GRAVE); - // U+0310: COMBINING CANDRABINDU - //addCombining('\u0310', ACCENT_CANDRABINDU); - // U+0311: COMBINING INVERTED BREVE - //addCombining('\u0311', ACCENT_INVERTED_BREVE); - // U+0312: COMBINING TURNED COMMA ABOVE - addCombining('\u0312', ACCENT_TURNED_COMMA_ABOVE); - // U+0313: COMBINING COMMA ABOVE - addCombining('\u0313', ACCENT_COMMA_ABOVE); - // U+0314: COMBINING REVERSED COMMA ABOVE - addCombining('\u0314', ACCENT_REVERSED_COMMA_ABOVE); - // U+0315: COMBINING COMMA ABOVE RIGHT - addCombining('\u0315', ACCENT_COMMA_ABOVE_RIGHT); - // U+031B: COMBINING HORN - addCombining('\u031B', ACCENT_HORN); - // U+0323: COMBINING DOT BELOW - addCombining('\u0323', ACCENT_DOT_BELOW); - // U+0326: COMBINING COMMA BELOW - //addCombining('\u0326', ACCENT_COMMA_BELOW); - // U+0327: COMBINING CEDILLA - addCombining('\u0327', ACCENT_CEDILLA); - // U+0328: COMBINING OGONEK - addCombining('\u0328', ACCENT_OGONEK); - // U+0329: COMBINING VERTICAL LINE BELOW - addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW); - // U+0331: COMBINING MACRON BELOW - addCombining('\u0331', ACCENT_MACRON_BELOW); - // U+0335: COMBINING SHORT STROKE OVERLAY - addCombining('\u0335', ACCENT_STROKE); - // U+0342: COMBINING GREEK PERISPOMENI - //addCombining('\u0342', ACCENT_PERISPOMENI); - // U+0344: COMBINING GREEK DIALYTIKA TONOS - //addCombining('\u0344', ACCENT_DIALYTIKA_TONOS); - // U+0345: COMBINING GREEK YPOGEGRAMMENI - //addCombining('\u0345', ACCENT_YPOGEGRAMMENI); - - // One-way mappings to equivalent preferred accents. - // U+0340: COMBINING GRAVE TONE MARK - sCombiningToAccent.append('\u0340', ACCENT_GRAVE); - // U+0341: COMBINING ACUTE TONE MARK - sCombiningToAccent.append('\u0341', ACCENT_ACUTE); - // U+0343: COMBINING GREEK KORONIS - sCombiningToAccent.append('\u0343', ACCENT_COMMA_ABOVE); - - // One-way legacy mappings to preserve compatibility with older applications. - // U+0300: COMBINING GRAVE ACCENT - sAccentToCombining.append(ACCENT_GRAVE_LEGACY, '\u0300'); - // U+0302: COMBINING CIRCUMFLEX ACCENT - sAccentToCombining.append(ACCENT_CIRCUMFLEX_LEGACY, '\u0302'); - // U+0303: COMBINING TILDE - sAccentToCombining.append(ACCENT_TILDE_LEGACY, '\u0303'); - } - - private static void addCombining(int combining, int accent) { - sCombiningToAccent.append(combining, accent); - sAccentToCombining.append(accent, combining); - } - - // Caution! This may only contain chars, not supplementary code points. It's unlikely - // it will ever need to, but if it does we'll have to change this - private static final SparseIntArray sNonstandardDeadCombinations = new SparseIntArray(); - static { - // Non-standard decompositions. - // Stroke modifier for Finnish multilingual keyboard and others. - // U+0110: LATIN CAPITAL LETTER D WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'D', '\u0110'); - // U+01E4: LATIN CAPITAL LETTER G WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'G', '\u01e4'); - // U+0126: LATIN CAPITAL LETTER H WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'H', '\u0126'); - // U+0197: LATIN CAPITAL LETTER I WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'I', '\u0197'); - // U+0141: LATIN CAPITAL LETTER L WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'L', '\u0141'); - // U+00D8: LATIN CAPITAL LETTER O WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'O', '\u00d8'); - // U+0166: LATIN CAPITAL LETTER T WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'T', '\u0166'); - // U+0111: LATIN SMALL LETTER D WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'd', '\u0111'); - // U+01E5: LATIN SMALL LETTER G WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'g', '\u01e5'); - // U+0127: LATIN SMALL LETTER H WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'h', '\u0127'); - // U+0268: LATIN SMALL LETTER I WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'i', '\u0268'); - // U+0142: LATIN SMALL LETTER L WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'l', '\u0142'); - // U+00F8: LATIN SMALL LETTER O WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 'o', '\u00f8'); - // U+0167: LATIN SMALL LETTER T WITH STROKE - addNonStandardDeadCombination(ACCENT_STROKE, 't', '\u0167'); - } - - private static void addNonStandardDeadCombination(final int deadCodePoint, - final int spacingCodePoint, final int result) { - final int combination = (deadCodePoint << 16) | spacingCodePoint; - sNonstandardDeadCombinations.put(combination, result); - } - - public static final int NOT_A_CHAR = 0; - public static final int BITS_TO_SHIFT_DEAD_CODE_POINT_FOR_NON_STANDARD_COMBINATION = 16; - // Get a non-standard combination - public static char getNonstandardCombination(final int deadCodePoint, - final int spacingCodePoint) { - final int combination = spacingCodePoint | - (deadCodePoint << BITS_TO_SHIFT_DEAD_CODE_POINT_FOR_NON_STANDARD_COMBINATION); - return (char)sNonstandardDeadCombinations.get(combination, NOT_A_CHAR); - } - } - // TODO: make this a list of events instead final StringBuilder mDeadSequence = new StringBuilder(); - @Nonnull - private Event createEventChainFromSequence(final @Nonnull CharSequence text, - final Event originalEvent) { - if (text.length() <= 0) { - return originalEvent; - } else { - Event lastEvent = null; - int codePoint = 0; - for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) { - codePoint = Character.codePointBefore(text, i); - final Event thisEvent = Event.createHardwareKeypressEvent(codePoint, - originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */); - lastEvent = thisEvent; - } - return lastEvent; - } - } - @Override @Nonnull public Event processEvent(final ArrayList previousEvents, final Event event) { @@ -249,48 +47,29 @@ public class DeadKeyCombiner implements Combiner { // simply returns the event as is. The majority of events will go through this path. return event; } else { - if (Character.isWhitespace(event.mCodePoint) - || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) { - // When whitespace or twice the same dead key, we should output the dead sequence - // as is. - final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(), - event); - mDeadSequence.setLength(0); - return resultEvent; - } else if (event.isFunctionalKeyEvent()) { - if (Constants.CODE_DELETE == event.mKeyCode) { - // Remove the last code point - final int trimIndex = mDeadSequence.length() - Character.charCount( - mDeadSequence.codePointBefore(mDeadSequence.length())); - mDeadSequence.setLength(trimIndex); - return Event.createConsumedEvent(event); - } else { - return event; - } - } else if (event.isDead()) { - mDeadSequence.appendCodePoint(event.mCodePoint); - return Event.createConsumedEvent(event); + // TODO: Allow combining for several dead chars rather than only the first one. + // The framework doesn't know how to do this now. + final int deadCodePoint = mDeadSequence.codePointAt(0); + mDeadSequence.setLength(0); + final int resultingCodePoint = + KeyCharacterMap.getDeadChar(deadCodePoint, event.mCodePoint); + if (0 == resultingCodePoint) { + // We can't combine both characters. We need to commit the dead key as a separate + // character, and the next char too unless it's a space (because as a special case, + // dead key + space should result in only the dead key being committed - that's + // how dead keys work). + // If the event is a space, we should commit the dead char alone, but if it's + // not, we need to commit both. + // TODO: this is not necessarily triggered by hardware key events, so it's not + // a good idea to masquerade as one. This should be typed as a software + // composite event or something. + return Event.createHardwareKeypressEvent(deadCodePoint, event.mKeyCode, + Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */, + false /* isKeyRepeat */); } else { - // Combine normally. - final StringBuilder sb = new StringBuilder(); - sb.appendCodePoint(event.mCodePoint); - int codePointIndex = 0; - while (codePointIndex < mDeadSequence.length()) { - final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex); - final char replacementSpacingChar = - Data.getNonstandardCombination(deadCodePoint, event.mCodePoint); - if (Data.NOT_A_CHAR != replacementSpacingChar) { - sb.setCharAt(0, replacementSpacingChar); - } else { - final int combining = Data.sAccentToCombining.get(deadCodePoint); - sb.appendCodePoint(0 == combining ? deadCodePoint : combining); - } - codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1; - } - final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC); - final Event resultEvent = createEventChainFromSequence(normalizedString, event); - mDeadSequence.setLength(0); - return resultEvent; + // We could combine the characters. + return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode, + null /* next */, false /* isKeyRepeat */); } } } diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index 729481326..43af66eb7 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -217,9 +217,6 @@ public final class Constants { public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿ public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡ - public static final int CODE_GRAVE_ACCENT = '`'; - public static final int CODE_CIRCUMFLEX_ACCENT = '^'; - public static final int CODE_TILDE = '~'; public static final String REGEXP_PERIOD = "\\."; public static final String STRING_SPACE = " "; diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index 55557de9d..38f0b3fee 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -41,9 +41,9 @@ public final class StringUtils { // This utility class is not publicly instantiable. } - public static int codePointCount(final CharSequence text) { + public static int codePointCount(final String text) { if (TextUtils.isEmpty(text)) return 0; - return Character.codePointCount(text, 0, text.length()); + return text.codePointCount(0, text.length()); } public static String newSingleCodePointString(int codePoint) { diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java deleted file mode 100644 index afe7dbe70..000000000 --- a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -import android.test.suitebuilder.annotation.LargeTest; - -import com.android.inputmethod.event.Event; - -import java.util.ArrayList; - -@LargeTest -public class InputLogicTestsDeadKeys extends InputTestsBase { - // A helper class for readability - private static class EventList extends ArrayList { - public EventList addCodePoint(final int codePoint, final boolean isDead) { - final Event event; - if (isDead) { - event = Event.createDeadEvent(codePoint, Event.NOT_A_KEY_CODE, null /* next */); - } else { - event = Event.createSoftwareKeypressEvent(codePoint, Event.NOT_A_KEY_CODE, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, - false /* isKeyRepeat */); - } - add(event); - return this; - } - - public EventList addKey(final int keyCode) { - add(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT, keyCode, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, - false /* isKeyRepeat */)); - return this; - } - } - - public void testDeadCircumflexSimple() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final String EXPECTED_RESULT = "aê"; - final EventList events = new EventList() - .addCodePoint('a', false) - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true) - .addCodePoint('e', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("simple dead circumflex", EXPECTED_RESULT, mEditText.getText().toString()); - } - - public void testDeadCircumflexBackspace() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final String EXPECTED_RESULT = "ae"; - final EventList events = new EventList() - .addCodePoint('a', false) - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true) - .addKey(Constants.CODE_DELETE) - .addCodePoint('e', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead circumflex backspace", EXPECTED_RESULT, mEditText.getText().toString()); - } - - public void testDeadCircumflexFeedback() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final String EXPECTED_RESULT = "a\u02C6"; - final EventList events = new EventList() - .addCodePoint('a', false) - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead circumflex gives feedback", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDeadDiaeresisSpace() { - final int MODIFIER_LETTER_DIAERESIS = 0xA8; - final String EXPECTED_RESULT = "a\u00A8e\u00A8i"; - final EventList events = new EventList() - .addCodePoint('a', false) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addCodePoint(Constants.CODE_SPACE, false) - .addCodePoint('e', false) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addCodePoint(Constants.CODE_ENTER, false) - .addCodePoint('i', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead diaeresis space commits the dead char", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDeadAcuteLetterBackspace() { - final int MODIFIER_LETTER_ACUTE = 0xB4; - final String EXPECTED_RESULT1 = "aá"; - final String EXPECTED_RESULT2 = "a"; - final EventList events = new EventList() - .addCodePoint('a', false) - .addCodePoint(MODIFIER_LETTER_ACUTE, true) - .addCodePoint('a', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead acute on a typed", EXPECTED_RESULT1, mEditText.getText().toString()); - mLatinIME.onEvent(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT, - Constants.CODE_DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, - false /* isKeyRepeat */)); - assertEquals("a with acute deleted", EXPECTED_RESULT2, mEditText.getText().toString()); - } - - public void testFinnishStroke() { - final int MODIFIER_LETTER_STROKE = '-'; - final String EXPECTED_RESULT = "x\u0110\u0127"; - final EventList events = new EventList() - .addCodePoint('x', false) - .addCodePoint(MODIFIER_LETTER_STROKE, true) - .addCodePoint('D', false) - .addCodePoint(MODIFIER_LETTER_STROKE, true) - .addCodePoint('h', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("Finnish dead stroke", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDoubleDeadOgonek() { - final int MODIFIER_LETTER_OGONEK = 0x02DB; - final String EXPECTED_RESULT = "txǫs\u02DBfk"; - final EventList events = new EventList() - .addCodePoint('t', false) - .addCodePoint('x', false) - .addCodePoint(MODIFIER_LETTER_OGONEK, true) - .addCodePoint('o', false) - .addCodePoint('s', false) - .addCodePoint(MODIFIER_LETTER_OGONEK, true) - .addCodePoint(MODIFIER_LETTER_OGONEK, true) - .addCodePoint('f', false) - .addCodePoint(MODIFIER_LETTER_OGONEK, true) - .addCodePoint(MODIFIER_LETTER_OGONEK, true) - .addKey(Constants.CODE_DELETE) - .addCodePoint('k', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("double dead ogonek, and backspace", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDeadCircumflexDeadDiaeresis() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final int MODIFIER_LETTER_DIAERESIS = 0xA8; - final String EXPECTED_RESULT = "r̂̈"; - - final EventList events = new EventList() - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addCodePoint('r', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("both circumflex and diaeresis on r", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDeadCircumflexDeadDiaeresisBackspace() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final int MODIFIER_LETTER_DIAERESIS = 0xA8; - final String EXPECTED_RESULT = "û"; - - final EventList events = new EventList() - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addKey(Constants.CODE_DELETE) - .addCodePoint('u', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead circumflex, dead diaeresis, backspace, u", EXPECTED_RESULT, - mEditText.getText().toString()); - } - - public void testDeadCircumflexDoubleDeadDiaeresisBackspace() { - final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6; - final int MODIFIER_LETTER_DIAERESIS = 0xA8; - final String EXPECTED_RESULT = "\u02C6u"; - - final EventList events = new EventList() - .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addCodePoint(MODIFIER_LETTER_DIAERESIS, true) - .addKey(Constants.CODE_DELETE) - .addCodePoint('u', false); - for (final Event event : events) { - mLatinIME.onEvent(event); - } - assertEquals("dead circumflex, double dead diaeresis, backspace, u", EXPECTED_RESULT, - mEditText.getText().toString()); - } -}