diff options
Diffstat (limited to 'java/src')
10 files changed, 134 insertions, 128 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index c8c4d30ef..5fd70ea63 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -331,16 +331,16 @@ public class Key implements Comparable<Key> { // code point nor as a surrogate pair. mLabel = new StringBuilder().appendCodePoint(code).toString(); } else { - mLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr, + mLabel = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr, R.styleable.Keyboard_Key_keyLabel), needsToUpperCase, locale); } if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) { mHintLabel = null; } else { - mHintLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr, + mHintLabel = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel), needsToUpperCase, locale); } - String outputText = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr, + String outputText = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr, R.styleable.Keyboard_Key_keyOutputText), needsToUpperCase, locale); // Choose the first letter of the label as primary code if not specified. if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) @@ -367,9 +367,9 @@ public class Key implements Comparable<Key> { mCode = CODE_OUTPUT_TEXT; } } else { - mCode = KeySpecParser.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale); + mCode = StringUtils.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale); } - final int altCode = KeySpecParser.toUpperCaseOfCodeForLocale( + final int altCode = StringUtils.toUpperCaseOfCodeForLocale( KeySpecParser.parseCode(style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED), needsToUpperCase, locale); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index accfaedcb..07c5cae8a 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -21,14 +21,12 @@ import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; import android.text.TextUtils; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.StringUtils; import java.util.ArrayList; import java.util.Arrays; -import java.util.Locale; /** * The string parser of more keys specification. @@ -50,15 +48,10 @@ import java.util.Locale; public final class KeySpecParser { private static final boolean DEBUG = LatinImeLogger.sDBG; - private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; - // Constants for parsing. private static final char COMMA = ','; private static final char BACKSLASH = '\\'; private static final char VERTICAL_BAR = '|'; - private static final String PREFIX_TEXT = "!text/"; - static final String PREFIX_ICON = "!icon/"; - private static final String PREFIX_CODE = "!code/"; private static final String PREFIX_HEX = "0x"; private static final String ADDITIONAL_MORE_KEY_MARKER = "%"; @@ -120,13 +113,13 @@ public final class KeySpecParser { } private static boolean hasIcon(final String moreKeySpec) { - return moreKeySpec.startsWith(PREFIX_ICON); + return moreKeySpec.startsWith(KeyboardIconsSet.PREFIX_ICON); } private static boolean hasCode(final String moreKeySpec) { final int end = indexOfLabelEnd(moreKeySpec, 0); if (end > 0 && end + 1 < moreKeySpec.length() && moreKeySpec.startsWith( - PREFIX_CODE, end + 1)) { + KeyboardCodesSet.PREFIX_CODE, end + 1)) { return true; } return false; @@ -248,8 +241,8 @@ public final class KeySpecParser { public static int parseCode(final String text, final KeyboardCodesSet codesSet, final int defCode) { if (text == null) return defCode; - if (text.startsWith(PREFIX_CODE)) { - return codesSet.getCode(text.substring(PREFIX_CODE.length())); + if (text.startsWith(KeyboardCodesSet.PREFIX_CODE)) { + return codesSet.getCode(text.substring(KeyboardCodesSet.PREFIX_CODE.length())); } else if (text.startsWith(PREFIX_HEX)) { return Integer.parseInt(text.substring(PREFIX_HEX.length()), 16); } else { @@ -259,29 +252,16 @@ public final class KeySpecParser { public static int getIconId(final String moreKeySpec) { if (moreKeySpec != null && hasIcon(moreKeySpec)) { - final int end = moreKeySpec.indexOf(VERTICAL_BAR, PREFIX_ICON.length()); - final String name = (end < 0) ? moreKeySpec.substring(PREFIX_ICON.length()) - : moreKeySpec.substring(PREFIX_ICON.length(), end); + final int end = moreKeySpec.indexOf( + VERTICAL_BAR, KeyboardIconsSet.PREFIX_ICON.length()); + final String name = (end < 0) + ? moreKeySpec.substring(KeyboardIconsSet.PREFIX_ICON.length()) + : moreKeySpec.substring(KeyboardIconsSet.PREFIX_ICON.length(), end); return KeyboardIconsSet.getIconId(name); } return KeyboardIconsSet.ICON_UNDEFINED; } - private static <T> ArrayList<T> arrayAsList(final T[] array, final int start, final int end) { - if (array == null) { - throw new NullPointerException(); - } - if (start < 0 || start > end || end > array.length) { - throw new IllegalArgumentException(); - } - - final ArrayList<T> list = CollectionUtils.newArrayList(end - start); - for (int i = start; i < end; i++) { - list.add(array[i]); - } - return list; - } - private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static String[] filterOutEmptyString(final String[] array) { @@ -293,7 +273,7 @@ public final class KeySpecParser { final String entry = array[i]; if (TextUtils.isEmpty(entry)) { if (out == null) { - out = arrayAsList(array, 0, i); + out = CollectionUtils.arrayAsList(array, 0, i); } } else if (out != null) { out.add(entry); @@ -328,7 +308,7 @@ public final class KeySpecParser { } else { // Filter out excessive '%' marker. if (out == null) { - out = arrayAsList(moreKeys, 0, moreKeyIndex); + out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeyIndex); } } } else { @@ -345,7 +325,7 @@ public final class KeySpecParser { + " moreKeys=" + Arrays.toString(moreKeys) + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); } - out = arrayAsList(additionalMoreKeys, additionalIndex, additionalCount); + out = CollectionUtils.arrayAsList(additionalMoreKeys, additionalIndex, additionalCount); for (int i = 0; i < moreKeysCount; i++) { out.add(moreKeys[i]); } @@ -357,7 +337,7 @@ public final class KeySpecParser { + " moreKeys=" + Arrays.toString(moreKeys) + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); } - out = arrayAsList(moreKeys, 0, moreKeysCount); + out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeysCount); for (int i = additionalIndex; i < additionalCount; i++) { out.add(additionalMoreKeys[additionalIndex]); } @@ -378,68 +358,6 @@ public final class KeySpecParser { } } - public static String resolveTextReference(final String rawText, - final KeyboardTextsSet textsSet) { - if (TextUtils.isEmpty(rawText)) { - return null; - } - int level = 0; - String text = rawText; - StringBuilder sb; - do { - level++; - if (level >= MAX_STRING_REFERENCE_INDIRECTION) { - throw new RuntimeException("too many @string/resource indirection: " + text); - } - - final int prefixLen = PREFIX_TEXT.length(); - final int size = text.length(); - if (size < prefixLen) { - return TextUtils.isEmpty(text) ? null : text; - } - - sb = null; - for (int pos = 0; pos < size; pos++) { - final char c = text.charAt(pos); - if (text.startsWith(PREFIX_TEXT, pos) && textsSet != null) { - if (sb == null) { - sb = new StringBuilder(text.substring(0, pos)); - } - final int end = searchTextNameEnd(text, pos + prefixLen); - final String name = text.substring(pos + prefixLen, end); - sb.append(textsSet.getText(name)); - pos = end - 1; - } else if (c == BACKSLASH) { - if (sb != null) { - // Append both escape character and escaped character. - sb.append(text.substring(pos, Math.min(pos + 2, size))); - } - pos++; - } else if (sb != null) { - sb.append(c); - } - } - - if (sb != null) { - text = sb.toString(); - } - } while (sb != null); - return TextUtils.isEmpty(text) ? null : text; - } - - private static int searchTextNameEnd(final String text, final int start) { - final int size = text.length(); - for (int pos = start; pos < size; pos++) { - final char c = text.charAt(pos); - // Label name should be consisted of [a-zA-Z_0-9]. - if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) { - continue; - } - return pos; - } - return size; - } - public static int getIntValue(final String[] moreKeys, final String key, final int defaultValue) { if (moreKeys == null) { @@ -482,20 +400,4 @@ public final class KeySpecParser { } return value; } - - public static int toUpperCaseOfCodeForLocale(final int code, final boolean needsToUpperCase, - final Locale locale) { - if (!Constants.isLetterCode(code) || !needsToUpperCase) return code; - final String text = StringUtils.newSingleCodePointString(code); - final String casedText = KeySpecParser.toUpperCaseOfStringForLocale( - text, needsToUpperCase, locale); - return StringUtils.codePointCount(casedText) == 1 - ? casedText.codePointAt(0) : CODE_UNSPECIFIED; - } - - public static String toUpperCaseOfStringForLocale(final String text, - final boolean needsToUpperCase, final Locale locale) { - if (text == null || !needsToUpperCase) return text; - return text.toUpperCase(locale); - } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java index e6a674334..a2242b841 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java @@ -32,14 +32,14 @@ public abstract class KeyStyle { protected String parseString(final TypedArray a, final int index) { if (a.hasValue(index)) { - return KeySpecParser.resolveTextReference(a.getString(index), mTextsSet); + return mTextsSet.resolveTextReference(a.getString(index)); } return null; } protected String[] parseStringArray(final TypedArray a, final int index) { if (a.hasValue(index)) { - final String text = KeySpecParser.resolveTextReference(a.getString(index), mTextsSet); + final String text = mTextsSet.resolveTextReference(a.getString(index)); return KeySpecParser.splitKeySpecs(text); } return null; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java index 78809d53b..aeb4db557 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -22,6 +22,8 @@ import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.HashMap; public final class KeyboardCodesSet { + public static final String PREFIX_CODE = "!code/"; + private static final HashMap<String, int[]> sLanguageToCodesMap = CollectionUtils.newHashMap(); private static final HashMap<String, Integer> sNameToIdMap = CollectionUtils.newHashMap(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index 0ee935f60..da8bf7d69 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -30,6 +30,7 @@ import java.util.HashMap; public final class KeyboardIconsSet { private static final String TAG = KeyboardIconsSet.class.getSimpleName(); + public static final String PREFIX_ICON = "!icon/"; public static final int ICON_UNDEFINED = 0; private static final int ATTR_UNDEFINED = 0; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index 4e8eb3ea7..96a5b089f 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal; import android.content.Context; import android.content.res.Resources; +import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.utils.CollectionUtils; @@ -45,6 +46,10 @@ import java.util.HashMap; * KeyboardTextsSet.java */ public final class KeyboardTextsSet { + public static final String PREFIX_TEXT = "!text/"; + private static final char BACKSLASH = '\\'; + private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; + // Language to texts map. private static final HashMap<String, String[]> sLocaleToTextsMap = CollectionUtils.newHashMap(); private static final HashMap<String, Integer> sNameToIdsMap = CollectionUtils.newHashMap(); @@ -87,6 +92,67 @@ public final class KeyboardTextsSet { return (text == null) ? LANGUAGE_DEFAULT[id] : text; } + private static int searchTextNameEnd(final String text, final int start) { + final int size = text.length(); + for (int pos = start; pos < size; pos++) { + final char c = text.charAt(pos); + // Label name should be consisted of [a-zA-Z_0-9]. + if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) { + continue; + } + return pos; + } + return size; + } + + public String resolveTextReference(final String rawText) { + if (TextUtils.isEmpty(rawText)) { + return null; + } + int level = 0; + String text = rawText; + StringBuilder sb; + do { + level++; + if (level >= MAX_STRING_REFERENCE_INDIRECTION) { + throw new RuntimeException("too many @string/resource indirection: " + text); + } + + final int prefixLen = PREFIX_TEXT.length(); + final int size = text.length(); + if (size < prefixLen) { + return TextUtils.isEmpty(text) ? null : text; + } + + sb = null; + for (int pos = 0; pos < size; pos++) { + final char c = text.charAt(pos); + if (text.startsWith(PREFIX_TEXT, pos)) { + if (sb == null) { + sb = new StringBuilder(text.substring(0, pos)); + } + final int end = searchTextNameEnd(text, pos + prefixLen); + final String name = text.substring(pos + prefixLen, end); + sb.append(getText(name)); + pos = end - 1; + } else if (c == BACKSLASH) { + if (sb != null) { + // Append both escape character and escaped character. + sb.append(text.substring(pos, Math.min(pos + 2, size))); + } + pos++; + } else if (sb != null) { + sb.append(c); + } + } + + if (sb != null) { + text = sb.toString(); + } + } while (sb != null); + return TextUtils.isEmpty(text) ? null : text; + } + // These texts' name should be aligned with the @string/<name> in // values*/strings-action-keys.xml. private static final String[] RESOURCE_NAMES = { diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java index 110936f8f..dd58e1ff4 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java @@ -31,9 +31,9 @@ public final class MoreKeySpec { public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, final Locale locale, final KeyboardCodesSet codesSet) { - mLabel = KeySpecParser.toUpperCaseOfStringForLocale( + mLabel = StringUtils.toUpperCaseOfStringForLocale( KeySpecParser.getLabel(moreKeySpec), needsToUpperCase, locale); - final int code = KeySpecParser.toUpperCaseOfCodeForLocale( + final int code = StringUtils.toUpperCaseOfCodeForLocale( KeySpecParser.getCode(moreKeySpec, codesSet), needsToUpperCase, locale); if (code == Constants.CODE_UNSPECIFIED) { // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters @@ -42,7 +42,7 @@ public final class MoreKeySpec { mOutputText = mLabel; } else { mCode = code; - mOutputText = KeySpecParser.toUpperCaseOfStringForLocale( + mOutputText = StringUtils.toUpperCaseOfStringForLocale( KeySpecParser.getOutputText(moreKeySpec), needsToUpperCase, locale); } mIconId = KeySpecParser.getIconId(moreKeySpec); @@ -74,7 +74,7 @@ public final class MoreKeySpec { @Override public String toString() { final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel - : KeySpecParser.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId)); + : KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId)); final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText : Constants.printableCode(mCode)); if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) { diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java index cc25102ce..bbfa0f091 100644 --- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java @@ -102,4 +102,19 @@ public final class CollectionUtils { public static <E> SparseArray<E> newSparseArray() { return new SparseArray<E>(); } + + public static <E> ArrayList<E> arrayAsList(final E[] array, final int start, final int end) { + if (array == null) { + throw new NullPointerException(); + } + if (start < 0 || start > end || end > array.length) { + throw new IllegalArgumentException(); + } + + final ArrayList<E> list = newArrayList(end - start); + for (int i = start; i < end; i++) { + list.add(array[i]); + } + return list; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java index 8eff2e6e7..4a0823155 100644 --- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java @@ -22,13 +22,11 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; +import com.android.inputmethod.latin.R; + public final class ImportantNoticeUtils { private static final String TAG = ImportantNoticeUtils.class.getSimpleName(); - // The current version number of an important notice. - // This number must be incremented whenever users should see a new important notice. - private static final int CURRENT_IMPORTANT_NOTICE_VERSION = 0; - // {@link SharedPreferences} name to save the last important notice version that has been // displayed to users. private static final String PREFERENCE_NAME = "important_notice"; @@ -60,16 +58,20 @@ public final class ImportantNoticeUtils { return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); } + private static int getCurrentImportantNoticeVersion(final Context context) { + return context.getResources().getInteger(R.integer.config_important_notice_version); + } + public static boolean hasNewImportantNotice(final Context context) { final SharedPreferences prefs = getImportantNoticePreferences(context); final int lastVersion = prefs.getInt(KEY_IMPORTANT_NOTICE_VERSION, 0); - return CURRENT_IMPORTANT_NOTICE_VERSION > lastVersion; + return getCurrentImportantNoticeVersion(context) > lastVersion; } public static void updateLastImportantNoticeVersion(final Context context) { final SharedPreferences prefs = getImportantNoticePreferences(context); prefs.edit() - .putInt(KEY_IMPORTANT_NOTICE_VERSION, CURRENT_IMPORTANT_NOTICE_VERSION) + .putInt(KEY_IMPORTANT_NOTICE_VERSION, getCurrentImportantNoticeVersion(context)) .apply(); } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index b154623ae..c632a71a9 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -16,6 +16,8 @@ package com.android.inputmethod.latin.utils; +import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; + import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; @@ -471,4 +473,20 @@ public final class StringUtils { } return bytes; } + + public static String toUpperCaseOfStringForLocale(final String text, + final boolean needsToUpperCase, final Locale locale) { + if (text == null || !needsToUpperCase) return text; + return text.toUpperCase(locale); + } + + public static int toUpperCaseOfCodeForLocale(final int code, final boolean needsToUpperCase, + final Locale locale) { + if (!Constants.isLetterCode(code) || !needsToUpperCase) return code; + final String text = newSingleCodePointString(code); + final String casedText = toUpperCaseOfStringForLocale( + text, needsToUpperCase, locale); + return codePointCount(casedText) == 1 + ? casedText.codePointAt(0) : CODE_UNSPECIFIED; + } } |