aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java29
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java727
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtype.java72
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java440
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java103
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java15
-rw-r--r--java/src/com/android/inputmethod/latin/ImfUtils.java4
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java8
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java95
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java17
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsActivity.java12
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java10
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java50
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeLocale.java34
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java194
17 files changed, 1172 insertions, 649 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index b7eb8f69c..233716acf 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
import android.text.InputType;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
@@ -23,7 +25,6 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.latin.InputTypeUtils;
-import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.SubtypeLocale;
import java.util.Arrays;
@@ -184,7 +185,7 @@ public class KeyboardId {
return String.format("[%s %s:%s %s%d %s %s %s%s%s%s%s%s%s%s]",
elementIdToName(mElementId),
mLocale,
- mSubtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET),
+ mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
(mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode),
imeAction(),
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 35209e0ad..8c7246855 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -16,6 +16,12 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_SETTINGS_KEY;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -29,11 +35,10 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.keyboard.KeyboardLayoutSet.Params.ElementParams;
+import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.InputTypeUtils;
-import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SubtypeLocale;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.XmlParseUtils;
@@ -229,8 +234,8 @@ public class KeyboardLayoutSet {
params.mMode = getKeyboardMode(editorInfo);
params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO;
- params.mNoSettingsKey = StringUtils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo);
+ params.mNoSettingsKey = InputAttributes.inPrivateImeOptions(
+ mPackageName, NO_SETTINGS_KEY, mEditorInfo);
}
public Builder setScreenGeometry(int orientation, int widthPixels) {
@@ -240,10 +245,10 @@ public class KeyboardLayoutSet {
}
public Builder setSubtype(InputMethodSubtype subtype) {
- final boolean asciiCapable = subtype.containsExtraValueKey(
- LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
- final boolean deprecatedForceAscii = StringUtils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo);
+ final boolean asciiCapable = subtype.containsExtraValueKey(ASCII_CAPABLE);
+ @SuppressWarnings("deprecation")
+ final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
+ mPackageName, FORCE_ASCII, mEditorInfo);
final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
mParams.mEditorInfo.imeOptions)
|| deprecatedForceAscii;
@@ -259,10 +264,10 @@ public class KeyboardLayoutSet {
public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain,
boolean languageSwitchKeyEnabled) {
@SuppressWarnings("deprecation")
- final boolean deprecatedNoMicrophone = StringUtils.inPrivateImeOptions(
- null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo);
- final boolean noMicrophone = StringUtils.inPrivateImeOptions(
- mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo)
+ final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
+ null, NO_MICROPHONE_COMPAT, mEditorInfo);
+ final boolean noMicrophone = InputAttributes.inPrivateImeOptions(
+ mPackageName, NO_MICROPHONE, mEditorInfo)
|| deprecatedNoMicrophone;
mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone;
mParams.mVoiceKeyOnMain = voiceKeyOnMain;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index 9bbd3a280..8261400b2 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -159,7 +159,7 @@ public class KeySpecParser {
return parseEscape(moreKeySpec.substring(end + /* LABEL_END */1));
}
- private static String getOutputText(String moreKeySpec) {
+ static String getOutputText(String moreKeySpec) {
if (hasCode(moreKeySpec)) {
return null;
}
@@ -183,7 +183,7 @@ public class KeySpecParser {
return (StringUtils.codePointCount(label) == 1) ? null : label;
}
- private static int getCode(String moreKeySpec, KeyboardCodesSet codesSet) {
+ static int getCode(String moreKeySpec, KeyboardCodesSet codesSet) {
if (hasCode(moreKeySpec)) {
final int end = indexOfLabelEnd(moreKeySpec, 0);
if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
@@ -219,7 +219,7 @@ public class KeySpecParser {
}
}
- private static int getIconId(String moreKeySpec) {
+ static int getIconId(String moreKeySpec) {
if (hasIcon(moreKeySpec)) {
final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length());
final String name = moreKeySpec.substring(PREFIX_ICON.length(), end);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java
index a46f3bf1b..0518b07ff 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java
@@ -138,75 +138,76 @@ public final class KeyboardLabelsSet {
/* 48 */ "more_keys_for_smiley",
/* 49 */ "more_keys_for_punctuation",
/* 50 */ "keyhintlabel_for_punctuation",
- /* 51 */ "keylabel_for_popular_domain",
- /* 52 */ "more_keys_for_popular_domain",
- /* 53 */ "keylabel_for_symbols_1",
- /* 54 */ "keylabel_for_symbols_2",
- /* 55 */ "keylabel_for_symbols_3",
- /* 56 */ "keylabel_for_symbols_4",
- /* 57 */ "keylabel_for_symbols_5",
- /* 58 */ "keylabel_for_symbols_6",
- /* 59 */ "keylabel_for_symbols_7",
- /* 60 */ "keylabel_for_symbols_8",
- /* 61 */ "keylabel_for_symbols_9",
- /* 62 */ "keylabel_for_symbols_0",
- /* 63 */ "additional_more_keys_for_symbols_1",
- /* 64 */ "additional_more_keys_for_symbols_2",
- /* 65 */ "additional_more_keys_for_symbols_3",
- /* 66 */ "additional_more_keys_for_symbols_4",
- /* 67 */ "additional_more_keys_for_symbols_5",
- /* 68 */ "additional_more_keys_for_symbols_6",
- /* 69 */ "additional_more_keys_for_symbols_7",
- /* 70 */ "additional_more_keys_for_symbols_8",
- /* 71 */ "additional_more_keys_for_symbols_9",
- /* 72 */ "additional_more_keys_for_symbols_0",
- /* 73 */ "more_keys_for_symbols_1",
- /* 74 */ "more_keys_for_symbols_2",
- /* 75 */ "more_keys_for_symbols_3",
- /* 76 */ "more_keys_for_symbols_4",
- /* 77 */ "more_keys_for_symbols_5",
- /* 78 */ "more_keys_for_symbols_6",
- /* 79 */ "more_keys_for_symbols_7",
- /* 80 */ "more_keys_for_symbols_8",
- /* 81 */ "more_keys_for_symbols_9",
- /* 82 */ "more_keys_for_symbols_0",
- /* 83 */ "more_keys_for_am_pm",
- /* 84 */ "settings_as_more_key",
- /* 85 */ "keylabel_for_comma",
- /* 86 */ "more_keys_for_comma",
- /* 87 */ "action_next_as_more_key",
- /* 88 */ "action_previous_as_more_key",
- /* 89 */ "keylabel_for_symbols_question",
- /* 90 */ "keylabel_for_symbols_semicolon",
- /* 91 */ "keylabel_for_symbols_percent",
- /* 92 */ "more_keys_for_symbols_question",
- /* 93 */ "more_keys_for_symbols_semicolon",
- /* 94 */ "more_keys_for_symbols_percent",
- /* 95 */ "keylabel_for_tablet_comma",
- /* 96 */ "keyhintlabel_for_tablet_comma",
- /* 97 */ "more_keys_for_tablet_comma",
- /* 98 */ "keyhintlabel_for_tablet_period",
- /* 99 */ "more_keys_for_tablet_period",
- /* 100 */ "keylabel_for_apostrophe",
- /* 101 */ "keylabel_for_dash",
- /* 102 */ "keyhintlabel_for_apostrophe",
- /* 103 */ "keyhintlabel_for_dash",
- /* 104 */ "more_keys_for_apostrophe",
- /* 105 */ "more_keys_for_dash",
- /* 106 */ "more_keys_for_bullet",
- /* 107 */ "more_keys_for_star",
- /* 108 */ "more_keys_for_plus",
- /* 109 */ "more_keys_for_left_parenthesis",
- /* 110 */ "more_keys_for_right_parenthesis",
- /* 111 */ "more_keys_for_less_than",
- /* 112 */ "more_keys_for_greater_than",
- /* 113 */ "label_to_more_symbol_key",
- /* 114 */ "label_to_more_symbol_for_tablet_key",
- /* 115 */ "label_tab_key",
- /* 116 */ "label_to_phone_numeric_key",
- /* 117 */ "label_to_phone_symbols_key",
- /* 118 */ "label_time_am",
- /* 119 */ "label_time_pm",
+ /* 51 */ "more_keys_for_star",
+ /* 52 */ "more_keys_for_plus",
+ /* 53 */ "more_keys_for_left_parenthesis",
+ /* 54 */ "more_keys_for_right_parenthesis",
+ /* 55 */ "more_keys_for_less_than",
+ /* 56 */ "more_keys_for_greater_than",
+ /* 57 */ "keylabel_for_popular_domain",
+ /* 58 */ "more_keys_for_popular_domain",
+ /* 59 */ "keylabel_for_symbols_1",
+ /* 60 */ "keylabel_for_symbols_2",
+ /* 61 */ "keylabel_for_symbols_3",
+ /* 62 */ "keylabel_for_symbols_4",
+ /* 63 */ "keylabel_for_symbols_5",
+ /* 64 */ "keylabel_for_symbols_6",
+ /* 65 */ "keylabel_for_symbols_7",
+ /* 66 */ "keylabel_for_symbols_8",
+ /* 67 */ "keylabel_for_symbols_9",
+ /* 68 */ "keylabel_for_symbols_0",
+ /* 69 */ "additional_more_keys_for_symbols_1",
+ /* 70 */ "additional_more_keys_for_symbols_2",
+ /* 71 */ "additional_more_keys_for_symbols_3",
+ /* 72 */ "additional_more_keys_for_symbols_4",
+ /* 73 */ "additional_more_keys_for_symbols_5",
+ /* 74 */ "additional_more_keys_for_symbols_6",
+ /* 75 */ "additional_more_keys_for_symbols_7",
+ /* 76 */ "additional_more_keys_for_symbols_8",
+ /* 77 */ "additional_more_keys_for_symbols_9",
+ /* 78 */ "additional_more_keys_for_symbols_0",
+ /* 79 */ "more_keys_for_symbols_1",
+ /* 80 */ "more_keys_for_symbols_2",
+ /* 81 */ "more_keys_for_symbols_3",
+ /* 82 */ "more_keys_for_symbols_4",
+ /* 83 */ "more_keys_for_symbols_5",
+ /* 84 */ "more_keys_for_symbols_6",
+ /* 85 */ "more_keys_for_symbols_7",
+ /* 86 */ "more_keys_for_symbols_8",
+ /* 87 */ "more_keys_for_symbols_9",
+ /* 88 */ "more_keys_for_symbols_0",
+ /* 89 */ "keylabel_for_comma",
+ /* 90 */ "more_keys_for_comma",
+ /* 91 */ "keylabel_for_symbols_question",
+ /* 92 */ "keylabel_for_symbols_semicolon",
+ /* 93 */ "keylabel_for_symbols_percent",
+ /* 94 */ "more_keys_for_symbols_question",
+ /* 95 */ "more_keys_for_symbols_semicolon",
+ /* 96 */ "more_keys_for_symbols_percent",
+ /* 97 */ "keylabel_for_tablet_comma",
+ /* 98 */ "keyhintlabel_for_tablet_comma",
+ /* 99 */ "more_keys_for_tablet_comma",
+ /* 100 */ "keyhintlabel_for_tablet_period",
+ /* 101 */ "more_keys_for_tablet_period",
+ /* 102 */ "keylabel_for_apostrophe",
+ /* 103 */ "keylabel_for_dash",
+ /* 104 */ "keyhintlabel_for_apostrophe",
+ /* 105 */ "keyhintlabel_for_dash",
+ /* 106 */ "more_keys_for_apostrophe",
+ /* 107 */ "more_keys_for_dash",
+ /* 108 */ "more_keys_for_bullet",
+ /* 109 */ "more_keys_for_am_pm",
+ /* 110 */ "settings_as_more_key",
+ /* 111 */ "shortcut_as_more_key",
+ /* 112 */ "action_next_as_more_key",
+ /* 113 */ "action_previous_as_more_key",
+ /* 114 */ "label_to_more_symbol_key",
+ /* 115 */ "label_to_more_symbol_for_tablet_key",
+ /* 116 */ "label_tab_key",
+ /* 117 */ "label_to_phone_numeric_key",
+ /* 118 */ "label_to_phone_symbols_key",
+ /* 119 */ "label_time_am",
+ /* 120 */ "label_time_pm",
};
private static final String EMPTY = "";
@@ -220,9 +221,11 @@ public final class KeyboardLabelsSet {
EMPTY, EMPTY,
/* ~40 */
/* 41 */ "!fixedColumnOrder!4,\u2018,\u2019,\u201A,\u201B",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;</string>
/* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
// U+00A2: "¢" CENT SIGN
// U+00A3: "£" POUND SIGN
@@ -236,120 +239,122 @@ public final class KeyboardLabelsSet {
/* 48 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
/* 49 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(,)",
/* 50 */ EMPTY,
- /* 51 */ ".com",
+ // U+2020: "†" DAGGER
+ // U+2021: "‡" DOUBLE DAGGER
+ // U+2605: "★" BLACK STAR
+ /* 51 */ "\u2020,\u2021,\u2605",
+ // U+00B1: "±" PLUS-MINUS SIGN
+ /* 52 */ "\u00B1",
+ // The all letters need to be mirrored are found at
+ // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
+ /* 53 */ "!fixedColumnOrder!3,<,{,[",
+ /* 54 */ "!fixedColumnOrder!3,>,},]",
+ // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ // U+2264: "≤" LESS-THAN OR EQUAL TO
+ // U+2265: "≥" GREATER-THAN EQUAL TO
+ // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 55 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
+ /* 56 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
+ /* 57 */ ".com",
// popular web domains for the locale - most popular, displayed on the keyboard
- /* 52 */ "!hasLabels!,.net,.org,.gov,.edu",
- /* 53 */ "1",
- /* 54 */ "2",
- /* 55 */ "3",
- /* 56 */ "4",
- /* 57 */ "5",
- /* 58 */ "6",
- /* 59 */ "7",
- /* 60 */ "8",
- /* 61 */ "9",
- /* 62 */ "0",
- /* 63~ */
+ /* 58 */ "!hasLabels!,.net,.org,.gov,.edu",
+ /* 59 */ "1",
+ /* 60 */ "2",
+ /* 61 */ "3",
+ /* 62 */ "4",
+ /* 63 */ "5",
+ /* 64 */ "6",
+ /* 65 */ "7",
+ /* 66 */ "8",
+ /* 67 */ "9",
+ /* 68 */ "0",
+ /* 69~ */
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
- /* ~72 */
+ /* ~78 */
// U+00B9: "¹" SUPERSCRIPT ONE
// U+00BD: "½" VULGAR FRACTION ONE HALF
// U+2153: "⅓" VULGAR FRACTION ONE THIRD
// U+00BC: "¼" VULGAR FRACTION ONE QUARTER
// U+215B: "⅛" VULGAR FRACTION ONE EIGHTH
- /* 73 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
+ /* 79 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
// U+00B2: "²" SUPERSCRIPT TWO
// U+2154: "⅔" VULGAR FRACTION TWO THIRDS
- /* 74 */ "\u00B2,\u2154",
+ /* 80 */ "\u00B2,\u2154",
// U+00B3: "³" SUPERSCRIPT THREE
// U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
// U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
- /* 75 */ "\u00B3,\u00BE,\u215C",
+ /* 81 */ "\u00B3,\u00BE,\u215C",
// U+2074: "⁴" SUPERSCRIPT FOUR
- /* 76 */ "\u2074",
+ /* 82 */ "\u2074",
// U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
- /* 77 */ "\u215D",
- /* 78 */ EMPTY,
+ /* 83 */ "\u215D",
+ /* 84 */ EMPTY,
// U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
- /* 79 */ "\u215E",
- /* 80 */ EMPTY,
- /* 81 */ EMPTY,
+ /* 85 */ "\u215E",
+ /* 86 */ EMPTY,
+ /* 87 */ EMPTY,
// U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
// U+2205: "∅" EMPTY SET
- /* 82 */ "\u207F,\u2205",
- /* 83 */ "!fixedColumnOrder!2,!hasLabels!,!label/label_time_am,!label/label_time_pm",
- /* 84 */ "!icon/settingsKey|!code/key_settings",
- /* 85 */ ",",
- /* 86 */ EMPTY,
- /* 87 */ "!hasLabels!,!label/label_next_key|!code/key_action_next",
- /* 88 */ "!hasLabels!,!label/label_previous_key|!code/key_action_previous",
- /* 89 */ "?",
- /* 90 */ ";",
- /* 91 */ "%",
+ /* 88 */ "\u207F,\u2205",
+ /* 89 */ ",",
+ /* 90 */ EMPTY,
+ /* 91 */ "?",
+ /* 92 */ ";",
+ /* 93 */ "%",
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 92 */ "\u00BF",
- /* 93 */ EMPTY,
+ /* 94 */ "\u00BF",
+ /* 95 */ EMPTY,
// U+2030: "‰" PER MILLE SIGN
- /* 94 */ "\u2030",
- /* 95 */ ",",
- /* 96 */ "!",
- /* 97 */ "!",
- /* 98 */ "?",
- /* 99 */ "?",
- /* 100 */ "\'",
- /* 101 */ "-",
- /* 102 */ "\"",
- /* 103 */ "_",
+ /* 96 */ "\u2030",
+ /* 97 */ ",",
+ /* 98 */ "!",
+ /* 99 */ "!",
+ /* 100 */ "?",
+ /* 101 */ "?",
+ /* 102 */ "\'",
+ /* 103 */ "-",
/* 104 */ "\"",
/* 105 */ "_",
+ /* 106 */ "\"",
+ /* 107 */ "_",
// U+266A: "♪" EIGHTH NOTE
// U+2665: "♥" BLACK HEART SUIT
// U+2660: "♠" BLACK SPADE SUIT
// U+2666: "♦" BLACK DIAMOND SUIT
// U+2663: "♣" BLACK CLUB SUIT
- /* 106 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
- // U+2020: "†" DAGGER
- // U+2021: "‡" DOUBLE DAGGER
- // U+2605: "★" BLACK STAR
- /* 107 */ "\u2020,\u2021,\u2605",
- // U+00B1: "±" PLUS-MINUS SIGN
- /* 108 */ "\u00B1",
- // The all letters need to be mirrored are found at
- // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 109 */ "!fixedColumnOrder!3,<,{,[",
- /* 110 */ "!fixedColumnOrder!3,>,},]",
- // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
- // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- // U+2264: "≤" LESS-THAN OR EQUAL TO
- // U+2265: "≥" GREATER-THAN EQUAL TO
- // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
- // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- // The following characters don't need BIDI mirroring.
- // U+2018: "‘" LEFT SINGLE QUOTATION MARK
- // U+2019: "’" RIGHT SINGLE QUOTATION MARK
- // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
- // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
- // U+201C: "“" LEFT DOUBLE QUOTATION MARK
- // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
- // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- /* 111 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
- /* 112 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
+ /* 108 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
+ /* 109 */ "!fixedColumnOrder!2,!hasLabels!,!label/label_time_am,!label/label_time_pm",
+ /* 110 */ "!icon/settingsKey|!code/key_settings",
+ /* 111 */ "!icon/shortcutKey|!code/key_shortcut",
+ /* 112 */ "!hasLabels!,!label/label_next_key|!code/key_action_next",
+ /* 113 */ "!hasLabels!,!label/label_previous_key|!code/key_action_previous",
// Label for "switch to more symbol" modifier key. Must be short to fit on key!
- /* 113 */ "= \\ <",
+ /* 114 */ "= \\ <",
// Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key!
- /* 114 */ "~ \\ {",
+ /* 115 */ "~ \\ {",
// Label for "Tab" key. Must be short to fit on key!
- /* 115 */ "Tab",
+ /* 116 */ "Tab",
// Label for "switch to phone numeric" key. Must be short to fit on key!
- /* 116 */ "123",
- // Label for "switch to phone symbols" key. Must be short to fit on key! U+FF0A: "*" FULLWIDTH ASTERISK
+ /* 117 */ "123",
+ // Label for "switch to phone symbols" key. Must be short to fit on key!
+ // U+FF0A: "*" FULLWIDTH ASTERISK
// U+FF03: "#" FULLWIDTH NUMBER SIGN
- /* 117 */ "\uFF0A\uFF03",
+ /* 118 */ "\uFF0A\uFF03",
// Key label for "ante meridiem"
- /* 118 */ "AM",
+ /* 119 */ "AM",
// Key label for "post meridiem"
- /* 119 */ "PM",
+ /* 120 */ "PM",
};
/* Language ar: Arabic */
@@ -359,132 +364,141 @@ public final class KeyboardLabelsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
/* ~41 */
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
/* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
/* 44~ */
null, null, null, null, null,
/* ~48 */
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
- // U+061B: "؛" ARABIC SEMICOLON U+0650: "ِ" ARABIC KASRA
+ // U+061B: "؛" ARABIC SEMICOLON
+ // U+0650: "ِ" ARABIC KASRA
// U+064E: "َ" ARABIC FATHA
// U+064D: "ٍ" ARABIC KASRATAN
// U+064B: "ً" ARABIC FATHATAN
// U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
// U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
// U+0655: "ٕ" ARABIC HAMZA BELOW
- // U+0654: "ٔ" ARABIC HAMZA ABOVE U+064F: "ُ" ARABIC DAMMA
+ // U+0654: "ٔ" ARABIC HAMZA ABOVE
+ // U+064F: "ُ" ARABIC DAMMA
// U+064C: "ٌ" ARABIC DAMMATAN
// U+0651: "ّ" ARABIC SHADDA
// U+0652: "ْ" ARABIC SUKUN
// U+0653: "ٓ" ARABIC MADDAH ABOVE
- // U+0640: "ـ" ARABIC TATWEEL In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ // U+0640: "ـ" ARABIC TATWEEL
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
/* 49 */ "!fixedColumnOrder!8,\",\',-,:,!,\u061F,\u060C,\u061B,\u0650,\u064E,\u064D,\u064B,\u0656,\u0670,\u0655,\u0654,\u064F,\u064C,\u0651,\u0652,\u0653,\u0640\u0640\u0640|\u0640,/",
/* 50 */ "\u064B",
- /* 51 */ null,
+ // U+2605: "★" BLACK STAR
+ // U+066D: "٭" ARABIC FIVE POINTED STAR
+ /* 51 */ "\u2605,\u066D",
/* 52 */ null,
+ // The all letters need to be mirrored are found at
+ // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
+ // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
+ // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS
+ // TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS
+ // TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS
+ /* 53 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 54 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ // U+2264: "≤" LESS-THAN OR EQUAL TO
+ // U+2265: "≥" GREATER-THAN EQUAL TO
+ // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 57 */ null,
+ /* 58 */ null,
// U+0661: "١" ARABIC-INDIC DIGIT ONE
- /* 53 */ "\u0661",
+ /* 59 */ "\u0661",
// U+0662: "٢" ARABIC-INDIC DIGIT TWO
- /* 54 */ "\u0662",
+ /* 60 */ "\u0662",
// U+0663: "٣" ARABIC-INDIC DIGIT THREE
- /* 55 */ "\u0663",
+ /* 61 */ "\u0663",
// U+0664: "٤" ARABIC-INDIC DIGIT FOUR
- /* 56 */ "\u0664",
+ /* 62 */ "\u0664",
// U+0665: "٥" ARABIC-INDIC DIGIT FIVE
- /* 57 */ "\u0665",
+ /* 63 */ "\u0665",
// U+0666: "٦" ARABIC-INDIC DIGIT SIX
- /* 58 */ "\u0666",
+ /* 64 */ "\u0666",
// U+0667: "٧" ARABIC-INDIC DIGIT SEVEN
- /* 59 */ "\u0667",
+ /* 65 */ "\u0667",
// U+0668: "٨" ARABIC-INDIC DIGIT EIGHT
- /* 60 */ "\u0668",
+ /* 66 */ "\u0668",
// U+0669: "٩" ARABIC-INDIC DIGIT NINE
- /* 61 */ "\u0669",
+ /* 67 */ "\u0669",
// U+0660: "٠" ARABIC-INDIC DIGIT ZERO
- /* 62 */ "\u0660",
- /* 63 */ "1",
- /* 64 */ "2",
- /* 65 */ "3",
- /* 66 */ "4",
- /* 67 */ "5",
- /* 68 */ "6",
- /* 69 */ "7",
- /* 70 */ "8",
- /* 71 */ "9",
+ /* 68 */ "\u0660",
+ /* 69 */ "1",
+ /* 70 */ "2",
+ /* 71 */ "3",
+ /* 72 */ "4",
+ /* 73 */ "5",
+ /* 74 */ "6",
+ /* 75 */ "7",
+ /* 76 */ "8",
+ /* 77 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 72 */ "0,\u066B,\u066C",
- /* 73~ */
- null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~84 */
+ /* 78 */ "0,\u066B,\u066C",
+ /* 79~ */
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~88 */
// U+060C: "،" ARABIC COMMA
- /* 85 */ "\u060C",
- /* 86 */ "\\,",
- /* 87 */ null,
- /* 88 */ null,
- /* 89 */ "\u061F",
- /* 90 */ "\u061B",
+ /* 89 */ "\u060C",
+ /* 90 */ "\\,",
+ /* 91 */ "\u061F",
+ /* 92 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 91 */ "\u066A",
- /* 92 */ "?",
- /* 93 */ ";",
+ /* 93 */ "\u066A",
+ /* 94 */ "?",
+ /* 95 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 94 */ "%,\u2030",
- /* 95~ */
+ /* 96 */ "%,\u2030",
+ /* 97~ */
null, null, null, null, null,
- /* ~99 */
+ /* ~101 */
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
- /* 100 */ "\u060C",
- /* 101 */ ".",
- /* 102 */ "\u061F",
- /* 103 */ "\u064B",
- /* 104 */ "\u061F,\u061B,!,:,-,/,\',\"",
+ /* 102 */ "\u060C",
+ /* 103 */ ".",
+ /* 104 */ "\u061F",
+ /* 105 */ "\u064B",
+ /* 106 */ "\u061F,\u061B,!,:,-,/,\',\"",
// U+0651: "ّ" ARABIC SHADDA
// U+0652: "ْ" ARABIC SUKUN
// U+064C: "ٌ" ARABIC DAMMATAN
// U+0653: "ٓ" ARABIC MADDAH ABOVE
- // U+064F: "ُ" ARABIC DAMMA U+0650: "ِ" ARABIC KASRA
+ // U+064F: "ُ" ARABIC DAMMA
+ // U+0650: "ِ" ARABIC KASRA
// U+064E: "َ" ARABIC FATHA
// U+064B: "ً" ARABIC FATHATAN
// U+0640: "ـ" ARABIC TATWEEL
- // U+064D: "ٍ" ARABIC KASRATAN U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
+ // U+064D: "ٍ" ARABIC KASRATAN
+ // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
// U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
// U+0654: "ٔ" ARABIC HAMZA ABOVE
- // U+0655: "ٕ" ARABIC HAMZA BELOW In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
- /* 105 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,\u0670",
+ // U+0655: "ٕ" ARABIC HAMZA BELOW
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ /* 107 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,\u0670",
// U+266A: "♪" EIGHTH NOTE
- /* 106 */ "\u266A",
- // U+2605: "★" BLACK STAR
- // U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 107 */ "\u2605,\u066D",
- /* 108 */ null,
- // The all letters need to be mirrored are found at
- // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
- // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS
- /* 109 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 110 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
- // U+2264: "≤" LESS-THAN OR EQUAL TO
- // U+2265: "≥" GREATER-THAN EQUAL TO
- // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
- // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
- // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- // The following characters don't need BIDI mirroring.
- // U+2018: "‘" LEFT SINGLE QUOTATION MARK
- // U+2019: "’" RIGHT SINGLE QUOTATION MARK
- // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
- // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
- // U+201C: "“" LEFT DOUBLE QUOTATION MARK
- // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
- // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 108 */ "\u266A",
};
/* Language be: Belarusian */
@@ -755,7 +769,7 @@ public final class KeyboardLabelsSet {
// U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
// U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
// U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
- /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0103",
+ /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
// U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
// U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
// U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
@@ -770,7 +784,7 @@ public final class KeyboardLabelsSet {
// U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
// U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
// U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
- /* 3 */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8\u014D,\u00F5",
+ /* 3 */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8,\u014D,\u00F5",
// U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
// U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
// U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -954,134 +968,143 @@ public final class KeyboardLabelsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
/* ~41 */
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
/* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
/* 44~ */
null, null, null, null, null,
/* ~48 */
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
- // U+061B: "؛" ARABIC SEMICOLON U+0650: "ِ" ARABIC KASRA
+ // U+061B: "؛" ARABIC SEMICOLON
+ // U+0650: "ِ" ARABIC KASRA
// U+064E: "َ" ARABIC FATHA
// U+064D: "ٍ" ARABIC KASRATAN
// U+064B: "ً" ARABIC FATHATAN
// U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
// U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
// U+0655: "ٕ" ARABIC HAMZA BELOW
- // U+0654: "ٔ" ARABIC HAMZA ABOVE U+064F: "ُ" ARABIC DAMMA
+ // U+0654: "ٔ" ARABIC HAMZA ABOVE
+ // U+064F: "ُ" ARABIC DAMMA
// U+064C: "ٌ" ARABIC DAMMATAN
// U+0651: "ّ" ARABIC SHADDA
// U+0652: "ْ" ARABIC SUKUN
// U+0653: "ٓ" ARABIC MADDAH ABOVE
- // U+0640: "ـ" ARABIC TATWEEL In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ // U+0640: "ـ" ARABIC TATWEEL
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
/* 49 */ "!fixedColumnOrder!8,\",\',-,:,!,\u061F,\u060C,\u061B,\u0650,\u064E,\u064D,\u064B,\u0656,\u0670,\u0655,\u0654,\u064F,\u064C,\u0651,\u0652,\u0653,\u0640\u0640\u0640|\u0640,/",
/* 50 */ "\u064B",
- /* 51 */ null,
+ // U+2605: "★" BLACK STAR
+ // U+066D: "٭" ARABIC FIVE POINTED STAR
+ /* 51 */ "\u2605,\u066D",
/* 52 */ null,
+ // The all letters need to be mirrored are found at
+ // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
+ // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
+ // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS
+ // TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS
+ // TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS
+ /* 53 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 54 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ // U+2264: "≤" LESS-THAN OR EQUAL TO
+ // U+2265: "≥" GREATER-THAN EQUAL TO
+ // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 57 */ null,
+ /* 58 */ null,
// U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE
- /* 53 */ "\u06F1",
+ /* 59 */ "\u06F1",
// U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO
- /* 54 */ "\u06F2",
+ /* 60 */ "\u06F2",
// U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE
- /* 55 */ "\u06F3",
+ /* 61 */ "\u06F3",
// U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR
- /* 56 */ "\u06F4",
+ /* 62 */ "\u06F4",
// U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE
- /* 57 */ "\u06F5",
+ /* 63 */ "\u06F5",
// U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX
- /* 58 */ "\u06F6",
+ /* 64 */ "\u06F6",
// U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN
- /* 59 */ "\u06F7",
+ /* 65 */ "\u06F7",
// U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT
- /* 60 */ "\u06F8",
+ /* 66 */ "\u06F8",
// U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE
- /* 61 */ "\u06F9",
+ /* 67 */ "\u06F9",
// U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO
- /* 62 */ "\u06F0",
- /* 63 */ "1",
- /* 64 */ "2",
- /* 65 */ "3",
- /* 66 */ "4",
- /* 67 */ "5",
- /* 68 */ "6",
- /* 69 */ "7",
- /* 70 */ "8",
- /* 71 */ "9",
+ /* 68 */ "\u06F0",
+ /* 69 */ "1",
+ /* 70 */ "2",
+ /* 71 */ "3",
+ /* 72 */ "4",
+ /* 73 */ "5",
+ /* 74 */ "6",
+ /* 75 */ "7",
+ /* 76 */ "8",
+ /* 77 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 72 */ "0,\u066B,\u066C",
- /* 73~ */
- null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~84 */
+ /* 78 */ "0,\u066B,\u066C",
+ /* 79~ */
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~88 */
// U+060C: "،" ARABIC COMMA
- /* 85 */ "\u060C",
- /* 86 */ "\\,",
- /* 87 */ null,
- /* 88 */ null,
- /* 89 */ "\u061F",
- /* 90 */ "\u061B",
+ /* 89 */ "\u060C",
+ /* 90 */ "\\,",
+ /* 91 */ "\u061F",
+ /* 92 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 91 */ "\u066A",
- /* 92 */ "?",
- /* 93 */ ";",
+ /* 93 */ "\u066A",
+ /* 94 */ "?",
+ /* 95 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 94 */ "%,\u2030",
+ /* 96 */ "%,\u2030",
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
- /* 95 */ "\u060C",
- /* 96 */ "!",
- /* 97 */ "!,\\,",
- /* 98 */ "\u061F",
- /* 99 */ "\u061F,?",
- /* 100~ */
+ /* 97 */ "\u060C",
+ /* 98 */ "!",
+ /* 99 */ "!,\\,",
+ /* 100 */ "\u061F",
+ /* 101 */ "\u061F,?",
+ /* 102~ */
null, null, null,
- /* ~102 */
- /* 103 */ "\u064B",
- /* 104 */ "\u061F,\u061B,!,:,-,/,\',\"",
+ /* ~104 */
+ /* 105 */ "\u064B",
+ /* 106 */ "\u061F,\u061B,!,:,-,/,\',\"",
// U+0651: "ّ" ARABIC SHADDA
// U+0652: "ْ" ARABIC SUKUN
// U+064C: "ٌ" ARABIC DAMMATAN
// U+0653: "ٓ" ARABIC MADDAH ABOVE
- // U+064F: "ُ" ARABIC DAMMA U+0650: "ِ" ARABIC KASRA
+ // U+064F: "ُ" ARABIC DAMMA
+ // U+0650: "ِ" ARABIC KASRA
// U+064E: "َ" ARABIC FATHA
// U+064B: "ً" ARABIC FATHATAN
// U+0640: "ـ" ARABIC TATWEEL
- // U+064D: "ٍ" ARABIC KASRATAN U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
+ // U+064D: "ٍ" ARABIC KASRATAN
+ // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
// U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
// U+0654: "ٔ" ARABIC HAMZA ABOVE
- // U+0655: "ٕ" ARABIC HAMZA BELOW In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
- /* 105 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,_,\u0670",
+ // U+0655: "ٕ" ARABIC HAMZA BELOW
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ /* 107 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,_,\u0670",
// U+266A: "♪" EIGHTH NOTE
- /* 106 */ "\u266A",
- // U+2605: "★" BLACK STAR
- // U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 107 */ "\u2605,\u066D",
- /* 108 */ null,
- // The all letters need to be mirrored are found at
- // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
- // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS
- /* 109 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 110 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
- // U+2264: "≤" LESS-THAN OR EQUAL TO
- // U+2265: "≥" GREATER-THAN EQUAL TO
- // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
- // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
- // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- // The following characters don't need BIDI mirroring.
- // U+2018: "‘" LEFT SINGLE QUOTATION MARK
- // U+2019: "’" RIGHT SINGLE QUOTATION MARK
- // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
- // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
- // U+201C: "“" LEFT DOUBLE QUOTATION MARK
- // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
- // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 108 */ "\u266A",
};
/* Language fi: Finnish */
@@ -1190,38 +1213,38 @@ public final class KeyboardLabelsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null,
- /* ~52 */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~58 */
// U+0967: "१" DEVANAGARI DIGIT ONE
- /* 53 */ "\u0967",
+ /* 59 */ "\u0967",
// U+0968: "२" DEVANAGARI DIGIT TWO
- /* 54 */ "\u0968",
+ /* 60 */ "\u0968",
// U+0969: "३" DEVANAGARI DIGIT THREE
- /* 55 */ "\u0969",
+ /* 61 */ "\u0969",
// U+096A: "४" DEVANAGARI DIGIT FOUR
- /* 56 */ "\u096A",
+ /* 62 */ "\u096A",
// U+096B: "५" DEVANAGARI DIGIT FIVE
- /* 57 */ "\u096B",
+ /* 63 */ "\u096B",
// U+096C: "६" DEVANAGARI DIGIT SIX
- /* 58 */ "\u096C",
+ /* 64 */ "\u096C",
// U+096D: "७" DEVANAGARI DIGIT SEVEN
- /* 59 */ "\u096D",
+ /* 65 */ "\u096D",
// U+096E: "८" DEVANAGARI DIGIT EIGHT
- /* 60 */ "\u096E",
+ /* 66 */ "\u096E",
// U+096F: "९" DEVANAGARI DIGIT NINE
- /* 61 */ "\u096F",
+ /* 67 */ "\u096F",
// U+0966: "०" DEVANAGARI DIGIT ZERO
- /* 62 */ "\u0966",
- /* 63 */ "1",
- /* 64 */ "2",
- /* 65 */ "3",
- /* 66 */ "4",
- /* 67 */ "5",
- /* 68 */ "6",
- /* 69 */ "7",
- /* 70 */ "8",
- /* 71 */ "9",
- /* 72 */ "0",
+ /* 68 */ "\u0966",
+ /* 69 */ "1",
+ /* 70 */ "2",
+ /* 71 */ "3",
+ /* 72 */ "4",
+ /* 73 */ "5",
+ /* 74 */ "6",
+ /* 75 */ "7",
+ /* 76 */ "8",
+ /* 77 */ "9",
+ /* 78 */ "0",
};
/* Language hr: Croatian */
@@ -1411,26 +1434,24 @@ public final class KeyboardLabelsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
/* ~41 */
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
/* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
/* 44~ */
- null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null,
- /* ~106 */
+ null, null, null, null, null, null, null,
+ /* ~50 */
// U+2605: "★" BLACK STAR
- /* 107 */ "\u2605",
+ /* 51 */ "\u2605",
// U+00B1: "±" PLUS-MINUS SIGN
// U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
- /* 108 */ "\u00B1,\uFB29",
+ /* 52 */ "\u00B1,\uFB29",
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 109 */ "!fixedColumnOrder!3,<|>,{|},[|]",
- /* 110 */ "!fixedColumnOrder!3,>|<,}|{,]|[",
+ /* 53 */ "!fixedColumnOrder!3,<|>,{|},[|]",
+ /* 54 */ "!fixedColumnOrder!3,>|<,}|{,]|[",
// U+2264: "≤" LESS-THAN OR EQUAL TO
// U+2265: "≥" GREATER-THAN EQUAL TO
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
@@ -1446,8 +1467,8 @@ public final class KeyboardLabelsSet {
// U+201D: "”" RIGHT DOUBLE QUOTATION MARK
// U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
// U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
};
/* Language ky: Kirghiz */
@@ -1682,9 +1703,12 @@ public final class KeyboardLabelsSet {
// U+201C: "“" LEFT DOUBLE QUOTATION MARK
// U+201D: "”" RIGHT DOUBLE QUOTATION MARK
// U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
/* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
};
@@ -2100,9 +2124,12 @@ public final class KeyboardLabelsSet {
// U+201C: "“" LEFT DOUBLE QUOTATION MARK
// U+201D: "”" RIGHT DOUBLE QUOTATION MARK
// U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
/* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB",
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
/* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
};
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index b24f06472..28cec56e6 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -16,6 +16,10 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
import android.view.inputmethod.InputMethodSubtype;
import java.util.HashMap;
@@ -24,9 +28,11 @@ public class AdditionalSubtype {
public static final String QWERTY = "qwerty";
public static final String QWERTZ = "qwertz";
public static final String AZERTY = "azerty";
-
- private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
- private static final String SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
+ public static final String[] PREDEFINED_KEYBOARD_LAYOUT_SET = {
+ QWERTY,
+ QWERTZ,
+ AZERTY
+ };
// Keyboard layout to subtype name resource id map.
private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
@@ -38,33 +44,57 @@ public class AdditionalSubtype {
sKeyboardLayoutToNameIdsMap.put(AZERTY, R.string.subtype_generic_azerty);
}
+ private AdditionalSubtype() {
+ // This utility class is not publicly instantiable.
+ }
+
public static boolean isAdditionalSubtype(InputMethodSubtype subtype) {
- return subtype.containsExtraValueKey(SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE);
+ return subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE);
}
+ private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
+ public static final String PREF_SUBTYPE_SEPARATOR = ";";
+
public static InputMethodSubtype createAdditionalSubtype(
- String localeString, String keyboardLayoutSet) {
- final String extraValue = String.format(
- "%s=%s,%s", LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET, keyboardLayoutSet,
- SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE);
- Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutSet);
+ String localeString, String keyboardLayoutSetName, String extraValue) {
+ final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
+ final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
+ IS_ADDITIONAL_SUBTYPE, extraValue);
+ Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutSetName);
if (nameId == null) nameId = R.string.subtype_generic;
return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
- localeString, SUBTYPE_MODE_KEYBOARD, extraValue, false, false);
+ localeString, KEYBOARD_MODE,
+ layoutExtraValue + "," + filteredExtraValue, false, false);
}
- private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
- private static final String SUBTYPE_SEPARATOR = ",";
+ public static String getPrefSubtype(InputMethodSubtype subtype) {
+ final String localeString = subtype.getLocale();
+ final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
+ final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
+ final String extraValue = StringUtils.removeFromCsvIfExists(layoutExtraValue,
+ StringUtils.removeFromCsvIfExists(IS_ADDITIONAL_SUBTYPE, subtype.getExtraValue()));
+ final String basePrefSubtype = localeString + LOCALE_AND_LAYOUT_SEPARATOR
+ + keyboardLayoutSetName;
+ return extraValue.isEmpty() ? basePrefSubtype
+ : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue;
+ }
+
+ public static InputMethodSubtype createAdditionalSubtype(String prefSubtype) {
+ final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
+ if (elems.length < 2 || elems.length > 3) {
+ throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype);
+ }
+ final String localeString = elems[0];
+ final String keyboardLayoutSetName = elems[1];
+ final String extraValue = (elems.length == 3) ? elems[2] : null;
+ return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue);
+ }
- public static InputMethodSubtype[] createAdditionalSubtypesArray(String csvSubtypes) {
- final String[] subtypeSpecs = csvSubtypes.split(SUBTYPE_SEPARATOR);
- final InputMethodSubtype[] subtypesArray = new InputMethodSubtype[subtypeSpecs.length];
- for (int i = 0; i < subtypeSpecs.length; i++) {
- final String elems[] = subtypeSpecs[i].split(LOCALE_AND_LAYOUT_SEPARATOR);
- final String localeString = elems[0];
- final String keyboardLayoutSetName = elems[1];
- subtypesArray[i] = AdditionalSubtype.createAdditionalSubtype(
- localeString, keyboardLayoutSetName);
+ public static InputMethodSubtype[] createAdditionalSubtypesArray(String prefSubtypes) {
+ final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR);
+ final InputMethodSubtype[] subtypesArray = new InputMethodSubtype[prefSubtypeArray.length];
+ for (int i = 0; i < prefSubtypeArray.length; i++) {
+ subtypesArray[i] = createAdditionalSubtype(prefSubtypeArray[i]);
}
return subtypesArray;
}
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
new file mode 100644
index 000000000..7a22c9742
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -0,0 +1,440 @@
+/**
+ * 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;
+
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
+
+import java.util.Locale;
+import java.util.TreeSet;
+
+public class AdditionalSubtypeSettings extends PreferenceFragment {
+ private SharedPreferences mPrefs;
+ private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
+ private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
+
+ private PreferenceGroup mSubtypePrefGroup;
+
+ private static final int MENU_ADD_SUBTYPE = Menu.FIRST;
+
+ static class SubtypeLocaleItem extends Pair<String, String>
+ implements Comparable<SubtypeLocaleItem> {
+ public SubtypeLocaleItem(String localeString, String displayName) {
+ super(localeString, displayName);
+ }
+
+ public SubtypeLocaleItem(String localeString) {
+ this(localeString, getDisplayName(localeString));
+ }
+
+ @Override
+ public String toString() {
+ return second;
+ }
+
+ @Override
+ public int compareTo(SubtypeLocaleItem o) {
+ return first.compareTo(o.first);
+ }
+
+ private static String getDisplayName(String localeString) {
+ final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
+ return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
+ }
+ }
+
+ static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
+ public SubtypeLocaleAdapter(Context context) {
+ super(context, android.R.layout.simple_spinner_item);
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ final TreeSet<SubtypeLocaleItem> items = new TreeSet<SubtypeLocaleItem>();
+ final InputMethodInfo imi = ImfUtils.getInputMethodInfoOfThisIme(context);
+ final int count = imi.getSubtypeCount();
+ for (int i = 0; i < count; i++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ if (subtype.containsExtraValueKey(ASCII_CAPABLE)) {
+ items.add(createItem(context, subtype.getLocale()));
+ }
+ }
+ // TODO: Should filter out already existing combinations of locale and layout.
+ addAll(items);
+ }
+
+ public static SubtypeLocaleItem createItem(Context context, String localeString) {
+ if (localeString.equals(SubtypeLocale.NO_LANGUAGE)) {
+ final String displayName = context.getString(R.string.subtype_no_language);
+ return new SubtypeLocaleItem(localeString, displayName);
+ } else {
+ return new SubtypeLocaleItem(localeString);
+ }
+ }
+ }
+
+ static class KeyboardLayoutSetItem extends Pair<String, String> {
+ public KeyboardLayoutSetItem(String keyboardLayoutSetName) {
+ super(keyboardLayoutSetName, getDisplayName(keyboardLayoutSetName));
+ }
+
+ @Override
+ public String toString() {
+ return second;
+ }
+
+ private static String getDisplayName(String keyboardLayoutSetName) {
+ return keyboardLayoutSetName.toUpperCase();
+ }
+ }
+
+ static class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
+ public KeyboardLayoutSetAdapter(Context context) {
+ super(context, android.R.layout.simple_spinner_item);
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ // TODO: Should filter out already existing combinations of locale and layout.
+ for (final String layout : AdditionalSubtype.PREDEFINED_KEYBOARD_LAYOUT_SET) {
+ add(new KeyboardLayoutSetItem(layout));
+ }
+ }
+ }
+
+ private interface SubtypeDialogProxy {
+ public void onRemovePressed(SubtypePreference subtypePref);
+ public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
+ public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
+ }
+
+ static class SubtypePreference extends DialogPreference {
+ private InputMethodSubtype mSubtype;
+
+ private final SubtypeDialogProxy mProxy;
+ private Spinner mSubtypeLocaleSpinner;
+ private Spinner mKeyboardLayoutSetSpinner;
+
+ public SubtypePreference(Context context, InputMethodSubtype subtype,
+ SubtypeDialogProxy proxy) {
+ super(context, null);
+ setPersistent(false);
+ mProxy = proxy;
+ setSubtype(subtype);
+ }
+
+ public void show() {
+ showDialog(null);
+ }
+
+ public InputMethodSubtype getSubtype() {
+ return mSubtype;
+ }
+
+ public void setSubtype(InputMethodSubtype subtype) {
+ mSubtype = subtype;
+ if (subtype == null) {
+ setTitle(null);
+ setDialogTitle(R.string.add_style);
+ } else {
+ final String displayName = SubtypeLocale.getFullDisplayName(subtype);
+ setTitle(displayName);
+ setDialogTitle(displayName);
+ }
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ final Context context = builder.getContext();
+ final View v = LayoutInflater.from(context).inflate(
+ R.layout.additional_subtype_dialog, null);
+ builder.setView(v);
+ mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
+ mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
+ mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
+ mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
+
+ if (mSubtype == null) {
+ builder.setPositiveButton(R.string.add, this)
+ .setNegativeButton(android.R.string.cancel, this);
+ } else {
+ builder.setPositiveButton(R.string.save, this)
+ .setNeutralButton(android.R.string.cancel, this)
+ .setNegativeButton(R.string.remove, this);
+ final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
+ context, mSubtype.getLocale());
+ final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(
+ SubtypeLocale.getKeyboardLayoutSetName(mSubtype));
+ setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
+ setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
+ }
+ }
+
+ private static void setSpinnerPosition(Spinner spinner, Object itemToSelect) {
+ final SpinnerAdapter adapter = spinner.getAdapter();
+ final int count = adapter.getCount();
+ for (int i = 0; i < count; i++) {
+ final Object item = spinner.getItemAtPosition(i);
+ if (item.equals(itemToSelect)) {
+ spinner.setSelection(i);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ final SubtypeLocaleItem locale =
+ (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
+ final KeyboardLayoutSetItem layout =
+ (KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
+ final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
+ locale.first, layout.first, ASCII_CAPABLE);
+ setSubtype(subtype);
+ notifyChanged();
+ break;
+ case DialogInterface.BUTTON_NEUTRAL:
+ // Nothing to do
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ mProxy.onRemovePressed(this);
+ break;
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final SavedState myState = new SavedState(super.onSaveInstanceState());
+ myState.mSubtype = mSubtype;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof SavedState) {
+ final SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(state);
+ setSubtype(myState.mSubtype);
+ } else {
+ super.onRestoreInstanceState(state);
+ }
+ }
+
+ static class SavedState extends Preference.BaseSavedState {
+ InputMethodSubtype mSubtype;
+ private static final byte VALID = 1;
+ private static final byte INVALID = 0;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ if (mSubtype != null) {
+ dest.writeByte(VALID);
+ mSubtype.writeToParcel(dest, 0);
+ } else {
+ dest.writeByte(INVALID);
+ }
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ if (source.readByte() == VALID) {
+ mSubtype = source.readParcelable(null);
+ } else {
+ mSubtype = null;
+ }
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel source) {
+ return new SavedState(source);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+ }
+
+ public AdditionalSubtypeSettings() {
+ // Empty constructor for fragment generation.
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.additional_subtype_settings);
+ setHasOptionsMenu(true);
+ mSubtypePrefGroup = getPreferenceScreen();
+
+ mPrefs = getPreferenceManager().getSharedPreferences();
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final Context context = getActivity();
+ mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
+ mKeyboardLayoutSetAdapter = new KeyboardLayoutSetAdapter(context);
+
+ // TODO: Restore editing dialog if any.
+ }
+
+ private final SubtypeDialogProxy mSubtypeProxy = new SubtypeDialogProxy() {
+ @Override
+ public void onRemovePressed(SubtypePreference subtypePref) {
+ final PreferenceGroup group = mSubtypePrefGroup;
+ if (group != null) {
+ group.removePreference(subtypePref);
+ }
+ }
+
+ @Override
+ public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
+ return mSubtypeLocaleAdapter;
+ }
+
+ @Override
+ public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
+ return mKeyboardLayoutSetAdapter;
+ }
+ };
+
+ private void setPrefSubtypes(String prefSubtypes, Context context) {
+ final PreferenceGroup group = mSubtypePrefGroup;
+ group.removeAll();
+ final String[] prefSubtypeArray = prefSubtypes.split(
+ AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
+ for (final String prefSubtype : prefSubtypeArray) {
+ final InputMethodSubtype subtype =
+ AdditionalSubtype.createAdditionalSubtype(prefSubtype);
+ final SubtypePreference pref = new SubtypePreference(
+ context, subtype, mSubtypeProxy);
+ group.addPreference(pref);
+ }
+ }
+
+ private String getPrefSubtypes() {
+ final StringBuilder sb = new StringBuilder();
+ final int count = mSubtypePrefGroup.getPreferenceCount();
+ for (int i = 0; i < count; i++) {
+ final Preference pref = mSubtypePrefGroup.getPreference(i);
+ if (pref instanceof SubtypePreference) {
+ final InputMethodSubtype subtype = ((SubtypePreference)pref).getSubtype();
+ if (sb.length() > 0) {
+ sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
+ }
+ sb.append(AdditionalSubtype.getPrefSubtype(subtype));
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ final String prefSubtypes =
+ SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
+ setPrefSubtypes(prefSubtypes, getActivity());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ final String oldSubtypes = SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
+ final String prefSubtypes = getPrefSubtypes();
+ if (prefSubtypes.equals(oldSubtypes)) {
+ return;
+ }
+
+ final SharedPreferences.Editor editor = mPrefs.edit();
+ try {
+ editor.putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
+ } finally {
+ editor.apply();
+ }
+ final InputMethodSubtype[] subtypes =
+ AdditionalSubtype.createAdditionalSubtypesArray(prefSubtypes);
+ ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), subtypes);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // TODO: save editing dialog state.
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen prefScreen, Preference pref) {
+ if (pref instanceof SubtypePreference) {
+ return true;
+ }
+ return super.onPreferenceTreeClick(prefScreen, pref);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ final MenuItem addSubtypeMenu = menu.add(0, MENU_ADD_SUBTYPE, 0, R.string.add_style);
+ addSubtypeMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == MENU_ADD_SUBTYPE) {
+ final SubtypePreference subtypePref = new SubtypePreference(
+ getActivity(), null, mSubtypeProxy);
+ mSubtypePrefGroup.addPreference(subtypePref);
+ subtypePref.show();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
new file mode 100644
index 000000000..b205cc004
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import android.view.inputmethod.EditorInfo;
+
+public final class Constants {
+ 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 {@link EditorInfo#IME_FLAG_FORCE_ASCII}.
+ */
+ @SuppressWarnings("dep-ann")
+ public static final String FORCE_ASCII = "forceAscii";
+
+ 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 the subtype keyboard layout set name.
+ */
+ public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
+
+ /**
+ * The subtype extra value used to indicate that the subtype keyboard layout is capable
+ * for typing ASCII characters.
+ */
+ public static final String ASCII_CAPABLE = "AsciiCapable";
+
+ /**
+ * The subtype extra value used to indicate that the subtype require network connection
+ * to work.
+ */
+ public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
+
+ /**
+ * The subtype extra value used to indicate that the subtype is additional subtype
+ * that the user defined. This extra value is private to LatinIME.
+ */
+ public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
+
+ private ExtraValue() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ private Subtype() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ private Constants() {
+ // This utility class is not publicly instantiable.
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 17d75368e..f5dc7b34a 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -30,7 +30,10 @@ import java.util.Locale;
* Factory for dictionary instances.
*/
public class DictionaryFactory {
- private static String TAG = DictionaryFactory.class.getSimpleName();
+ private static final String TAG = DictionaryFactory.class.getSimpleName();
+ // This class must be located in the same package as LatinIME.java.
+ private static final String RESOURCE_PACKAGE_NAME =
+ DictionaryFactory.class.getPackage().getName();
/**
* Initializes a dictionary from a dictionary pack, with explicit flags.
@@ -166,20 +169,19 @@ public class DictionaryFactory {
*/
private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
final Locale locale) {
- final String packageName = LatinIME.class.getPackage().getName();
int resId;
-
// Try to find main_language_country dictionary.
if (!locale.getCountry().isEmpty()) {
final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase();
- if ((resId = res.getIdentifier(dictLanguageCountry, "raw", packageName)) != 0) {
+ if ((resId = res.getIdentifier(
+ dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
return resId;
}
}
// Try to find main_language dictionary.
final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
- if ((resId = res.getIdentifier(dictLanguage, "raw", packageName)) != 0) {
+ if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
return resId;
}
@@ -195,7 +197,6 @@ public class DictionaryFactory {
public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
if (0 != resourceId) return resourceId;
- final String packageName = LatinIME.class.getPackage().getName();
- return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", packageName);
+ return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
}
}
diff --git a/java/src/com/android/inputmethod/latin/ImfUtils.java b/java/src/com/android/inputmethod/latin/ImfUtils.java
index bd7d89fe7..4633b82f5 100644
--- a/java/src/com/android/inputmethod/latin/ImfUtils.java
+++ b/java/src/com/android/inputmethod/latin/ImfUtils.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
+
import android.content.Context;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -131,7 +133,7 @@ public class ImfUtils {
// both explicitly and implicitly enabled input method subtype.
// (The current IME should be LatinIME.)
for (InputMethodSubtype subtype : subtypes) {
- if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) {
+ if (KEYBOARD_MODE.equals(subtype.getMode())) {
++keyboardCount;
}
}
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index a6ce04069..9c32f947c 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -162,4 +162,12 @@ public class InputAttributes {
+ "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn
+ "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn;
}
+
+ public static boolean inPrivateImeOptions(String packageName, String key,
+ EditorInfo editorInfo) {
+ if (editorInfo == null) return false;
+ final String findingKey = (packageName != null) ? packageName + "." + key
+ : key;
+ return StringUtils.containsInCsv(findingKey, editorInfo.privateImeOptions);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 682901cbc..41884d34a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,6 +16,10 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -81,49 +85,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final boolean TRACE = false;
private static boolean DEBUG;
- /**
- * 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 LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed.
- */
- @SuppressWarnings("dep-ann")
- public static final String IME_OPTION_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 IME_OPTION_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 IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey";
-
- /**
- * The private IME option used to indicate that the given text field needs
- * ASCII code points input.
- *
- * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}.
- */
- @SuppressWarnings("dep-ann")
- public static final String IME_OPTION_FORCE_ASCII = "forceAscii";
-
- /**
- * The subtype extra value used to indicate that the subtype keyboard layout set name.
- */
- public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
-
- /**
- * The subtype extra value used to indicate that the subtype keyboard layout is capable for
- * typing ASCII characters.
- */
- public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
-
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
// How many continuous deletes at which to start deleting at a higher speed.
@@ -193,6 +154,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private final SubtypeSwitcher mSubtypeSwitcher;
private boolean mShouldSwitchToLastSubtype = true;
+ private boolean mIsMainDictionaryAvailable;
private UserDictionary mUserDictionary;
private UserHistoryDictionary mUserHistoryDictionary;
private boolean mIsUserDictionaryAvailable;
@@ -488,14 +450,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return new SettingsValues(mPrefs, LatinIME.this);
}
};
- mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getInputLocale());
+ mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues);
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
private void initSuggest() {
- final String localeStr = mSubtypeSwitcher.getInputLocaleStr();
- final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale();
+ final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ final String localeStr = subtypeLocale.toString();
final Dictionary oldContactsDictionary;
if (mSuggest != null) {
@@ -504,11 +466,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
oldContactsDictionary = null;
}
- mSuggest = new Suggest(this, keyboardLocale);
+ mSuggest = new Suggest(this, subtypeLocale);
if (mSettingsValues.mAutoCorrectEnabled) {
mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
}
+ mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
+
mUserDictionary = new UserDictionary(this, localeStr);
mSuggest.setUserDictionary(mUserDictionary);
mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
@@ -550,7 +514,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
if (USE_BINARY_CONTACTS_DICTIONARY) {
dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS,
- mSubtypeSwitcher.getInputLocale());
+ mSubtypeSwitcher.getCurrentSubtypeLocale());
} else {
dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS);
}
@@ -562,7 +526,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
/* package private */ void resetSuggestMainDict() {
- mSuggest.resetMainDict(this, mSubtypeSwitcher.getInputLocale());
+ final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ mSuggest.resetMainDict(this, subtypeLocale);
+ mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
}
@Override
@@ -642,13 +608,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
- SubtypeSwitcher.getInstance().updateSubtype(subtype);
+ mSubtypeSwitcher.updateSubtype(subtype);
}
private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) {
super.onStartInput(editorInfo, restarting);
}
+ @SuppressWarnings("deprecation")
private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
super.onStartInputView(editorInfo, restarting);
final KeyboardSwitcher switcher = mKeyboardSwitcher;
@@ -669,12 +636,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onStartInputViewInternal(editorInfo);
}
- if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) {
+ if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: "
+ editorInfo.privateImeOptions);
- Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead");
+ Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
}
- if (StringUtils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) {
+ if (InputAttributes.inPrivateImeOptions(getPackageName(), FORCE_ASCII, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: "
+ editorInfo.privateImeOptions);
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
@@ -1077,7 +1044,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ic == null) return false;
final CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
- && StringUtils.canBeFollowedByPeriod(lastThree.charAt(0))
+ && canBeFollowedByPeriod(lastThree.charAt(0))
&& lastThree.charAt(1) == Keyboard.CODE_SPACE
&& lastThree.charAt(2) == Keyboard.CODE_SPACE
&& mHandler.isAcceptingDoubleSpaces()) {
@@ -1093,6 +1060,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return false;
}
+ private static boolean canBeFollowedByPeriod(final int codePoint) {
+ // TODO: Check again whether there really ain't a better way to check this.
+ // TODO: This should probably be language-dependant...
+ return Character.isLetterOrDigit(codePoint)
+ || codePoint == Keyboard.CODE_SINGLE_QUOTE
+ || codePoint == Keyboard.CODE_DOUBLE_QUOTE
+ || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
+ || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
+ || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
+ || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
+ }
+
// "ic" may be null
private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) {
if (ic == null) return;
@@ -1920,7 +1899,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mSettingsValues.mEnableSuggestionSpanInsertion) {
final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
- this, bestWord, suggestedWords, mSubtypeSwitcher.isDictionaryAvailable()),
+ this, bestWord, suggestedWords, mIsMainDictionaryAvailable),
1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(bestWord);
@@ -1998,7 +1977,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
final String secondWord;
if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
- secondWord = suggestion.toString().toLowerCase(mSubtypeSwitcher.getInputLocale());
+ secondWord = suggestion.toString().toLowerCase(
+ mSubtypeSwitcher.getCurrentSubtypeLocale());
} else {
secondWord = suggestion.toString();
}
@@ -2326,8 +2306,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void showOptionDialogInternal(AlertDialog dialog) {
- final IBinder windowToken = KeyboardSwitcher.getInstance().getKeyboardView()
- .getWindowToken();
+ final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
if (windowToken == null) return;
dialog.setCancelable(true);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 29825df7d..13264f7e8 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -33,6 +33,7 @@ import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.inputmethod.InputMethodSubtype;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
@@ -255,6 +256,7 @@ public class Settings extends InputMethodSettingsFragment
}
updateShowCorrectionSuggestionsSummary();
updateKeyPreviewPopupDelaySummary();
+ updateCustomInputStylesSummary();
}
@Override
@@ -294,6 +296,21 @@ public class Settings extends InputMethodSettingsFragment
mShowCorrectionSuggestionsPreference.getValue())]);
}
+ private void updateCustomInputStylesSummary() {
+ final PreferenceScreen customInputStyles =
+ (PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
+ final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+ final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, getResources());
+ final InputMethodSubtype[] subtypes =
+ AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
+ final StringBuilder styles = new StringBuilder();
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (styles.length() > 0) styles.append(", ");
+ styles.append(SubtypeLocale.getFullDisplayName(subtype));
+ }
+ customInputStyles.setSummary(styles);
+ }
+
private void updateKeyPreviewPopupDelaySummary() {
final ListPreference lp = mKeyPreviewPopupDismissDelay;
lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
diff --git a/java/src/com/android/inputmethod/latin/SettingsActivity.java b/java/src/com/android/inputmethod/latin/SettingsActivity.java
index 556701364..68f8582fc 100644
--- a/java/src/com/android/inputmethod/latin/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/SettingsActivity.java
@@ -20,11 +20,15 @@ import android.content.Intent;
import android.preference.PreferenceActivity;
public class SettingsActivity extends PreferenceActivity {
+ private static final String DEFAULT_FRAGMENT = Settings.class.getName();
+
@Override
public Intent getIntent() {
- final Intent modIntent = new Intent(super.getIntent());
- modIntent.putExtra(EXTRA_SHOW_FRAGMENT, Settings.class.getName());
- modIntent.putExtra(EXTRA_NO_HEADERS, true);
- return modIntent;
+ final Intent intent = super.getIntent();
+ if (!intent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT);
+ }
+ intent.putExtra(EXTRA_NO_HEADERS, true);
+ return intent;
}
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index c160555f0..5f9e1bc76 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -28,7 +28,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Locale;
/**
* When you call the constructor of this class, you may want to change the current system locale by
@@ -148,9 +147,8 @@ public class SettingsValues {
mAutoCorrectionThresholdRawValue);
mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
-
mAdditionalSubtypes = AdditionalSubtype.createAdditionalSubtypesArray(
- getCsvAdditionalSubtypes(prefs, res));
+ getPrefAdditionalSubtypes(prefs, res));
}
// Helper functions to create member values.
@@ -315,10 +313,10 @@ public class SettingsValues {
return mAdditionalSubtypes;
}
- public static String getCsvAdditionalSubtypes(final SharedPreferences prefs,
+ public static String getPrefAdditionalSubtypes(final SharedPreferences prefs,
final Resources res) {
- final String csvPredefinedSubtypes = res.getString(R.string.predefined_subtypes, "");
- return prefs.getString(Settings.PREF_CUSTOM_INPUT_STYLES, csvPredefinedSubtypes);
+ final String prefSubtypes = res.getString(R.string.predefined_subtypes, "");
+ return prefs.getString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
}
// Accessed from the settings interface, hence public
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index a599933d8..160581cbe 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -17,9 +17,6 @@
package com.android.inputmethod.latin;
import android.text.TextUtils;
-import android.view.inputmethod.EditorInfo;
-
-import com.android.inputmethod.keyboard.Keyboard;
import java.util.ArrayList;
import java.util.Locale;
@@ -29,39 +26,38 @@ public class StringUtils {
// This utility class is not publicly instantiable.
}
- public static boolean canBeFollowedByPeriod(final int codePoint) {
- // TODO: Check again whether there really ain't a better way to check this.
- // TODO: This should probably be language-dependant...
- return Character.isLetterOrDigit(codePoint)
- || codePoint == Keyboard.CODE_SINGLE_QUOTE
- || codePoint == Keyboard.CODE_DOUBLE_QUOTE
- || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
- || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
- || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
- || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
- }
-
public static int codePointCount(String text) {
if (TextUtils.isEmpty(text)) return 0;
return text.codePointCount(0, text.length());
}
- private static boolean containsInCsv(String key, String csv) {
- if (csv == null)
- return false;
- for (String option : csv.split(",")) {
- if (option.equals(key))
- return true;
+ public static boolean containsInArray(String key, String[] array) {
+ for (final String element : array) {
+ if (key.equals(element)) return true;
}
return false;
}
- public static boolean inPrivateImeOptions(String packageName, String key,
- EditorInfo editorInfo) {
- if (editorInfo == null)
- return false;
- return containsInCsv(packageName != null ? packageName + "." + key : key,
- editorInfo.privateImeOptions);
+ public static boolean containsInCsv(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return false;
+ return containsInArray(key, csv.split(","));
+ }
+
+ public static String appendToCsvIfNotExists(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return key;
+ if (containsInCsv(key, csv)) return csv;
+ return csv + "," + key;
+ }
+
+ public static String removeFromCsvIfExists(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return "";
+ final String[] elements = csv.split(",");
+ if (!containsInArray(key, elements)) return csv;
+ final ArrayList<String> result = new ArrayList<String>(elements.length - 1);
+ for (final String element : elements) {
+ if (!key.equals(element)) result.add(element);
+ }
+ return TextUtils.join(",", result);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 37f46fc79..fc6193287 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
import android.content.Context;
import android.content.res.Resources;
import android.view.inputmethod.InputMethodSubtype;
@@ -24,6 +26,8 @@ import java.util.HashMap;
import java.util.Locale;
public class SubtypeLocale {
+ private static final String TAG = SubtypeLocale.class.getSimpleName();
+
// Special language code to represent "no language".
public static final String NO_LANGUAGE = "zz";
@@ -56,26 +60,29 @@ public class SubtypeLocale {
// zz qwerty F QWERTY QWERTY
// fr qwertz T Fr Français Français (QWERTZ)
// de qwerty T De Deutsch Deutsch (QWERTY)
- // en azerty T En English English (AZERTY)
+ // en_US azerty T En English English (US) (AZERTY)
// zz azerty T AZERTY AZERTY
// Get InputMethodSubtype's full display name in its locale.
public static String getFullDisplayName(InputMethodSubtype subtype) {
- final String value = sExceptionalDisplayNamesMap.get(subtype.getLocale());
- if (value != null) {
- return value;
- }
-
if (isNoLanguage(subtype)) {
return getKeyboardLayoutSetDisplayName(subtype);
}
+ final String exceptionalValue = sExceptionalDisplayNamesMap.get(subtype.getLocale());
+
final Locale locale = getSubtypeLocale(subtype);
- final String language = StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
if (AdditionalSubtype.isAdditionalSubtype(subtype)) {
- return String.format("%s (%s)",
- language, getKeyboardLayoutSetDisplayName(subtype));
+ final String language = (exceptionalValue != null) ? exceptionalValue
+ : StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
+ final String layout = getKeyboardLayoutSetDisplayName(subtype);
+ return String.format("%s (%s)", language, layout);
}
+
+ if (exceptionalValue != null) {
+ return exceptionalValue;
+ }
+
return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
}
@@ -112,11 +119,14 @@ public class SubtypeLocale {
}
public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {
- final String keyboardLayoutSet = subtype.getExtraValueOf(
- LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET);
+ final String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
// TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is
// fixed.
- if (keyboardLayoutSet == null) return AdditionalSubtype.QWERTY;
+ if (keyboardLayoutSet == null) {
+ android.util.Log.w(TAG, "KeyboardLayoutSet not found, use QWERTY: " +
+ "locale=" + subtype.getLocale() + " extraValue=" + subtype.getExtraValue());
+ return AdditionalSubtype.QWERTY;
+ }
return keyboardLayoutSet;
}
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index cf95a7e1a..3b9a4069d 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -16,16 +16,16 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
+
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.IBinder;
-import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -33,7 +33,6 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -42,41 +41,42 @@ public class SubtypeSwitcher {
private static boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = SubtypeSwitcher.class.getSimpleName();
- public static final String KEYBOARD_MODE = "keyboard";
- private static final char LOCALE_SEPARATOR = '_';
- private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY =
- "requireNetworkConnectivity";
-
- private final TextUtils.SimpleStringSplitter mLocaleSplitter =
- new TextUtils.SimpleStringSplitter(LOCALE_SEPARATOR);
-
private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
private /* final */ LatinIME mService;
private /* final */ InputMethodManager mImm;
private /* final */ Resources mResources;
private /* final */ ConnectivityManager mConnectivityManager;
- private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod =
- new ArrayList<InputMethodSubtype>();
- private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>();
/*-----------------------------------------------------------*/
// Variants which should be changed only by reload functions.
- private boolean mNeedsToDisplayLanguage;
- private boolean mIsDictionaryAvailable;
- private boolean mIsSystemLanguageSameAsInputLanguage;
+ private NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage();
private InputMethodInfo mShortcutInputMethodInfo;
private InputMethodSubtype mShortcutSubtype;
- private List<InputMethodSubtype> mAllEnabledSubtypesOfCurrentInputMethod;
private InputMethodSubtype mNoLanguageSubtype;
// Note: This variable is always non-null after {@link #initialize(LatinIME)}.
private InputMethodSubtype mCurrentSubtype;
- private Locale mSystemLocale;
- private Locale mInputLocale;
- private String mInputLocaleStr;
+ private Locale mCurrentSystemLocale;
/*-----------------------------------------------------------*/
private boolean mIsNetworkConnected;
+ static class NeedsToDisplayLanguage {
+ private int mEnabledSubtypeCount;
+ private boolean mIsSystemLanguageSameAsInputLanguage;
+
+ public boolean getValue() {
+ return mEnabledSubtypeCount >= 2 || !mIsSystemLanguageSameAsInputLanguage;
+ }
+
+ public void updateEnabledSubtypeCount(int count) {
+ mEnabledSubtypeCount = count;
+ }
+
+ public void updateIsSystemLanguageSameAsInputLanguage(boolean isSame) {
+ mIsSystemLanguageSameAsInputLanguage = isSame;
+ }
+ }
+
public static SubtypeSwitcher getInstance() {
return sInstance;
}
@@ -97,13 +97,8 @@ public class SubtypeSwitcher {
mImm = ImfUtils.getInputMethodManager(service);
mConnectivityManager = (ConnectivityManager) service.getSystemService(
Context.CONNECTIVITY_SERVICE);
- mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
- mEnabledLanguagesOfCurrentInputMethod.clear();
- mSystemLocale = null;
- mInputLocale = null;
- mInputLocaleStr = null;
+ mCurrentSystemLocale = mResources.getConfiguration().locale;
mCurrentSubtype = mImm.getCurrentInputMethodSubtype();
- mAllEnabledSubtypesOfCurrentInputMethod = null;
mNoLanguageSubtype = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
service, SubtypeLocale.NO_LANGUAGE, AdditionalSubtype.QWERTY);
@@ -114,7 +109,7 @@ public class SubtypeSwitcher {
// Update all parameters stored in SubtypeSwitcher.
// Only configuration changed event is allowed to call this because this is heavy.
private void updateAllParameters() {
- mSystemLocale = mResources.getConfiguration().locale;
+ mCurrentSystemLocale = mResources.getConfiguration().locale;
updateSubtype(mImm.getCurrentInputMethodSubtype());
updateParametersOnStartInputView();
}
@@ -128,31 +123,20 @@ public class SubtypeSwitcher {
// Reload enabledSubtypes from the framework.
private void updateEnabledSubtypes() {
- final String currentMode = mCurrentSubtype.getMode();
+ final InputMethodSubtype currentSubtype = mCurrentSubtype;
boolean foundCurrentSubtypeBecameDisabled = true;
- mAllEnabledSubtypesOfCurrentInputMethod = mImm.getEnabledInputMethodSubtypeList(
- null, true);
- mEnabledLanguagesOfCurrentInputMethod.clear();
- mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
- for (InputMethodSubtype ims : mAllEnabledSubtypesOfCurrentInputMethod) {
- final String locale = ims.getLocale();
- final String mode = ims.getMode();
- mLocaleSplitter.setString(locale);
- if (mLocaleSplitter.hasNext()) {
- mEnabledLanguagesOfCurrentInputMethod.add(mLocaleSplitter.next());
- }
- if (locale.equals(mInputLocaleStr) && mode.equals(currentMode)) {
+ final List<InputMethodSubtype> enabledSubtypesOfThisIme =
+ mImm.getEnabledInputMethodSubtypeList(null, true);
+ for (InputMethodSubtype ims : enabledSubtypesOfThisIme) {
+ if (ims.equals(currentSubtype)) {
foundCurrentSubtypeBecameDisabled = false;
}
- if (KEYBOARD_MODE.equals(ims.getMode())) {
- mEnabledKeyboardSubtypesOfCurrentInputMethod.add(ims);
- }
}
- mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
- && mIsSystemLanguageSameAsInputLanguage);
+ mNeedsToDisplayLanguage.updateEnabledSubtypeCount(enabledSubtypesOfThisIme.size());
if (foundCurrentSubtypeBecameDisabled) {
if (DBG) {
- Log.w(TAG, "Current subtype: " + mInputLocaleStr + ", " + currentMode);
+ Log.w(TAG, "Last subtype: "
+ + currentSubtype.getLocale() + "/" + currentSubtype.getExtraValue());
Log.w(TAG, "Last subtype was disabled. Update to the current one.");
}
updateSubtype(mImm.getCurrentInputMethodSubtype());
@@ -193,70 +177,20 @@ public class SubtypeSwitcher {
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
public void updateSubtype(InputMethodSubtype newSubtype) {
- final String newLocale = newSubtype.getLocale();
- final String newMode = newSubtype.getMode();
- final String oldMode = mCurrentSubtype.getMode();
if (DBG) {
- Log.w(TAG, "Update subtype to:" + newLocale + "," + newMode
- + ", from: " + mInputLocaleStr + ", " + oldMode);
- }
- boolean languageChanged = false;
- if (!newLocale.equals(mInputLocaleStr)) {
- if (mInputLocaleStr != null) {
- languageChanged = true;
- }
- updateInputLocale(newLocale);
+ Log.w(TAG, "onCurrentInputMethodSubtypeChanged: to: "
+ + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: "
+ + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue());
}
- boolean modeChanged = false;
- if (!newMode.equals(oldMode)) {
- if (oldMode != null) {
- modeChanged = true;
- }
- }
- mCurrentSubtype = newSubtype;
+ if (newSubtype.equals(mCurrentSubtype)) return;
- if (KEYBOARD_MODE.equals(mCurrentSubtype.getMode())) {
- if (modeChanged || languageChanged) {
- updateShortcutIME();
- mService.onRefreshKeyboard();
- }
- } else {
- final String packageName = mService.getPackageName();
- int version = -1;
- try {
- version = mService.getPackageManager().getPackageInfo(
- packageName, 0).versionCode;
- } catch (NameNotFoundException e) {
- }
- Log.w(TAG, "Unknown subtype mode: " + newMode + "," + version + ", " + packageName
- + ". IME is already changed to other IME.");
- Log.w(TAG, "Subtype mode:" + newSubtype.getMode());
- Log.w(TAG, "Subtype locale:" + newSubtype.getLocale());
- Log.w(TAG, "Subtype extra value:" + newSubtype.getExtraValue());
- Log.w(TAG, "Subtype is auxiliary:" + newSubtype.isAuxiliary());
- }
- }
+ final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
+ mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(
+ mCurrentSystemLocale.equals(newLocale));
- // Update the current input locale from Locale string.
- private void updateInputLocale(String inputLocaleStr) {
- // example: inputLocaleStr = "en_US" "en" ""
- // "en_US" --> language: en & country: US
- // "en" --> language: en
- // "" --> the system locale
- if (!TextUtils.isEmpty(inputLocaleStr)) {
- mInputLocale = LocaleUtils.constructLocaleFromString(inputLocaleStr);
- mInputLocaleStr = inputLocaleStr;
- } else {
- mInputLocale = mSystemLocale;
- String country = mSystemLocale.getCountry();
- mInputLocaleStr = mSystemLocale.getLanguage()
- + (TextUtils.isEmpty(country) ? "" : "_" + mSystemLocale.getLanguage());
- }
- mIsSystemLanguageSameAsInputLanguage = getSystemLocale().getLanguage().equalsIgnoreCase(
- getInputLocale().getLanguage());
- mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
- && mIsSystemLanguageSameAsInputLanguage);
- mIsDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(mService, mInputLocale);
+ mCurrentSubtype = newSubtype;
+ updateShortcutIME();
+ mService.onRefreshKeyboard();
}
////////////////////////////
@@ -309,8 +243,7 @@ public class SubtypeSwitcher {
return false;
if (mShortcutSubtype == null)
return true;
- if (mShortcutSubtype.containsExtraValueKey(
- SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY)) {
+ if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
return mIsNetworkConnected;
}
return true;
@@ -325,62 +258,31 @@ public class SubtypeSwitcher {
}
//////////////////////////////////
- // Language Switching functions //
+ // Subtype Switching functions //
//////////////////////////////////
- public int getEnabledKeyboardLocaleCount() {
- return mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
- }
-
public boolean needsToDisplayLanguage(Locale keyboardLocale) {
if (keyboardLocale.toString().equals(SubtypeLocale.NO_LANGUAGE)) {
return true;
}
- if (!keyboardLocale.equals(mInputLocale)) {
+ if (!keyboardLocale.equals(getCurrentSubtypeLocale())) {
return false;
}
- return mNeedsToDisplayLanguage;
- }
-
- public Locale getInputLocale() {
- return mInputLocale;
+ return mNeedsToDisplayLanguage.getValue();
}
- public String getInputLocaleStr() {
- return mInputLocaleStr;
- }
-
- public String[] getEnabledLanguages() {
- int enabledLanguageCount = mEnabledLanguagesOfCurrentInputMethod.size();
- // Workaround for explicitly specifying the voice language
- if (enabledLanguageCount == 1) {
- mEnabledLanguagesOfCurrentInputMethod.add(mEnabledLanguagesOfCurrentInputMethod
- .get(0));
- ++enabledLanguageCount;
- }
- return mEnabledLanguagesOfCurrentInputMethod.toArray(new String[enabledLanguageCount]);
- }
-
- public Locale getSystemLocale() {
- return mSystemLocale;
- }
-
- public boolean isSystemLanguageSameAsInputLanguage() {
- return mIsSystemLanguageSameAsInputLanguage;
+ public Locale getCurrentSubtypeLocale() {
+ return SubtypeLocale.getSubtypeLocale(mCurrentSubtype);
}
public void onConfigurationChanged(Configuration conf) {
final Locale systemLocale = conf.locale;
// If system configuration was changed, update all parameters.
- if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) {
+ if (!systemLocale.equals(mCurrentSystemLocale)) {
updateAllParameters();
}
}
- public boolean isDictionaryAvailable() {
- return mIsDictionaryAvailable;
- }
-
public InputMethodSubtype getCurrentSubtype() {
return mCurrentSubtype;
}