aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java20
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java111
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java115
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java111
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java37
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java80
9 files changed, 324 insertions, 220 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index ebd61505d..3a9423f4b 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -101,7 +101,7 @@ public class Key {
/** Text to output when pressed. This can be multiple characters, like ".com" */
public final CharSequence mOutputText;
/** More keys */
- public final CharSequence[] mMoreKeys;
+ public final String[] mMoreKeys;
/** More keys maximum column number */
public final int mMaxMoreKeysColumn;
@@ -166,7 +166,12 @@ public class Key {
}
private static Drawable getIcon(Keyboard.Params params, String moreKeySpec) {
- return params.mIconsSet.getIconByIconId(MoreKeySpecParser.getIconId(moreKeySpec));
+ final int iconAttrId = MoreKeySpecParser.getIconAttrId(moreKeySpec);
+ if (iconAttrId == KeyboardIconsSet.ICON_UNDEFINED) {
+ return null;
+ } else {
+ return params.mIconsSet.getIconByAttrId(iconAttrId);
+ }
}
/**
@@ -255,7 +260,7 @@ public class Key {
// Update row to have current x coordinate.
row.setXPos(keyXPos + keyWidth);
- final CharSequence[] moreKeys = style.getTextArray(keyAttr,
+ final String[] moreKeys = style.getTextArray(keyAttr,
R.styleable.Keyboard_Key_moreKeys);
// In Arabic symbol layouts, we'd like to keep digits in more keys regardless of
// config_digit_more_keys_enabled.
@@ -277,12 +282,15 @@ 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);
- mPreviewIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+ final int previewIconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED));
- mIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+ mPreviewIcon = iconsSet.getIconByAttrId(previewIconAttrId);
+ final int iconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED));
- mDisabledIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+ mIcon = iconsSet.getIconByAttrId(iconAttrId);
+ final int disabledIconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED));
+ mDisabledIcon = iconsSet.getIconByAttrId(disabledIconAttrId);
mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 22ab3e4e5..4967a5e80 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -137,8 +137,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
mKeyboardSet = builder.build();
final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId();
try {
- mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
- hasDistinctMultitouch());
+ mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols));
} catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e);
LatinImeLogger.logOnException(mainKeyboardId.toString(), e);
@@ -316,7 +315,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
}
/**
- * Updates state machine to figure out when to automatically snap back to the previous mode.
+ * Updates state machine to figure out when to automatically switch back to the previous mode.
*/
public void onCodeInput(int code) {
mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState());
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index 548b5ea85..974291373 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -34,7 +34,7 @@ public class MiniKeyboard extends Keyboard {
}
public static class Builder extends Keyboard.Builder<Builder.MiniKeyboardParams> {
- private final CharSequence[] mMoreKeys;
+ private final String[] mMoreKeys;
public static class MiniKeyboardParams extends Keyboard.Params {
/* package */int mTopRowAdjustment;
@@ -230,16 +230,14 @@ public class MiniKeyboard extends Keyboard {
parentKey.mX + (mParams.mDefaultKeyWidth - width) / 2, view.getMeasuredWidth());
}
- private static int getMaxKeyWidth(KeyboardView view, CharSequence[] moreKeys,
- int minKeyWidth) {
+ private static int getMaxKeyWidth(KeyboardView view, String[] moreKeys, int minKeyWidth) {
final int padding = (int) view.getContext().getResources()
.getDimension(R.dimen.mini_keyboard_key_horizontal_padding);
Paint paint = null;
int maxWidth = minKeyWidth;
- for (CharSequence moreKeySpec : moreKeys) {
- final CharSequence label = MoreKeySpecParser.getLabel(moreKeySpec.toString());
- // If the label is single letter, minKeyWidth is enough to hold
- // the label.
+ for (String moreKeySpec : moreKeys) {
+ final String label = MoreKeySpecParser.getLabel(moreKeySpec);
+ // If the label is single letter, minKeyWidth is enough to hold the label.
if (label != null && label.length() > 1) {
if (paint == null) {
paint = new Paint();
@@ -258,7 +256,7 @@ public class MiniKeyboard extends Keyboard {
public MiniKeyboard build() {
final MiniKeyboardParams params = mParams;
for (int n = 0; n < mMoreKeys.length; n++) {
- final String moreKeySpec = mMoreKeys[n].toString();
+ final String moreKeySpec = mMoreKeys[n];
final int row = n / params.mNumColumns;
final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 5dd8340fc..faea38941 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -16,11 +16,13 @@
package com.android.inputmethod.keyboard.internal;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.Log;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.XmlParseUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -30,7 +32,7 @@ import java.util.ArrayList;
import java.util.HashMap;
public class KeyStyles {
- private static final String TAG = "KeyStyles";
+ private static final String TAG = KeyStyles.class.getSimpleName();
private static final boolean DEBUG = false;
private final HashMap<String, DeclaredKeyStyle> mStyles =
@@ -38,19 +40,19 @@ public class KeyStyles {
private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle();
public interface KeyStyle {
- public CharSequence[] getTextArray(TypedArray a, int index);
+ public String[] getTextArray(TypedArray a, int index);
public CharSequence getText(TypedArray a, int index);
public int getInt(TypedArray a, int index, int defaultValue);
public int getFlag(TypedArray a, int index, int defaultValue);
}
- /* package */ static class EmptyKeyStyle implements KeyStyle {
+ private static class EmptyKeyStyle implements KeyStyle {
EmptyKeyStyle() {
// Nothing to do.
}
@Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
+ public String[] getTextArray(TypedArray a, int index) {
return parseTextArray(a, index);
}
@@ -69,64 +71,77 @@ public class KeyStyles {
return a.getInt(index, defaultValue);
}
- protected static CharSequence[] parseTextArray(TypedArray a, int index) {
+ protected static String[] parseTextArray(TypedArray a, int index) {
if (!a.hasValue(index))
return null;
final CharSequence text = a.getText(index);
- return parseCsvText(text);
- }
-
- /* package */ static CharSequence[] parseCsvText(CharSequence text) {
- final int size = text.length();
- if (size == 0) return null;
- if (size == 1) return new CharSequence[] { text };
- final StringBuilder sb = new StringBuilder();
- ArrayList<CharSequence> list = null;
- int start = 0;
- for (int pos = 0; pos < size; pos++) {
- final char c = text.charAt(pos);
- if (c == ',') {
- if (list == null) list = new ArrayList<CharSequence>();
- if (sb.length() == 0) {
- list.add(text.subSequence(start, pos));
- } else {
- list.add(sb.toString());
- sb.setLength(0);
+ return parseCsvText(text.toString(), a.getResources(), R.string.english_ime_name);
+ }
+ }
+
+ /* package for test */
+ static String[] parseCsvText(String rawText, Resources res, int packageNameResId) {
+ final String text = Utils.resolveStringResource(rawText, res, packageNameResId);
+ final int size = text.length();
+ if (size == 0) {
+ return null;
+ }
+ if (size == 1) {
+ return new String[] { text };
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ ArrayList<String> list = null;
+ int start = 0;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (c == ',') {
+ if (list == null) {
+ list = new ArrayList<String>();
+ }
+ if (sb.length() == 0) {
+ list.add(text.substring(start, pos));
+ } else {
+ list.add(sb.toString());
+ sb.setLength(0);
+ }
+ start = pos + 1;
+ continue;
+ } else if (c == Utils.ESCAPE_CHAR) {
+ if (start == pos) {
+ // Skip escape character at the beginning of the value.
+ start++;
+ pos++;
+ } else {
+ if (start < pos && sb.length() == 0) {
+ sb.append(text.subSequence(start, pos));
}
- start = pos + 1;
- continue;
- } else if (c == '\\') {
- if (start == pos) {
- // Skip escape character at the beginning of the value.
- start++;
- pos++;
- } else {
- if (start < pos && sb.length() == 0)
- sb.append(text.subSequence(start, pos));
- pos++;
- if (pos < size)
- sb.append(text.charAt(pos));
+ pos++;
+ if (pos < size) {
+ sb.append(text.charAt(pos));
}
- } else if (sb.length() > 0) {
- sb.append(c);
}
+ } else if (sb.length() > 0) {
+ sb.append(c);
}
- if (list == null) {
- return new CharSequence[] { sb.length() > 0 ? sb : text.subSequence(start, size) };
- } else {
- list.add(sb.length() > 0 ? sb : text.subSequence(start, size));
- return list.toArray(new CharSequence[list.size()]);
- }
+ }
+ if (list == null) {
+ return new String[] {
+ sb.length() > 0 ? sb.toString() : text.substring(start)
+ };
+ } else {
+ list.add(sb.length() > 0 ? sb.toString() : text.substring(start));
+ return list.toArray(new String[list.size()]);
}
}
- /* package */ static class DeclaredKeyStyle extends EmptyKeyStyle {
+ private static class DeclaredKeyStyle extends EmptyKeyStyle {
private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
@Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
+ public String[] getTextArray(TypedArray a, int index) {
return a.hasValue(index)
- ? super.getTextArray(a, index) : (CharSequence[])mAttributes.get(index);
+ ? super.getTextArray(a, index) : (String[])mAttributes.get(index);
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 6313a61b5..09ecbcaa0 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -31,34 +31,36 @@ public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
public static final int ICON_UNDEFINED = 0;
+ private static final int ATTR_UNDEFINED = 0;
private final Map<Integer, Drawable> mIcons = new HashMap<Integer, Drawable>();
// The key value should be aligned with the enum value of Keyboard.icon*.
private static final Map<Integer, Integer> ICONS_TO_ATTRS_MAP = new HashMap<Integer, Integer>();
+ private static final Map<String, Integer> NAME_TO_ATTRS_MAP = new HashMap<String, Integer>();
private static final Collection<Integer> VALID_ATTRS;
static {
- addIconIdMap(1, R.styleable.Keyboard_iconShiftKey);
- addIconIdMap(2, R.styleable.Keyboard_iconDeleteKey);
- // This is also represented as "@icon/3" in keyboard layout XML.
- addIconIdMap(3, R.styleable.Keyboard_iconSettingsKey);
- addIconIdMap(4, R.styleable.Keyboard_iconSpaceKey);
- addIconIdMap(5, R.styleable.Keyboard_iconReturnKey);
- addIconIdMap(6, R.styleable.Keyboard_iconSearchKey);
- // This is also represented as "@icon/7" in keyboard layout XML.
- addIconIdMap(7, R.styleable.Keyboard_iconTabKey);
- addIconIdMap(8, R.styleable.Keyboard_iconShortcutKey);
- addIconIdMap(9, R.styleable.Keyboard_iconShortcutForLabel);
- addIconIdMap(10, R.styleable.Keyboard_iconSpaceKeyForNumberLayout);
- addIconIdMap(11, R.styleable.Keyboard_iconShiftKeyShifted);
- addIconIdMap(12, R.styleable.Keyboard_iconDisabledShortcutKey);
- addIconIdMap(13, R.styleable.Keyboard_iconPreviewTabKey);
+ 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);
VALID_ATTRS = ICONS_TO_ATTRS_MAP.values();
}
- private static void addIconIdMap(int iconId, int attrId) {
+ private static void addIconIdMap(int iconId, String name, Integer attrId) {
ICONS_TO_ATTRS_MAP.put(iconId, attrId);
+ NAME_TO_ATTRS_MAP.put(name, attrId);
}
public void loadIcons(final TypedArray keyboardAttrs) {
@@ -76,18 +78,29 @@ public class KeyboardIconsSet {
}
}
- public Drawable getIconByIconId(final Integer iconId) {
+ public static int getIconAttrId(final Integer iconId) {
if (iconId == ICON_UNDEFINED) {
- return null;
+ return ATTR_UNDEFINED;
}
final Integer attrId = ICONS_TO_ATTRS_MAP.get(iconId);
if (attrId == null) {
throw new IllegalArgumentException("icon id is out of range: " + iconId);
}
- return getIconByAttrId(attrId);
+ return attrId;
+ }
+
+ public static int getIconAttrId(final String iconName) {
+ final Integer attrId = NAME_TO_ATTRS_MAP.get(iconName);
+ if (attrId == null) {
+ throw new IllegalArgumentException("unknown icon name: " + iconName);
+ }
+ return attrId;
}
public Drawable getIconByAttrId(final Integer attrId) {
+ if (attrId == ATTR_UNDEFINED) {
+ return null;
+ }
if (!VALID_ATTRS.contains(attrId)) {
throw new IllegalArgumentException("unknown icon attribute id: " + attrId);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index c43b9852b..af16e4907 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -26,7 +26,7 @@ import com.android.inputmethod.keyboard.Keyboard;
*
* This class contains all keyboard state transition logic.
*
- * The input events are {@link #onLoadKeyboard(String, boolean)}, {@link #onSaveKeyboardState()},
+ * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()},
* {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)},
* {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)},
* {@link #onUpdateShiftState(boolean)}.
@@ -58,7 +58,7 @@ public class KeyboardState {
public void requestUpdatingShiftState();
}
- private KeyboardShiftState mKeyboardShiftState = new KeyboardShiftState();
+ private final SwitchActions mSwitchActions;
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
@@ -72,17 +72,15 @@ public class KeyboardState {
private static final int SWITCH_STATE_CHORDING_ALPHA = 5;
private static final int SWITCH_STATE_CHORDING_SYMBOL = 6;
private int mSwitchState = SWITCH_STATE_ALPHA;
-
private String mLayoutSwitchBackSymbols;
- private boolean mHasDistinctMultitouch;
-
- private final SwitchActions mSwitchActions;
private boolean mIsAlphabetMode;
+ private KeyboardShiftState mAlphabetShiftState = new KeyboardShiftState();
private boolean mIsSymbolShifted;
+ private boolean mPrevMainKeyboardWasShiftLocked;
+ private boolean mPrevSymbolsKeyboardWasShifted;
private final SavedKeyboardState mSavedKeyboardState = new SavedKeyboardState();
- private boolean mPrevMainKeyboardWasShiftLocked;
static class SavedKeyboardState {
public boolean mIsValid;
@@ -95,17 +93,17 @@ public class KeyboardState {
mSwitchActions = switchActions;
}
- public void onLoadKeyboard(String layoutSwitchBackSymbols, boolean hasDistinctMultitouch) {
+ public void onLoadKeyboard(String layoutSwitchBackSymbols) {
if (DEBUG_EVENT) {
Log.d(TAG, "onLoadKeyboard");
}
mLayoutSwitchBackSymbols = layoutSwitchBackSymbols;
- mHasDistinctMultitouch = hasDistinctMultitouch;
- mKeyboardShiftState.setShifted(false);
- mKeyboardShiftState.setShiftLocked(false);
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mPrevMainKeyboardWasShiftLocked = false;
+ mPrevSymbolsKeyboardWasShifted = false;
mShiftKeyState.onRelease();
mSymbolKeyState.onRelease();
- mPrevMainKeyboardWasShiftLocked = false;
onRestoreKeyboardState();
}
@@ -113,9 +111,9 @@ public class KeyboardState {
final SavedKeyboardState state = mSavedKeyboardState;
state.mIsAlphabetMode = mIsAlphabetMode;
if (mIsAlphabetMode) {
- state.mIsShiftLocked = mKeyboardShiftState.isShiftLocked();
+ state.mIsShiftLocked = mAlphabetShiftState.isShiftLocked();
state.mIsShifted = !state.mIsShiftLocked
- && mKeyboardShiftState.isShiftedOrShiftLocked();
+ && mAlphabetShiftState.isShiftedOrShiftLocked();
} else {
state.mIsShiftLocked = false;
state.mIsShifted = mIsSymbolShifted;
@@ -157,25 +155,23 @@ public class KeyboardState {
// TODO: Remove this method.
public boolean isShiftLocked() {
- return mKeyboardShiftState.isShiftLocked();
+ return mAlphabetShiftState.isShiftLocked();
}
private void setShifted(int shiftMode) {
if (DEBUG_ACTION) {
Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode));
}
- if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) {
- mKeyboardShiftState.setAutomaticTemporaryUpperCase();
- } else {
- final boolean shifted = (shiftMode == SwitchActions.MANUAL_SHIFT);
- // On non-distinct multi touch panel device, we should also turn off the shift locked
- // state when shift key is pressed to go to normal mode.
- // On the other hand, on distinct multi touch panel device, turning off the shift
- // locked state with shift key pressing is handled by onReleaseShift().
- if (!mHasDistinctMultitouch && !shifted && mKeyboardShiftState.isShiftLocked()) {
- mSwitchActions.setShiftLocked(false);
- }
- mKeyboardShiftState.setShifted(shifted);
+ switch (shiftMode) {
+ case SwitchActions.AUTOMATIC_SHIFT:
+ mAlphabetShiftState.setAutomaticTemporaryUpperCase();
+ break;
+ case SwitchActions.MANUAL_SHIFT:
+ mAlphabetShiftState.setShifted(true);
+ break;
+ case SwitchActions.UNSHIFT:
+ mAlphabetShiftState.setShifted(false);
+ break;
}
mSwitchActions.setShifted(shiftMode);
}
@@ -184,7 +180,7 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked);
}
- mKeyboardShiftState.setShiftLocked(shiftLocked);
+ mAlphabetShiftState.setShiftLocked(shiftLocked);
mSwitchActions.setShiftLocked(shiftLocked);
}
@@ -208,6 +204,7 @@ public class KeyboardState {
if (DEBUG_ACTION) {
Log.d(TAG, "setAlphabetKeyboard");
}
+ mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
mSwitchActions.setAlphabetKeyboard();
mIsAlphabetMode = true;
mIsSymbolShifted = false;
@@ -219,13 +216,21 @@ public class KeyboardState {
// TODO: Make this method private
public void setSymbolsKeyboard() {
+ mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
+ if (mPrevSymbolsKeyboardWasShifted) {
+ setSymbolsShiftedKeyboard();
+ return;
+ }
+
if (DEBUG_ACTION) {
Log.d(TAG, "setSymbolsKeyboard");
}
- mPrevMainKeyboardWasShiftLocked = mKeyboardShiftState.isShiftLocked();
mSwitchActions.setSymbolsKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = false;
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mPrevSymbolsKeyboardWasShifted = false;
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
}
@@ -236,6 +241,9 @@ public class KeyboardState {
mSwitchActions.setSymbolsShiftedKeyboard();
mIsAlphabetMode = false;
mIsSymbolShifted = true;
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mPrevSymbolsKeyboardWasShifted = false;
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
}
@@ -273,7 +281,7 @@ public class KeyboardState {
}
private void onReleaseSymbol() {
- // Snap back to the previous keyboard mode if the user chords the mode change key and
+ // Switch back to the previous keyboard mode if the user chords the mode change key and
// another key, then releases the mode change key.
if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
toggleAlphabetAndSymbols();
@@ -290,7 +298,7 @@ public class KeyboardState {
private void onUpdateShiftStateInternal(boolean autoCaps) {
if (mIsAlphabetMode) {
- if (!mKeyboardShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
+ if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
if (mShiftKeyState.isReleasing() && autoCaps) {
// Only when shift key is releasing, automatic temporary upper case will be set.
setShifted(SwitchActions.AUTOMATIC_SHIFT);
@@ -308,17 +316,17 @@ public class KeyboardState {
private void onPressShift() {
if (mIsAlphabetMode) {
- if (mKeyboardShiftState.isShiftLocked()) {
+ if (mAlphabetShiftState.isShiftLocked()) {
// Shift key is pressed while caps lock state, we will treat this state as shifted
// caps lock state and mark as if shift key pressed while normal state.
setShifted(SwitchActions.MANUAL_SHIFT);
mShiftKeyState.onPress();
- } else if (mKeyboardShiftState.isAutomaticTemporaryUpperCase()) {
+ } else if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) {
// Shift key is pressed while automatic temporary upper case, we have to move to
// manual temporary upper case.
setShifted(SwitchActions.MANUAL_SHIFT);
mShiftKeyState.onPress();
- } else if (mKeyboardShiftState.isShiftedOrShiftLocked()) {
+ } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) {
// In manual upper case state, we just record shift key has been pressing while
// shifted state.
mShiftKeyState.onPressOnShifted();
@@ -337,30 +345,34 @@ public class KeyboardState {
private void onReleaseShift(boolean withSliding) {
if (mIsAlphabetMode) {
- final boolean isShiftLocked = mKeyboardShiftState.isShiftLocked();
+ final boolean isShiftLocked = mAlphabetShiftState.isShiftLocked();
if (mShiftKeyState.isMomentary()) {
// After chording input while normal state.
- setShifted(SwitchActions.UNSHIFT);
- } else if (isShiftLocked && !mKeyboardShiftState.isShiftLockShifted()
+ if (mAlphabetShiftState.isShiftLockShifted()) {
+ setShiftLocked(true);
+ } else {
+ setShifted(SwitchActions.UNSHIFT);
+ }
+ } else if (isShiftLocked && !mAlphabetShiftState.isShiftLockShifted()
&& (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted())
&& !withSliding) {
// Shift has been long pressed, ignore this release.
} else if (isShiftLocked && !mShiftKeyState.isIgnoring() && !withSliding) {
// Shift has been pressed without chording while caps lock state.
setShiftLocked(false);
- } else if (mKeyboardShiftState.isShiftedOrShiftLocked()
+ } else if (mAlphabetShiftState.isShiftedOrShiftLocked()
&& mShiftKeyState.isPressingOnShifted() && !withSliding) {
// Shift has been pressed without chording while shifted state.
setShifted(SwitchActions.UNSHIFT);
- } else if (mKeyboardShiftState.isManualTemporaryUpperCaseFromAuto()
+ } else if (mAlphabetShiftState.isManualTemporaryUpperCaseFromAuto()
&& mShiftKeyState.isPressing() && !withSliding) {
// Shift has been pressed without chording while manual temporary upper case
// transited from automatic temporary upper case.
setShifted(SwitchActions.UNSHIFT);
}
} else {
- // In symbol mode, snap back to the previous keyboard mode if the user chords the shift
- // key and another key, then releases the shift key.
+ // In symbol mode, switch back to the previous keyboard mode if the user chords the
+ // shift key and another key, then releases the shift key.
if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) {
toggleShiftInSymbols();
}
@@ -372,7 +384,7 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
}
- // Snap back to the previous keyboard mode if the user cancels sliding input.
+ // Switch back to the previous keyboard mode if the user cancels sliding input.
if (isSinglePointer) {
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
toggleAlphabetAndSymbols();
@@ -405,7 +417,7 @@ public class KeyboardState {
}
if (mIsAlphabetMode && code == Keyboard.CODE_CAPSLOCK) {
- if (mKeyboardShiftState.isShiftLocked()) {
+ if (mAlphabetShiftState.isShiftLocked()) {
setShiftLocked(false);
// Shift key is long pressed or double tapped while caps lock state, we will
// toggle back to normal state. And mark as if shift key is released.
@@ -431,13 +443,13 @@ public class KeyboardState {
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
}
} else if (isSinglePointer) {
- // Snap back to the previous keyboard mode if the user pressed the mode change key
+ // Switch back to the previous keyboard mode if the user pressed the mode change key
// and slid to other key, then released the finger.
- // If the user cancels the sliding input, snapping back to the previous keyboard
+ // If the user cancels the sliding input, switching back to the previous keyboard
// mode is handled by {@link #onCancelInput}.
toggleAlphabetAndSymbols();
} else {
- // Chording input is being started. The keyboard mode will be snapped back to the
+ // Chording input is being started. The keyboard mode will be switched back to the
// previous mode in {@link onReleaseSymbol} when the mode change key is released.
mSwitchState = SWITCH_STATE_CHORDING_ALPHA;
}
@@ -447,12 +459,12 @@ public class KeyboardState {
// Detected only the shift key has been pressed on symbol layout, and then released.
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} else if (isSinglePointer) {
- // Snap back to the previous keyboard mode if the user pressed the shift key on
+ // Switch back to the previous keyboard mode if the user pressed the shift key on
// symbol mode and slid to other key, then released the finger.
toggleShiftInSymbols();
mSwitchState = SWITCH_STATE_SYMBOL;
} else {
- // Chording input is being started. The keyboard mode will be snapped back to the
+ // Chording input is being started. The keyboard mode will be switched back to the
// previous mode in {@link onReleaseShift} when the shift key is released.
mSwitchState = SWITCH_STATE_CHORDING_SYMBOL;
}
@@ -462,14 +474,14 @@ public class KeyboardState {
|| code == Keyboard.CODE_OUTPUT_TEXT)) {
mSwitchState = SWITCH_STATE_SYMBOL;
}
- // Snap back to alpha keyboard mode immediately if user types a quote character.
+ // Switch back to alpha keyboard mode immediately if user types a quote character.
if (isLayoutSwitchBackCharacter(code)) {
setAlphabetKeyboard();
}
break;
case SWITCH_STATE_SYMBOL:
case SWITCH_STATE_CHORDING_SYMBOL:
- // Snap back to alpha keyboard mode if user types one or more non-space/enter
+ // Switch back to alpha keyboard mode if user types one or more non-space/enter
// characters followed by a space/enter or a quote character.
if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
setAlphabetKeyboard();
@@ -507,7 +519,8 @@ public class KeyboardState {
@Override
public String toString() {
- return "[keyboard=" + mKeyboardShiftState
+ return "[keyboard=" + (mIsAlphabetMode ? mAlphabetShiftState.toString()
+ : (mIsSymbolShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS"))
+ " shift=" + mShiftKeyState
+ " symbol=" + mSymbolKeyState
+ " switch=" + switchStateToString(mSwitchState) + "]";
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
index 93be31ed9..16777733e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
@@ -18,10 +18,10 @@ package com.android.inputmethod.keyboard.internal;
import android.content.res.Resources;
import android.text.TextUtils;
-import android.util.Log;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.Utils;
import java.util.ArrayList;
@@ -31,20 +31,16 @@ import java.util.ArrayList;
* Each "more key" specification is one of the following:
* - A single letter (Letter)
* - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText).
- * - Icon followed by keyOutputText or code (@icon/icon_number|@integer/key_code)
+ * - Icon followed by keyOutputText or code (@icon/icon_name|@integer/key_code)
* Special character, comma ',' backslash '\', and bar '|' can be escaped by '\'
* character.
* Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well.
* See {@link KeyboardIconsSet} about icon_number.
*/
public class MoreKeySpecParser {
- private static final String TAG = MoreKeySpecParser.class.getSimpleName();
-
- private static final char ESCAPE = '\\';
- private static final String LABEL_END = "|";
- private static final String PREFIX_AT = "@";
- private static final String PREFIX_ICON = PREFIX_AT + "icon/";
- private static final String PREFIX_CODE = PREFIX_AT + "integer/";
+ private static final char LABEL_END = '|';
+ private static final String PREFIX_ICON = Utils.PREFIX_AT + "icon" + Utils.SUFFIX_SLASH;
+ private static final String PREFIX_CODE = Utils.PREFIX_AT + "integer" + Utils.SUFFIX_SLASH;
private MoreKeySpecParser() {
// Intentional empty constructor for utility class.
@@ -53,8 +49,9 @@ public class MoreKeySpecParser {
private static boolean hasIcon(String moreKeySpec) {
if (moreKeySpec.startsWith(PREFIX_ICON)) {
final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (end > 0)
+ if (end > 0) {
return true;
+ }
throw new MoreKeySpecParserError("outputText or code not specified: " + moreKeySpec);
}
return false;
@@ -70,13 +67,14 @@ public class MoreKeySpecParser {
}
private static String parseEscape(String text) {
- if (text.indexOf(ESCAPE) < 0)
+ if (text.indexOf(Utils.ESCAPE_CHAR) < 0) {
return text;
+ }
final int length = text.length();
final StringBuilder sb = new StringBuilder();
for (int pos = 0; pos < length; pos++) {
final char c = text.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
+ if (c == Utils.ESCAPE_CHAR && pos + 1 < length) {
sb.append(text.charAt(++pos));
} else {
sb.append(c);
@@ -86,18 +84,19 @@ public class MoreKeySpecParser {
}
private static int indexOfLabelEnd(String moreKeySpec, int start) {
- if (moreKeySpec.indexOf(ESCAPE, start) < 0) {
+ if (moreKeySpec.indexOf(Utils.ESCAPE_CHAR, start) < 0) {
final int end = moreKeySpec.indexOf(LABEL_END, start);
- if (end == 0)
+ if (end == 0) {
throw new MoreKeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec);
+ }
return end;
}
final int length = moreKeySpec.length();
for (int pos = start; pos < length; pos++) {
final char c = moreKeySpec.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
+ if (c == Utils.ESCAPE_CHAR && pos + 1 < length) {
pos++;
- } else if (moreKeySpec.startsWith(LABEL_END, pos)) {
+ } else if (c == LABEL_END) {
return pos;
}
}
@@ -105,79 +104,75 @@ public class MoreKeySpecParser {
}
public static String getLabel(String moreKeySpec) {
- if (hasIcon(moreKeySpec))
+ if (hasIcon(moreKeySpec)) {
return null;
+ }
final int end = indexOfLabelEnd(moreKeySpec, 0);
final String label = (end > 0) ? parseEscape(moreKeySpec.substring(0, end))
: parseEscape(moreKeySpec);
- if (TextUtils.isEmpty(label))
+ if (TextUtils.isEmpty(label)) {
throw new MoreKeySpecParserError("Empty label: " + moreKeySpec);
+ }
return label;
}
public static String getOutputText(String moreKeySpec) {
- if (hasCode(moreKeySpec))
+ if (hasCode(moreKeySpec)) {
return null;
+ }
final int end = indexOfLabelEnd(moreKeySpec, 0);
if (end > 0) {
- if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0)
+ if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": "
+ moreKeySpec);
- final String outputText = parseEscape(moreKeySpec.substring(end + LABEL_END.length()));
- if (!TextUtils.isEmpty(outputText))
+ }
+ final String outputText = parseEscape(
+ moreKeySpec.substring(end + /* LABEL_END */1));
+ if (!TextUtils.isEmpty(outputText)) {
return outputText;
+ }
throw new MoreKeySpecParserError("Empty outputText: " + moreKeySpec);
}
final String label = getLabel(moreKeySpec);
- if (label == null)
+ if (label == null) {
throw new MoreKeySpecParserError("Empty label: " + moreKeySpec);
+ }
// Code is automatically generated for one letter label. See {@link getCode()}.
- if (label.length() == 1)
- return null;
- return label;
+ return (label.length() == 1) ? null : label;
}
public static int getCode(Resources res, String moreKeySpec) {
if (hasCode(moreKeySpec)) {
final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0)
+ if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec);
- final int resId = getResourceId(res,
- moreKeySpec.substring(end + LABEL_END.length() + PREFIX_AT.length()));
+ }
+ final int resId = Utils.getResourceId(res,
+ moreKeySpec.substring(end + /* LABEL_END */1 + /* PREFIX_AT */1),
+ R.string.english_ime_name);
final int code = res.getInteger(resId);
return code;
}
- if (indexOfLabelEnd(moreKeySpec, 0) > 0)
- return Keyboard.CODE_UNSPECIFIED;
+ if (indexOfLabelEnd(moreKeySpec, 0) > 0) {
+ return Keyboard.CODE_OUTPUT_TEXT;
+ }
final String label = getLabel(moreKeySpec);
// Code is automatically generated for one letter label.
- if (label != null && label.length() == 1)
+ if (label != null && label.length() == 1) {
return label.charAt(0);
- return Keyboard.CODE_UNSPECIFIED;
+ }
+ return Keyboard.CODE_OUTPUT_TEXT;
}
- public static int getIconId(String moreKeySpec) {
+ public static int getIconAttrId(String moreKeySpec) {
if (hasIcon(moreKeySpec)) {
- int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length() + 1);
- final String iconId = moreKeySpec.substring(PREFIX_ICON.length(), end);
- try {
- return Integer.valueOf(iconId);
- } catch (NumberFormatException e) {
- Log.w(TAG, "illegal icon id specified: " + iconId);
- return KeyboardIconsSet.ICON_UNDEFINED;
- }
+ final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length());
+ final String name = moreKeySpec.substring(PREFIX_ICON.length(), end);
+ return KeyboardIconsSet.getIconAttrId(name);
}
return KeyboardIconsSet.ICON_UNDEFINED;
}
- private static int getResourceId(Resources res, String name) {
- String packageName = res.getResourcePackageName(R.string.english_ime_name);
- int resId = res.getIdentifier(name, null, packageName);
- if (resId == 0)
- throw new MoreKeySpecParserError("Unknown resource: " + name);
- return resId;
- }
-
@SuppressWarnings("serial")
public static class MoreKeySpecParserError extends RuntimeException {
public MoreKeySpecParserError(String message) {
@@ -196,21 +191,19 @@ public class MoreKeySpecParser {
}
};
- public static CharSequence[] filterOut(Resources res, CharSequence[] moreKeys,
- CodeFilter filter) {
+ public static String[] filterOut(Resources res, String[] moreKeys, CodeFilter filter) {
if (moreKeys == null || moreKeys.length < 1) {
return null;
}
- if (moreKeys.length == 1
- && filter.shouldFilterOut(getCode(res, moreKeys[0].toString()))) {
+ if (moreKeys.length == 1 && filter.shouldFilterOut(getCode(res, moreKeys[0]))) {
return null;
}
- ArrayList<CharSequence> filtered = null;
+ ArrayList<String> filtered = null;
for (int i = 0; i < moreKeys.length; i++) {
- final CharSequence moreKeySpec = moreKeys[i];
- if (filter.shouldFilterOut(getCode(res, moreKeySpec.toString()))) {
+ final String moreKeySpec = moreKeys[i];
+ if (filter.shouldFilterOut(getCode(res, moreKeySpec))) {
if (filtered == null) {
- filtered = new ArrayList<CharSequence>();
+ filtered = new ArrayList<String>();
for (int j = 0; j < i; j++) {
filtered.add(moreKeys[j]);
}
@@ -225,6 +218,6 @@ public class MoreKeySpecParser {
if (filtered.size() == 0) {
return null;
}
- return filtered.toArray(new CharSequence[filtered.size()]);
+ return filtered.toArray(new String[filtered.size()]);
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d11aaeb96..94c47bdc9 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1881,6 +1881,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
return;
}
+ // We need to log before we commit, because the word composer will store away the user
+ // typed word.
+ LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
+ suggestion.toString(), index, suggestions.mWords);
mExpectingUpdateSelection = true;
commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK);
// Add the word to the auto dictionary if it's not a known word
@@ -1890,10 +1894,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
- // TODO: the following is fishy, because it seems there may be cases where we are not
- // composing a word at all. Maybe throw an exception if !mWordComposer.isComposingWord() ?
- LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
- suggestion.toString(), index, suggestions.mWords);
// Follow it with a space
if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) {
sendMagicSpace();
@@ -1924,8 +1924,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Updating the predictions right away may be slow and feel unresponsive on slower
// terminals. On the other hand if we just postUpdateBigramPredictions() it will
// take a noticeable delay to update them which may feel uneasy.
- }
- if (showingAddToDictionaryHint) {
+ } else {
if (mIsUserDictionaryAvailable) {
mSuggestionsView.showAddToDictionaryHint(
suggestion, mSettingsValues.mHintToSaveText);
@@ -1942,9 +1941,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
* Commits the chosen word to the text field and saves it for later retrieval.
*/
private void commitChosenWord(final CharSequence bestWord, final int commitType) {
- final KeyboardSwitcher switcher = mKeyboardSwitcher;
- if (!switcher.isKeyboardAvailable())
- return;
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators);
@@ -2133,12 +2129,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final String wordBeforeCursor =
ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength)
.toString();
- if (!autoCorrectedTo.equals(wordBeforeCursor)) {
+ if (!TextUtils.equals(autoCorrectedTo, wordBeforeCursor)) {
throw new RuntimeException("cancelAutoCorrect check failed: we thought we were "
+ "reverting \"" + autoCorrectedTo
+ "\", but before the cursor we found \"" + wordBeforeCursor + "\"");
}
- if (originallyTypedWord.equals(wordBeforeCursor)) {
+ if (TextUtils.equals(originallyTypedWord, wordBeforeCursor)) {
throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel "
+ "auto correction and revert to \"" + originallyTypedWord
+ "\" but we found this very string before the cursor");
@@ -2158,12 +2154,22 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// "ic" must not be null
private void restartSuggestionsOnManuallyPickedTypedWord(final InputConnection ic) {
+ // Note: this relies on the last word still being held in the WordComposer, in
+ // the field for suggestion resuming.
+ // Note: in the interest of code simplicity, we may want to just call
+ // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving
+ // the old WordComposer allows to reuse the actual typed coordinates.
+ mWordComposer.resumeSuggestionOnKeptWord();
+ // We resume suggestion, and then we want to set the composing text to the content
+ // of the word composer again. But since we just manually picked a word, there is
+ // no composing text at the moment, so we have to delete the word before we set a
+ // new composing text.
final int restartLength = mWordComposer.size();
if (DEBUG) {
final String wordBeforeCursor =
ic.getTextBeforeCursor(restartLength + 1, 0).subSequence(0, restartLength)
.toString();
- if (!mWordComposer.getTypedWord().equals(wordBeforeCursor)) {
+ if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) {
throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord "
+ "check failed: we thought we were reverting \""
+ mWordComposer.getTypedWord()
@@ -2171,13 +2177,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
+ wordBeforeCursor + "\"");
}
}
+ // Warning: this +1 takes into account the extra space added by the manual pick process.
ic.deleteSurroundingText(restartLength + 1, 0);
-
- // Note: this relies on the last word still being held in the WordComposer
- // Note: in the interest of code simplicity, we may want to just call
- // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving
- // the old WordComposer allows to reuse the actual typed coordinates.
- mWordComposer.resumeSuggestionOnKeptWord();
ic.setComposingText(mWordComposer.getTypedWord(), 1);
mHandler.cancelUpdateBigramPredictions();
mHandler.postUpdateSuggestions();
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 8e0cfa122..bc8a1301c 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -16,14 +16,6 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.define.JniLibName;
-
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -41,6 +33,14 @@ import android.text.format.DateUtils;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
+import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
+import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
+import com.android.inputmethod.compat.InputTypeCompatUtils;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.define.JniLibName;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -62,6 +62,12 @@ public class Utils {
private static boolean DBG = LatinImeLogger.sDBG;
private static boolean DBG_EDIT_DISTANCE = false;
+ // Constants for resource name parsing.
+ public static final char ESCAPE_CHAR = '\\';
+ public static final char PREFIX_AT = '@';
+ public static final char SUFFIX_SLASH = '/';
+ private static final String PREFIX_STRING = PREFIX_AT + "string";
+
private Utils() {
// Intentional empty constructor for utility class.
}
@@ -793,4 +799,62 @@ public class Utils {
LatinImeLogger.logOnAutoCorrectionCancelled();
}
}
+
+ public static int getResourceId(Resources res, String name, int packageNameResId) {
+ String packageName = res.getResourcePackageName(packageNameResId);
+ int resId = res.getIdentifier(name, null, packageName);
+ if (resId == 0) {
+ throw new RuntimeException("Unknown resource: " + name);
+ }
+ return resId;
+ }
+
+ public static String resolveStringResource(String text, Resources res, int packageNameResId) {
+ final int size = text.length();
+ if (size < PREFIX_STRING.length()) {
+ return text;
+ }
+
+ StringBuilder sb = null;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) {
+ if (sb == null) {
+ sb = new StringBuilder(text.substring(0, pos));
+ }
+ final int end = Utils.searchResourceNameEnd(text, pos + PREFIX_STRING.length());
+ final String resName = text.substring(pos + 1, end);
+ final int resId = getResourceId(res, resName, packageNameResId);
+ sb.append(res.getString(resId));
+ pos = end - 1;
+ } else if (c == ESCAPE_CHAR) {
+ pos++;
+ if (sb != null) {
+ sb.append(c);
+ if (pos < size) {
+ sb.append(text.charAt(pos));
+ }
+ }
+ } else if (sb != null) {
+ sb.append(c);
+ }
+ }
+ return (sb == null) ? text : sb.toString();
+ }
+
+ private static int searchResourceNameEnd(String text, int start) {
+ final int size = text.length();
+ if (start >= size || text.charAt(start) != SUFFIX_SLASH) {
+ throw new RuntimeException("Resource name not specified");
+ }
+ for (int pos = start + 1; 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')) {
+ continue;
+ }
+ return pos;
+ }
+ return size;
+ }
}