aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java76
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java12
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java63
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java34
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java79
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java27
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java (renamed from java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java)785
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtype.java22
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java19
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java20
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java71
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java99
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java31
-rw-r--r--java/src/com/android/inputmethod/latin/ResearchLogger.java267
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeLocale.java49
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java188
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java97
21 files changed, 924 insertions, 1046 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
index bb5890ad2..004ee4c22 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.accessibility;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
+import android.os.Bundle;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
@@ -185,14 +186,15 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat
* the host View, with the given <code>virtualViewId</code> or the host View itself if
* <code>virtualViewId</code> equals to {@link View#NO_ID}.
*
- * @param action The action to perform.
* @param virtualViewId A client defined virtual view id.
+ * @param action The action to perform.
+ * @param arguments Optional arguments.
* @return True if the action was performed.
* @see #createAccessibilityNodeInfo(int)
* @see AccessibilityNodeInfoCompat
*/
@Override
- public boolean performAccessibilityAction(int action, int virtualViewId) {
+ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
if (virtualViewId == View.NO_ID) {
// Perform the action on the host View.
switch (action) {
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 68858e5bf..0d78c39f2 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -16,6 +16,12 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_OUTPUT_TEXT;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_SHIFT;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED;
+import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
+
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -170,11 +176,11 @@ public class Key {
mLabel = label;
mOutputText = outputText;
mCode = code;
- mEnabled = (code != Keyboard.CODE_UNSPECIFIED);
- mAltCode = Keyboard.CODE_UNSPECIFIED;
+ mEnabled = (code != CODE_UNSPECIFIED);
+ mAltCode = CODE_UNSPECIFIED;
mIconId = iconId;
- mDisabledIconId = KeyboardIconsSet.ICON_UNDEFINED;
- mPreviewIconId = KeyboardIconsSet.ICON_UNDEFINED;
+ mDisabledIconId = ICON_UNDEFINED;
+ mPreviewIconId = ICON_UNDEFINED;
// Horizontal gap is divided equally to both sides of the key.
mX = x + mHorizontalGap / 2;
mY = y;
@@ -208,9 +214,9 @@ public class Key {
if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
style = keyStyles.getKeyStyle(styleName);
- if (style == null)
- throw new XmlParseUtils.ParseException(
- "Unknown key style: " + styleName, parser);
+ if (style == null) {
+ throw new XmlParseUtils.ParseException("Unknown key style: " + styleName, parser);
+ }
} else {
style = keyStyles.getEmptyKeyStyle();
}
@@ -235,12 +241,12 @@ public class Key {
R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0);
mVisualInsetsRight = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0);
- mPreviewIconId = style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED);
- mIconId = style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED);
- mDisabledIconId = style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED);
+ mIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIcon));
+ mDisabledIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIconDisabled));
+ mPreviewIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIconPreview));
mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
| row.getDefaultKeyLabelFlags();
@@ -272,8 +278,8 @@ public class Key {
if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) {
additionalMoreKeys = null;
} else {
- additionalMoreKeys = style.getStringArray(
- keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
+ additionalMoreKeys = style.getStringArray(keyAttr,
+ R.styleable.Keyboard_Key_additionalMoreKeys);
}
moreKeys = KeySpecParser.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
if (moreKeys != null) {
@@ -291,22 +297,21 @@ public class Key {
if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
mLabel = params.mId.mCustomActionLabel;
} else {
- mLabel = adjustCaseOfStringForKeyboardId(style.getString(
- keyAttr, R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
+ mLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
}
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
mHintLabel = null;
} else {
- mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(
- keyAttr, R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
+ mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
}
- String outputText = adjustCaseOfStringForKeyboardId(style.getString(
- keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
- final int code = KeySpecParser.parseCode(style.getString(
- keyAttr, R.styleable.Keyboard_Key_code),
- params.mCodesSet, Keyboard.CODE_UNSPECIFIED);
+ String outputText = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
+ final int code = KeySpecParser.parseCode(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_code), params.mCodesSet, CODE_UNSPECIFIED);
// Choose the first letter of the label as primary code if not specified.
- if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
+ if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
&& !TextUtils.isEmpty(mLabel)) {
if (StringUtils.codePointCount(mLabel) == 1) {
// Use the first letter of the hint label if shiftedLetterActivated flag is
@@ -321,22 +326,21 @@ public class Key {
// In some locale and case, the character might be represented by multiple code
// points, such as upper case Eszett of German alphabet.
outputText = mLabel;
- mCode = Keyboard.CODE_OUTPUT_TEXT;
+ mCode = CODE_OUTPUT_TEXT;
}
- } else if (code == Keyboard.CODE_UNSPECIFIED && outputText != null) {
+ } else if (code == CODE_UNSPECIFIED && outputText != null) {
if (StringUtils.codePointCount(outputText) == 1) {
mCode = outputText.codePointAt(0);
outputText = null;
} else {
- mCode = Keyboard.CODE_OUTPUT_TEXT;
+ mCode = CODE_OUTPUT_TEXT;
}
} else {
mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId);
}
mOutputText = outputText;
- mAltCode = adjustCaseOfCodeForKeyboardId(KeySpecParser.parseCode(style.getString(
- keyAttr, R.styleable.Keyboard_Key_altCode),
- params.mCodesSet, Keyboard.CODE_UNSPECIFIED),
+ mAltCode = adjustCaseOfCodeForKeyboardId(KeySpecParser.parseCode(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED),
preserveCase, params.mId);
mHashCode = computeHashCode(this);
@@ -353,7 +357,7 @@ public class Key {
final String text = new String(new int[] { code } , 0, 1);
final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id);
return StringUtils.codePointCount(casedText) == 1
- ? casedText.codePointAt(0) : Keyboard.CODE_UNSPECIFIED;
+ ? casedText.codePointAt(0) : CODE_UNSPECIFIED;
}
private static String adjustCaseOfStringForKeyboardId(String text, boolean preserveCase,
@@ -463,11 +467,11 @@ public class Key {
}
public boolean isShift() {
- return mCode == Keyboard.CODE_SHIFT;
+ return mCode == CODE_SHIFT;
}
public boolean isModifier() {
- return mCode == Keyboard.CODE_SHIFT || mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
+ return mCode == CODE_SHIFT || mCode == CODE_SWITCH_ALPHA_SYMBOL;
}
public boolean isRepeatable() {
@@ -586,7 +590,7 @@ public class Key {
}
public Drawable getPreviewIcon(KeyboardIconsSet iconSet) {
- return mPreviewIconId != KeyboardIconsSet.ICON_UNDEFINED
+ return mPreviewIconId != ICON_UNDEFINED
? iconSet.getIconDrawable(mPreviewIconId)
: iconSet.getIconDrawable(mIconId);
}
@@ -726,7 +730,7 @@ public class Key {
* This constructor is being used only for divider in more keys keyboard.
*/
protected Spacer(Keyboard.Params params, int x, int y, int width, int height) {
- super(params, null, null, KeyboardIconsSet.ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED,
+ super(params, null, null, ICON_UNDEFINED, CODE_UNSPECIFIED,
null, x, y, width, height, 0);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index fca8f56c8..28855f561 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -30,7 +30,7 @@ import android.view.InflateException;
import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyboardCodesSet;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardLabelsSet;
+import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
import com.android.inputmethod.latin.R;
@@ -236,8 +236,8 @@ public class Keyboard {
public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>();
public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
public final KeyboardCodesSet mCodesSet = new KeyboardCodesSet();
- public final KeyboardLabelsSet mLabelsSet = new KeyboardLabelsSet();
- public final KeyStyles mKeyStyles = new KeyStyles(mLabelsSet);
+ public final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
+ public final KeyStyles mKeyStyles = new KeyStyles(mTextsSet);
public KeyboardLayoutSet.KeysCache mKeysCache;
@@ -313,8 +313,11 @@ public class Keyboard {
public void onAddKey(Key newKey) {
final Key key = (mKeysCache != null) ? mKeysCache.get(newKey) : newKey;
- mKeys.add(key);
- updateHistogram(key);
+ final boolean zeroWidthSpacer = key.isSpacer() && key.mWidth == 0;
+ if (!zeroWidthSpacer) {
+ mKeys.add(key);
+ updateHistogram(key);
+ }
if (key.mCode == Keyboard.CODE_SHIFT) {
mShiftKeys.add(key);
}
@@ -776,11 +779,11 @@ public class Keyboard {
params.mIconsSet.loadIcons(keyboardAttr);
final String language = params.mId.mLocale.getLanguage();
params.mCodesSet.setLanguage(language);
- params.mLabelsSet.setLanguage(language);
+ params.mTextsSet.setLanguage(language);
final RunInLocale<Void> job = new RunInLocale<Void>() {
@Override
protected Void job(Resources res) {
- params.mLabelsSet.loadStringResources(mContext);
+ params.mTextsSet.loadStringResources(mContext);
return null;
}
};
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index efb0d77ea..d50d096c6 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -467,6 +467,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet) : null;
final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinKeyboardView_setKeyboard(keyboard);
+ }
}
/**
diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
index 392afca97..5712df1fc 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
@@ -18,9 +18,6 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-import com.android.inputmethod.latin.ResearchLogger;
-import com.android.inputmethod.latin.define.ProductionFlag;
-
public class AlphabetShiftState {
private static final String TAG = AlphabetShiftState.class.getSimpleName();
private static final boolean DEBUG = false;
@@ -62,9 +59,6 @@ public class AlphabetShiftState {
}
if (DEBUG)
Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this);
- }
}
public void setShiftLocked(boolean newShiftLockState) {
@@ -84,9 +78,6 @@ public class AlphabetShiftState {
if (DEBUG)
Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
+ " > " + this);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this);
- }
}
public void setAutomaticShifted() {
@@ -94,9 +85,6 @@ public class AlphabetShiftState {
mState = AUTOMATIC_SHIFTED;
if (DEBUG)
Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this);
- }
}
public boolean isShiftedOrShiftLocked() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index 8261400b2..a44ddf182 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -30,8 +30,8 @@ import java.util.Arrays;
* The specification is comma separated texts each of which represents one "more key".
* The specification might have label or string resource reference in it. These references are
* expanded before parsing comma.
- * - Label reference should be a string representation of label (!label/label_name)
- * - String resource reference should be a string representation of resource (!label/resource_name)
+ * - Label reference should be a string representation of label (!text/label_name)
+ * - String resource reference should be a string representation of resource (!text/resource_name)
* Each "more key" specification is one of the following:
* - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText).
* - Icon followed by keyOutputText or code (!icon/icon_name|!code/code_name)
@@ -51,7 +51,7 @@ public class KeySpecParser {
private static int COMMA = ',';
private static final char ESCAPE_CHAR = '\\';
private static final char LABEL_END = '|';
- private static final String PREFIX_LABEL = "!label/";
+ private static final String PREFIX_TEXT = "!text/";
private static final String PREFIX_ICON = "!icon/";
private static final String PREFIX_CODE = "!code/";
private static final String PREFIX_HEX = "0x";
@@ -76,20 +76,13 @@ public class KeySpecParser {
}
private static boolean hasIcon(String moreKeySpec) {
- if (moreKeySpec.startsWith(PREFIX_ICON)) {
- final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (end > 0) {
- return true;
- }
- throw new KeySpecParserError("outputText or code not specified: " + moreKeySpec);
- }
- return false;
+ return moreKeySpec.regionMatches(true, 0, PREFIX_ICON, 0, PREFIX_ICON.length());
}
private static boolean hasCode(String moreKeySpec) {
final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (end > 0 && end + 1 < moreKeySpec.length()
- && moreKeySpec.substring(end + 1).startsWith(PREFIX_CODE)) {
+ if (end > 0 && end + 1 < moreKeySpec.length() && moreKeySpec.regionMatches(
+ true, end + 1, PREFIX_CODE, 0, PREFIX_CODE.length())) {
return true;
}
return false;
@@ -210,19 +203,20 @@ public class KeySpecParser {
public static int parseCode(String text, KeyboardCodesSet codesSet, int defCode) {
if (text == null) return defCode;
- if (text.startsWith(PREFIX_CODE)) {
+ if (text.regionMatches(true, 0, PREFIX_CODE, 0, PREFIX_CODE.length())) {
return codesSet.getCode(text.substring(PREFIX_CODE.length()));
- } else if (text.startsWith(PREFIX_HEX)) {
+ } else if (text.regionMatches(true, 0, PREFIX_HEX, 0, PREFIX_HEX.length())) {
return Integer.parseInt(text.substring(PREFIX_HEX.length()), 16);
} else {
return Integer.parseInt(text);
}
}
- static int getIconId(String moreKeySpec) {
- if (hasIcon(moreKeySpec)) {
+ public static int getIconId(String moreKeySpec) {
+ if (moreKeySpec != null && hasIcon(moreKeySpec)) {
final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length());
- final String name = moreKeySpec.substring(PREFIX_ICON.length(), end);
+ final String name = (end < 0) ? moreKeySpec.substring(PREFIX_ICON.length())
+ : moreKeySpec.substring(PREFIX_ICON.length(), end);
return KeyboardIconsSet.getIconId(name);
}
return KeyboardIconsSet.ICON_UNDEFINED;
@@ -340,7 +334,7 @@ public class KeySpecParser {
}
}
- public static String resolveLabelReference(String rawText, KeyboardLabelsSet labelsSet) {
+ public static String resolveTextReference(String rawText, KeyboardTextsSet textsSet) {
int level = 0;
String text = rawText;
StringBuilder sb;
@@ -350,21 +344,23 @@ public class KeySpecParser {
throw new RuntimeException("too many @string/resource indirection: " + text);
}
+ final int prefixLen = PREFIX_TEXT.length();
final int size = text.length();
- if (size < PREFIX_LABEL.length()) {
+ if (size < prefixLen) {
return text;
}
sb = null;
for (int pos = 0; pos < size; pos++) {
final char c = text.charAt(pos);
- if (text.startsWith(PREFIX_LABEL, pos) && labelsSet != null) {
+ if (text.regionMatches(true, pos, PREFIX_TEXT, 0, prefixLen)
+ && textsSet != null) {
if (sb == null) {
sb = new StringBuilder(text.substring(0, pos));
}
- final int end = searchLabelNameEnd(text, pos + PREFIX_LABEL.length());
- final String name = text.substring(pos + PREFIX_LABEL.length(), end);
- sb.append(labelsSet.getLabel(name));
+ final int end = searchTextNameEnd(text, pos + prefixLen);
+ final String name = text.substring(pos + prefixLen, end);
+ sb.append(textsSet.getText(name));
pos = end - 1;
} else if (c == ESCAPE_CHAR) {
if (sb != null) {
@@ -385,12 +381,13 @@ public class KeySpecParser {
return text;
}
- private static int searchLabelNameEnd(String text, int start) {
+ private static int searchTextNameEnd(String text, int start) {
final int size = text.length();
for (int pos = start; pos < size; pos++) {
final char c = text.charAt(pos);
- // String resource name should be consisted of [a-z_0-9].
- if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
+ // Label name should be consisted of [a-zA-Z_0-9].
+ if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')) {
continue;
}
return pos;
@@ -398,8 +395,8 @@ public class KeySpecParser {
return size;
}
- public static String[] parseCsvString(String rawText, KeyboardLabelsSet labelsSet) {
- final String text = resolveLabelReference(rawText, labelsSet);
+ public static String[] parseCsvString(String rawText, KeyboardTextsSet textsSet) {
+ final String text = resolveTextReference(rawText, textsSet);
final int size = text.length();
if (size == 0) {
return null;
@@ -442,17 +439,19 @@ public class KeySpecParser {
if (moreKeys == null) {
return defaultValue;
}
+ final int keyLen = key.length();
boolean foundValue = false;
int value = defaultValue;
for (int i = 0; i < moreKeys.length; i++) {
final String moreKeySpec = moreKeys[i];
- if (moreKeySpec == null || !moreKeySpec.startsWith(key)) {
+ if (moreKeySpec == null || !moreKeySpec.regionMatches(true, 0, key, 0, keyLen)) {
continue;
}
moreKeys[i] = null;
try {
if (!foundValue) {
- value = Integer.parseInt(moreKeySpec.substring(key.length()));
+ value = Integer.parseInt(moreKeySpec.substring(keyLen));
+ foundValue = true;
}
} catch (NumberFormatException e) {
throw new RuntimeException(
@@ -469,7 +468,7 @@ public class KeySpecParser {
boolean value = false;
for (int i = 0; i < moreKeys.length; i++) {
final String moreKeySpec = moreKeys[i];
- if (moreKeySpec == null || !moreKeySpec.equals(key)) {
+ if (moreKeySpec == null || !moreKeySpec.equalsIgnoreCase(key)) {
continue;
}
moreKeys[i] = null;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 8e0b21607..b32172ebe 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -35,19 +35,19 @@ public class KeyStyles {
private final HashMap<String, DeclaredKeyStyle> mStyles =
new HashMap<String, DeclaredKeyStyle>();
- private final KeyboardLabelsSet mLabelsSet;
+ private final KeyboardTextsSet mTextsSet;
private final KeyStyle mEmptyKeyStyle;
- public KeyStyles(KeyboardLabelsSet labelsSet) {
- mLabelsSet = labelsSet;
- mEmptyKeyStyle = new EmptyKeyStyle(labelsSet);
+ public KeyStyles(KeyboardTextsSet textsSet) {
+ mTextsSet = textsSet;
+ mEmptyKeyStyle = new EmptyKeyStyle(textsSet);
}
public static abstract class KeyStyle {
- protected final KeyboardLabelsSet mLabelsSet;
+ protected final KeyboardTextsSet mTextsSet;
- public KeyStyle(KeyboardLabelsSet labelsSet) {
- mLabelsSet = labelsSet;
+ public KeyStyle(KeyboardTextsSet textsSet) {
+ mTextsSet = textsSet;
}
public abstract String[] getStringArray(TypedArray a, int index);
@@ -57,22 +57,22 @@ public class KeyStyles {
protected String parseString(TypedArray a, int index) {
if (a.hasValue(index)) {
- return KeySpecParser.resolveLabelReference(a.getString(index), mLabelsSet);
+ return KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
}
return null;
}
protected String[] parseStringArray(TypedArray a, int index) {
if (a.hasValue(index)) {
- return KeySpecParser.parseCsvString(a.getString(index), mLabelsSet);
+ return KeySpecParser.parseCsvString(a.getString(index), mTextsSet);
}
return null;
}
}
private static class EmptyKeyStyle extends KeyStyle {
- public EmptyKeyStyle(KeyboardLabelsSet labelsSet) {
- super(labelsSet);
+ public EmptyKeyStyle(KeyboardTextsSet textsSet) {
+ super(textsSet);
}
@Override
@@ -99,8 +99,8 @@ public class KeyStyles {
private static class DeclaredKeyStyle extends KeyStyle {
private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>();
- public DeclaredKeyStyle(KeyboardLabelsSet labelsSet) {
- super(labelsSet);
+ public DeclaredKeyStyle(KeyboardTextsSet textsSet) {
+ super(textsSet);
}
@Override
@@ -145,9 +145,9 @@ public class KeyStyles {
readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIcon);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
readFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
@@ -195,7 +195,7 @@ public class KeyStyles {
}
}
- final DeclaredKeyStyle style = new DeclaredKeyStyle(mLabelsSet);
+ final DeclaredKeyStyle style = new DeclaredKeyStyle(mTextsSet);
if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
final String parentStyle = keyStyleAttr.getString(
R.styleable.Keyboard_KeyStyle_parentStyle);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index 736a96c56..c10a394c1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -33,7 +33,10 @@ public class KeyboardCodesSet {
}
public int getCode(final String name) {
- final Integer id = sNameToIdMap.get(name);
+ Integer id = sNameToIdMap.get(name);
+ if (id == null) {
+ id = sNameToIdMap.get(name.toLowerCase());
+ }
if (id == null) throw new RuntimeException("Unknown key code: " + name);
return mCodes[id];
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index ded89b1b8..a86a9577f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -28,46 +28,52 @@ import java.util.HashMap;
public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
- // The value should be aligned with the enum value of Key.keyIcon.
public static final int ICON_UNDEFINED = 0;
- private static final int NUM_ICONS = 16;
-
- private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1];
+ private static final int ATTR_UNDEFINED = 0;
private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID
= new HashMap<Integer, Integer>();
- private static final HashMap<String, Integer> NAME_TO_ICON_ID = new HashMap<String, Integer>();
- private static final String[] ICON_NAMES = new String[NUM_ICONS + 1];
- private static final int ATTR_UNDEFINED = 0;
- static {
- // The key value should be aligned with the enum value of Key.keyIcon.
- addIconIdMap(0, "undefined", ATTR_UNDEFINED);
- addIconIdMap(1, "shiftKey", R.styleable.Keyboard_iconShiftKey);
- addIconIdMap(2, "deleteKey", R.styleable.Keyboard_iconDeleteKey);
- addIconIdMap(3, "settingsKey", R.styleable.Keyboard_iconSettingsKey);
- addIconIdMap(4, "spaceKey", R.styleable.Keyboard_iconSpaceKey);
- addIconIdMap(5, "returnKey", R.styleable.Keyboard_iconReturnKey);
- addIconIdMap(6, "searchKey", R.styleable.Keyboard_iconSearchKey);
- addIconIdMap(7, "tabKey", R.styleable.Keyboard_iconTabKey);
- addIconIdMap(8, "shortcutKey", R.styleable.Keyboard_iconShortcutKey);
- addIconIdMap(9, "shortcutForLabel", R.styleable.Keyboard_iconShortcutForLabel);
- addIconIdMap(10, "spaceKeyForNumberLayout",
- R.styleable.Keyboard_iconSpaceKeyForNumberLayout);
- addIconIdMap(11, "shiftKeyShifted", R.styleable.Keyboard_iconShiftKeyShifted);
- addIconIdMap(12, "disabledShortcurKey", R.styleable.Keyboard_iconDisabledShortcutKey);
- addIconIdMap(13, "previewTabKey", R.styleable.Keyboard_iconPreviewTabKey);
- addIconIdMap(14, "languageSwitchKey", R.styleable.Keyboard_iconLanguageSwitchKey);
- addIconIdMap(15, "zwnjKey", R.styleable.Keyboard_iconZwnjKey);
- addIconIdMap(16, "zwjKey", R.styleable.Keyboard_iconZwjKey);
- }
+ // Lower case icon name to icon id map.
+ private static final HashMap<String, Integer> sLowerCaseNameToIdsMap =
+ new HashMap<String, Integer>();
+
+ private static final Object[] NAMES_AND_ATTR_IDS = {
+ "undefined", ATTR_UNDEFINED,
+ "shift_key", R.styleable.Keyboard_iconShiftKey,
+ "delete_key", R.styleable.Keyboard_iconDeleteKey,
+ "settings_key", R.styleable.Keyboard_iconSettingsKey,
+ "space_key", R.styleable.Keyboard_iconSpaceKey,
+ "enter_key", R.styleable.Keyboard_iconEnterKey,
+ "search_key", R.styleable.Keyboard_iconSearchKey,
+ "tab_key", R.styleable.Keyboard_iconTabKey,
+ "shortcut_key", R.styleable.Keyboard_iconShortcutKey,
+ "shortcut_for_label", R.styleable.Keyboard_iconShortcutForLabel,
+ "space_key_for_number_layout", R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
+ "shift_key_shifted", R.styleable.Keyboard_iconShiftKeyShifted,
+ "shortcut_key_disabled", R.styleable.Keyboard_iconShortcutKeyDisabled,
+ "tab_key_preview", R.styleable.Keyboard_iconTabKeyPreview,
+ "language_switch_key", R.styleable.Keyboard_iconLanguageSwitchKey,
+ "zwnj_key", R.styleable.Keyboard_iconZwnjKey,
+ "zwj_key", R.styleable.Keyboard_iconZwjKey,
+ };
+
+ private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
+ private static final String[] ICON_NAMES = new String[NUM_ICONS];
+ private final Drawable[] mIcons = new Drawable[NUM_ICONS];
- private static void addIconIdMap(int iconId, String name, int attrId) {
- if (attrId != ATTR_UNDEFINED) {
- ATTR_ID_TO_ICON_ID.put(attrId, iconId);
+ static {
+ int iconId = ICON_UNDEFINED;
+ for (int i = 0; i < NAMES_AND_ATTR_IDS.length; i += 2) {
+ final String name = (String)NAMES_AND_ATTR_IDS[i];
+ final Integer attrId = (Integer)NAMES_AND_ATTR_IDS[i + 1];
+ if (attrId != ATTR_UNDEFINED) {
+ ATTR_ID_TO_ICON_ID.put(attrId, iconId);
+ }
+ sLowerCaseNameToIdsMap.put(name, iconId);
+ ICON_NAMES[iconId] = name;
+ iconId++;
}
- NAME_TO_ICON_ID.put(name, iconId);
- ICON_NAMES[iconId] = name;
}
public void loadIcons(final TypedArray keyboardAttrs) {
@@ -93,8 +99,11 @@ public class KeyboardIconsSet {
return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">";
}
- public static int getIconId(final String name) {
- final Integer iconId = NAME_TO_ICON_ID.get(name);
+ static int getIconId(final String name) {
+ Integer iconId = sLowerCaseNameToIdsMap.get(name);
+ if (iconId == null) {
+ iconId = sLowerCaseNameToIdsMap.get(name.toLowerCase());
+ }
if (iconId != null) {
return iconId;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 6949c9d12..2d80a798d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -141,9 +141,6 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString());
- }
}
private void onRestoreKeyboardState() {
@@ -151,9 +148,6 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString());
- }
if (!state.mIsValid || state.mIsAlphabetMode) {
setAlphabetKeyboard();
} else {
@@ -186,9 +180,6 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode));
- }
if (!mIsAlphabetMode) return;
final int prevShiftMode;
if (mAlphabetShiftState.isAutomaticShifted()) {
@@ -228,9 +219,6 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked);
- }
if (!mIsAlphabetMode) return;
if (shiftLocked && (!mAlphabetShiftState.isShiftLocked()
|| mAlphabetShiftState.isShiftLockShifted())) {
@@ -246,9 +234,6 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "toggleAlphabetAndSymbols: " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this);
- }
if (mIsAlphabetMode) {
mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
if (mPrevSymbolsKeyboardWasShifted) {
@@ -280,9 +265,6 @@ public class KeyboardState {
Log.d(TAG, "setAlphabetKeyboard");
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_setAlphabetKeyboard();
- }
mSwitchActions.setAlphabetKeyboard();
mIsAlphabetMode = true;
mIsSymbolShifted = false;
@@ -294,9 +276,6 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setSymbolsKeyboard");
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_setSymbolsKeyboard();
- }
mSwitchActions.setSymbolsKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = false;
@@ -309,9 +288,6 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setSymbolsShiftedKeyboard");
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_setSymbolsShiftedKeyboard();
- }
mSwitchActions.setSymbolsShiftedKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = true;
@@ -399,9 +375,6 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps);
- }
updateAlphabetShiftState(autoCaps);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 3ade2dda7..d0f27a9a8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -25,22 +25,23 @@ import java.util.HashMap;
/**
* !!!!! DO NOT EDIT THIS FILE !!!!!
- * This file is generated by tools/makelabel.
+ * This file is generated by tools/maketext.
*/
-public final class KeyboardLabelsSet {
- // Language to labels map.
- private static final HashMap<String, String[]> sLocaleToLabelsMap =
+public final class KeyboardTextsSet {
+ // Language to texts map.
+ private static final HashMap<String, String[]> sLocaleToTextsMap =
new HashMap<String, String[]>();
- private static final HashMap<String, Integer> sNameToIdMap = new HashMap<String, Integer>();
+ private static final HashMap<String, Integer> sLowerCaseNameToIdsMap =
+ new HashMap<String, Integer>();
- private String[] mLabels;
- // Resource name to label map.
- private HashMap<String, String> mResourceNameToLabelsMap = new HashMap<String, String>();
+ private String[] mTexts;
+ // Resource name to text map.
+ private HashMap<String, String> mResourceNameToTextsMap = new HashMap<String, String>();
public void setLanguage(final String language) {
- mLabels = sLocaleToLabelsMap.get(language);
- if (mLabels == null) {
- mLabels = LANGUAGE_DEFAULT;
+ mTexts = sLocaleToTextsMap.get(language);
+ if (mTexts == null) {
+ mTexts = LANGUAGE_DEFAULT;
}
}
@@ -55,22 +56,31 @@ public final class KeyboardLabelsSet {
final String packageName = res.getResourcePackageName(referenceId);
for (final String resName : resourceNames) {
final int resId = res.getIdentifier(resName, "string", packageName);
- mResourceNameToLabelsMap.put(resName, res.getString(resId));
+ mResourceNameToTextsMap.put(resName, res.getString(resId));
}
}
- public String getLabel(final String name) {
- if (mResourceNameToLabelsMap.containsKey(name)) {
- return mResourceNameToLabelsMap.get(name);
+ public String getText(final String name) {
+ String lowerCaseName = null;
+ String text = mResourceNameToTextsMap.get(name);
+ if (text == null) {
+ lowerCaseName = name.toLowerCase();
+ text = mResourceNameToTextsMap.get(lowerCaseName);
+ }
+ if (text != null) {
+ return text;
+ }
+ Integer id = sLowerCaseNameToIdsMap.get(name);
+ if (id == null) {
+ id = sLowerCaseNameToIdsMap.get(lowerCaseName); // lowerCaseName != null
}
- final Integer id = sNameToIdMap.get(name);
if (id == null) throw new RuntimeException("Unknown label: " + name);
- final String label = (id < mLabels.length) ? mLabels[id] : null;
- return (label == null) ? LANGUAGE_DEFAULT[id] : label;
+ text = (id < mTexts.length) ? mTexts[id] : null;
+ return (text == null) ? LANGUAGE_DEFAULT[id] : text;
}
private static final String[] RESOURCE_NAMES = {
- // These labels' name should be aligned with the @string/<name> in values/strings.xml.
+ // These texts' name should be aligned with the @string/<name> in values/strings.xml.
// Labels for action.
"label_go_key",
// "label_search_key",
@@ -138,80 +148,81 @@ 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 = "";
- /* Default labels */
+ /* Default texts */
private static final String[] LANGUAGE_DEFAULT = {
/* 0~ */
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
@@ -220,9 +231,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 +249,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!,!text/label_time_am,!text/label_time_pm",
+ /* 110 */ "!icon/settings_key|!code/key_settings",
+ /* 111 */ "!icon/shortcut_key|!code/key_shortcut",
+ /* 112 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
+ /* 113 */ "!hasLabels!,!text/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 +374,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 */
@@ -954,134 +978,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 +1223,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 +1444,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 +1477,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 +1713,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 +2134,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",
};
@@ -2421,7 +2458,7 @@ public final class KeyboardLabelsSet {
/* 19 */ "\u0175",
};
- private static final Object[] LANGUAGES_AND_LABELS = {
+ private static final Object[] LANGUAGES_AND_TEXTS = {
"DEFAULT", LANGUAGE_DEFAULT, /* default */
"ar", LANGUAGE_ar, /* Arabic */
"be", LANGUAGE_be, /* Belarusian */
@@ -2465,13 +2502,13 @@ public final class KeyboardLabelsSet {
static {
int id = 0;
for (final String name : NAMES) {
- sNameToIdMap.put(name, id++);
+ sLowerCaseNameToIdsMap.put(name, id++);
}
- for (int i = 0; i < LANGUAGES_AND_LABELS.length; i += 2) {
- final String language = (String)LANGUAGES_AND_LABELS[i];
- final String[] labels = (String[])LANGUAGES_AND_LABELS[i + 1];
- sLocaleToLabelsMap.put(language, labels);
+ for (int i = 0; i < LANGUAGES_AND_TEXTS.length; i += 2) {
+ final String language = (String)LANGUAGES_AND_TEXTS[i];
+ final String[] texts = (String[])LANGUAGES_AND_TEXTS[i + 1];
+ sLocaleToTextsMap.put(language, texts);
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
index 28cec56e6..458d9ee14 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -22,27 +22,8 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR
import android.view.inputmethod.InputMethodSubtype;
-import java.util.HashMap;
public class AdditionalSubtype {
- public static final String QWERTY = "qwerty";
- public static final String QWERTZ = "qwertz";
- public static final String AZERTY = "azerty";
- 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 =
- new HashMap<String, Integer>();
-
- static {
- sKeyboardLayoutToNameIdsMap.put(QWERTY, R.string.subtype_generic_qwerty);
- sKeyboardLayoutToNameIdsMap.put(QWERTZ, R.string.subtype_generic_qwertz);
- sKeyboardLayoutToNameIdsMap.put(AZERTY, R.string.subtype_generic_azerty);
- }
private AdditionalSubtype() {
// This utility class is not publicly instantiable.
@@ -60,7 +41,8 @@ public class AdditionalSubtype {
final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
IS_ADDITIONAL_SUBTYPE, extraValue);
- Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutSetName);
+ Integer nameId = SubtypeLocale.getSubtypeNameIdFromKeyboardLayoutName(
+ keyboardLayoutSetName);
if (nameId == null) nameId = R.string.subtype_generic;
return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
localeString, KEYBOARD_MODE,
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index 7a22c9742..613c20304 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -109,18 +109,15 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
}
static class KeyboardLayoutSetItem extends Pair<String, String> {
- public KeyboardLayoutSetItem(String keyboardLayoutSetName) {
- super(keyboardLayoutSetName, getDisplayName(keyboardLayoutSetName));
+ public KeyboardLayoutSetItem(InputMethodSubtype subtype) {
+ super(SubtypeLocale.getKeyboardLayoutSetName(subtype),
+ SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype));
}
@Override
public String toString() {
return second;
}
-
- private static String getDisplayName(String keyboardLayoutSetName) {
- return keyboardLayoutSetName.toUpperCase();
- }
}
static class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
@@ -129,8 +126,11 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
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));
+ for (final String layout : SubtypeLocale.getPredefinedKeyboardLayoutSet()) {
+ // This is a dummy subtype with NO_LANGUAGE, only for display.
+ final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
+ SubtypeLocale.NO_LANGUAGE, layout, null);
+ add(new KeyboardLayoutSetItem(subtype));
}
}
}
@@ -196,8 +196,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment {
.setNegativeButton(R.string.remove, this);
final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
context, mSubtype.getLocale());
- final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(
- SubtypeLocale.getKeyboardLayoutSetName(mSubtype));
+ final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(mSubtype);
setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index e4d081b56..a4670daf2 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -49,7 +49,10 @@ public class BinaryDictionaryFileDumper {
*/
private static final int FILE_READ_BUFFER_SIZE = 1024;
// TODO: make the following data common with the native code
- private static final byte[] MAGIC_NUMBER = new byte[] { 0x78, (byte)0xB1 };
+ private static final byte[] MAGIC_NUMBER_VERSION_1 =
+ new byte[] { (byte)0x78, (byte)0xB1, (byte)0x00, (byte)0x00 };
+ private static final byte[] MAGIC_NUMBER_VERSION_2 =
+ new byte[] { (byte)0x9B, (byte)0xC1, (byte)0x3A, (byte)0xFE };
private static final String DICTIONARY_PROJECTION[] = { "id" };
@@ -268,15 +271,18 @@ public class BinaryDictionaryFileDumper {
private static void checkMagicAndCopyFileTo(final BufferedInputStream input,
final FileOutputStream output) throws FileNotFoundException, IOException {
// Check the magic number
- final byte[] magicNumberBuffer = new byte[MAGIC_NUMBER.length];
- final int readMagicNumberSize = input.read(magicNumberBuffer, 0, MAGIC_NUMBER.length);
- if (readMagicNumberSize < MAGIC_NUMBER.length) {
+ final int length = MAGIC_NUMBER_VERSION_2.length;
+ final byte[] magicNumberBuffer = new byte[length];
+ final int readMagicNumberSize = input.read(magicNumberBuffer, 0, length);
+ if (readMagicNumberSize < length) {
throw new IOException("Less bytes to read than the magic number length");
}
- if (!Arrays.equals(MAGIC_NUMBER, magicNumberBuffer)) {
- throw new IOException("Wrong magic number for downloaded file");
+ if (!Arrays.equals(MAGIC_NUMBER_VERSION_2, magicNumberBuffer)) {
+ if (!Arrays.equals(MAGIC_NUMBER_VERSION_1, magicNumberBuffer)) {
+ throw new IOException("Wrong magic number for downloaded file");
+ }
}
- output.write(MAGIC_NUMBER);
+ output.write(magicNumberBuffer);
// Actually copy the file
final byte[] buffer = new byte[FILE_READ_BUFFER_SIZE];
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 072dec9d1..5acd62904 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -24,6 +24,7 @@ import android.util.Log;
import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Locale;
/**
@@ -46,6 +47,10 @@ class BinaryDictionaryGetter {
*/
private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs";
+ // Name of the category for the main dictionary
+ private static final String MAIN_DICTIONARY_CATEGORY = "main";
+ public static final String ID_CATEGORY_SEPARATOR = ":";
+
// Prevents this from being instantiated
private BinaryDictionaryGetter() {}
@@ -206,7 +211,40 @@ class BinaryDictionaryGetter {
}
/**
- * Returns the list of cached files for a specific locale.
+ * Returns the category for a given file name.
+ *
+ * This parses the file name, extracts the category, and returns it. See
+ * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
+ * @return The category as a string or null if it can't be found in the file name.
+ */
+ private static String getCategoryFromFileName(final String fileName) {
+ final String id = getWordListIdFromFileName(fileName);
+ final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
+ if (2 != idArray.length) return null;
+ return idArray[0];
+ }
+
+ /**
+ * Utility class for the {@link #getCachedWordLists} method
+ */
+ private static class FileAndMatchLevel {
+ final File mFile;
+ final int mMatchLevel;
+ public FileAndMatchLevel(final File file, final int matchLevel) {
+ mFile = file;
+ mMatchLevel = matchLevel;
+ }
+ }
+
+ /**
+ * Returns the list of cached files for a specific locale, one for each category.
+ *
+ * This will return exactly one file for each word list category that matches
+ * the passed locale. If several files match the locale for any given category,
+ * this returns the file with the closest match to the locale. For example, if
+ * the passed word list is en_US, and for a category we have an en and an en_US
+ * word list available, we'll return only the en_US one.
+ * Thus, the list will contain as many files as there are categories.
*
* @param locale the locale to find the dictionary files for, as a string.
* @param context the context on which to open the files upon.
@@ -216,21 +254,32 @@ class BinaryDictionaryGetter {
final Context context) {
final File[] directoryList = getCachedDirectoryList(context);
if (null == directoryList) return EMPTY_FILE_ARRAY;
- final ArrayList<File> cacheFiles = new ArrayList<File>();
+ final HashMap<String, FileAndMatchLevel> cacheFiles =
+ new HashMap<String, FileAndMatchLevel>();
for (File directory : directoryList) {
if (!directory.isDirectory()) continue;
final String dirLocale = getWordListIdFromFileName(directory.getName());
- if (LocaleUtils.isMatch(LocaleUtils.getMatchLevel(dirLocale, locale))) {
+ final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale);
+ if (LocaleUtils.isMatch(matchLevel)) {
final File[] wordLists = directory.listFiles();
if (null != wordLists) {
for (File wordList : wordLists) {
- cacheFiles.add(wordList);
+ final String category = getCategoryFromFileName(wordList.getName());
+ final FileAndMatchLevel currentBestMatch = cacheFiles.get(category);
+ if (null == currentBestMatch || currentBestMatch.mMatchLevel < matchLevel) {
+ cacheFiles.put(category, new FileAndMatchLevel(wordList, matchLevel));
+ }
}
}
}
}
if (cacheFiles.isEmpty()) return EMPTY_FILE_ARRAY;
- return cacheFiles.toArray(EMPTY_FILE_ARRAY);
+ final File[] result = new File[cacheFiles.size()];
+ int index = 0;
+ for (final FileAndMatchLevel entry : cacheFiles.values()) {
+ result[index++] = entry.mFile;
+ }
+ return result;
}
/**
@@ -245,7 +294,13 @@ class BinaryDictionaryGetter {
// This works because we don't include by default different dictionaries for
// different countries. This actually needs to return the id that we would
// like to use for word lists included in resources, and the following is okay.
- return locale.getLanguage().toString();
+ return MAIN_DICTIONARY_CATEGORY + ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
+ }
+
+ private static boolean isMainWordListId(final String id) {
+ final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
+ if (2 != idArray.length) return false;
+ return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
}
/**
@@ -270,9 +325,7 @@ class BinaryDictionaryGetter {
BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context,
hasDefaultWordList);
final File[] cachedWordLists = getCachedWordLists(locale.toString(), context);
-
final String mainDictId = getMainDictId(locale);
-
final DictPackSettings dictPackSettings = new DictPackSettings(context);
boolean foundMainDict = false;
@@ -280,7 +333,7 @@ class BinaryDictionaryGetter {
// cachedWordLists may not be null, see doc for getCachedDictionaryList
for (final File f : cachedWordLists) {
final String wordListId = getWordListIdFromFileName(f.getName());
- if (wordListId.equals(mainDictId)) {
+ if (isMainWordListId(wordListId)) {
foundMainDict = true;
}
if (!dictPackSettings.isWordListActive(wordListId)) continue;
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
index b3f613bae..7d673175e 100644
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtils.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.latin;
-import android.text.TextUtils;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
@@ -37,30 +36,6 @@ public class EditingUtils {
// Unintentional empty constructor for singleton.
}
- /**
- * Append newText to the text field represented by connection.
- * The new text becomes selected.
- */
- public static void appendText(InputConnection connection, String newText) {
- if (connection == null) {
- return;
- }
-
- // Commit the composing text
- connection.finishComposingText();
-
- // Add a space if the field already has text.
- String text = newText;
- CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0);
- if (charBeforeCursor != null
- && !charBeforeCursor.equals(" ")
- && (charBeforeCursor.length() > 0)) {
- text = " " + text;
- }
-
- connection.setComposingText(text, 1);
- }
-
private static int getCursorPosition(InputConnection connection) {
if (null == connection) return INVALID_CURSOR_POSITION;
ExtractedText extracted = connection.getExtractedText(
@@ -146,7 +121,6 @@ public class EditingUtils {
private static final Pattern spaceRegex = Pattern.compile("\\s+");
-
public static CharSequence getPreviousWord(InputConnection connection,
String sentenceSeperators) {
//TODO: Should fix this. This could be slow!
@@ -205,77 +179,4 @@ public class EditingUtils {
return w[w.length - 1];
}
-
- public static class SelectedWord {
- public final int mStart;
- public final int mEnd;
- public final CharSequence mWord;
-
- public SelectedWord(int start, int end, CharSequence word) {
- mStart = start;
- mEnd = end;
- mWord = word;
- }
- }
-
- /**
- * Takes a character sequence with a single character and checks if the character occurs
- * in a list of word separators or is empty.
- * @param singleChar A CharSequence with null, zero or one character
- * @param wordSeparators A String containing the word separators
- * @return true if the character is at a word boundary, false otherwise
- */
- private static boolean isWordBoundary(CharSequence singleChar, String wordSeparators) {
- return TextUtils.isEmpty(singleChar) || wordSeparators.contains(singleChar);
- }
-
- /**
- * Checks if the cursor is inside a word or the current selection is a whole word.
- * @param ic the InputConnection for accessing the text field
- * @param selStart the start position of the selection within the text field
- * @param selEnd the end position of the selection within the text field. This could be
- * the same as selStart, if there's no selection.
- * @param wordSeparators the word separator characters for the current language
- * @return an object containing the text and coordinates of the selected/touching word,
- * null if the selection/cursor is not marking a whole word.
- */
- public static SelectedWord getWordAtCursorOrSelection(final InputConnection ic,
- int selStart, int selEnd, String wordSeparators) {
- if (selStart == selEnd) {
- // There is just a cursor, so get the word at the cursor
- // getWordRangeAtCursor returns null if the connection is null
- final EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators);
- if (range != null && !TextUtils.isEmpty(range.mWord)) {
- return new SelectedWord(selStart - range.mCharsBefore, selEnd + range.mCharsAfter,
- range.mWord);
- }
- } else {
- if (null == ic) return null;
- // Is the previous character empty or a word separator? If not, return null.
- final CharSequence charsBefore = ic.getTextBeforeCursor(1, 0);
- if (!isWordBoundary(charsBefore, wordSeparators)) {
- return null;
- }
-
- // Is the next character empty or a word separator? If not, return null.
- final CharSequence charsAfter = ic.getTextAfterCursor(1, 0);
- if (!isWordBoundary(charsAfter, wordSeparators)) {
- return null;
- }
-
- // Extract the selection alone
- final CharSequence touching = ic.getSelectedText(0);
- if (TextUtils.isEmpty(touching)) return null;
- // Is any part of the selection a separator? If so, return null.
- final int length = touching.length();
- for (int i = 0; i < length; i++) {
- if (wordSeparators.contains(touching.subSequence(i, i + 1))) {
- return null;
- }
- }
- // Prepare the selected word
- return new SelectedWord(selStart, selEnd, touching);
- }
- return null;
- }
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 31c832c31..e1978fca1 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -154,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;
@@ -449,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) {
@@ -465,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();
@@ -511,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);
}
@@ -523,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
@@ -603,7 +608,7 @@ 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) {
@@ -629,7 +634,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
editorInfo.inputType, editorInfo.imeOptions));
}
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_onStartInputViewInternal(editorInfo);
+ ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
}
if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: "
@@ -1843,6 +1848,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mExpectingUpdateSelection = true;
commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
LastComposedWord.NOT_A_SEPARATOR);
+ // Don't allow cancellation of manual pick
+ mLastComposedWord.deactivate();
// Add the word to the user history dictionary
addToUserHistoryDictionary(suggestion);
mSpaceState = SPACE_STATE_PHANTOM;
@@ -1894,7 +1901,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);
@@ -1972,7 +1979,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();
}
@@ -2300,8 +2308,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/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 7072dda23..566af7061 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -18,10 +18,12 @@ package com.android.inputmethod.latin;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.os.SystemClock;
+import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
@@ -31,7 +33,6 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.internal.AlphabetShiftState;
import com.android.inputmethod.keyboard.internal.KeyboardState;
import com.android.inputmethod.latin.define.ProductionFlag;
@@ -45,6 +46,7 @@ import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
+import java.util.Map;
/**
* Logs the use of the LatinIME keyboard.
@@ -68,7 +70,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
* Isolates management of files. This variable should never be null, but can be changed
* to support testing.
*/
- private LogFileManager mLogFileManager;
+ /* package */ LogFileManager mLogFileManager;
/**
* Manages the file(s) that stores the logs.
@@ -93,63 +95,53 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mIms = ims;
}
- public synchronized boolean createLogFile() {
- try {
- return createLogFile(DEFAULT_FILENAME);
- } catch (IOException e) {
- e.printStackTrace();
- Log.w(TAG, e);
- return false;
- }
+ public synchronized void createLogFile() throws IOException {
+ createLogFile(DEFAULT_FILENAME);
}
- public synchronized boolean createLogFile(final SharedPreferences prefs) {
- try {
- final String filename =
- prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME);
- return createLogFile(filename);
- } catch (IOException e) {
- Log.w(TAG, e);
- e.printStackTrace();
- }
- return false;
+ public synchronized void createLogFile(final SharedPreferences prefs)
+ throws IOException {
+ final String filename =
+ prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME);
+ createLogFile(filename);
}
- public synchronized boolean createLogFile(final String filename)
+ public synchronized void createLogFile(final String filename)
throws IOException {
if (mIms == null) {
- Log.w(TAG, "InputMethodService is not configured. Logging is off.");
- return false;
+ final String msg = "InputMethodService is not configured. Logging is off.";
+ Log.w(TAG, msg);
+ throw new IOException(msg);
}
final File filesDir = mIms.getFilesDir();
if (filesDir == null || !filesDir.exists()) {
- Log.w(TAG, "Storage directory does not exist. Logging is off.");
- return false;
+ final String msg = "Storage directory does not exist. Logging is off.";
+ Log.w(TAG, msg);
+ throw new IOException(msg);
}
close();
final File file = new File(filesDir, filename);
mFile = file;
- file.setReadable(false, false);
boolean append = true;
if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL <
System.currentTimeMillis()) {
append = false;
}
mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true);
- return true;
}
public synchronized boolean append(final String s) {
- final PrintWriter printWriter = mPrintWriter;
- if (printWriter == null) {
+ PrintWriter printWriter = mPrintWriter;
+ if (printWriter == null || !mFile.exists()) {
if (DEBUG) {
Log.w(TAG, "PrintWriter is null... attempting to create default log file");
}
- if (!createLogFile()) {
- if (DEBUG) {
- Log.w(TAG, "Failed to create log file. Not logging.");
- return false;
- }
+ try {
+ createLogFile();
+ printWriter = mPrintWriter;
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to create log file. Not logging.");
+ return false;
}
}
printWriter.print(s);
@@ -161,9 +153,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (mPrintWriter != null) {
mPrintWriter.close();
mPrintWriter = null;
+ if (DEBUG) {
+ Log.d(TAG, "logfile closed");
+ }
}
if (mFile != null) {
mFile.delete();
+ if (DEBUG) {
+ Log.d(TAG, "logfile deleted");
+ }
mFile = null;
}
}
@@ -173,6 +171,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mPrintWriter.close();
mPrintWriter = null;
mFile = null;
+ if (DEBUG) {
+ Log.d(TAG, "logfile closed");
+ }
}
}
@@ -240,12 +241,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
sInstance.initInternal(ims, prefs);
}
- public void initInternal(final InputMethodService ims, final SharedPreferences prefs) {
+ /* package */ void initInternal(final InputMethodService ims, final SharedPreferences prefs) {
mIms = ims;
final LogFileManager logFileManager = mLogFileManager;
if (logFileManager != null) {
logFileManager.init(ims);
- logFileManager.createLogFile(prefs);
+ try {
+ logFileManager.createLogFile(prefs);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
if (prefs != null) {
sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
@@ -254,19 +259,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
/**
- * Change to a different logFileManager.
- *
- * @throws IllegalArgumentException if logFileManager is null
- */
- void setLogFileManager(final LogFileManager manager) {
- if (manager == null) {
- throw new IllegalArgumentException("warning: trying to set null logFileManager");
- } else {
- mLogFileManager = manager;
- }
- }
-
- /**
* Represents a category of logging events that share the same subfield structure.
*/
private static enum LogGroup {
@@ -334,26 +326,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
public static class UnsLogGroup {
private static final boolean DEFAULT_ENABLED = true;
- private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED;
- private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED;
- private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED
- = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED;
private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED
- = DEFAULT_ENABLED;
private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED;
@@ -377,6 +354,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED;
private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED
= DEFAULT_ENABLED;
+ private static final boolean LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED = DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED
= DEFAULT_ENABLED;
private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED
@@ -413,12 +391,21 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (DEBUG) {
Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log);
}
- if (mLogFileManager.append(builder.toString())) {
+ final String s = builder.toString();
+ if (mLogFileManager.append(s)) {
// success
} else {
if (DEBUG) {
Log.w(TAG, "Unable to write to log.");
}
+ // perhaps logfile was deleted. try to recreate and relog.
+ try {
+ mLogFileManager.createLogFile(PreferenceManager
+ .getDefaultSharedPreferences(mIms));
+ mLogFileManager.append(s);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
});
@@ -448,32 +435,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
}
- public static void alphabetShiftState_setShifted(final boolean newShiftState,
- final int oldState, final AlphabetShiftState alphabetShiftState) {
- if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) {
- final String s = "setShifted(" + newShiftState + "): " + oldState
- + " > " + alphabetShiftState;
- logUnstructured("AlphabetShiftState_setShifted", s);
- }
- }
-
- public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState,
- final int oldState, final AlphabetShiftState alphabetShiftState) {
- if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) {
- final String s = "setShiftLocked(" + newShiftLockState + "): "
- + oldState + " > " + alphabetShiftState;
- logUnstructured("AlphabetShiftState_setShiftLocked", s);
- }
- }
-
- public static void alphabetShiftState_setAutomaticShifted(final int oldState,
- final AlphabetShiftState alphabetShiftState) {
- if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) {
- final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState;
- logUnstructured("AlphabetShiftState_setAutomaticShifted", s);
- }
- }
-
public static void keyboardState_onCancelInput(final boolean isSinglePointer,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) {
@@ -520,76 +481,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
- public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState,
- final String savedKeyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) {
- final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " "
- + keyboardState;
- logUnstructured("KeyboardState_onRestoreKeyboardState", s);
- }
- }
-
- public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState,
- final String savedKeyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) {
- final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " "
- + keyboardState;
- logUnstructured("KeyboardState_onSaveKeyboardState", s);
- }
- }
-
- public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState,
- final boolean autoCaps) {
- if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) {
- final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState;
- logUnstructured("KeyboardState_onUpdateShiftState", s);
- }
- }
-
- public static void keyboardState_setAlphabetKeyboard() {
- if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) {
- final String s = "setAlphabetKeyboard";
- logUnstructured("KeyboardState_setAlphabetKeyboard", s);
- }
- }
-
- public static void keyboardState_setShifted(final KeyboardState keyboardState,
- final String shiftMode) {
- if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) {
- final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState;
- logUnstructured("KeyboardState_setShifted", s);
- }
- }
-
- public static void keyboardState_setShiftLocked(final KeyboardState keyboardState,
- final boolean shiftLocked) {
- if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) {
- final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState;
- logUnstructured("KeyboardState_setShiftLocked", s);
- }
- }
-
- public static void keyboardState_setSymbolsKeyboard() {
- if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) {
- final String s = "setSymbolsKeyboard";
- logUnstructured("KeyboardState_setSymbolsKeyboard", s);
- }
- }
-
- public static void keyboardState_setSymbolsShiftedKeyboard() {
- if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) {
- final String s = "setSymbolsShiftedKeyboard";
- logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s);
- }
- }
-
- public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) {
- final String s = "toggleAlphabetAndSymbols: " + keyboardState;
- logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s);
- }
- }
-
public static void latinIME_commitCurrentAutoCorrection(final String typedWord,
final String autoCorrection) {
if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) {
@@ -637,14 +528,22 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
- public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) {
+ public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
+ final SharedPreferences prefs) {
if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) {
final StringBuilder builder = new StringBuilder();
builder.append("onStartInputView: editorInfo:");
- builder.append("inputType=");
- builder.append(editorInfo.inputType);
- builder.append("imeOptions=");
- builder.append(editorInfo.imeOptions);
+ builder.append("\tinputType=");
+ builder.append(Integer.toHexString(editorInfo.inputType));
+ builder.append("\timeOptions=");
+ builder.append(Integer.toHexString(editorInfo.imeOptions));
+ builder.append("\tdisplay="); builder.append(Build.DISPLAY);
+ builder.append("\tmodel="); builder.append(Build.MODEL);
+ for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
+ builder.append("\t" + entry.getKey());
+ Object value = entry.getValue();
+ builder.append("=" + ((value == null) ? "<null>" : value.toString()));
+ }
logUnstructured("LatinIME_onStartInputViewInternal", builder.toString());
}
}
@@ -745,6 +644,42 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
+ public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
+ if (UnsLogGroup.LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("id=");
+ builder.append(keyboard.mId);
+ builder.append("\tw=");
+ builder.append(keyboard.mOccupiedWidth);
+ builder.append("\th=");
+ builder.append(keyboard.mOccupiedHeight);
+ builder.append("\tkeys=[");
+ boolean first = true;
+ for (Key key : keyboard.mKeys) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(",");
+ }
+ builder.append("{code:");
+ builder.append(key.mCode);
+ builder.append(",altCode:");
+ builder.append(key.mAltCode);
+ builder.append(",x:");
+ builder.append(key.mX);
+ builder.append(",y:");
+ builder.append(key.mY);
+ builder.append(",w:");
+ builder.append(key.mWidth);
+ builder.append(",h:");
+ builder.append(key.mHeight);
+ builder.append("}");
+ }
+ builder.append("]");
+ logUnstructured("LatinKeyboardView_setKeyboard", builder.toString());
+ }
+ }
+
public static void latinIME_revertCommit(final String originallyTypedWord) {
if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) {
logUnstructured("LatinIME_revertCommit", originallyTypedWord);
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index fc6193287..33ad23a60 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -27,10 +27,23 @@ import java.util.Locale;
public class SubtypeLocale {
private static final String TAG = SubtypeLocale.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();
// Special language code to represent "no language".
public static final String NO_LANGUAGE = "zz";
+ public static final String QWERTY = "qwerty";
+
+ private static String[] sPredefinedKeyboardLayoutSet;
+ // Keyboard layout to its display name map.
+ private static final HashMap<String, String> sKeyboardKayoutToDisplayNameMap =
+ new HashMap<String, String>();
+ // Keyboard layout to subtype name resource id map.
+ private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
+ new HashMap<String, Integer>();
+ private static final String SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX = "string/subtype_generic_";
// Exceptional locales to display name map.
private static final HashMap<String, String> sExceptionalDisplayNamesMap =
new HashMap<String, String>();
@@ -41,13 +54,36 @@ public class SubtypeLocale {
public static void init(Context context) {
final Resources res = context.getResources();
- final String[] locales = res.getStringArray(R.array.subtype_locale_exception_keys);
- final String[] displayNames = res.getStringArray(R.array.subtype_locale_exception_values);
- for (int i = 0; i < locales.length; i++) {
- sExceptionalDisplayNamesMap.put(locales[i], displayNames[i]);
+
+ final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
+ sPredefinedKeyboardLayoutSet = predefinedLayoutSet;
+ final String[] layoutDisplayNames = res.getStringArray(
+ R.array.predefined_layout_display_names);
+ for (int i = 0; i < predefinedLayoutSet.length; i++) {
+ final String layoutName = predefinedLayoutSet[i];
+ sKeyboardKayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
+ final String resourceName = SUBTYPE_RESOURCE_GENERIC_NAME_PREFIX + layoutName;
+ final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
+ sKeyboardLayoutToNameIdsMap.put(layoutName, resId);
+ }
+
+ final String[] exceptionalLocales = res.getStringArray(
+ R.array.subtype_locale_exception_keys);
+ final String[] exceptionalDisplayNames = res.getStringArray(
+ R.array.subtype_locale_exception_values);
+ for (int i = 0; i < exceptionalLocales.length; i++) {
+ sExceptionalDisplayNamesMap.put(exceptionalLocales[i], exceptionalDisplayNames[i]);
}
}
+ public static String[] getPredefinedKeyboardLayoutSet() {
+ return sPredefinedKeyboardLayoutSet;
+ }
+
+ public static int getSubtypeNameIdFromKeyboardLayoutName(String keyboardLayoutName) {
+ return sKeyboardLayoutToNameIdsMap.get(keyboardLayoutName);
+ }
+
// Get InputMethodSubtype's display name in its locale.
// isAdditionalSubtype (T=true, F=false)
// locale layout | Short Middle Full
@@ -115,7 +151,8 @@ public class SubtypeLocale {
}
public static String getKeyboardLayoutSetDisplayName(InputMethodSubtype subtype) {
- return getKeyboardLayoutSetName(subtype).toUpperCase();
+ final String layoutName = getKeyboardLayoutSetName(subtype);
+ return sKeyboardKayoutToDisplayNameMap.get(layoutName);
}
public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {
@@ -125,7 +162,7 @@ public class SubtypeLocale {
if (keyboardLayoutSet == null) {
android.util.Log.w(TAG, "KeyboardLayoutSet not found, use QWERTY: " +
"locale=" + subtype.getLocale() + " extraValue=" + subtype.getExtraValue());
- return AdditionalSubtype.QWERTY;
+ return QWERTY;
}
return keyboardLayoutSet;
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 1a9f373a1..804287309 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -16,19 +16,16 @@
package com.android.inputmethod.latin;
-import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
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;
@@ -36,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;
@@ -45,37 +41,42 @@ public class SubtypeSwitcher {
private static boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = SubtypeSwitcher.class.getSimpleName();
- private static final char LOCALE_SEPARATOR = '_';
- 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;
}
@@ -96,15 +97,10 @@ 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);
+ service, SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY);
final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
mIsNetworkConnected = (info != null && info.isConnected());
@@ -113,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();
}
@@ -127,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());
@@ -192,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);
+ Log.w(TAG, "onCurrentInputMethodSubtypeChanged: to: "
+ + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: "
+ + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue());
}
- boolean languageChanged = false;
- if (!newLocale.equals(mInputLocaleStr)) {
- if (mInputLocaleStr != null) {
- languageChanged = true;
- }
- updateInputLocale(newLocale);
- }
- 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();
}
////////////////////////////
@@ -323,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;
- }
-
- 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]);
+ return mNeedsToDisplayLanguage.getValue();
}
- 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;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index d22332116..97df98e34 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -21,6 +21,7 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions
import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
@@ -272,6 +273,29 @@ public class BinaryDictInputOutput {
}
/**
+ * Writes a string with our character format to a ByteArrayOutputStream.
+ *
+ * This will also write the terminator byte.
+ *
+ * @param buffer the ByteArrayOutputStream to write to.
+ * @param word the string to write.
+ */
+ private static void writeString(ByteArrayOutputStream buffer, final String word) {
+ final int length = word.length();
+ for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
+ final int codePoint = word.codePointAt(i);
+ if (1 == getCharSize(codePoint)) {
+ buffer.write((byte) codePoint);
+ } else {
+ buffer.write((byte) (0xFF & (codePoint >> 16)));
+ buffer.write((byte) (0xFF & (codePoint >> 8)));
+ buffer.write((byte) (0xFF & codePoint));
+ }
+ }
+ buffer.write(GROUP_CHARACTERS_TERMINATOR);
+ }
+
+ /**
* Reads a string from a RandomAccessFile. This is the converse of the above method.
*/
private static String readString(final RandomAccessFile source) throws IOException {
@@ -894,15 +918,11 @@ public class BinaryDictInputOutput {
final FusionDictionary dict, final int version)
throws IOException, UnsupportedFormatException {
- // Addresses are limited to 3 bytes, so we'll just make a 16MB buffer. Since addresses
- // can be relative to each node, the structure itself is not limited to 16MB at all, but
- // I doubt this will ever be shot. If it is, deciding the order of the nodes becomes
- // a quite complicated problem, because though the dictionary itself does not have a
- // size limit, each node must still be within 16MB of all its children and parents.
- // As long as this is ensured, the dictionary file may grow to any size.
- // Anyway, to make a dictionary bigger than 16MB just increase the size of this buffer.
- final byte[] buffer = new byte[1 << 24];
- int index = 0;
+ // Addresses are limited to 3 bytes, but since addresses can be relative to each node, the
+ // structure itself is not limited to 16MB. However, if it is over 16MB deciding the order
+ // of the nodes becomes a quite complicated problem, because though the dictionary itself
+ // does not have a size limit, each node must still be within 16MB of all its children and
+ // parents. As long as this is ensured, the dictionary file may grow to any size.
if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION) {
throw new UnsupportedFormatException("Requested file format version " + version
@@ -910,47 +930,54 @@ public class BinaryDictInputOutput {
+ MINIMUM_SUPPORTED_VERSION + " through " + MAXIMUM_SUPPORTED_VERSION);
}
+ ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256);
+
// The magic number in big-endian order.
if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
// Magic number for version 2+.
- buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 24));
- buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16));
- buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8));
- buffer[index++] = (byte) (0xFF & VERSION_2_MAGIC_NUMBER);
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 24)));
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16)));
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8)));
+ headerBuffer.write((byte) (0xFF & VERSION_2_MAGIC_NUMBER));
// Dictionary version.
- buffer[index++] = (byte) (0xFF & (version >> 8));
- buffer[index++] = (byte) (0xFF & version);
+ headerBuffer.write((byte) (0xFF & (version >> 8)));
+ headerBuffer.write((byte) (0xFF & version));
} else {
// Magic number for version 1.
- buffer[index++] = (byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8));
- buffer[index++] = (byte) (0xFF & VERSION_1_MAGIC_NUMBER);
+ headerBuffer.write((byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8)));
+ headerBuffer.write((byte) (0xFF & VERSION_1_MAGIC_NUMBER));
// Dictionary version.
- buffer[index++] = (byte) (0xFF & version);
+ headerBuffer.write((byte) (0xFF & version));
}
// Options flags
final int options = makeOptionsValue(dict.mOptions);
- buffer[index++] = (byte) (0xFF & (options >> 8));
- buffer[index++] = (byte) (0xFF & options);
+ headerBuffer.write((byte) (0xFF & (options >> 8)));
+ headerBuffer.write((byte) (0xFF & options));
if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
- final int headerSizeOffset = index;
- index += 4; // Size of the header size
-
+ final int headerSizeOffset = headerBuffer.size();
+ // Placeholder to be written later with header size.
+ for (int i = 0; i < 4; ++i) {
+ headerBuffer.write(0);
+ }
// Write out the options.
for (final String key : dict.mOptions.mAttributes.keySet()) {
final String value = dict.mOptions.mAttributes.get(key);
- index += CharEncoding.writeString(buffer, index, key);
- index += CharEncoding.writeString(buffer, index, value);
+ CharEncoding.writeString(headerBuffer, key);
+ CharEncoding.writeString(headerBuffer, value);
}
-
+ final int size = headerBuffer.size();
+ final byte[] bytes = headerBuffer.toByteArray();
// Write out the header size.
- buffer[headerSizeOffset] = (byte) (0xFF & (index >> 24));
- buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 16));
- buffer[headerSizeOffset + 2] = (byte) (0xFF & (index >> 8));
- buffer[headerSizeOffset + 3] = (byte) (0xFF & (index >> 0));
+ bytes[headerSizeOffset] = (byte) (0xFF & (size >> 24));
+ bytes[headerSizeOffset + 1] = (byte) (0xFF & (size >> 16));
+ bytes[headerSizeOffset + 2] = (byte) (0xFF & (size >> 8));
+ bytes[headerSizeOffset + 3] = (byte) (0xFF & (size >> 0));
+ destination.write(bytes);
+ } else {
+ headerBuffer.writeTo(destination);
}
- destination.write(buffer, 0, index);
- index = 0;
+ headerBuffer.close();
// Leave the choice of the optimal node order to the flattenTree function.
MakedictLog.i("Flattening the tree...");
@@ -961,6 +988,12 @@ public class BinaryDictInputOutput {
MakedictLog.i("Checking array...");
checkFlatNodeArray(flatNodes);
+ // Create a buffer that matches the final dictionary size.
+ final Node lastNode = flatNodes.get(flatNodes.size() - 1);
+ final int bufferSize =(lastNode.mCachedAddress + lastNode.mCachedSize);
+ final byte[] buffer = new byte[bufferSize];
+ int index = 0;
+
MakedictLog.i("Writing file...");
int dataEndOffset = 0;
for (Node n : flatNodes) {