diff options
18 files changed, 134 insertions, 101 deletions
diff --git a/java/proguard.flags b/java/proguard.flags index 33af890ec..caf1ea183 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -35,6 +35,6 @@ *; } --keep class com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder$MiniKeyboardParams { +-keep class com.android.inputmethod.keyboard.MiniKeyboard$Builder$MiniKeyboardParams { <init>(...); } diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index 4f8bfed58..b3f71d2bb 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -23,10 +23,12 @@ <integer name="key_tab">9</integer> <integer name="key_return">10</integer> <integer name="key_space">32</integer> - <integer name="key_dummy">0</integer> <integer name="key_shift">-1</integer> <integer name="key_switch_alpha_symbol">-2</integer> + <integer name="key_capslock">-3</integer> + <integer name="key_output_text">-4</integer> <integer name="key_delete">-5</integer> <integer name="key_settings">-6</integer> <integer name="key_shortcut">-7</integer> + <integer name="key_unspecified">-9</integer> </resources> diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml index 1dd0307c7..ab90c9894 100644 --- a/java/res/xml-sw600dp/kbd_key_styles.xml +++ b/java/res/xml-sw600dp/kbd_key_styles.xml @@ -78,14 +78,12 @@ latin:keyIcon="iconShortcutKey" latin:keyIconDisabled="iconDisabledShortcutKey" latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" - latin:altCode="@integer/key_dummy" latin:parentStyle="f2PopupStyle" /> <key-style latin:styleName="settingsKeyStyle" latin:code="@integer/key_settings" latin:keyIcon="iconSettingsKey" latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" - latin:altCode="@integer/key_dummy" latin:backgroundType="functional" /> <key-style latin:styleName="tabKeyStyle" diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml index 7292fe169..72a1a4c77 100644 --- a/java/res/xml-sw768dp/kbd_key_styles.xml +++ b/java/res/xml-sw768dp/kbd_key_styles.xml @@ -60,14 +60,12 @@ latin:keyIcon="iconShortcutKey" latin:keyIconDisabled="iconDisabledShortcutKey" latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" - latin:altCode="@integer/key_dummy" latin:backgroundType="functional" /> <key-style latin:styleName="settingsKeyStyle" latin:code="@integer/key_settings" latin:keyIcon="iconSettingsKey" latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" - latin:altCode="@integer/key_dummy" latin:backgroundType="functional" /> <key-style latin:styleName="tabKeyStyle" diff --git a/java/res/xml/kbd_rows_slavic.xml b/java/res/xml/kbd_rows_slavic.xml index 6536eaeb3..426be72dd 100644 --- a/java/res/xml/kbd_rows_slavic.xml +++ b/java/res/xml/kbd_rows_slavic.xml @@ -75,8 +75,7 @@ latin:keyWidth="9.091%p" > <Key - latin:keyLabel="ф" - latin:keyWidth="8.75%p" /> + latin:keyLabel="ф" /> <Key latin:keyLabel="@string/keylabel_for_slavic_yery" latin:moreKeys="@string/more_keys_for_slavic_yery" /> diff --git a/java/res/xml/kbd_settings_or_tab.xml b/java/res/xml/kbd_settings_or_tab.xml index b947d18ad..2d35e3b4a 100644 --- a/java/res/xml/kbd_settings_or_tab.xml +++ b/java/res/xml/kbd_settings_or_tab.xml @@ -26,10 +26,10 @@ latin:hasSettingsKey="true" > <!-- Because this settings key is not adjacent to the space key, this key should be - just ignored while typing (altCode=CODE_DUMMY). --> + just ignored while typing (altCode=CODE_UNSPECIFIED). --> <Key latin:keyStyle="settingsKeyStyle" - latin:altCode="@integer/key_dummy" + latin:altCode="@integer/key_unspecified" latin:keyWidth="9.2%p" /> </case> <!-- hasSettingsKey="false" --> diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 3d5ab05c3..efaf58fc2 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -142,7 +142,7 @@ public class KeyCodeDescriptionMapper { } // Just attempt to speak the description. - if (key.mCode != Keyboard.CODE_DUMMY) { + if (key.mCode != Keyboard.CODE_UNSPECIFIED) { return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); } diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index e1e74fc9a..ebd61505d 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -198,7 +198,7 @@ public class Key { mLabel = label; mOutputText = outputText; mCode = code; - mAltCode = Keyboard.CODE_DUMMY; + mAltCode = Keyboard.CODE_UNSPECIFIED; mIcon = icon; mDisabledIcon = null; mPreviewIcon = null; @@ -299,13 +299,13 @@ public class Key { } final int firstChar = mLabel.charAt(0); mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard); - } else if (code != Keyboard.CODE_UNSPECIFIED) { - mCode = code; + } else if (code == Keyboard.CODE_UNSPECIFIED && mOutputText != null) { + mCode = Keyboard.CODE_OUTPUT_TEXT; } else { - mCode = Keyboard.CODE_DUMMY; + mCode = code; } mAltCode = style.getInt(keyAttr, - R.styleable.Keyboard_Key_altCode, Keyboard.CODE_DUMMY); + R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED); mHashCode = hashCode(this); keyAttr.recycle(); @@ -508,7 +508,7 @@ public class Key { * @param y the y-coordinate of the point * @return whether or not the point falls on the key. If the key is attached to an edge, it * will assume that all points between the key and the edge are considered to be on the key. - * @see #markAsLeftEdge(KeyboardParams) etc. + * @see #markAsLeftEdge(Keyboard.Params) etc. */ public boolean isOnKey(int x, int y) { return mHitBox.contains(x, y); @@ -615,7 +615,7 @@ 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_DUMMY, null, x, y, width, height); + super(params, null, null, icon, Keyboard.CODE_UNSPECIFIED, null, x, y, width, height); } @Override diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 3540577ca..c1d024cef 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -67,7 +67,9 @@ import java.util.Set; public class Keyboard { private static final String TAG = Keyboard.class.getSimpleName(); - /** Some common keys code. These should be aligned with values/keycodes.xml */ + /** Some common keys code. Must be positive. + * These should be aligned with values/keycodes.xml + */ public static final int CODE_ENTER = '\n'; public static final int CODE_TAB = '\t'; public static final int CODE_SPACE = ' '; @@ -84,17 +86,20 @@ public class Keyboard { public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; public static final int CODE_DIGIT0 = '0'; public static final int CODE_PLUS = '+'; + private static final int MINIMUM_LETTER_CODE = CODE_TAB; - /** Special keys code. These should be aligned with values/keycodes.xml */ - public static final int CODE_DUMMY = 0; + /** Special keys code. Must be negative. + * These should be aligned with values/keycodes.xml + */ public static final int CODE_SHIFT = -1; public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; public static final int CODE_CAPSLOCK = -3; + public static final int CODE_OUTPUT_TEXT = -4; public static final int CODE_DELETE = -5; public static final int CODE_SETTINGS = -6; public static final int CODE_SHORTCUT = -7; // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -99; + public static final int CODE_UNSPECIFIED = -9; public final KeyboardId mId; public final int mThemeId; @@ -163,7 +168,7 @@ public class Keyboard { } public Key getKey(int code) { - if (code == CODE_DUMMY) { + if (code == CODE_UNSPECIFIED) { return null; } final Integer keyCode = code; @@ -248,6 +253,10 @@ public class Keyboard { return label; } + public static boolean isLetterCode(int code) { + return code >= MINIMUM_LETTER_CODE; + } + public static class Params { public KeyboardId mId; public int mThemeId; @@ -420,9 +429,9 @@ public class Keyboard { case CODE_SHIFT: return "shift"; case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; case CODE_CAPSLOCK: return "capslock"; + case CODE_OUTPUT_TEXT: return "text"; case CODE_DELETE: return "delete"; case CODE_SHORTCUT: return "shortcut"; - case CODE_DUMMY: return "dummy"; case CODE_UNSPECIFIED: return "unspec"; default: if (code < 0) Log.w(TAG, "Unknow negative key code=" + code); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index fa073b671..e5097152b 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -332,7 +332,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, * Updates state machine to figure out when to automatically snap back to the previous mode. */ public void onCodeInput(int code) { - mState.onCodeInput(code, isSinglePointer()); + mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState()); } public LatinKeyboardView getKeyboardView() { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 7c14b5888..2183e8ed6 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -262,10 +262,8 @@ public class PointerTracker { final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); final boolean alterCode = key.altCodeWhileTyping() && mTimerProxy.isTyping(); final int code = alterCode ? key.mAltCode : primaryCode; - // If code is CODE_DUMMY here, this key will be ignored or generate text. - final CharSequence text = (code != Keyboard.CODE_DUMMY) ? null : key.mOutputText; if (DEBUG_LISTENER) { - Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + text + Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText + " codes="+ KeyDetector.printableCodes(keyCodes) + " x=" + x + " y=" + y + " ignoreModifier=" + ignoreModifierKey + " alterCode=" + alterCode + " enabled=" + key.isEnabled()); @@ -274,10 +272,10 @@ public class PointerTracker { return; } if (key.isEnabled()) { - if (code != Keyboard.CODE_DUMMY) { + if (code == Keyboard.CODE_OUTPUT_TEXT) { + mListener.onTextInput(key.mOutputText); + } else if (code != Keyboard.CODE_UNSPECIFIED) { mListener.onCodeInput(code, keyCodes, x, y); - } else if (text != null) { - mListener.onTextInput(text); } if (!key.altCodeWhileTyping() && !key.isModifier()) { mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 623cab303..f54bdbb05 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -29,9 +29,10 @@ import com.android.inputmethod.keyboard.Keyboard; * * The input events are {@link #onLoadKeyboard(String, boolean)}, {@link #onSaveKeyboardState()}, * {@link #onPressShift(boolean)}, {@link #onReleaseShift(boolean)}, {@link #onPressSymbol()}, - * {@link #onReleaseSymbol()}, {@link #onOtherKeyPressed()}, {@link #onCodeInput(int, boolean)}, - * {@link #onCancelInput(boolean)}, {@link #onUpdateShiftState(boolean)}, {@link #onToggleShift()}, - * {@link #onToggleCapsLock()}, and {@link #onToggleAlphabetAndSymbols()}. + * {@link #onReleaseSymbol()}, {@link #onOtherKeyPressed()}, + * {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)}, + * {@link #onUpdateShiftState(boolean)}, {@link #onToggleShift()}, {@link #onToggleCapsLock()}, + * and {@link #onToggleAlphabetAndSymbols()}. * * The actions are {@link SwitchActions}'s methods. */ @@ -267,6 +268,10 @@ public class KeyboardState { if (DEBUG_STATE) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } + onUpdateShiftStateInternal(autoCaps); + } + + private void onUpdateShiftStateInternal(boolean autoCaps) { if (mIsAlphabetMode) { if (!mKeyboardShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { if (mShiftKeyState.isReleasing() && autoCaps) { @@ -381,10 +386,10 @@ public class KeyboardState { return false; } - public void onCodeInput(int code, boolean isSinglePointer) { + public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) { if (DEBUG_STATE) { Log.d(TAG, "onCodeInput: code=" + code + " isSinglePointer=" + isSinglePointer - + " " + this); + + " autoCaps=" + autoCaps + " " + this); } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: @@ -429,7 +434,8 @@ public class KeyboardState { } break; case SWITCH_STATE_SYMBOL_BEGIN: - if (!isSpaceCharacter(code) && code >= 0) { + if (!isSpaceCharacter(code) && (Keyboard.isLetterCode(code) + || code == Keyboard.CODE_OUTPUT_TEXT)) { mSwitchState = SWITCH_STATE_SYMBOL; } // Snap back to alpha keyboard mode immediately if user types a quote character. @@ -446,6 +452,11 @@ public class KeyboardState { } break; } + + // If the code is a letter, update keyboard shift state. + if (Keyboard.isLetterCode(code)) { + onUpdateShiftStateInternal(autoCaps); + } } public void onToggleShift() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java index a490b0ad6..93be31ed9 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java @@ -148,12 +148,12 @@ public class MoreKeySpecParser { return code; } if (indexOfLabelEnd(moreKeySpec, 0) > 0) - return Keyboard.CODE_DUMMY; + return Keyboard.CODE_UNSPECIFIED; final String label = getLabel(moreKeySpec); // Code is automatically generated for one letter label. if (label != null && label.length() == 1) return label.charAt(0); - return Keyboard.CODE_DUMMY; + return Keyboard.CODE_UNSPECIFIED; } public static int getIconId(String moreKeySpec) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d2b1e9bca..4cb60558c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1305,7 +1305,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.commitText(text, 1); ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); - mKeyboardSwitcher.onCodeInput(Keyboard.CODE_DUMMY); + mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); mSpaceState = SPACE_STATE_NONE; mEnteredText = text; mWordComposer.reset(); @@ -1496,7 +1496,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic); } - switcher.updateShiftState(); if (mSettingsValues.isWordSeparator(code)) { Utils.Stats.onSeparator((char)code, x, y); } else { @@ -1581,7 +1580,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar Utils.Stats.onSeparator((char)primaryCode, x, y); - mKeyboardSwitcher.updateShiftState(); if (ic != null) { ic.endBatchEdit(); } diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java index 3cd6a8944..1f6141e50 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTests.java @@ -90,7 +90,8 @@ public class KeyboardStateTests extends AndroidTestCase { // Argument for KeyboardState.onCodeInput. private static final boolean SINGLE = true; private static final boolean MULTI = false; - + private static final boolean NO_AUTO_CAPS = false; + private static final boolean AUTO_CAPS = true; private void assertAlphabetNormal() { assertEquals(ALPHABET_UNSHIFTED, mSwitcher.mLayout); @@ -213,7 +214,7 @@ public class KeyboardStateTests extends AndroidTestCase { // Long press recognized in LatinKeyboardView.KeyTimerHandler. mState.onToggleCapsLock(); assertAlphabetShiftLocked(); - mState.onCodeInput(Keyboard.CODE_CAPSLOCK, SINGLE); + mState.onCodeInput(Keyboard.CODE_CAPSLOCK, SINGLE, NO_AUTO_CAPS); assertAlphabetShiftLocked(); mState.onReleaseShift(NOT_SLIDING); assertAlphabetShiftLocked(); @@ -224,7 +225,7 @@ public class KeyboardStateTests extends AndroidTestCase { // Long press recognized in LatinKeyboardView.KeyTimerHandler. mState.onToggleCapsLock(); assertAlphabetNormal(); - mState.onCodeInput(Keyboard.CODE_CAPSLOCK, SINGLE); + mState.onCodeInput(Keyboard.CODE_CAPSLOCK, SINGLE, NO_AUTO_CAPS); assertAlphabetNormal(); mState.onReleaseShift(NOT_SLIDING); assertAlphabetNormal(); @@ -236,7 +237,7 @@ public class KeyboardStateTests extends AndroidTestCase { // First shift key tap. mState.onPressShift(NOT_SLIDING); assertAlphabetManualShifted(); - mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE); + mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE, NO_AUTO_CAPS); assertAlphabetManualShifted(); mState.onReleaseShift(NOT_SLIDING); assertAlphabetManualShifted(); @@ -244,13 +245,13 @@ public class KeyboardStateTests extends AndroidTestCase { // Double tap recognized in LatinKeyboardView.KeyTimerHandler. mState.onToggleCapsLock(); assertAlphabetShiftLocked(); - mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE); + mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE, NO_AUTO_CAPS); assertAlphabetShiftLocked(); // First shift key tap. mState.onPressShift(NOT_SLIDING); assertAlphabetManualShifted(); - mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE); + mState.onCodeInput(Keyboard.CODE_SHIFT, SINGLE, NO_AUTO_CAPS); assertAlphabetManualShifted(); mState.onReleaseShift(NOT_SLIDING); assertAlphabetNormal(); diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java index 798fca0f5..0eb324234 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java @@ -89,78 +89,78 @@ public class MoreKeySpecParserTests extends AndroidTestCase { assertParser("Single escaped at", "\\@", "@", null, ICON_UNDEFINED, '@'); assertParser("Single letter with outputText", "a|abc", - "a", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "abc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with escaped outputText", "a|a\\|c", - "a", "a|c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "a|c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with comma outputText", "a|a,b", - "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with escaped comma outputText", "a|a\\,b", - "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with outputText starts with at", "a|@bc", - "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with outputText contains at", "a|a@c", - "a", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "a@c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with escaped at outputText", "a|\\@bc", - "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single escaped escape with outputText", "\\\\|\\\\", - "\\", "\\", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "\\", "\\", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single escaped bar with outputText", "\\||\\|", - "|", "|", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "|", "|", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Single letter with code", "a|" + CODE_SETTINGS, "a", null, ICON_UNDEFINED, mCodeSettings); } public void testLabel() { assertParser("Simple label", "abc", - "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped bar", "a\\|c", - "a|c", "a|c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a|c", "a|c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped escape", "a\\\\c", - "a\\c", "a\\c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a\\c", "a\\c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with comma", "a,c", - "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped comma", "a\\,c", - "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label starts with at", "@bc", - "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label contains at", "a@c", - "a@c", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a@c", "a@c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped at", "\\@bc", - "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped letter", "\\abc", - "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with outputText", "abc|def", - "abc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with comma and outputText", "a,c|def", - "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Escaped comma label with outputText", "a\\,c|def", - "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Escaped label with outputText", "a\\|c|def", - "a|c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a|c", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Escaped escape label with outputText", "a\\\\|def", - "a\\", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a\\", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label starts with at and outputText", "@bc|def", - "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label contains at label and outputText", "a@c|def", - "a@c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a@c", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Escaped at label with outputText", "\\@bc|def", - "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with comma outputText", "abc|a,b", - "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped comma outputText", "abc|a\\,b", - "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with outputText starts with at", "abc|@bc", - "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with outputText contains at", "abc|a@c", - "abc", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "a@c", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped at outputText", "abc|\\@bc", - "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Escaped bar label with escaped bar outputText", "a\\|c|d\\|f", - "a|c", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + "a|c", "d|f", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParser("Label with code", "abc|" + CODE_SETTINGS, "abc", null, ICON_UNDEFINED, mCodeSettings); assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS, @@ -169,13 +169,13 @@ public class MoreKeySpecParserTests extends AndroidTestCase { public void testIconAndCode() { assertParser("Icon with outputText", ICON_SETTINGS + "|abc", - null, "abc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); + null, "abc", ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); assertParser("Icon with outputText starts with at", ICON_SETTINGS + "|@bc", - null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); + null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); assertParser("Icon with outputText contains at", ICON_SETTINGS + "|a@c", - null, "a@c", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); + null, "a@c", ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); assertParser("Icon with escaped at outputText", ICON_SETTINGS + "|\\@bc", - null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); + null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); assertParser("Label starts with at and code", "@bc|" + CODE_SETTINGS, "@bc", null, ICON_UNDEFINED, mCodeSettings); assertParser("Label contains at and code", "a@c|" + CODE_SETTINGS, @@ -190,7 +190,7 @@ public class MoreKeySpecParserTests extends AndroidTestCase { assertParserError("Empty spec", "", null, null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParserError("Empty label with outputText", "|a", - null, "a", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + null, "a", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParserError("Empty label with code", "|" + CODE_SETTINGS, null, null, ICON_UNDEFINED, mCodeSettings); assertParserError("Empty outputText with label", "a|", @@ -200,9 +200,9 @@ public class MoreKeySpecParserTests extends AndroidTestCase { assertParserError("Empty icon and code", "|", null, null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParserError("Icon without code", ICON_SETTINGS, - null, null, ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); + null, null, ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); assertParser("Non existing icon", ICON_NON_EXISTING + "|abc", - null, "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); + null, "abc", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParserError("Non existing code", "abc|" + CODE_NON_EXISTING, "abc", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); assertParserError("Third bar at end", "a|b|", diff --git a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java b/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java index afd602308..2fcd5750a 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java +++ b/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java @@ -39,11 +39,13 @@ public class DictionaryMaker { private final static String OPTION_VERSION_2 = "-2"; private final static String OPTION_INPUT_SOURCE = "-s"; private final static String OPTION_INPUT_BIGRAM_XML = "-b"; + private final static String OPTION_INPUT_SHORTCUT_XML = "-c"; private final static String OPTION_OUTPUT_BINARY = "-d"; private final static String OPTION_OUTPUT_XML = "-x"; private final static String OPTION_HELP = "-h"; public final String mInputBinary; public final String mInputUnigramXml; + public final String mInputShortcutXml; public final String mInputBigramXml; public final String mOutputBinary; public final String mOutputXml; @@ -72,8 +74,9 @@ public class DictionaryMaker { private void displayHelp() { MakedictLog.i("Usage: makedict " - + "[-s <unigrams.xml> [-b <bigrams.xml>] | -s <binary input>] " - + " [-d <binary output>] [-x <xml output>] [-2]\n" + + "[-s <unigrams.xml> [-b <bigrams.xml>] [-c <shortcuts.xml>] " + + "| -s <binary input>] " + + "[-d <binary output>] [-x <xml output>] [-2]\n" + "\n" + " Converts a source dictionary file to one or several outputs.\n" + " Source can be an XML file, with an optional XML bigrams file, or a\n" @@ -90,6 +93,7 @@ public class DictionaryMaker { } String inputBinary = null; String inputUnigramXml = null; + String inputShortcutXml = null; String inputBigramXml = null; String outputBinary = null; String outputXml = null; @@ -116,6 +120,8 @@ public class DictionaryMaker { } else { inputUnigramXml = filename; } + } else if (OPTION_INPUT_SHORTCUT_XML.equals(arg)) { + inputShortcutXml = filename; } else if (OPTION_INPUT_BIGRAM_XML.equals(arg)) { inputBigramXml = filename; } else if (OPTION_OUTPUT_BINARY.equals(arg)) { @@ -143,6 +149,7 @@ public class DictionaryMaker { mInputBinary = inputBinary; mInputUnigramXml = inputUnigramXml; + mInputShortcutXml = inputShortcutXml; mInputBigramXml = inputBigramXml; mOutputBinary = outputBinary; mOutputXml = outputXml; @@ -170,7 +177,7 @@ public class DictionaryMaker { if (null != args.mInputBinary) { return readBinaryFile(args.mInputBinary); } else if (null != args.mInputUnigramXml) { - return readXmlFile(args.mInputUnigramXml, args.mInputBigramXml); + return readXmlFile(args.mInputUnigramXml, args.mInputShortcutXml, args.mInputBigramXml); } else { throw new RuntimeException("No input file specified"); } @@ -195,6 +202,7 @@ public class DictionaryMaker { * Read a dictionary from a unigram XML file, and optionally a bigram XML file. * * @param unigramXmlFilename the name of the unigram XML file. May not be null. + * @param shortcutXmlFilename the name of the shortcut XML file, or null if there is none. * @param bigramXmlFilename the name of the bigram XML file. Pass null if there are no bigrams. * @return the read dictionary. * @throws FileNotFoundException if one of the files can't be found @@ -203,12 +211,14 @@ public class DictionaryMaker { * @throws ParserConfigurationException if the system can't create a SAX parser */ private static FusionDictionary readXmlFile(final String unigramXmlFilename, - final String bigramXmlFilename) throws FileNotFoundException, SAXException, - IOException, ParserConfigurationException { + final String shortcutXmlFilename, final String bigramXmlFilename) + throws FileNotFoundException, SAXException, IOException, ParserConfigurationException { final FileInputStream unigrams = new FileInputStream(new File(unigramXmlFilename)); + final FileInputStream shortcuts = null == shortcutXmlFilename ? null : + new FileInputStream(new File(shortcutXmlFilename)); final FileInputStream bigrams = null == bigramXmlFilename ? null : new FileInputStream(new File(bigramXmlFilename)); - return XmlDictInputOutput.readDictionaryXml(unigrams, bigrams); + return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams); } /** diff --git a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java index 19ed9d8d2..1562b693b 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java +++ b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java @@ -61,6 +61,7 @@ public class XmlDictInputOutput { int mState; // the state of the parser int mFreq; // the currently read freq String mWord; // the current word + final HashMap<String, ArrayList<WeightedString>> mShortcutsMap; final HashMap<String, ArrayList<WeightedString>> mBigramsMap; /** @@ -69,9 +70,11 @@ public class XmlDictInputOutput { * @param dict the dictionary to construct. * @param bigrams the bigrams as a map. This may be empty, but may not be null. */ - public UnigramHandler(FusionDictionary dict, - HashMap<String, ArrayList<WeightedString>> bigrams) { + public UnigramHandler(final FusionDictionary dict, + final HashMap<String, ArrayList<WeightedString>> shortcuts, + final HashMap<String, ArrayList<WeightedString>> bigrams) { mDictionary = dict; + mShortcutsMap = shortcuts; mBigramsMap = bigrams; mWord = ""; mState = START; @@ -107,8 +110,7 @@ public class XmlDictInputOutput { @Override public void endElement(String uri, String localName, String qName) { if (WORD == mState) { - // TODO: pass the shortcut targets - mDictionary.add(mWord, mFreq, null, mBigramsMap.get(mWord)); + mDictionary.add(mWord, mFreq, mShortcutsMap.get(mWord), mBigramsMap.get(mWord)); mState = START; } } @@ -208,9 +210,12 @@ public class XmlDictInputOutput { * representation. * * @param unigrams the file to read the data from. + * @param shortcuts the file to read the shortcuts from, or null. + * @param bigrams the file to read the bigrams from, or null. * @return the in-memory representation of the dictionary. */ - public static FusionDictionary readDictionaryXml(InputStream unigrams, InputStream bigrams) + public static FusionDictionary readDictionaryXml(final InputStream unigrams, + final InputStream shortcuts, final InputStream bigrams) throws SAXException, IOException, ParserConfigurationException { final SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); @@ -218,9 +223,13 @@ public class XmlDictInputOutput { final BigramHandler bigramHandler = new BigramHandler(); if (null != bigrams) parser.parse(bigrams, bigramHandler); + final ShortcutHandler shortcutHandler = new ShortcutHandler(); + if (null != shortcuts) parser.parse(shortcuts, shortcutHandler); + final FusionDictionary dict = new FusionDictionary(); final UnigramHandler unigramHandler = - new UnigramHandler(dict, bigramHandler.getBigramMap()); + new UnigramHandler(dict, shortcutHandler.getShortcutMap(), + bigramHandler.getBigramMap()); parser.parse(unigrams, unigramHandler); return dict; } |