diff options
author | 2024-12-16 21:45:41 -0500 | |
---|---|---|
committer | 2025-01-11 14:17:35 -0500 | |
commit | e9a0e66716dab4dd3184d009d8920de1961efdfa (patch) | |
tree | 02dcc096643d74645bf28459c2834c3d4a2ad7f2 /common/src/com/android/inputmethod/latin | |
parent | fb3b9360d70596d7e921de8bf7d3ca99564a077e (diff) | |
download | latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.gz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.xz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.zip |
Rename to Kelar Keyboard (org.kelar.inputmethod.latin)
Diffstat (limited to 'common/src/com/android/inputmethod/latin')
12 files changed, 0 insertions, 2093 deletions
diff --git a/common/src/com/android/inputmethod/latin/common/CodePointUtils.java b/common/src/com/android/inputmethod/latin/common/CodePointUtils.java deleted file mode 100644 index ec59de850..000000000 --- a/common/src/com/android/inputmethod/latin/common/CodePointUtils.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2013 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import java.util.Random; - -import javax.annotation.Nonnull; - -// Utility methods related with code points used for tests. -// TODO: Figure out where this class should be. -@UsedForTesting -public class CodePointUtils { - private CodePointUtils() { - // This utility class is not publicly instantiable. - } - - public static final int[] LATIN_ALPHABETS_LOWER = { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - 0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */, - 0x00E1 /* LATIN SMALL LETTER A WITH ACUTE */, - 0x00E2 /* LATIN SMALL LETTER A WITH CIRCUMFLEX */, - 0x00E3 /* LATIN SMALL LETTER A WITH TILDE */, - 0x00E4 /* LATIN SMALL LETTER A WITH DIAERESIS */, - 0x00E5 /* LATIN SMALL LETTER A WITH RING ABOVE */, - 0x00E6 /* LATIN SMALL LETTER AE */, - 0x00E7 /* LATIN SMALL LETTER C WITH CEDILLA */, - 0x00E8 /* LATIN SMALL LETTER E WITH GRAVE */, - 0x00E9 /* LATIN SMALL LETTER E WITH ACUTE */, - 0x00EA /* LATIN SMALL LETTER E WITH CIRCUMFLEX */, - 0x00EB /* LATIN SMALL LETTER E WITH DIAERESIS */, - 0x00EC /* LATIN SMALL LETTER I WITH GRAVE */, - 0x00ED /* LATIN SMALL LETTER I WITH ACUTE */, - 0x00EE /* LATIN SMALL LETTER I WITH CIRCUMFLEX */, - 0x00EF /* LATIN SMALL LETTER I WITH DIAERESIS */, - 0x00F0 /* LATIN SMALL LETTER ETH */, - 0x00F1 /* LATIN SMALL LETTER N WITH TILDE */, - 0x00F2 /* LATIN SMALL LETTER O WITH GRAVE */, - 0x00F3 /* LATIN SMALL LETTER O WITH ACUTE */, - 0x00F4 /* LATIN SMALL LETTER O WITH CIRCUMFLEX */, - 0x00F5 /* LATIN SMALL LETTER O WITH TILDE */, - 0x00F6 /* LATIN SMALL LETTER O WITH DIAERESIS */, - 0x00F7 /* LATIN SMALL LETTER O WITH STROKE */, - 0x00F9 /* LATIN SMALL LETTER U WITH GRAVE */, - 0x00FA /* LATIN SMALL LETTER U WITH ACUTE */, - 0x00FB /* LATIN SMALL LETTER U WITH CIRCUMFLEX */, - 0x00FC /* LATIN SMALL LETTER U WITH DIAERESIS */, - 0x00FD /* LATIN SMALL LETTER Y WITH ACUTE */, - 0x00FE /* LATIN SMALL LETTER THORN */, - 0x00FF /* LATIN SMALL LETTER Y WITH DIAERESIS */ - }; - - @UsedForTesting - @Nonnull - public static int[] generateCodePointSet(final int codePointSetSize, - @Nonnull final Random random) { - final int[] codePointSet = new int[codePointSetSize]; - for (int i = codePointSet.length - 1; i >= 0; ) { - final int r = Math.abs(random.nextInt()); - if (r < 0) { - continue; - } - // Don't insert 0~0x20, but insert any other code point. - // Code points are in the range 0~0x10FFFF. - final int candidateCodePoint = 0x20 + r % (Character.MAX_CODE_POINT - 0x20); - // Code points between MIN_ and MAX_SURROGATE are not valid on their own. - if (candidateCodePoint >= Character.MIN_SURROGATE - && candidateCodePoint <= Character.MAX_SURROGATE) { - continue; - } - codePointSet[i] = candidateCodePoint; - --i; - } - return codePointSet; - } - - /** - * Generates a random word. - */ - @UsedForTesting - @Nonnull - public static String generateWord(@Nonnull final Random random, - @Nonnull final int[] codePointSet) { - final StringBuilder builder = new StringBuilder(); - // 8 * 4 = 32 chars max, but we do it the following way so as to bias the random toward - // longer words. This should be closer to natural language, and more importantly, it will - // exercise the algorithms in dicttool much more. - final int count = 1 + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5) - + (Math.abs(random.nextInt()) % 5); - while (builder.length() < count) { - builder.appendCodePoint(codePointSet[Math.abs(random.nextInt()) % codePointSet.length]); - } - return builder.toString(); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/CollectionUtils.java b/common/src/com/android/inputmethod/latin/common/CollectionUtils.java deleted file mode 100644 index 80fae5f51..000000000 --- a/common/src/com/android/inputmethod/latin/common/CollectionUtils.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Utility methods for working with collections. - */ -public final class CollectionUtils { - private CollectionUtils() { - // This utility class is not publicly instantiable. - } - - /** - * Converts a sub-range of the given array to an ArrayList of the appropriate type. - * @param array Array to be converted. - * @param start First index inclusive to be converted. - * @param end Last index exclusive to be converted. - * @throws IllegalArgumentException if start or end are out of range or start > end. - */ - @Nonnull - public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start, - final int end) { - if (start < 0 || start > end || end > array.length) { - throw new IllegalArgumentException("Invalid start: " + start + " end: " + end - + " with array.length: " + array.length); - } - - final ArrayList<E> list = new ArrayList<>(end - start); - for (int i = start; i < end; i++) { - list.add(array[i]); - } - return list; - } - - /** - * Tests whether c contains no elements, true if c is null or c is empty. - * @param c Collection to test. - * @return Whether c contains no elements. - */ - @UsedForTesting - public static boolean isNullOrEmpty(@Nullable final Collection c) { - return c == null || c.isEmpty(); - } - - /** - * Tests whether map contains no elements, true if map is null or map is empty. - * @param map Map to test. - * @return Whether map contains no elements. - */ - @UsedForTesting - public static boolean isNullOrEmpty(@Nullable final Map map) { - return map == null || map.isEmpty(); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/ComposedData.java b/common/src/com/android/inputmethod/latin/common/ComposedData.java deleted file mode 100644 index 7f0966050..000000000 --- a/common/src/com/android/inputmethod/latin/common/ComposedData.java +++ /dev/null @@ -1,66 +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.common; - -import javax.annotation.Nonnull; - -/** - * An immutable class that encapsulates a snapshot of word composition data. - */ -public class ComposedData { - @Nonnull - public final InputPointers mInputPointers; - public final boolean mIsBatchMode; - @Nonnull - public final String mTypedWord; - - public ComposedData(@Nonnull final InputPointers inputPointers, final boolean isBatchMode, - @Nonnull final String typedWord) { - mInputPointers = inputPointers; - mIsBatchMode = isBatchMode; - mTypedWord = typedWord; - } - - /** - * Copy the code points in the typed word to a destination array of ints. - * - * If the array is too small to hold the code points in the typed word, nothing is copied and - * -1 is returned. - * - * @param destination the array of ints. - * @return the number of copied code points. - */ - public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( - @Nonnull final int[] destination) { - // lastIndex is exclusive - final int lastIndex = mTypedWord.length() - - StringUtils.getTrailingSingleQuotesCount(mTypedWord); - if (lastIndex <= 0) { - // The string is empty or contains only single quotes. - return 0; - } - - // The following function counts the number of code points in the text range which begins - // at index 0 and extends to the character at lastIndex. - final int codePointSize = Character.codePointCount(mTypedWord, 0, lastIndex); - if (codePointSize > destination.length) { - return -1; - } - return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWord, 0, - lastIndex, true /* downCase */); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/Constants.java b/common/src/com/android/inputmethod/latin/common/Constants.java deleted file mode 100644 index b491c8cfd..000000000 --- a/common/src/com/android/inputmethod/latin/common/Constants.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import javax.annotation.Nonnull; - -public final class Constants { - - public static final class Color { - /** - * The alpha value for fully opaque. - */ - public final static int ALPHA_OPAQUE = 255; - } - - public static final class ImeOption { - /** - * The private IME option used to indicate that no microphone should be shown for a given - * text field. For instance, this is specified by the search dialog when the dialog is - * already showing a voice search button. - * - * @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed. - */ - @SuppressWarnings("dep-ann") - public static final String NO_MICROPHONE_COMPAT = "nm"; - - /** - * The private IME option used to indicate that no microphone should be shown for a given - * text field. For instance, this is specified by the search dialog when the dialog is - * already showing a voice search button. - */ - public static final String NO_MICROPHONE = "noMicrophoneKey"; - - /** - * The private IME option used to indicate that no settings key should be shown for a given - * text field. - */ - public static final String NO_SETTINGS_KEY = "noSettingsKey"; - - /** - * The private IME option used to indicate that the given text field needs ASCII code points - * input. - * - * @deprecated Use EditorInfo#IME_FLAG_FORCE_ASCII. - */ - @SuppressWarnings("dep-ann") - public static final String FORCE_ASCII = "forceAscii"; - - /** - * The private IME option used to suppress the floating gesture preview for a given text - * field. This overrides the corresponding keyboard settings preference. - * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled} - */ - public static final String NO_FLOATING_GESTURE_PREVIEW = "noGestureFloatingPreview"; - - private ImeOption() { - // This utility class is not publicly instantiable. - } - } - - public static final class Subtype { - /** - * The subtype mode used to indicate that the subtype is a keyboard. - */ - public static final String KEYBOARD_MODE = "keyboard"; - - public static final class ExtraValue { - /** - * The subtype extra value used to indicate that this subtype is capable of - * entering ASCII characters. - */ - public static final String ASCII_CAPABLE = "AsciiCapable"; - - /** - * The subtype extra value used to indicate that this subtype is enabled - * when the default subtype is not marked as ascii capable. - */ - public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = - "EnabledWhenDefaultIsNotAsciiCapable"; - - /** - * The subtype extra value used to indicate that this subtype is capable of - * entering emoji characters. - */ - public static final String EMOJI_CAPABLE = "EmojiCapable"; - - /** - * The subtype extra value used to indicate that this subtype requires a network - * connection to work. - */ - public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; - - /** - * The subtype extra value used to indicate that the display name of this subtype - * contains a "%s" for printf-like replacement and it should be replaced by - * this extra value. - * This extra value is supported on JellyBean and later. - */ - public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME = - "UntranslatableReplacementStringInSubtypeName"; - - /** - * The subtype extra value used to indicate this subtype keyboard layout set name. - * This extra value is private to LatinIME. - */ - public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet"; - - /** - * The subtype extra value used to indicate that this subtype is an additional subtype - * that the user defined. This extra value is private to LatinIME. - */ - public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype"; - - /** - * The subtype extra value used to specify the combining rules. - */ - public static final String COMBINING_RULES = "CombiningRules"; - - private ExtraValue() { - // This utility class is not publicly instantiable. - } - } - - private Subtype() { - // This utility class is not publicly instantiable. - } - } - - public static final class TextUtils { - /** - * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize - * characters. This value may be used with - * {@link android.text.TextUtils#CAP_MODE_CHARACTERS}, - * {@link android.text.TextUtils#CAP_MODE_WORDS}, and - * {@link android.text.TextUtils#CAP_MODE_SENTENCES}. - */ - // TODO: Straighten this out. It's bizarre to have to use android.text.TextUtils.CAP_MODE_* - // except for OFF that is in Constants.TextUtils. - public static final int CAP_MODE_OFF = 0; - - private TextUtils() { - // This utility class is not publicly instantiable. - } - } - - public static final int NOT_A_CODE = -1; - public static final int NOT_A_CURSOR_POSITION = -1; - // TODO: replace the following constants with state in InputTransaction? - public static final int NOT_A_COORDINATE = -1; - public static final int SUGGESTION_STRIP_COORDINATE = -2; - public static final int EXTERNAL_KEYBOARD_COORDINATE = -4; - - // A hint on how many characters to cache from the TextView. A good value of this is given by - // how many characters we need to be able to almost always find the caps mode. - public static final int EDITOR_CONTENTS_CACHE_SIZE = 1024; - // How many characters we accept for the recapitalization functionality. This needs to be - // large enough for all reasonable purposes, but avoid purposeful attacks. 100k sounds about - // right for this. - public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100; - - // Key events coming any faster than this are long-presses. - public static final int LONG_PRESS_MILLISECONDS = 200; - // TODO: Set this value appropriately. - public static final int GET_SUGGESTED_WORDS_TIMEOUT = 200; - // How many continuous deletes at which to start deleting at a higher speed. - public static final int DELETE_ACCELERATE_AT = 20; - - public static final String WORD_SEPARATOR = " "; - - public static boolean isValidCoordinate(final int coordinate) { - // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE}, - // and {@link SPELL_CHECKER_COORDINATE}. - return coordinate >= 0; - } - - /** - * Custom request code used in - * {@link com.android.inputmethod.keyboard.KeyboardActionListener#onCustomRequest(int)}. - */ - // The code to show input method picker. - public static final int CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER = 1; - - /** - * Some common keys code. Must be positive. - */ - public static final int CODE_ENTER = '\n'; - public static final int CODE_TAB = '\t'; - public static final int CODE_SPACE = ' '; - public static final int CODE_PERIOD = '.'; - public static final int CODE_COMMA = ','; - public static final int CODE_DASH = '-'; - public static final int CODE_SINGLE_QUOTE = '\''; - public static final int CODE_DOUBLE_QUOTE = '"'; - public static final int CODE_SLASH = '/'; - public static final int CODE_BACKSLASH = '\\'; - public static final int CODE_VERTICAL_BAR = '|'; - public static final int CODE_COMMERCIAL_AT = '@'; - public static final int CODE_PLUS = '+'; - public static final int CODE_PERCENT = '%'; - public static final int CODE_CLOSING_PARENTHESIS = ')'; - public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; - public static final int CODE_CLOSING_CURLY_BRACKET = '}'; - 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 = " "; - - /** - * Special keys code. Must be negative. - * These should be aligned with constants in - * {@link com.android.inputmethod.keyboard.internal.KeyboardCodesSet}. - */ - public static final int CODE_SHIFT = -1; - public static final int CODE_CAPSLOCK = -2; - public static final int CODE_SWITCH_ALPHA_SYMBOL = -3; - public static final int CODE_OUTPUT_TEXT = -4; - public static final int CODE_DELETE = -5; - public static final int CODE_SETTINGS = -6; - public static final int CODE_SHORTCUT = -7; - public static final int CODE_ACTION_NEXT = -8; - public static final int CODE_ACTION_PREVIOUS = -9; - public static final int CODE_LANGUAGE_SWITCH = -10; - public static final int CODE_EMOJI = -11; - public static final int CODE_SHIFT_ENTER = -12; - public static final int CODE_SYMBOL_SHIFT = -13; - public static final int CODE_ALPHA_FROM_EMOJI = -14; - // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -15; - - public static boolean isLetterCode(final int code) { - return code >= CODE_SPACE; - } - - @Nonnull - public static String printableCode(final int code) { - switch (code) { - case CODE_SHIFT: return "shift"; - case CODE_CAPSLOCK: return "capslock"; - case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; - case CODE_OUTPUT_TEXT: return "text"; - case CODE_DELETE: return "delete"; - case CODE_SETTINGS: return "settings"; - case CODE_SHORTCUT: return "shortcut"; - case CODE_ACTION_NEXT: return "actionNext"; - case CODE_ACTION_PREVIOUS: return "actionPrevious"; - case CODE_LANGUAGE_SWITCH: return "languageSwitch"; - case CODE_EMOJI: return "emoji"; - case CODE_SHIFT_ENTER: return "shiftEnter"; - case CODE_ALPHA_FROM_EMOJI: return "alpha"; - case CODE_UNSPECIFIED: return "unspec"; - case CODE_TAB: return "tab"; - case CODE_ENTER: return "enter"; - case CODE_SPACE: return "space"; - default: - if (code < CODE_SPACE) return String.format("\\u%02X", code); - if (code < 0x100) return String.format("%c", code); - if (code < 0x10000) return String.format("\\u%04X", code); - return String.format("\\U%05X", code); - } - } - - @Nonnull - public static String printableCodes(@Nonnull final int[] codes) { - final StringBuilder sb = new StringBuilder(); - boolean addDelimiter = false; - for (final int code : codes) { - if (code == NOT_A_CODE) break; - if (addDelimiter) sb.append(", "); - sb.append(printableCode(code)); - addDelimiter = true; - } - return "[" + sb + "]"; - } - - /** - * Screen metrics (a.k.a. Device form factor) constants of - * {@link com.android.inputmethod.latin.R.integer#config_screen_metrics}. - */ - public static final int SCREEN_METRICS_SMALL_PHONE = 0; - public static final int SCREEN_METRICS_LARGE_PHONE = 1; - public static final int SCREEN_METRICS_LARGE_TABLET = 2; - public static final int SCREEN_METRICS_SMALL_TABLET = 3; - - @UsedForTesting - public static boolean isPhone(final int screenMetrics) { - return screenMetrics == SCREEN_METRICS_SMALL_PHONE - || screenMetrics == SCREEN_METRICS_LARGE_PHONE; - } - - @UsedForTesting - public static boolean isTablet(final int screenMetrics) { - return screenMetrics == SCREEN_METRICS_SMALL_TABLET - || screenMetrics == SCREEN_METRICS_LARGE_TABLET; - } - - /** - * Default capacity of gesture points container. - * This constant is used by {@link com.android.inputmethod.keyboard.internal.BatchInputArbiter} - * and etc. to preallocate regions that contain gesture event points. - */ - public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128; - - public static final int MAX_IME_DECODER_RESULTS = 20; - public static final int DECODER_SCORE_SCALAR = 1000000; - public static final int DECODER_MAX_SCORE = 1000000000; - - public static final int EVENT_BACKSPACE = 1; - public static final int EVENT_REJECTION = 2; - public static final int EVENT_REVERT = 3; - - private Constants() { - // This utility class is not publicly instantiable. - } -} diff --git a/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java b/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java deleted file mode 100644 index 031662411..000000000 --- a/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import javax.annotation.Nonnull; - -public final class CoordinateUtils { - private static final int INDEX_X = 0; - private static final int INDEX_Y = 1; - private static final int ELEMENT_SIZE = INDEX_Y + 1; - - private CoordinateUtils() { - // This utility class is not publicly instantiable. - } - - @Nonnull - public static int[] newInstance() { - return new int[ELEMENT_SIZE]; - } - - public static int x(@Nonnull final int[] coords) { - return coords[INDEX_X]; - } - - public static int y(@Nonnull final int[] coords) { - return coords[INDEX_Y]; - } - - public static void set(@Nonnull final int[] coords, final int x, final int y) { - coords[INDEX_X] = x; - coords[INDEX_Y] = y; - } - - public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) { - destination[INDEX_X] = source[INDEX_X]; - destination[INDEX_Y] = source[INDEX_Y]; - } - - @Nonnull - public static int[] newCoordinateArray(final int arraySize) { - return new int[ELEMENT_SIZE * arraySize]; - } - - @Nonnull - public static int[] newCoordinateArray(final int arraySize, - final int defaultX, final int defaultY) { - final int[] result = new int[ELEMENT_SIZE * arraySize]; - for (int i = 0; i < arraySize; ++i) { - setXYInArray(result, i, defaultX, defaultY); - } - return result; - } - - public static int xFromArray(@Nonnull final int[] coordsArray, final int index) { - return coordsArray[ELEMENT_SIZE * index + INDEX_X]; - } - - public static int yFromArray(@Nonnull final int[] coordsArray, final int index) { - return coordsArray[ELEMENT_SIZE * index + INDEX_Y]; - } - - @Nonnull - public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) { - final int[] coords = newInstance(); - set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index)); - return coords; - } - - public static void setXYInArray(@Nonnull final int[] coordsArray, final int index, - final int x, final int y) { - final int baseIndex = ELEMENT_SIZE * index; - coordsArray[baseIndex + INDEX_X] = x; - coordsArray[baseIndex + INDEX_Y] = y; - } - - public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index, - @Nonnull final int[] coords) { - setXYInArray(coordsArray, index, x(coords), y(coords)); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/FileUtils.java b/common/src/com/android/inputmethod/latin/common/FileUtils.java deleted file mode 100644 index e593c9932..000000000 --- a/common/src/com/android/inputmethod/latin/common/FileUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 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.common; - -import java.io.File; -import java.io.FilenameFilter; - -/** - * A simple class to help with removing directories recursively. - */ -public class FileUtils { - private static final String TAG = "FileUtils"; - - public static boolean deleteRecursively(final File path) { - if (path.isDirectory()) { - final File[] files = path.listFiles(); - if (files != null) { - for (final File child : files) { - deleteRecursively(child); - } - } - } - return path.delete(); - } - - public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) { - if (!dir.isDirectory()) { - return false; - } - final File[] files = dir.listFiles(fileNameFilter); - if (files == null) { - return false; - } - boolean hasDeletedAllFiles = true; - for (final File file : files) { - if (!deleteRecursively(file)) { - hasDeletedAllFiles = false; - } - } - return hasDeletedAllFiles; - } - - public static boolean renameTo(final File fromFile, final File toFile) { - toFile.delete(); - return fromFile.renameTo(toFile); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/InputPointers.java b/common/src/com/android/inputmethod/latin/common/InputPointers.java deleted file mode 100644 index 4b2ae7e76..000000000 --- a/common/src/com/android/inputmethod/latin/common/InputPointers.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import javax.annotation.Nonnull; - -// TODO: This class is not thread-safe. -public final class InputPointers { - private static final boolean DEBUG_TIME = false; - - private final int mDefaultCapacity; - private final ResizableIntArray mXCoordinates; - private final ResizableIntArray mYCoordinates; - private final ResizableIntArray mPointerIds; - private final ResizableIntArray mTimes; - - public InputPointers(final int defaultCapacity) { - mDefaultCapacity = defaultCapacity; - mXCoordinates = new ResizableIntArray(defaultCapacity); - mYCoordinates = new ResizableIntArray(defaultCapacity); - mPointerIds = new ResizableIntArray(defaultCapacity); - mTimes = new ResizableIntArray(defaultCapacity); - } - - private void fillWithLastTimeUntil(final int index) { - final int fromIndex = mTimes.getLength(); - // Fill the gap with the latest time. - // See {@link #getTime(int)} and {@link #isValidTimeStamps()}. - if (fromIndex <= 0) { - return; - } - final int fillLength = index - fromIndex + 1; - if (fillLength <= 0) { - return; - } - final int lastTime = mTimes.get(fromIndex - 1); - mTimes.fill(lastTime, fromIndex, fillLength); - } - - public void addPointerAt(final int index, final int x, final int y, final int pointerId, - final int time) { - mXCoordinates.addAt(index, x); - mYCoordinates.addAt(index, y); - mPointerIds.addAt(index, pointerId); - if (DEBUG_TIME) { - fillWithLastTimeUntil(index); - } - mTimes.addAt(index, time); - } - - @UsedForTesting - public void addPointer(final int x, final int y, final int pointerId, final int time) { - mXCoordinates.add(x); - mYCoordinates.add(y); - mPointerIds.add(pointerId); - mTimes.add(time); - } - - public void set(@Nonnull final InputPointers ip) { - mXCoordinates.set(ip.mXCoordinates); - mYCoordinates.set(ip.mYCoordinates); - mPointerIds.set(ip.mPointerIds); - mTimes.set(ip.mTimes); - } - - public void copy(@Nonnull final InputPointers ip) { - mXCoordinates.copy(ip.mXCoordinates); - mYCoordinates.copy(ip.mYCoordinates); - mPointerIds.copy(ip.mPointerIds); - mTimes.copy(ip.mTimes); - } - - /** - * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray} - * to the end of this. - * @param pointerId the pointer id of the source. - * @param times the source {@link ResizableIntArray} to read the event times from. - * @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from. - * @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from. - * @param startPos the starting index of the data in {@code times} and etc. - * @param length the number of data to be appended. - */ - public void append(final int pointerId, @Nonnull final ResizableIntArray times, - @Nonnull final ResizableIntArray xCoordinates, - @Nonnull final ResizableIntArray yCoordinates, final int startPos, final int length) { - if (length == 0) { - return; - } - mXCoordinates.append(xCoordinates, startPos, length); - mYCoordinates.append(yCoordinates, startPos, length); - mPointerIds.fill(pointerId, mPointerIds.getLength(), length); - mTimes.append(times, startPos, length); - } - - /** - * Shift to the left by elementCount, discarding elementCount pointers at the start. - * @param elementCount how many elements to shift. - */ - @UsedForTesting - public void shift(final int elementCount) { - mXCoordinates.shift(elementCount); - mYCoordinates.shift(elementCount); - mPointerIds.shift(elementCount); - mTimes.shift(elementCount); - } - - public void reset() { - final int defaultCapacity = mDefaultCapacity; - mXCoordinates.reset(defaultCapacity); - mYCoordinates.reset(defaultCapacity); - mPointerIds.reset(defaultCapacity); - mTimes.reset(defaultCapacity); - } - - public int getPointerSize() { - return mXCoordinates.getLength(); - } - - @Nonnull - public int[] getXCoordinates() { - return mXCoordinates.getPrimitiveArray(); - } - - @Nonnull - public int[] getYCoordinates() { - return mYCoordinates.getPrimitiveArray(); - } - - @Nonnull - public int[] getPointerIds() { - return mPointerIds.getPrimitiveArray(); - } - - /** - * Gets the time each point was registered, in milliseconds, relative to the first event in the - * sequence. - * @return The time each point was registered, in milliseconds, relative to the first event in - * the sequence. - */ - @Nonnull - public int[] getTimes() { - return mTimes.getPrimitiveArray(); - } - - @Override - public String toString() { - return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes - + " x=" + mXCoordinates + " y=" + mYCoordinates; - } -} diff --git a/common/src/com/android/inputmethod/latin/common/LocaleUtils.java b/common/src/com/android/inputmethod/latin/common/LocaleUtils.java deleted file mode 100644 index d5878c024..000000000 --- a/common/src/com/android/inputmethod/latin/common/LocaleUtils.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2011 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.common; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * A class to help with handling Locales in string form. - * - * This file has the same meaning and features (and shares all of its code) with the one with the - * same name in Latin IME. They need to be kept synchronized; for any update/bugfix to - * this file, consider also updating/fixing the version in Latin IME. - */ -public final class LocaleUtils { - private LocaleUtils() { - // Intentional empty constructor for utility class. - } - - // Locale match level constants. - // A higher level of match is guaranteed to have a higher numerical value. - // Some room is left within constants to add match cases that may arise necessary - // in the future, for example differentiating between the case where the countries - // are both present and different, and the case where one of the locales does not - // specify the countries. This difference is not needed now. - - // Nothing matches. - public static final int LOCALE_NO_MATCH = 0; - // The languages matches, but the country are different. Or, the reference locale requires a - // country and the tested locale does not have one. - public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3; - // The languages and country match, but the variants are different. Or, the reference locale - // requires a variant and the tested locale does not have one. - public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6; - // The required locale is null or empty so it will accept anything, and the tested locale - // is non-null and non-empty. - public static final int LOCALE_ANY_MATCH = 10; - // The language matches, and the tested locale specifies a country but the reference locale - // does not require one. - public static final int LOCALE_LANGUAGE_MATCH = 15; - // The language and the country match, and the tested locale specifies a variant but the - // reference locale does not require one. - public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20; - // The compared locales are fully identical. This is the best match level. - public static final int LOCALE_FULL_MATCH = 30; - - // The level at which a match is "normally" considered a locale match with standard algorithms. - // Don't use this directly, use #isMatch to test. - private static final int LOCALE_MATCH = LOCALE_ANY_MATCH; - - // Make this match the maximum match level. If this evolves to have more than 2 digits - // when written in base 10, also adjust the getMatchLevelSortedString method. - private static final int MATCH_LEVEL_MAX = 30; - - /** - * Return how well a tested locale matches a reference locale. - * - * This will check the tested locale against the reference locale and return a measure of how - * a well it matches the reference. The general idea is that the tested locale has to match - * every specified part of the required locale. A full match occur when they are equal, a - * partial match when the tested locale agrees with the reference locale but is more specific, - * and a difference when the tested locale does not comply with all requirements from the - * reference locale. - * In more detail, if the reference locale specifies at least a language and the testedLocale - * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the - * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH - * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and - * tested locale agree on the language, but not on the country, - * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country, - * and LOCALE_LANGUAGE_MATCH otherwise. - * If they agree on both the language and the country, but not on the variant, - * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale - * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches, - * LOCALE_FULL_MATCH is returned. - * Examples: - * en <=> en_US => LOCALE_LANGUAGE_MATCH - * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER - * en_US_POSIX <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER - * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH - * sp_US <=> en_US => LOCALE_NO_MATCH - * de <=> de => LOCALE_FULL_MATCH - * en_US <=> en_US => LOCALE_FULL_MATCH - * "" <=> en_US => LOCALE_ANY_MATCH - * - * @param referenceLocale the reference locale to test against. - * @param testedLocale the locale to test. - * @return a constant that measures how well the tested locale matches the reference locale. - */ - public static int getMatchLevel(@Nullable final String referenceLocale, - @Nullable final String testedLocale) { - if (StringUtils.isEmpty(referenceLocale)) { - return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH; - } - if (null == testedLocale) return LOCALE_NO_MATCH; - final String[] referenceParams = referenceLocale.split("_", 3); - final String[] testedParams = testedLocale.split("_", 3); - // By spec of String#split, [0] cannot be null and length cannot be 0. - if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH; - switch (referenceParams.length) { - case 1: - return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH; - case 2: - if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER; - if (!referenceParams[1].equals(testedParams[1])) - return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER; - if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH; - return LOCALE_FULL_MATCH; - case 3: - if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER; - if (!referenceParams[1].equals(testedParams[1])) - return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER; - if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER; - if (!referenceParams[2].equals(testedParams[2])) - return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER; - return LOCALE_FULL_MATCH; - } - // It should be impossible to come here - return LOCALE_NO_MATCH; - } - - /** - * Return a string that represents this match level, with better matches first. - * - * The strings are sorted in lexicographic order: a better match will always be less than - * a worse match when compared together. - */ - public static String getMatchLevelSortedString(final int matchLevel) { - // This works because the match levels are 0~99 (actually 0~30) - // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel - return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel); - } - - /** - * Find out whether a match level should be considered a match. - * - * This method takes a match level as returned by the #getMatchLevel method, and returns whether - * it should be considered a match in the usual sense with standard Locale functions. - * - * @param level the match level, as returned by getMatchLevel. - * @return whether this is a match or not. - */ - public static boolean isMatch(final int level) { - return LOCALE_MATCH <= level; - } - - private static final HashMap<String, Locale> sLocaleCache = new HashMap<>(); - - /** - * Creates a locale from a string specification. - * @param localeString a string specification of a locale, in a format of "ll_cc_variant" where - * "ll" is a language code, "cc" is a country code. - */ - @Nonnull - public static Locale constructLocaleFromString(@Nonnull final String localeString) { - synchronized (sLocaleCache) { - if (sLocaleCache.containsKey(localeString)) { - return sLocaleCache.get(localeString); - } - final String[] elements = localeString.split("_", 3); - final Locale locale; - if (elements.length == 1) { - locale = new Locale(elements[0] /* language */); - } else if (elements.length == 2) { - locale = new Locale(elements[0] /* language */, elements[1] /* country */); - } else { // localeParams.length == 3 - locale = new Locale(elements[0] /* language */, elements[1] /* country */, - elements[2] /* variant */); - } - sLocaleCache.put(localeString, locale); - return locale; - } - } - - // TODO: Get this information from the framework instead of maintaining here by ourselves. - private static final HashSet<String> sRtlLanguageCodes = new HashSet<>(); - static { - // List of known Right-To-Left language codes. - sRtlLanguageCodes.add("ar"); // Arabic - sRtlLanguageCodes.add("fa"); // Persian - sRtlLanguageCodes.add("iw"); // Hebrew - sRtlLanguageCodes.add("ku"); // Kurdish - sRtlLanguageCodes.add("ps"); // Pashto - sRtlLanguageCodes.add("sd"); // Sindhi - sRtlLanguageCodes.add("ug"); // Uyghur - sRtlLanguageCodes.add("ur"); // Urdu - sRtlLanguageCodes.add("yi"); // Yiddish - } - - public static boolean isRtlLanguage(@Nonnull final Locale locale) { - return sRtlLanguageCodes.contains(locale.getLanguage()); - } -} diff --git a/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java b/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java deleted file mode 100644 index d673442ca..000000000 --- a/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 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.common; - -public class NativeSuggestOptions { - // Need to update suggest_options.h when you add, remove or reorder options. - private static final int IS_GESTURE = 0; - private static final int USE_FULL_EDIT_DISTANCE = 1; - private static final int BLOCK_OFFENSIVE_WORDS = 2; - private static final int SPACE_AWARE_GESTURE_ENABLED = 3; - private static final int WEIGHT_FOR_LOCALE_IN_THOUSANDS = 4; - private static final int OPTIONS_SIZE = 5; - - private final int[] mOptions; - - public NativeSuggestOptions() { - mOptions = new int[OPTIONS_SIZE]; - } - - public void setIsGesture(final boolean value) { - setBooleanOption(IS_GESTURE, value); - } - - public void setUseFullEditDistance(final boolean value) { - setBooleanOption(USE_FULL_EDIT_DISTANCE, value); - } - - public void setBlockOffensiveWords(final boolean value) { - setBooleanOption(BLOCK_OFFENSIVE_WORDS, value); - } - - public void setWeightForLocale(final float value) { - // We're passing this option as a fixed point value, in thousands. This is decoded in - // native code by SuggestOptions#weightForLocale(). - setIntegerOption(WEIGHT_FOR_LOCALE_IN_THOUSANDS, (int) (value * 1000)); - } - - public int[] getOptions() { - return mOptions; - } - - private void setBooleanOption(final int key, final boolean value) { - mOptions[key] = value ? 1 : 0; - } - - private void setIntegerOption(final int key, final int value) { - mOptions[key] = value; - } -} diff --git a/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java b/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java deleted file mode 100644 index 77f5c4cd5..000000000 --- a/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import java.util.Arrays; - -import javax.annotation.Nonnull; - -// TODO: This class is not thread-safe. -public final class ResizableIntArray { - @Nonnull - private int[] mArray; - private int mLength; - - public ResizableIntArray(final int capacity) { - reset(capacity); - } - - public int get(final int index) { - if (index < mLength) { - return mArray[index]; - } - throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index); - } - - public void addAt(final int index, final int val) { - if (index < mLength) { - mArray[index] = val; - } else { - mLength = index; - add(val); - } - } - - public void add(final int val) { - final int currentLength = mLength; - ensureCapacity(currentLength + 1); - mArray[currentLength] = val; - mLength = currentLength + 1; - } - - /** - * Calculate the new capacity of {@code mArray}. - * @param minimumCapacity the minimum capacity that the {@code mArray} should have. - * @return the new capacity that the {@code mArray} should have. Returns zero when there is no - * need to expand {@code mArray}. - */ - private int calculateCapacity(final int minimumCapacity) { - final int currentCapcity = mArray.length; - if (currentCapcity < minimumCapacity) { - final int nextCapacity = currentCapcity * 2; - // The following is the same as return Math.max(minimumCapacity, nextCapacity); - return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity; - } - return 0; - } - - private void ensureCapacity(final int minimumCapacity) { - final int newCapacity = calculateCapacity(minimumCapacity); - if (newCapacity > 0) { - // TODO: Implement primitive array pool. - mArray = Arrays.copyOf(mArray, newCapacity); - } - } - - public int getLength() { - return mLength; - } - - public void setLength(final int newLength) { - ensureCapacity(newLength); - mLength = newLength; - } - - public void reset(final int capacity) { - // TODO: Implement primitive array pool. - mArray = new int[capacity]; - mLength = 0; - } - - @Nonnull - public int[] getPrimitiveArray() { - return mArray; - } - - public void set(@Nonnull final ResizableIntArray ip) { - // TODO: Implement primitive array pool. - mArray = ip.mArray; - mLength = ip.mLength; - } - - public void copy(@Nonnull final ResizableIntArray ip) { - final int newCapacity = calculateCapacity(ip.mLength); - if (newCapacity > 0) { - // TODO: Implement primitive array pool. - mArray = new int[newCapacity]; - } - System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength); - mLength = ip.mLength; - } - - public void append(@Nonnull final ResizableIntArray src, final int startPos, final int length) { - if (length == 0) { - return; - } - final int currentLength = mLength; - final int newLength = currentLength + length; - ensureCapacity(newLength); - System.arraycopy(src.mArray, startPos, mArray, currentLength, length); - mLength = newLength; - } - - public void fill(final int value, final int startPos, final int length) { - if (startPos < 0 || length < 0) { - throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length); - } - final int endPos = startPos + length; - ensureCapacity(endPos); - Arrays.fill(mArray, startPos, endPos, value); - if (mLength < endPos) { - mLength = endPos; - } - } - - /** - * Shift to the left by elementCount, discarding elementCount pointers at the start. - * @param elementCount how many elements to shift. - */ - @UsedForTesting - public void shift(final int elementCount) { - System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount); - mLength -= elementCount; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < mLength; i++) { - if (i != 0) { - sb.append(","); - } - sb.append(mArray[i]); - } - return "[" + sb + "]"; - } -} diff --git a/common/src/com/android/inputmethod/latin/common/StringUtils.java b/common/src/com/android/inputmethod/latin/common/StringUtils.java deleted file mode 100644 index 572f0cd9b..000000000 --- a/common/src/com/android/inputmethod/latin/common/StringUtils.java +++ /dev/null @@ -1,704 +0,0 @@ -/* - * Copyright (C) 2012 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.common; - -import com.android.inputmethod.annotations.UsedForTesting; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public final class StringUtils { - public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case - public static final int CAPITALIZE_FIRST = 1; // First only - public static final int CAPITALIZE_ALL = 2; // All caps - - @Nonnull - private static final String EMPTY_STRING = ""; - - private static final char CHAR_LINE_FEED = 0X000A; - private static final char CHAR_VERTICAL_TAB = 0X000B; - private static final char CHAR_FORM_FEED = 0X000C; - private static final char CHAR_CARRIAGE_RETURN = 0X000D; - private static final char CHAR_NEXT_LINE = 0X0085; - private static final char CHAR_LINE_SEPARATOR = 0X2028; - private static final char CHAR_PARAGRAPH_SEPARATOR = 0X2029; - - private StringUtils() { - // This utility class is not publicly instantiable. - } - - // Taken from android.text.TextUtils. We are extensively using this method in many places, - // some of which don't have the android libraries available. - /** - * Returns true if the string is null or 0-length. - * @param str the string to be examined - * @return true if str is null or zero length - */ - public static boolean isEmpty(@Nullable final CharSequence str) { - return (str == null || str.length() == 0); - } - - // Taken from android.text.TextUtils to cut the dependency to the Android framework. - /** - * Returns a string containing the tokens joined by delimiters. - * @param delimiter the delimiter - * @param tokens an array objects to be joined. Strings will be formed from - * the objects by calling object.toString(). - */ - @Nonnull - public static String join(@Nonnull final CharSequence delimiter, - @Nonnull final Iterable<?> tokens) { - final StringBuilder sb = new StringBuilder(); - boolean firstTime = true; - for (final Object token: tokens) { - if (firstTime) { - firstTime = false; - } else { - sb.append(delimiter); - } - sb.append(token); - } - return sb.toString(); - } - - // Taken from android.text.TextUtils to cut the dependency to the Android framework. - /** - * Returns true if a and b are equal, including if they are both null. - * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if - * both the arguments were instances of String.</i></p> - * @param a first CharSequence to check - * @param b second CharSequence to check - * @return true if a and b are equal - */ - public static boolean equals(@Nullable final CharSequence a, @Nullable final CharSequence b) { - if (a == b) { - return true; - } - final int length; - if (a != null && b != null && (length = a.length()) == b.length()) { - if (a instanceof String && b instanceof String) { - return a.equals(b); - } - for (int i = 0; i < length; i++) { - if (a.charAt(i) != b.charAt(i)) { - return false; - } - } - return true; - } - return false; - } - - public static int codePointCount(@Nullable final CharSequence text) { - if (isEmpty(text)) { - return 0; - } - return Character.codePointCount(text, 0, text.length()); - } - - @Nonnull - public static String newSingleCodePointString(final int codePoint) { - if (Character.charCount(codePoint) == 1) { - // Optimization: avoid creating a temporary array for characters that are - // represented by a single char value - return String.valueOf((char) codePoint); - } - // For surrogate pair - return new String(Character.toChars(codePoint)); - } - - public static boolean containsInArray(@Nonnull final String text, - @Nonnull final String[] array) { - for (final String element : array) { - if (text.equals(element)) { - return true; - } - } - return false; - } - - /** - * Comma-Splittable Text is similar to Comma-Separated Values (CSV) but has much simpler syntax. - * Unlike CSV, Comma-Splittable Text has no escaping mechanism, so that the text can't contain - * a comma character in it. - */ - @Nonnull - private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ","; - - public static boolean containsInCommaSplittableText(@Nonnull final String text, - @Nullable final String extraValues) { - if (isEmpty(extraValues)) { - return false; - } - return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT)); - } - - @Nonnull - public static String removeFromCommaSplittableTextIfExists(@Nonnull final String text, - @Nullable final String extraValues) { - if (isEmpty(extraValues)) { - return EMPTY_STRING; - } - final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT); - if (!containsInArray(text, elements)) { - return extraValues; - } - final ArrayList<String> result = new ArrayList<>(elements.length - 1); - for (final String element : elements) { - if (!text.equals(element)) { - result.add(element); - } - } - return join(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT, result); - } - - /** - * Remove duplicates from an array of strings. - * - * This method will always keep the first occurrence of all strings at their position - * in the array, removing the subsequent ones. - */ - public static void removeDupes(@Nonnull final ArrayList<String> suggestions) { - if (suggestions.size() < 2) { - return; - } - int i = 1; - // Don't cache suggestions.size(), since we may be removing items - while (i < suggestions.size()) { - final String cur = suggestions.get(i); - // Compare each suggestion with each previous suggestion - for (int j = 0; j < i; j++) { - final String previous = suggestions.get(j); - if (equals(cur, previous)) { - suggestions.remove(i); - i--; - break; - } - } - i++; - } - } - - @Nonnull - public static String capitalizeFirstCodePoint(@Nonnull final String s, - @Nonnull final Locale locale) { - if (s.length() <= 1) { - return s.toUpperCase(getLocaleUsedForToTitleCase(locale)); - } - // Please refer to the comment below in - // {@link #capitalizeFirstAndDowncaseRest(String,Locale)} as this has the same shortcomings - final int cutoff = s.offsetByCodePoints(0, 1); - return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale)) - + s.substring(cutoff); - } - - @Nonnull - public static String capitalizeFirstAndDowncaseRest(@Nonnull final String s, - @Nonnull final Locale locale) { - if (s.length() <= 1) { - return s.toUpperCase(getLocaleUsedForToTitleCase(locale)); - } - // TODO: fix the bugs below - // - It does not work for Serbian, because it fails to account for the "lj" character, - // which should be "Lj" in title case and "LJ" in upper case. - // - It does not work for Dutch, because it fails to account for the "ij" digraph when it's - // written as two separate code points. They are two different characters but both should - // be capitalized as "IJ" as if they were a single letter in most words (not all). If the - // unicode char for the ligature is used however, it works. - final int cutoff = s.offsetByCodePoints(0, 1); - return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale)) - + s.substring(cutoff).toLowerCase(locale); - } - - @Nonnull - public static int[] toCodePointArray(@Nonnull final CharSequence charSequence) { - return toCodePointArray(charSequence, 0, charSequence.length()); - } - - @Nonnull - private static final int[] EMPTY_CODEPOINTS = {}; - - /** - * Converts a range of a string to an array of code points. - * @param charSequence the source string. - * @param startIndex the start index inside the string in java chars, inclusive. - * @param endIndex the end index inside the string in java chars, exclusive. - * @return a new array of code points. At most endIndex - startIndex, but possibly less. - */ - @Nonnull - public static int[] toCodePointArray(@Nonnull final CharSequence charSequence, - final int startIndex, final int endIndex) { - final int length = charSequence.length(); - if (length <= 0) { - return EMPTY_CODEPOINTS; - } - final int[] codePoints = - new int[Character.codePointCount(charSequence, startIndex, endIndex)]; - copyCodePointsAndReturnCodePointCount(codePoints, charSequence, startIndex, endIndex, - false /* downCase */); - return codePoints; - } - - /** - * Copies the codepoints in a CharSequence to an int array. - * - * This method assumes there is enough space in the array to store the code points. The size - * can be measured with Character#codePointCount(CharSequence, int, int) before passing to this - * method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown. - * Also, this method makes no effort to be thread-safe. Do not modify the CharSequence while - * this method is running, or the behavior is undefined. - * This method can optionally downcase code points before copying them, but it pays no attention - * to locale while doing so. - * - * @param destination the int array. - * @param charSequence the CharSequence. - * @param startIndex the start index inside the string in java chars, inclusive. - * @param endIndex the end index inside the string in java chars, exclusive. - * @param downCase if this is true, code points will be downcased before being copied. - * @return the number of copied code points. - */ - public static int copyCodePointsAndReturnCodePointCount(@Nonnull final int[] destination, - @Nonnull final CharSequence charSequence, final int startIndex, final int endIndex, - final boolean downCase) { - int destIndex = 0; - for (int index = startIndex; index < endIndex; - index = Character.offsetByCodePoints(charSequence, index, 1)) { - final int codePoint = Character.codePointAt(charSequence, index); - // TODO: stop using this, as it's not aware of the locale and does not always do - // the right thing. - destination[destIndex] = downCase ? Character.toLowerCase(codePoint) : codePoint; - destIndex++; - } - return destIndex; - } - - @Nonnull - public static int[] toSortedCodePointArray(@Nonnull final String string) { - final int[] codePoints = toCodePointArray(string); - Arrays.sort(codePoints); - return codePoints; - } - - /** - * Construct a String from a code point array - * - * @param codePoints a code point array that is null terminated when its logical length is - * shorter than the array length. - * @return a string constructed from the code point array. - */ - @Nonnull - public static String getStringFromNullTerminatedCodePointArray( - @Nonnull final int[] codePoints) { - int stringLength = codePoints.length; - for (int i = 0; i < codePoints.length; i++) { - if (codePoints[i] == 0) { - stringLength = i; - break; - } - } - return new String(codePoints, 0 /* offset */, stringLength); - } - - // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE. - public static int getCapitalizationType(@Nonnull final String text) { - // If the first char is not uppercase, then the word is either all lower case or - // camel case, and in either case we return CAPITALIZE_NONE. - final int len = text.length(); - int index = 0; - for (; index < len; index = text.offsetByCodePoints(index, 1)) { - if (Character.isLetter(text.codePointAt(index))) { - break; - } - } - if (index == len) return CAPITALIZE_NONE; - if (!Character.isUpperCase(text.codePointAt(index))) { - return CAPITALIZE_NONE; - } - int capsCount = 1; - int letterCount = 1; - for (index = text.offsetByCodePoints(index, 1); index < len; - index = text.offsetByCodePoints(index, 1)) { - if (1 != capsCount && letterCount != capsCount) break; - final int codePoint = text.codePointAt(index); - if (Character.isUpperCase(codePoint)) { - ++capsCount; - ++letterCount; - } else if (Character.isLetter(codePoint)) { - // We need to discount non-letters since they may not be upper-case, but may - // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME") - ++letterCount; - } - } - // We know the first char is upper case. So we want to test if either every letter other - // than the first is lower case, or if they are all upper case. If the string is exactly - // one char long, then we will arrive here with letterCount 1, and this is correct, too. - if (1 == capsCount) return CAPITALIZE_FIRST; - return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE); - } - - public static boolean isIdenticalAfterUpcase(@Nonnull final String text) { - final int length = text.length(); - int i = 0; - while (i < length) { - final int codePoint = text.codePointAt(i); - if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) { - return false; - } - i += Character.charCount(codePoint); - } - return true; - } - - public static boolean isIdenticalAfterDowncase(@Nonnull final String text) { - final int length = text.length(); - int i = 0; - while (i < length) { - final int codePoint = text.codePointAt(i); - if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) { - return false; - } - i += Character.charCount(codePoint); - } - return true; - } - - public static boolean isIdenticalAfterCapitalizeEachWord(@Nonnull final String text, - @Nonnull final int[] sortedSeparators) { - boolean needsCapsNext = true; - final int len = text.length(); - for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) { - final int codePoint = text.codePointAt(i); - if (Character.isLetter(codePoint)) { - if ((needsCapsNext && !Character.isUpperCase(codePoint)) - || (!needsCapsNext && !Character.isLowerCase(codePoint))) { - return false; - } - } - // We need a capital letter next if this is a separator. - needsCapsNext = (Arrays.binarySearch(sortedSeparators, codePoint) >= 0); - } - return true; - } - - // TODO: like capitalizeFirst*, this does not work perfectly for Dutch because of the IJ digraph - // which should be capitalized together in *some* cases. - @Nonnull - public static String capitalizeEachWord(@Nonnull final String text, - @Nonnull final int[] sortedSeparators, @Nonnull final Locale locale) { - final StringBuilder builder = new StringBuilder(); - boolean needsCapsNext = true; - final int len = text.length(); - for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) { - final String nextChar = text.substring(i, text.offsetByCodePoints(i, 1)); - if (needsCapsNext) { - builder.append(nextChar.toUpperCase(locale)); - } else { - builder.append(nextChar.toLowerCase(locale)); - } - // We need a capital letter next if this is a separator. - needsCapsNext = (Arrays.binarySearch(sortedSeparators, nextChar.codePointAt(0)) >= 0); - } - return builder.toString(); - } - - /** - * Approximates whether the text before the cursor looks like a URL. - * - * This is not foolproof, but it should work well in the practice. - * Essentially it walks backward from the cursor until it finds something that's not a letter, - * digit, or common URL symbol like underscore. If it hasn't found a period yet, then it - * does not look like a URL. - * If the text: - * - starts with www and contains a period - * - starts with a slash preceded by either a slash, whitespace, or start-of-string - * Then it looks like a URL and we return true. Otherwise, we return false. - * - * Note: this method is called quite often, and should be fast. - * - * TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the - * code complexity, but ideally it should not. It's acceptable for now. - */ - public static boolean lastPartLooksLikeURL(@Nonnull final CharSequence text) { - int i = text.length(); - if (0 == i) { - return false; - } - int wCount = 0; - int slashCount = 0; - boolean hasSlash = false; - boolean hasPeriod = false; - int codePoint = 0; - while (i > 0) { - codePoint = Character.codePointBefore(text, i); - if (codePoint < Constants.CODE_PERIOD || codePoint > 'z') { - // Handwavy heuristic to see if that's a URL character. Anything between period - // and z. This includes all lower- and upper-case ascii letters, period, - // underscore, arrobase, question mark, equal sign. It excludes spaces, exclamation - // marks, double quotes... - // Anything that's not a URL-like character causes us to break from here and - // evaluate normally. - break; - } - if (Constants.CODE_PERIOD == codePoint) { - hasPeriod = true; - } - if (Constants.CODE_SLASH == codePoint) { - hasSlash = true; - if (2 == ++slashCount) { - return true; - } - } else { - slashCount = 0; - } - if ('w' == codePoint) { - ++wCount; - } else { - wCount = 0; - } - i = Character.offsetByCodePoints(text, i, -1); - } - // End of the text run. - // If it starts with www and includes a period, then it looks like a URL. - if (wCount >= 3 && hasPeriod) { - return true; - } - // If it starts with a slash, and the code point before is whitespace, it looks like an URL. - if (1 == slashCount && (0 == i || Character.isWhitespace(codePoint))) { - return true; - } - // If it has both a period and a slash, it looks like an URL. - if (hasPeriod && hasSlash) { - return true; - } - // Otherwise, it doesn't look like an URL. - return false; - } - - /** - * Examines the string and returns whether we're inside a double quote. - * - * This is used to decide whether we should put an automatic space before or after a double - * quote character. If we're inside a quotation, then we want to close it, so we want a space - * after and not before. Otherwise, we want to open the quotation, so we want a space before - * and not after. Exception: after a digit, we never want a space because the "inch" or - * "minutes" use cases is dominant after digits. - * In the practice, we determine whether we are in a quotation or not by finding the previous - * double quote character, and looking at whether it's followed by whitespace. If so, that - * was a closing quotation mark, so we're not inside a double quote. If it's not followed - * by whitespace, then it was an opening quotation mark, and we're inside a quotation. - * - * @param text the text to examine. - * @return whether we're inside a double quote. - */ - public static boolean isInsideDoubleQuoteOrAfterDigit(@Nonnull final CharSequence text) { - int i = text.length(); - if (0 == i) { - return false; - } - int codePoint = Character.codePointBefore(text, i); - if (Character.isDigit(codePoint)) { - return true; - } - int prevCodePoint = 0; - while (i > 0) { - codePoint = Character.codePointBefore(text, i); - if (Constants.CODE_DOUBLE_QUOTE == codePoint) { - // If we see a double quote followed by whitespace, then that - // was a closing quote. - if (Character.isWhitespace(prevCodePoint)) { - return false; - } - } - if (Character.isWhitespace(codePoint) && Constants.CODE_DOUBLE_QUOTE == prevCodePoint) { - // If we see a double quote preceded by whitespace, then that - // was an opening quote. No need to continue seeking. - return true; - } - i -= Character.charCount(codePoint); - prevCodePoint = codePoint; - } - // We reached the start of text. If the first char is a double quote, then we're inside - // a double quote. Otherwise we're not. - return Constants.CODE_DOUBLE_QUOTE == codePoint; - } - - public static boolean isEmptyStringOrWhiteSpaces(@Nonnull final String s) { - final int N = codePointCount(s); - for (int i = 0; i < N; ++i) { - if (!Character.isWhitespace(s.codePointAt(i))) { - return false; - } - } - return true; - } - - @UsedForTesting - @Nonnull - public static String byteArrayToHexString(@Nullable final byte[] bytes) { - if (bytes == null || bytes.length == 0) { - return EMPTY_STRING; - } - final StringBuilder sb = new StringBuilder(); - for (final byte b : bytes) { - sb.append(String.format("%02x", b & 0xff)); - } - return sb.toString(); - } - - /** - * Convert hex string to byte array. The string length must be an even number. - */ - @UsedForTesting - @Nullable - public static byte[] hexStringToByteArray(@Nullable final String hexString) { - if (isEmpty(hexString)) { - return null; - } - final int N = hexString.length(); - if (N % 2 != 0) { - throw new NumberFormatException("Input hex string length must be an even number." - + " Length = " + N); - } - final byte[] bytes = new byte[N / 2]; - for (int i = 0; i < N; i += 2) { - bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) - + Character.digit(hexString.charAt(i + 1), 16)); - } - return bytes; - } - - private static final String LANGUAGE_GREEK = "el"; - - @Nonnull - private static Locale getLocaleUsedForToTitleCase(@Nonnull final Locale locale) { - // In Greek locale {@link String#toUpperCase(Locale)} eliminates accents from its result. - // In order to get accented upper case letter, {@link Locale#ROOT} should be used. - if (LANGUAGE_GREEK.equals(locale.getLanguage())) { - return Locale.ROOT; - } - return locale; - } - - @Nullable - public static String toTitleCaseOfKeyLabel(@Nullable final String label, - @Nonnull final Locale locale) { - if (label == null) { - return label; - } - return label.toUpperCase(getLocaleUsedForToTitleCase(locale)); - } - - public static int toTitleCaseOfKeyCode(final int code, @Nonnull final Locale locale) { - if (!Constants.isLetterCode(code)) { - return code; - } - final String label = newSingleCodePointString(code); - final String titleCaseLabel = toTitleCaseOfKeyLabel(label, locale); - return codePointCount(titleCaseLabel) == 1 - ? titleCaseLabel.codePointAt(0) : Constants.CODE_UNSPECIFIED; - } - - public static int getTrailingSingleQuotesCount(@Nonnull final CharSequence charSequence) { - final int lastIndex = charSequence.length() - 1; - int i = lastIndex; - while (i >= 0 && charSequence.charAt(i) == Constants.CODE_SINGLE_QUOTE) { - --i; - } - return lastIndex - i; - } - - @UsedForTesting - public static class Stringizer<E> { - @Nonnull - private static final String[] EMPTY_STRING_ARRAY = new String[0]; - - @UsedForTesting - @Nonnull - public String stringize(@Nullable final E element) { - if (element == null) { - return "null"; - } - return element.toString(); - } - - @UsedForTesting - @Nonnull - public final String join(@Nullable final E[] array) { - return joinStringArray(toStringArray(array), null /* delimiter */); - } - - @UsedForTesting - public final String join(@Nullable final E[] array, @Nullable final String delimiter) { - return joinStringArray(toStringArray(array), delimiter); - } - - @Nonnull - protected String[] toStringArray(@Nullable final E[] array) { - if (array == null) { - return EMPTY_STRING_ARRAY; - } - final String[] stringArray = new String[array.length]; - for (int index = 0; index < array.length; index++) { - stringArray[index] = stringize(array[index]); - } - return stringArray; - } - - @Nonnull - protected String joinStringArray(@Nonnull final String[] stringArray, - @Nullable final String delimiter) { - if (delimiter == null) { - return Arrays.toString(stringArray); - } - final StringBuilder sb = new StringBuilder(); - for (int index = 0; index < stringArray.length; index++) { - sb.append(index == 0 ? "[" : delimiter); - sb.append(stringArray[index]); - } - return sb + "]"; - } - } - - /** - * Returns whether the last composed word contains line-breaking character (e.g. CR or LF). - * @param text the text to be examined. - * @return {@code true} if the last composed word contains line-breaking separator. - */ - public static boolean hasLineBreakCharacter(@Nullable final String text) { - if (isEmpty(text)) { - return false; - } - for (int i = text.length() - 1; i >= 0; --i) { - final char c = text.charAt(i); - switch (c) { - case CHAR_LINE_FEED: - case CHAR_VERTICAL_TAB: - case CHAR_FORM_FEED: - case CHAR_CARRIAGE_RETURN: - case CHAR_NEXT_LINE: - case CHAR_LINE_SEPARATOR: - case CHAR_PARAGRAPH_SEPARATOR: - return true; - } - } - return false; - } -} diff --git a/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java b/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java deleted file mode 100644 index 10974634d..000000000 --- a/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2015 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.common; - -/** - * Emojis are supplementary characters expressed as a low+high pair. For instance, - * the emoji U+1F625 is encoded as "\uD83D\uDE25" in UTF-16, where '\uD83D' is in - * the range of [0xd800, 0xdbff] and '\uDE25' is in the range of [0xdc00, 0xdfff]. - * {@see http://docs.oracle.com/javase/6/docs/api/java/lang/Character.html#unicode} - */ -public final class UnicodeSurrogate { - private static final char LOW_SURROGATE_MIN = '\uD800'; - private static final char LOW_SURROGATE_MAX = '\uDBFF'; - private static final char HIGH_SURROGATE_MIN = '\uDC00'; - private static final char HIGH_SURROGATE_MAX = '\uDFFF'; - - public static boolean isLowSurrogate(final char c) { - return c >= LOW_SURROGATE_MIN && c <= LOW_SURROGATE_MAX; - } - - public static boolean isHighSurrogate(final char c) { - return c >= HIGH_SURROGATE_MIN && c <= HIGH_SURROGATE_MAX; - } -} |