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.java101
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSet.java15
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java12
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java68
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java72
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java6
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java14
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java137
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java5
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java5
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java11
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java24
14 files changed, 239 insertions, 249 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 8f2efab29..686392da8 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -25,10 +25,10 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;
+import com.android.inputmethod.keyboard.internal.KeySpecParser;
import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeySpecParser;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.XmlParseUtils;
@@ -74,13 +74,11 @@ public class Key {
private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000;
/** Icon to display instead of a label. Icon takes precedence over a label */
- private final int mIconAttrId;
- // TODO: Remove this variable.
- private Drawable mIcon;
+ private final int mIconId;
/** Icon for disabled state */
- private final int mDisabledIconAttrId;
+ private final int mDisabledIconId;
/** Preview version of the icon, for the preview popup */
- public final int mPreviewIconAttrId;
+ private final int mPreviewIconId;
/** Width of the key, not including the gap */
public final int mWidth;
@@ -128,21 +126,13 @@ public class Key {
/** Key is enabled and responds on press */
private boolean mEnabled = true;
- private static Drawable getIcon(Keyboard.Params params, String moreKeySpec) {
- final int iconAttrId = KeySpecParser.getIconAttrId(moreKeySpec);
- if (iconAttrId == KeyboardIconsSet.ICON_UNDEFINED) {
- return null;
- } else {
- return params.mIconsSet.getIconByAttrId(iconAttrId);
- }
- }
-
/**
* This constructor is being used only for key in more keys keyboard.
*/
public Key(Resources res, Keyboard.Params params, String moreKeySpec,
int x, int y, int width, int height) {
- this(params, KeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec),
+ this(params, KeySpecParser.getLabel(moreKeySpec), null,
+ KeySpecParser.getIconId(moreKeySpec),
KeySpecParser.getCode(res, moreKeySpec),
KeySpecParser.getOutputText(moreKeySpec),
x, y, width, height);
@@ -151,7 +141,7 @@ public class Key {
/**
* This constructor is being used only for key in popup suggestions pane.
*/
- public Key(Keyboard.Params params, String label, String hintLabel, Drawable icon,
+ public Key(Keyboard.Params params, String label, String hintLabel, int iconId,
int code, CharSequence outputText, int x, int y, int width, int height) {
mHeight = height - params.mVerticalGap;
mHorizontalGap = params.mHorizontalGap;
@@ -168,10 +158,9 @@ public class Key {
mOutputText = outputText;
mCode = code;
mAltCode = Keyboard.CODE_UNSPECIFIED;
- mIconAttrId = KeyboardIconsSet.ATTR_UNDEFINED;
- mIcon = icon;
- mDisabledIconAttrId = KeyboardIconsSet.ATTR_UNDEFINED;
- mPreviewIconAttrId = KeyboardIconsSet.ATTR_UNDEFINED;
+ mIconId = iconId;
+ mDisabledIconId = KeyboardIconsSet.ICON_UNDEFINED;
+ mPreviewIconId = KeyboardIconsSet.ICON_UNDEFINED;
// Horizontal gap is divided equally to both sides of the key.
mX = x + mHorizontalGap / 2;
mY = y;
@@ -228,18 +217,16 @@ public class Key {
mBackgroundType = style.getInt(keyAttr,
R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
- final KeyboardIconsSet iconsSet = params.mIconsSet;
mVisualInsetsLeft = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0);
mVisualInsetsRight = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0);
- mPreviewIconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED));
- mIconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED));
- mIcon = iconsSet.getIconByAttrId(mIconAttrId);
- mDisabledIconAttrId = KeyboardIconsSet.getIconAttrId(style.getInt(keyAttr,
- R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED));
+ 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);
mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags, 0);
final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0;
@@ -336,16 +323,15 @@ public class Key {
key.mCode,
key.mLabel,
key.mHintLabel,
- key.mIconAttrId,
+ key.mIconId,
key.mBackgroundType,
// Key can be distinguishable without the following members.
// key.mAltCode,
// key.mOutputText,
// key.mActionFlags,
// key.mLabelFlags,
- // key.mIcon,
- // key.mDisabledIconAttrId,
- // key.mPreviewIconAttrId,
+ // key.mDisabledIconId,
+ // key.mPreviewIconId,
// key.mHorizontalGap,
// key.mVerticalGap,
// key.mVisualInsetLeft,
@@ -364,8 +350,8 @@ public class Key {
&& o.mCode == mCode
&& TextUtils.equals(o.mLabel, mLabel)
&& TextUtils.equals(o.mHintLabel, mHintLabel)
- && o.mIconAttrId != mIconAttrId
- && o.mBackgroundType != mBackgroundType;
+ && o.mIconId == mIconId
+ && o.mBackgroundType == mBackgroundType;
}
@Override
@@ -380,11 +366,20 @@ public class Key {
@Override
public String toString() {
- String top = Keyboard.printableCode(mCode);
- if (Utils.codePointCount(mLabel) != 1) {
- top += "/\"" + mLabel + '"';
+ return String.format("%s/%s %d,%d %dx%d %s/%s/%s",
+ Keyboard.printableCode(mCode), mLabel, mX, mY, mWidth, mHeight, mHintLabel,
+ KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType));
+ }
+
+ private static String backgroundName(int backgroundType) {
+ switch (backgroundType) {
+ case BACKGROUND_TYPE_NORMAL: return "normal";
+ case BACKGROUND_TYPE_FUNCTIONAL: return "functional";
+ case BACKGROUND_TYPE_ACTION: return "action";
+ case BACKGROUND_TYPE_STICKY_OFF: return "stickyOff";
+ case BACKGROUND_TYPE_STICKY_ON: return "stickyOn";
+ default: return null;
}
- return String.format("%s %d,%d", top, mX, mY);
}
public void markAsLeftEdge(Keyboard.Params params) {
@@ -403,8 +398,8 @@ public class Key {
mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
}
- public boolean isSpacer() {
- return false;
+ public final boolean isSpacer() {
+ return this instanceof Spacer;
}
public boolean isShift() {
@@ -498,14 +493,18 @@ public class Key {
return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0;
}
- // TODO: Get rid of this method.
public Drawable getIcon(KeyboardIconsSet iconSet) {
- return mEnabled ? mIcon : iconSet.getIconByAttrId(mDisabledIconAttrId);
+ return iconSet.getIconDrawable(mIconId);
+ }
+
+ public Drawable getDisabledIcon(KeyboardIconsSet iconSet) {
+ return iconSet.getIconDrawable(mDisabledIconId);
}
- // TODO: Get rid of this method.
- public void setIcon(Drawable icon) {
- mIcon = icon;
+ public Drawable getPreviewIcon(KeyboardIconsSet iconSet) {
+ return mPreviewIconId != KeyboardIconsSet.ICON_UNDEFINED
+ ? iconSet.getIconDrawable(mPreviewIconId)
+ : iconSet.getIconDrawable(mIconId);
}
/**
@@ -642,13 +641,9 @@ public class Key {
/**
* This constructor is being used only for divider in more keys keyboard.
*/
- public Spacer(Keyboard.Params params, Drawable icon, int x, int y, int width, int height) {
- super(params, null, null, icon, Keyboard.CODE_UNSPECIFIED, null, x, y, width, height);
- }
-
- @Override
- public boolean isSpacer() {
- return true;
+ protected Spacer(Keyboard.Params params, int x, int y, int width, int height) {
+ super(params, null, null, KeyboardIconsSet.ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED,
+ null, x, y, width, height);
}
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index dce2c37f2..6e13b95b5 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -48,14 +48,17 @@ public interface KeyboardActionListener {
* presses of a key adjacent to the intended key.
* @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
* {@link PointerTracker#onTouchEvent} or so, the value should be
- * {@link #NOT_A_TOUCH_COORDINATE}.
+ * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion
+ * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}.
* @param y y-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
* {@link PointerTracker#onTouchEvent} or so, the value should be
- * {@link #NOT_A_TOUCH_COORDINATE}.
+ * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion
+ * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}.
*/
public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y);
public static final int NOT_A_TOUCH_COORDINATE = -1;
+ public static final int SUGGESTION_STRIP_COORDINATE = -2;
/**
* Sends a sequence of characters to the listener.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
index 664e7656e..82eaa1d17 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -57,7 +57,10 @@ public class KeyboardSet {
private final Context mContext;
private final Params mParams;
- private final KeysCache mKeysCache = new KeysCache();
+
+ private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
+ new HashMap<KeyboardId, SoftReference<Keyboard>>();
+ private static final KeysCache sKeysCache = new KeysCache();
public static class KeyboardSetException extends RuntimeException {
public final KeyboardId mKeyboardId;
@@ -74,6 +77,10 @@ public class KeyboardSet {
mMap = new HashMap<Key, Key>();
}
+ public void clear() {
+ mMap.clear();
+ }
+
public Key get(Key key) {
final Key existingKey = mMap.get(key);
if (existingKey != null) {
@@ -103,11 +110,9 @@ public class KeyboardSet {
Params() {}
}
- private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
- new HashMap<KeyboardId, SoftReference<Keyboard>>();
-
public static void clearKeyboardCache() {
sKeyboardCache.clear();
+ sKeysCache.clear();
}
private KeyboardSet(Context context, Params params) {
@@ -156,7 +161,7 @@ public class KeyboardSet {
final Keyboard.Builder<Keyboard.Params> builder =
new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params());
if (id.isAlphabetKeyboard()) {
- builder.setAutoGenerate(mKeysCache);
+ builder.setAutoGenerate(sKeysCache);
}
builder.load(keyboardXmlId, id);
builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index c6fb75489..d65253ede 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -185,7 +185,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
public final int mKeyShiftedLetterHintInactivatedColor;
public final int mKeyShiftedLetterHintActivatedColor;
- private final float mKeyLetterRatio;
+ /* package */ final float mKeyLetterRatio;
private final float mKeyLargeLetterRatio;
private final float mKeyLabelRatio;
private final float mKeyHintLetterRatio;
@@ -486,8 +486,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
- if (key.isSpacer()) return;
- onDrawKeyBackground(key, canvas, params);
+ if (!key.isSpacer()) {
+ onDrawKeyBackground(key, canvas, params);
+ }
onDrawKeyTopVisuals(key, canvas, paint, params);
}
@@ -861,10 +862,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
previewText.setText(key.mLabel);
} else {
- final Drawable previewIcon = mKeyboard.mIconsSet.getIconByAttrId(
- key.mPreviewIconAttrId);
previewText.setCompoundDrawables(null, null, null,
- previewIcon != null ? previewIcon : key.getIcon(mKeyboard.mIconsSet));
+ key.getPreviewIcon(mKeyboard.mIconsSet));
previewText.setText(null);
}
previewText.setBackgroundDrawable(params.mPreviewBackground);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index f3583fefc..870c7cb25 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -42,6 +42,7 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
@@ -132,7 +133,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
switch (msg.what) {
case MSG_REPEAT_KEY:
tracker.onRepeatKey(tracker.getKey());
- startKeyRepeatTimer(tracker);
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
break;
case MSG_LONGPRESS_KEY:
if (tracker != null) {
@@ -144,11 +145,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
}
+ private void startKeyRepeatTimer(PointerTracker tracker, long delay) {
+ sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
+ }
+
@Override
public void startKeyRepeatTimer(PointerTracker tracker) {
mInKeyRepeat = true;
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker),
- mParams.mKeyRepeatStartTimeout);
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout);
}
public void cancelKeyRepeatTimer() {
@@ -390,7 +394,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
mMoreKeysPanelCache.clear();
mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE);
- mSpaceIcon = keyboard.mIconsSet.getIconByAttrId(R.styleable.Keyboard_iconSpaceKey);
+ mSpaceIcon = keyboard.mIconsSet.getIconDrawable(KeyboardIconsSet.ICON_SPACE);
final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
mSpacebarLocale = keyboard.mId.mLocale;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index ba12676ad..adb5f4759 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -48,7 +48,7 @@ public class KeySpecParser {
private static final char ESCAPE_CHAR = '\\';
private static final char PREFIX_AT = '@';
private static final char SUFFIX_SLASH = '/';
- private static final String PREFIX_STRING = PREFIX_AT + "string";
+ private static final String PREFIX_STRING = PREFIX_AT + "string" + SUFFIX_SLASH;
private static final char LABEL_END = '|';
private static final String PREFIX_ICON = PREFIX_AT + "icon" + SUFFIX_SLASH;
private static final String PREFIX_CODE = PREFIX_AT + "integer" + SUFFIX_SLASH;
@@ -179,11 +179,11 @@ public class KeySpecParser {
return Keyboard.CODE_OUTPUT_TEXT;
}
- public static int getIconAttrId(String moreKeySpec) {
+ public static int getIconId(String moreKeySpec) {
if (hasIcon(moreKeySpec)) {
final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length());
final String name = moreKeySpec.substring(PREFIX_ICON.length(), end);
- return KeyboardIconsSet.getIconAttrId(name);
+ return KeyboardIconsSet.getIconId(name);
}
return KeyboardIconsSet.ICON_UNDEFINED;
}
@@ -293,13 +293,11 @@ public class KeySpecParser {
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));
- }
+ // Append both escape character and escaped character.
+ sb.append(text.substring(pos, Math.min(pos + 2, size)));
}
+ pos++;
} else if (sb != null) {
sb.append(c);
}
@@ -309,10 +307,7 @@ public class KeySpecParser {
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++) {
+ 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')) {
@@ -330,56 +325,35 @@ public class KeySpecParser {
return null;
}
if (Utils.codePointCount(text) == 1) {
- return new String[] { text };
+ return text.codePointAt(0) == COMMA ? null : 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 == COMMA) {
- if (list == null) {
- list = new ArrayList<String>();
- }
- if (sb.length() == 0) {
+ // Skip empty entry.
+ if (pos - start > 0) {
+ if (list == null) {
+ list = new ArrayList<String>();
+ }
list.add(text.substring(start, pos));
- } else {
- list.add(sb.toString());
- sb.setLength(0);
}
// Skip comma
start = pos + 1;
- continue;
- }
- // TODO: Only parse escaped comma. Other escaped character should be passed through
- // with escaped character prefixed.
- // Skip escaped sequence.
- if (c == ESCAPE_CHAR) {
- if (start == pos) {
- // Skip escaping comma at the beginning of the text.
- start++;
- pos++;
- } else {
- if (start < pos && sb.length() == 0) {
- sb.append(text.substring(start, pos));
- }
- // Skip comma
- pos++;
- if (pos < size) {
- sb.append(text.charAt(pos));
- }
- }
- } else if (sb.length() > 0) {
- sb.append(c);
+ } else if (c == ESCAPE_CHAR) {
+ // Skip escape character and escaped character.
+ pos++;
}
}
+ final String remain = (size - start > 0) ? text.substring(start) : null;
if (list == null) {
- return new String[] {
- sb.length() > 0 ? sb.toString() : text.substring(start)
- };
+ return remain != null ? new String[] { remain } : null;
} else {
- list.add(sb.length() > 0 ? sb.toString() : text.substring(start));
+ if (remain != null) {
+ list.add(remain);
+ }
return list.toArray(new String[list.size()]);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index bec6ae1cc..162e96d06 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -23,7 +23,6 @@ import android.util.Log;
import com.android.inputmethod.latin.R;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -31,16 +30,20 @@ public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
public static final int ICON_UNDEFINED = 0;
- public static final int ATTR_UNDEFINED = 0;
+ // The value should be aligned with the enum value of Key.keyIcon.
+ public static final int ICON_SPACE = 4;
+ private static final int NUM_ICONS = 13;
- private final Map<Integer, Drawable> mIcons = new HashMap<Integer, Drawable>();
+ private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1];
- // 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;
+ private static final Map<Integer, Integer> ATTR_ID_TO_ICON_ID = new HashMap<Integer, Integer>();
+ private static final Map<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);
@@ -55,21 +58,23 @@ public class KeyboardIconsSet {
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, String name, Integer attrId) {
- ICONS_TO_ATTRS_MAP.put(iconId, attrId);
- NAME_TO_ATTRS_MAP.put(name, attrId);
+ private static void addIconIdMap(int iconId, String name, int attrId) {
+ if (attrId != ATTR_UNDEFINED) {
+ ATTR_ID_TO_ICON_ID.put(attrId, iconId);
+ }
+ NAME_TO_ICON_ID.put(name, iconId);
+ ICON_NAMES[iconId] = name;
}
public void loadIcons(final TypedArray keyboardAttrs) {
- for (final Integer attrId : VALID_ATTRS) {
+ for (final Integer attrId : ATTR_ID_TO_ICON_ID.keySet()) {
try {
final Drawable icon = keyboardAttrs.getDrawable(attrId);
- if (icon == null) continue;
setDefaultBounds(icon);
- mIcons.put(attrId, icon);
+ final Integer iconId = ATTR_ID_TO_ICON_ID.get(attrId);
+ mIcons[iconId] = icon;
} catch (Resources.NotFoundException e) {
Log.w(TAG, "Drawable resource for icon #"
+ keyboardAttrs.getResources().getResourceEntryName(attrId)
@@ -78,39 +83,32 @@ public class KeyboardIconsSet {
}
}
- public static int getIconAttrId(final Integer iconId) {
- if (iconId == ICON_UNDEFINED) {
- 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 attrId;
+ private static boolean isValidIconId(final int iconId) {
+ return iconId >= 0 && iconId < ICON_NAMES.length;
}
- 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 static String getIconName(final int iconId) {
+ return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">";
}
- public Drawable getIconByAttrId(final Integer attrId) {
- if (attrId == ATTR_UNDEFINED) {
- return null;
+ public static int getIconId(final String name) {
+ final Integer iconId = NAME_TO_ICON_ID.get(name);
+ if (iconId != null) {
+ return iconId;
}
- if (!VALID_ATTRS.contains(attrId)) {
- throw new IllegalArgumentException("unknown icon attribute id: " + attrId);
+ throw new RuntimeException("unknown icon name: " + name);
+ }
+
+ public Drawable getIconDrawable(final int iconId) {
+ if (isValidIconId(iconId)) {
+ return mIcons[iconId];
}
- return mIcons.get(attrId);
+ throw new RuntimeException("unknown icon id: " + getIconName(iconId));
}
- private static Drawable setDefaultBounds(final Drawable icon) {
+ private static void setDefaultBounds(final Drawable icon) {
if (icon != null) {
icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
}
- return icon;
}
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index b333e4873..79441c557 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -75,7 +75,8 @@ class BinaryDictionaryGetter {
// This assumes '%' is fully available as a non-separator, normal
// character in a file name. This is probably true for all file systems.
final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < name.length(); ++i) {
+ final int nameLength = name.length();
+ for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
final int codePoint = name.codePointAt(i);
if (isFileNameCharacter(codePoint)) {
sb.appendCodePoint(codePoint);
@@ -92,7 +93,8 @@ class BinaryDictionaryGetter {
*/
private static String getWordListIdFromFileName(final String fname) {
final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < fname.length(); ++i) {
+ final int fnameLength = fname.length();
+ for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
final int codePoint = fname.codePointAt(i);
if ('%' != codePoint) {
sb.appendCodePoint(codePoint);
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index f5cf953c4..3de5c1d48 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -28,7 +28,6 @@ import com.android.inputmethod.compat.InputTypeCompatUtils;
public class InputAttributes {
private final String TAG = InputAttributes.class.getSimpleName();
- final public boolean mInsertSpaceOnPickSuggestionManually;
final public boolean mInputTypeNoAutoCorrect;
final public boolean mIsSettingsSuggestionStripOn;
final public boolean mApplicationSpecifiedCompletionOn;
@@ -52,7 +51,6 @@ public class InputAttributes {
+ " imeOptions=0x%08x",
inputType, editorInfo.imeOptions));
}
- mInsertSpaceOnPickSuggestionManually = false;
mIsSettingsSuggestionStripOn = false;
mInputTypeNoAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
@@ -80,15 +78,6 @@ public class InputAttributes {
mIsSettingsSuggestionStripOn = true;
}
- if (InputTypeCompatUtils.isEmailVariation(variation)
- || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
- // The point in turning this off is that we don't want to insert a space after
- // a name when filling a form: we can't delete trailing spaces when changing fields
- mInsertSpaceOnPickSuggestionManually = false;
- } else {
- mInsertSpaceOnPickSuggestionManually = true;
- }
-
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
// If NO_SUGGESTIONS is set, don't do prediction.
@@ -109,8 +98,7 @@ public class InputAttributes {
// Pretty print
@Override
public String toString() {
- return "\n mInsertSpaceOnPickSuggestionManually = " + mInsertSpaceOnPickSuggestionManually
- + "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect
+ return "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect
+ "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn
+ "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn;
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 1bc55a583..24007f95a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -160,18 +160,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
SUGGESTION_VISIBILILTY_HIDE_VALUE
};
- // Magic space: a space that should disappear on space/apostrophe insertion, move after the
- // punctuation on punctuation insertion, and become a real space on alpha char insertion.
- // Weak space: a space that should be swapped only by suggestion strip punctuation.
+ private static final int SPACE_STATE_NONE = 0;
// Double space: the state where the user pressed space twice quickly, which LatinIME
// resolved as period-space. Undoing this converts the period to a space.
+ private static final int SPACE_STATE_DOUBLE = 1;
// Swap punctuation: the state where a (weak or magic) space and a punctuation from the
// suggestion strip have just been swapped. Undoing this swaps them back.
- private static final int SPACE_STATE_NONE = 0;
- private static final int SPACE_STATE_DOUBLE = 1;
private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
- private static final int SPACE_STATE_MAGIC = 3;
- private static final int SPACE_STATE_WEAK = 4;
+ // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
+ // spaces happen when the user presses space, accepting the current suggestion (whether
+ // it's an auto-correction or not).
+ private static final int SPACE_STATE_WEAK = 3;
+ // Phantom space: a not-yet-inserted space that should get inserted on the next input,
+ // character provided it's not a separator. If it's a separator, the phantom space is dropped.
+ // Phantom spaces happen when a user chooses a word from the suggestion strip.
+ private static final int SPACE_STATE_PHANTOM = 4;
// Current space state of the input method. This can be any of the above constants.
private int mSpaceState;
@@ -1162,18 +1165,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return false;
}
- // "ic" must not be null
- private static void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) {
- // When the text's first character is '.', remove the previous period
- // if there is one.
- final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == Keyboard.CODE_PERIOD
- && text.charAt(0) == Keyboard.CODE_PERIOD) {
- ic.deleteSurroundingText(1, 0);
- }
- }
-
// "ic" may be null
private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) {
if (ic == null) return;
@@ -1234,26 +1225,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
private void insertPunctuationFromSuggestionStrip(final InputConnection ic, final int code) {
- final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : null;
- final int toLeft = TextUtils.isEmpty(beforeText) ? 0 : beforeText.charAt(0);
- final boolean shouldRegisterSwapPunctuation;
- // If we have a space left of the cursor and it's a weak or a magic space, then we should
- // swap it, and override the space state with SPACESTATE_SWAP_PUNCTUATION.
- // To swap it, we fool handleSeparator to think the previous space state was a
- // magic space.
- if (Keyboard.CODE_SPACE == toLeft && mSpaceState == SPACE_STATE_WEAK
- && mSettingsValues.isMagicSpaceSwapper(code)) {
- mSpaceState = SPACE_STATE_MAGIC;
- shouldRegisterSwapPunctuation = true;
- } else {
- shouldRegisterSwapPunctuation = false;
- }
onCodeInput(code, new int[] { code },
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
- if (shouldRegisterSwapPunctuation) {
- mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
- }
+ KeyboardActionListener.SUGGESTION_STRIP_COORDINATE,
+ KeyboardActionListener.SUGGESTION_STRIP_COORDINATE);
}
// Implementation of {@link KeyboardActionListener}.
@@ -1331,7 +1305,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (ic == null) return;
ic.beginBatchEdit();
commitTyped(ic);
- maybeRemovePreviousPeriod(ic, text);
+ text = specificTldProcessingOnTextInput(ic, text);
+ if (SPACE_STATE_PHANTOM == mSpaceState) {
+ sendKeyChar((char)Keyboard.CODE_SPACE);
+ }
ic.commitText(text, 1);
ic.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
@@ -1341,6 +1318,24 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
resetComposingState(true /* alsoResetLastComposedWord */);
}
+ // ic may not be null
+ private CharSequence specificTldProcessingOnTextInput(final InputConnection ic,
+ final CharSequence text) {
+ if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD
+ || !Character.isLetter(text.charAt(1))) {
+ // Not a tld: do nothing.
+ return text;
+ }
+ final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
+ if (lastOne != null && lastOne.length() == 1
+ && lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
+ mSpaceState = SPACE_STATE_NONE;
+ return text.subSequence(1, text.length());
+ } else {
+ return text;
+ }
+ }
+
@Override
public void onCancelInput() {
// User released a finger outside any key
@@ -1492,13 +1487,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// "ic" may be null without this crashing, but the behavior will be really strange
private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes,
final int x, final int y, final int spaceState, final InputConnection ic) {
- if (SPACE_STATE_MAGIC == spaceState
- && mSettingsValues.isMagicSpaceStripper(primaryCode)) {
- if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic);
- }
-
boolean isComposingWord = mWordComposer.isComposingWord();
int code = primaryCode;
+
+ if (SPACE_STATE_PHANTOM == spaceState &&
+ !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) {
+ if (isComposingWord) {
+ // Sanity check
+ throw new RuntimeException("Should not be composing here");
+ }
+ sendKeyChar((char)Keyboard.CODE_SPACE);
+ }
+
if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code))
&& isSuggestionsRequested() && !isCursorTouchingWord()) {
if (!isComposingWord) {
@@ -1530,10 +1530,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
sendKeyChar((char)code);
}
- if (SPACE_STATE_MAGIC == spaceState
- && mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic);
- }
if (mSettingsValues.isWordSeparator(code)) {
Utils.Stats.onSeparator((char)code, x, y);
@@ -1575,24 +1571,28 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- final boolean swapMagicSpace;
- if (Keyboard.CODE_ENTER == primaryCode && (SPACE_STATE_MAGIC == spaceState
- || SPACE_STATE_SWAP_PUNCTUATION == spaceState)) {
+ final boolean swapWeakSpace;
+ if (Keyboard.CODE_ENTER == primaryCode && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
removeTrailingSpaceWhileInBatchEdit(ic);
- swapMagicSpace = false;
- } else if (SPACE_STATE_MAGIC == spaceState) {
+ swapWeakSpace = false;
+ } else if ((SPACE_STATE_WEAK == spaceState || SPACE_STATE_SWAP_PUNCTUATION == spaceState)
+ && KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x) {
if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- swapMagicSpace = true;
+ swapWeakSpace = true;
} else {
- swapMagicSpace = false;
+ swapWeakSpace = false;
if (mSettingsValues.isMagicSpaceStripper(primaryCode)) {
removeTrailingSpaceWhileInBatchEdit(ic);
}
}
} else {
- swapMagicSpace = false;
+ swapWeakSpace = false;
}
+ // TODO: rethink interactions of sendKeyChar, commitText("\n") and actions. sendKeyChar
+ // with a CODE_ENTER parameter will have the default InputMethodService implementation
+ // possibly redirect on the keyboard action. That may be the right thing to do, but
+ // on Shift+Enter, it's generally not, so we may want to do the redirection right here.
sendKeyChar((char)primaryCode);
if (Keyboard.CODE_SPACE == primaryCode) {
@@ -1610,9 +1610,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.postUpdateBigramPredictions();
}
} else {
- if (swapMagicSpace) {
+ if (swapWeakSpace) {
swapSwapperAndSpaceWhileInBatchEdit(ic);
- mSpaceState = SPACE_STATE_MAGIC;
+ mSpaceState = SPACE_STATE_WEAK;
+ } else if (SPACE_STATE_PHANTOM == spaceState) {
+ // If we are in phantom space state, and the user presses a separator, we want to
+ // stay in phantom space state so that the next keypress has a chance to add the
+ // space. For example, if I type "Good dat", pick "day" from the suggestion strip
+ // then insert a comma and go on to typing the next word, I want the space to be
+ // inserted automatically before the next word, the same way it is when I don't
+ // input the comma.
+ mSpaceState = SPACE_STATE_PHANTOM;
}
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
@@ -1921,10 +1929,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
- // Follow it with a space
- if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) {
- sendMagicSpace();
- }
+ mSpaceState = SPACE_STATE_PHANTOM;
+ // TODO: is this necessary?
+ mKeyboardSwitcher.updateShiftState();
// We should show the "Touch again to save" hint if the user pressed the first entry
// AND either:
@@ -2259,12 +2266,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return mSettingsValues.isWordSeparator(code);
}
- private void sendMagicSpace() {
- sendKeyChar((char)Keyboard.CODE_SPACE);
- mSpaceState = SPACE_STATE_MAGIC;
- mKeyboardSwitcher.updateShiftState();
- }
-
public boolean preferCapitalization() {
return mWordComposer.isFirstCharCapitalized();
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 8e2f605c4..589cb6f86 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -93,7 +93,8 @@ public class SettingsValues {
mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
if (LatinImeLogger.sDBG) {
- for (int i = 0; i < mMagicSpaceStrippers.length(); ++i) {
+ final int length = mMagicSpaceStrippers.length();
+ for (int i = 0; i < length; i = mMagicSpaceStrippers.offsetByCodePoints(i, 1)) {
if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) {
throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i)
+ " is both a magic space swapper and stripper.");
@@ -234,10 +235,12 @@ public class SettingsValues {
}
public boolean isMagicSpaceStripper(int code) {
+ // TODO: this does not work if the code does not fit in a char
return mMagicSpaceStrippers.contains(String.valueOf((char)code));
}
public boolean isMagicSpaceSwapper(int code) {
+ // TODO: this does not work if the code does not fit in a char
return mMagicSpaceSwappers.contains(String.valueOf((char)code));
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index bd244b913..dd24432f7 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -212,6 +212,7 @@ public class WordComposer {
final int lastPos = size - 1;
char lastChar = mTypedWord.charAt(lastPos);
mCodes.remove(lastPos);
+ // TODO: This crashes and catches fire if the code point doesn't fit a char
mTypedWord.deleteCharAt(lastPos);
if (Character.isUpperCase(lastChar)) mCapsCount--;
}
@@ -221,7 +222,9 @@ public class WordComposer {
if (mTrailingSingleQuotesCount > 0) {
--mTrailingSingleQuotesCount;
} else {
- for (int i = mTypedWord.length() - 1; i >= 0; --i) {
+ int i = mTypedWord.length();
+ while (i > 0) {
+ i = mTypedWord.offsetByCodePoints(i, -1);
if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break;
++mTrailingSingleQuotesCount;
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 88ac043ed..8ac82ee5b 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -431,9 +431,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService
// If the first char is not uppercase, then the word is either all lower case,
// and in either case we return CAPITALIZE_NONE.
if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
- final int len = text.codePointCount(0, text.length());
+ final int len = text.length();
int capsCount = 1;
- for (int i = 1; i < len; ++i) {
+ for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
if (1 != capsCount && i != capsCount) break;
if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
}
@@ -522,13 +522,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService
// Filter contents
final int length = text.length();
int letterCount = 0;
- for (int i = 0; i < length; ++i) {
+ for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
final int codePoint = text.codePointAt(i);
// Any word containing a '@' is probably an e-mail address
// Any word containing a '/' is probably either an ad-hoc combination of two
// words or a URI - in either case we don't want to spell check that
- if ('@' == codePoint
- || '/' == codePoint) return true;
+ if ('@' == codePoint || '/' == codePoint) return true;
if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
}
// Guestimate heuristic: perform spell checking if at least 3/4 of the characters
@@ -570,7 +569,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
suggestionsLimit);
final WordComposer composer = new WordComposer();
final int length = text.length();
- for (int i = 0; i < length; ++i) {
+ for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
final int character = text.codePointAt(i);
final int proximityIndex =
SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index f42b8e681..4ef5bd386 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -25,6 +25,7 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
@@ -199,6 +200,21 @@ public class MoreSuggestions extends Keyboard {
return info;
}
+ private static class Divider extends Key.Spacer {
+ private final Drawable mIcon;
+
+ public Divider(Keyboard.Params params, Drawable icon, int x, int y, int width,
+ int height) {
+ super(params, x, y, width, height);
+ mIcon = icon;
+ }
+
+ @Override
+ public Drawable getIcon(KeyboardIconsSet iconSet) {
+ return mIcon;
+ }
+ }
+
@Override
public MoreSuggestions build() {
final MoreSuggestionsParam params = mParams;
@@ -210,16 +226,16 @@ public class MoreSuggestions extends Keyboard {
final String info = getDebugInfo(mSuggestions, pos);
final int index = pos + SUGGESTION_CODE_BASE;
final Key key = new Key(
- params, word, info, null, index, null, x, y, width,
- params.mDefaultRowHeight);
+ params, word, info, KeyboardIconsSet.ICON_UNDEFINED, index, null, x, y,
+ width, params.mDefaultRowHeight);
params.markAsEdgeKey(key, pos);
params.onAddKey(key);
final int columnNumber = params.getColumnNumber(pos);
final int numColumnInRow = params.getNumColumnInRow(pos);
if (columnNumber < numColumnInRow - 1) {
- final Key.Spacer spacer = new Key.Spacer(params, params.mDivider, x + width, y,
+ final Divider divider = new Divider(params, params.mDivider, x + width, y,
params.mDividerWidth, params.mDefaultRowHeight);
- params.onAddKey(spacer);
+ params.onAddKey(divider);
}
}
return new MoreSuggestions(params);