diff options
Diffstat (limited to 'java/src/com/android')
28 files changed, 296 insertions, 299 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index a1269c801..cf68c565d 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -60,6 +60,7 @@ public class Key implements Comparable<Key> { private final int mLabelFlags; private static final int LABEL_FLAGS_ALIGN_LEFT = 0x01; private static final int LABEL_FLAGS_ALIGN_RIGHT = 0x02; + private static final int LABEL_FLAGS_ALIGN_BUTTOM = 0x04; private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08; private static final int LABEL_FLAGS_FONT_NORMAL = 0x10; private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x20; @@ -646,6 +647,10 @@ public class Key implements Comparable<Key> { return (mLabelFlags & LABEL_FLAGS_ALIGN_RIGHT) != 0; } + public final boolean isAlignButtom() { + return (mLabelFlags & LABEL_FLAGS_ALIGN_BUTTOM) != 0; + } + public final boolean isAlignLeftOfCenter() { return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT_OF_CENTER) != 0; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index b7a76944e..61d51d1c9 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -61,10 +61,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private final KeyboardTextsSet mKeyboardTextsSet = new KeyboardTextsSet(); private SettingsValues mCurrentSettingsValues; - /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of - * what user actually typed. */ - private boolean mIsAutoCorrectionActive; - private KeyboardTheme mKeyboardTheme; private Context mThemeContext; @@ -142,12 +138,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } - public void onFinishInputView() { - mIsAutoCorrectionActive = false; - } - public void onHideWindow() { - mIsAutoCorrectionActive = false; if (mKeyboardView != null) { mKeyboardView.onHideWindow(); } @@ -168,7 +159,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mCurrentSettingsValues.mKeyPreviewShowUpDuration, mCurrentSettingsValues.mKeyPreviewDismissEndScale, mCurrentSettingsValues.mKeyPreviewDismissDuration); - keyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive); keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady()); final boolean subtypeChanged = (oldKeyboard == null) || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); @@ -367,15 +357,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } - public void onAutoCorrectionStateChanged(final boolean isAutoCorrection) { - if (mIsAutoCorrectionActive != isAutoCorrection) { - mIsAutoCorrectionActive = isAutoCorrection; - if (mKeyboardView != null) { - mKeyboardView.updateAutoCorrectionState(isAutoCorrection); - } - } - } - public int getKeyboardShiftMode() { final Keyboard keyboard = getKeyboard(); if (keyboard == null) { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java index e0b74fa14..1f14aa2e3 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java @@ -29,20 +29,20 @@ import java.util.Comparator; public final class KeyboardTheme { private static final String TAG = KeyboardTheme.class.getSimpleName(); - static final String KITKAT_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916"; - static final String KEYBOARD_THEME_KEY = "pref_keyboard_theme_20140509"; + static final String KLP_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916"; + static final String LXX_KEYBOARD_THEME_KEY = "pref_keyboard_theme_20140509"; static final int THEME_ID_ICS = 0; static final int THEME_ID_KLP = 2; - static final int THEME_ID_LXX = 3; + static final int THEME_ID_LXX_DARK = 3; static final int DEFAULT_THEME_ID = THEME_ID_KLP; private static final KeyboardTheme[] KEYBOARD_THEMES = { new KeyboardTheme(THEME_ID_ICS, R.style.KeyboardTheme_ICS, - VERSION_CODES.ICE_CREAM_SANDWICH), + VERSION_CODES.BASE), new KeyboardTheme(THEME_ID_KLP, R.style.KeyboardTheme_KLP, - VERSION_CODES.KITKAT), - new KeyboardTheme(THEME_ID_LXX, R.style.KeyboardTheme_LXX, + VERSION_CODES.ICE_CREAM_SANDWICH), + new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark, // TODO: Update this constant once the *next* version becomes available. VERSION_CODES.CUR_DEVELOPMENT), }; @@ -88,7 +88,7 @@ public final class KeyboardTheme { return 5; case THEME_ID_KLP: return 9; - case THEME_ID_LXX: + case THEME_ID_LXX_DARK: return 10; default: // Invalid theme return -1; @@ -116,22 +116,23 @@ public final class KeyboardTheme { static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) { - final String obsoleteIdString = prefs.getString(KITKAT_KEYBOARD_THEME_KEY, null); - if (obsoleteIdString != null) { - // Remove old preference. - prefs.edit().remove(KITKAT_KEYBOARD_THEME_KEY).apply(); + final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null); + if (klpThemeIdString != null) { if (sdkVersion <= VERSION_CODES.KITKAT) { try { - final int themeId = Integer.parseInt(obsoleteIdString); + final int themeId = Integer.parseInt(klpThemeIdString); final KeyboardTheme theme = searchKeyboardThemeById(themeId); if (theme != null) { return theme; } - Log.w(TAG, "Unknown keyboard theme in preference: " + obsoleteIdString); + Log.w(TAG, "Unknown keyboard theme in KLP preference: " + klpThemeIdString); } catch (final NumberFormatException e) { - Log.w(TAG, "Illegal keyboard theme in preference: " + obsoleteIdString); + Log.w(TAG, "Illegal keyboard theme in KLP preference: " + klpThemeIdString, e); } } + // Remove old preference. + Log.i(TAG, "Remove KLP keyboard theme preference: " + klpThemeIdString); + prefs.edit().remove(KLP_KEYBOARD_THEME_KEY).apply(); } // TODO: This search algorithm isn't optimal if there are many themes. for (final KeyboardTheme theme : KEYBOARD_THEMES) { @@ -144,27 +145,43 @@ public final class KeyboardTheme { public static void saveKeyboardThemeId(final String themeIdString, final SharedPreferences prefs) { - prefs.edit().putString(KEYBOARD_THEME_KEY, themeIdString).apply(); + saveKeyboardThemeId(themeIdString, prefs, getSdkVersion()); + } + + static String getPreferenceKey(final int sdkVersion) { + if (sdkVersion <= VERSION_CODES.KITKAT) { + return KLP_KEYBOARD_THEME_KEY; + } + return LXX_KEYBOARD_THEME_KEY; + } + + static void saveKeyboardThemeId(final String themeIdString, final SharedPreferences prefs, + final int sdkVersion) { + final String prefKey = getPreferenceKey(sdkVersion); + prefs.edit().putString(prefKey, themeIdString).apply(); } public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) { - final int sdkVersion = getSdkVersion(); - final String themeIdString = prefs.getString(KEYBOARD_THEME_KEY, null); - if (themeIdString == null) { + return getKeyboardTheme(prefs, getSdkVersion()); + } + + static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) { + final String lxxThemeIdString = prefs.getString(LXX_KEYBOARD_THEME_KEY, null); + if (lxxThemeIdString == null) { return getDefaultKeyboardTheme(prefs, sdkVersion); } try { - final int themeId = Integer.parseInt(themeIdString); + final int themeId = Integer.parseInt(lxxThemeIdString); final KeyboardTheme theme = searchKeyboardThemeById(themeId); if (theme != null) { return theme; } - Log.w(TAG, "Unknown keyboard theme in preference: " + themeIdString); + Log.w(TAG, "Unknown keyboard theme in LXX preference: " + lxxThemeIdString); } catch (final NumberFormatException e) { - Log.w(TAG, "Illegal keyboard theme in preference: " + themeIdString); + Log.w(TAG, "Illegal keyboard theme in LXX preference: " + lxxThemeIdString, e); } - // Remove preference. - prefs.edit().remove(KEYBOARD_THEME_KEY).apply(); + // Remove preference that contains unknown or illegal theme id. + prefs.edit().remove(LXX_KEYBOARD_THEME_KEY).apply(); return getDefaultKeyboardTheme(prefs, sdkVersion); } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index a6eac4cd7..edfc5fded 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -28,6 +28,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; import android.view.View; @@ -49,6 +50,7 @@ import java.util.HashSet; * @attr ref R.styleable#KeyboardView_keyBackground * @attr ref R.styleable#KeyboardView_functionalKeyBackground * @attr ref R.styleable#KeyboardView_spacebarBackground + * @attr ref R.styleable#KeyboardView_spacebarIconWidthRatio * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding * @attr ref R.styleable#KeyboardView_keyHintLetterPadding * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding @@ -85,6 +87,7 @@ public class KeyboardView extends View { private final Drawable mKeyBackground; private final Drawable mFunctionalKeyBackground; private final Drawable mSpacebarBackground; + private final float mSpacebarIconWidthRatio; private final Rect mKeyBackgroundPadding = new Rect(); private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f; @@ -135,8 +138,9 @@ public class KeyboardView extends View { : mKeyBackground; final Drawable spacebarBackground = keyboardViewAttr.getDrawable( R.styleable.KeyboardView_spacebarBackground); - mSpacebarBackground = (spacebarBackground != null) ? spacebarBackground - : mKeyBackground; + mSpacebarBackground = (spacebarBackground != null) ? spacebarBackground : mKeyBackground; + mSpacebarIconWidthRatio = keyboardViewAttr.getFloat( + R.styleable.KeyboardView_spacebarIconWidthRatio, 1.0f); mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset( R.styleable.KeyboardView_keyLabelHorizontalPadding, 0); mKeyHintLetterPadding = keyboardViewAttr.getDimension( @@ -513,10 +517,16 @@ public class KeyboardView extends View { // Draw key icon. if (label == null && icon != null) { - final int iconWidth = Math.min(icon.getIntrinsicWidth(), keyWidth); + final int iconWidth; + if (key.getCode() == Constants.CODE_SPACE && icon instanceof NinePatchDrawable) { + iconWidth = (int)(keyWidth * mSpacebarIconWidthRatio); + } else { + iconWidth = Math.min(icon.getIntrinsicWidth(), keyWidth); + } final int iconHeight = icon.getIntrinsicHeight(); final int iconX, alignX; - final int iconY = (keyHeight - iconHeight) / 2; + final int iconY = key.isAlignButtom() ? keyHeight - iconHeight + : (keyHeight - iconHeight) / 2; if (key.isAlignLeft()) { iconX = mKeyLabelHorizontalPadding; alignX = iconX; diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 4a0976845..26b6dd06a 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -27,7 +27,6 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; -import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; import android.util.AttributeSet; import android.util.Log; @@ -70,8 +69,6 @@ import java.util.WeakHashMap; /** * A view that is responsible for detecting key presses and touch movements. * - * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedEnabled - * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedIcon * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextRatio * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowRadius @@ -118,7 +115,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack /* Space key and its icon and background. */ private Key mSpaceKey; - private Drawable mSpacebarIcon; // Stuff to draw language name on spacebar. private final int mLanguageOnSpacebarFinalAlpha; private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; @@ -133,11 +129,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private static final float LANGUAGE_ON_SPACEBAR_TEXT_SHADOW_RADIUS_DISABLED = -1.0f; // The minimum x-scale to fit the language name on spacebar. private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f; - // Stuff to draw auto correction LED on spacebar. - private boolean mAutoCorrectionSpacebarLedOn; - private final boolean mAutoCorrectionSpacebarLedEnabled; - private final Drawable mAutoCorrectionSpacebarLedIcon; - private static final int SPACE_LED_LENGTH_PERCENT = 80; // Stuff to draw altCodeWhileTyping keys. private final ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; @@ -221,10 +212,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack R.styleable.MainKeyboardView_backgroundDimAlpha, 0); mBackgroundDimAlphaPaint.setColor(Color.BLACK); mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha); - mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean( - R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false); - mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable( - R.styleable.MainKeyboardView_autoCorrectionSpacebarLedIcon); mLanguageOnSpacebarTextRatio = mainKeyboardViewAttr.getFraction( R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f); mLanguageOnSpacebarTextColor = mainKeyboardViewAttr.getColor( @@ -400,8 +387,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mMoreKeysKeyboardCache.clear(); mSpaceKey = keyboard.getKey(Constants.CODE_SPACE); - mSpacebarIcon = (mSpaceKey != null) - ? mSpaceKey.getIcon(keyboard.mIconsSet, Constants.Color.ALPHA_OPAQUE) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio; if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { @@ -834,14 +819,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack invalidateKey(mSpaceKey); } - public void updateAutoCorrectionState(final boolean isAutoCorrection) { - if (!mAutoCorrectionSpacebarLedEnabled) { - return; - } - mAutoCorrectionSpacebarLedOn = isAutoCorrection; - invalidateKey(mSpaceKey); - } - private void dimEntireKeyboard(final boolean dimmed) { final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed; mNeedsToDimEntireKeyboard = dimmed; @@ -866,18 +843,19 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (key.altCodeWhileTyping() && key.isEnabled()) { params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; } + super.onDrawKeyTopVisuals(key, canvas, paint, params); final int code = key.getCode(); if (code == Constants.CODE_SPACE) { - drawSpacebar(key, canvas, paint); + // If input language are explicitly selected. + if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) { + drawLanguageOnSpacebar(key, canvas, paint); + } // Whether space key needs to show the "..." popup hint for special purposes if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) { drawKeyPopupHint(key, canvas, paint, params); } } else if (code == Constants.CODE_LANGUAGE_SWITCH) { - super.onDrawKeyTopVisuals(key, canvas, paint, params); drawKeyPopupHint(key, canvas, paint, params); - } else { - super.onDrawKeyTopVisuals(key, canvas, paint, params); } } @@ -917,48 +895,29 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return ""; } - private void drawSpacebar(final Key key, final Canvas canvas, final Paint paint) { + private void drawLanguageOnSpacebar(final Key key, final Canvas canvas, final Paint paint) { final int width = key.getWidth(); final int height = key.getHeight(); - - // If input language are explicitly selected. - if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) { - paint.setTextAlign(Align.CENTER); - paint.setTypeface(Typeface.DEFAULT); - paint.setTextSize(mLanguageOnSpacebarTextSize); - final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; - final String language = layoutLanguageOnSpacebar(paint, subtype, width); - // Draw language text with shadow - final float descent = paint.descent(); - final float textHeight = -paint.ascent() + descent; - final float baseline = height / 2 + textHeight / 2; - if (mLanguageOnSpacebarTextShadowRadius > 0.0f) { - paint.setShadowLayer(mLanguageOnSpacebarTextShadowRadius, 0, 0, - mLanguageOnSpacebarTextShadowColor); - } else { - paint.clearShadowLayer(); - } - paint.setColor(mLanguageOnSpacebarTextColor); - paint.setAlpha(mLanguageOnSpacebarAnimAlpha); - canvas.drawText(language, width / 2, baseline - descent, paint); + paint.setTextAlign(Align.CENTER); + paint.setTypeface(Typeface.DEFAULT); + paint.setTextSize(mLanguageOnSpacebarTextSize); + final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; + final String language = layoutLanguageOnSpacebar(paint, subtype, width); + // Draw language text with shadow + final float descent = paint.descent(); + final float textHeight = -paint.ascent() + descent; + final float baseline = height / 2 + textHeight / 2; + if (mLanguageOnSpacebarTextShadowRadius > 0.0f) { + paint.setShadowLayer(mLanguageOnSpacebarTextShadowRadius, 0, 0, + mLanguageOnSpacebarTextShadowColor); + } else { paint.clearShadowLayer(); - paint.setTextScaleX(1.0f); - } - - // Draw the spacebar icon at the bottom - if (mAutoCorrectionSpacebarLedOn) { - final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; - final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight); - } else if (mSpacebarIcon != null) { - final int iconWidth = mSpacebarIcon.getIntrinsicWidth(); - final int iconHeight = mSpacebarIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - drawIcon(canvas, mSpacebarIcon, x, y, iconWidth, iconHeight); } + paint.setColor(mLanguageOnSpacebarTextColor); + paint.setAlpha(mLanguageOnSpacebarAnimAlpha); + canvas.drawText(language, width / 2, baseline - descent, paint); + paint.clearShadowLayer(); + paint.setTextScaleX(1.0f); } @Override diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java index dd0e3e838..495fa554b 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java @@ -70,12 +70,12 @@ final class EmojiCategory { "emoticons" }; private static final int[] sCategoryIcon = { - R.drawable.ic_emoji_recent_light, - R.drawable.ic_emoji_people_light, - R.drawable.ic_emoji_objects_light, - R.drawable.ic_emoji_nature_light, - R.drawable.ic_emoji_places_light, - R.drawable.ic_emoji_symbols_light, + R.drawable.ic_emoji_recent_holo_dark, + R.drawable.ic_emoji_people_holo_dark, + R.drawable.ic_emoji_objects_holo_dark, + R.drawable.ic_emoji_nature_holo_dark, + R.drawable.ic_emoji_places_holo_dark, + R.drawable.ic_emoji_symbols_holo_dark, 0 }; private static final String[] sCategoryLabel = diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java index 74cfd9b4b..f5aa1079e 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java @@ -38,7 +38,7 @@ public final class EmojiCategoryPageIndicatorView extends LinearLayout { public EmojiCategoryPageIndicatorView(final Context context, final AttributeSet attrs) { super(context, attrs); mPaint.setColor(context.getResources().getColor( - R.color.emoji_category_page_id_view_foreground)); + R.color.emoji_category_page_id_foreground_holo)); } public void setCategoryPageId(final int size, final int id, final float offset) { diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java index 3813c578a..8e4595703 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -416,14 +416,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange private static class DeleteKeyOnTouchListener implements OnTouchListener { static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30); - final int mDeleteKeyPressedBackgroundColor; final long mKeyRepeatStartTimeout; final long mKeyRepeatInterval; public DeleteKeyOnTouchListener(Context context) { final Resources res = context.getResources(); - mDeleteKeyPressedBackgroundColor = - res.getColor(R.color.emoji_key_pressed_background_color); mKeyRepeatStartTimeout = res.getInteger(R.integer.config_key_repeat_start_timeout); mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); mTimer = new CountDownTimer(MAX_REPEAT_COUNT_TIME, mKeyRepeatInterval) { @@ -500,7 +497,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange mTimer.cancel(); mRepeatCount = 0; handleKeyDown(); - v.setBackgroundColor(mDeleteKeyPressedBackgroundColor); + v.setPressed(true /* pressed */); mState = KEY_REPEAT_STATE_KEY_DOWN; mTimer.start(); } @@ -510,7 +507,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (mState == KEY_REPEAT_STATE_KEY_DOWN) { handleKeyUp(); } - v.setBackgroundColor(Color.TRANSPARENT); + v.setPressed(false /* pressed */); mState = KEY_REPEAT_STATE_INITIALIZED; } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 1e31c96ec..b8cf3f89c 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -113,11 +113,8 @@ public final class BinaryDictionary extends Dictionary { synchronized(mDicTraverseSessions) { DicTraverseSession traverseSession = mDicTraverseSessions.get(traverseSessionId); if (traverseSession == null) { - traverseSession = mDicTraverseSessions.get(traverseSessionId); - if (traverseSession == null) { - traverseSession = new DicTraverseSession(mLocale, mNativeDict, mDictSize); - mDicTraverseSessions.put(traverseSessionId, traverseSession); - } + traverseSession = new DicTraverseSession(mLocale, mNativeDict, mDictSize); + mDicTraverseSessions.put(traverseSessionId, traverseSession); } return traverseSession; } @@ -266,19 +263,9 @@ public final class BinaryDictionary extends Dictionary { new FormatSpec.FormatOptions(outFormatVersion[0], hasHistoricalInfo)); } - @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { - return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight); - } - - @Override - public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId, final float[] inOutLanguageWeight) { if (!isValidDictionary()) { @@ -287,8 +274,8 @@ public final class BinaryDictionary extends Dictionary { Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE); // TODO: toLowerCase in the native code - final int[] prevWordCodePointArray = (null == prevWord) - ? null : StringUtils.toCodePointArray(prevWord); + final int[] prevWordCodePointArray = (null == prevWordsInfo.mPrevWord) + ? null : StringUtils.toCodePointArray(prevWordsInfo.mPrevWord); final InputPointers inputPointers = composer.getInputPointers(); final boolean isGesture = composer.isBatchMode(); final int inputSize; diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index cd380db6b..aab16653e 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -69,31 +69,20 @@ public abstract class Dictionary { * Searches for suggestions for a given context. For the moment the context is only the * previous word. * @param composer the key sequence to match with coordinate info, as a WordComposer - * @param prevWord the previous word, or null if none + * @param prevWordsInfo the information of previous words. * @param proximityInfo the object for key proximity. May be ignored by some implementations. * @param blockOffensiveWords whether to block potentially offensive words * @param additionalFeaturesOptions options about additional features used for the suggestion. + * @param sessionId the session id. * @param inOutLanguageWeight the language weight used for generating suggestions. * inOutLanguageWeight is a float array that has only one element. This can be updated when the * different language weight is used. * @return the list of suggestions (possibly null if none) */ - // TODO: pass more context than just the previous word, to enable better suggestions (n-gram - // and more) abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight); - - // The default implementation of this method ignores sessionId. - // Subclasses that want to use sessionId need to override this method. - public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final int sessionId, final float[] inOutLanguageWeight) { - return getSuggestions(composer, prevWord, proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, inOutLanguageWeight); - } + final int sessionId, final float[] inOutLanguageWeight); /** * Checks if the given word occurs in the dictionary @@ -165,9 +154,9 @@ public abstract class Dictionary { @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { + final int sessionId, final float[] inOutLanguageWeight) { return null; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 16173fffc..e6e4e0938 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -57,22 +57,22 @@ public final class DictionaryCollection extends Dictionary { @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { + final int sessionId, final float[] inOutLanguageWeight) { final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries; if (dictionaries.isEmpty()) return null; // To avoid creating unnecessary objects, we get the list out of the first // dictionary and add the rest to it if not null, hence the get(0) ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composer, - prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, - inOutLanguageWeight); + prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, + sessionId, inOutLanguageWeight); if (null == suggestions) suggestions = CollectionUtils.newArrayList(); final int length = dictionaries.size(); for (int i = 1; i < length; ++ i) { final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer, - prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, - inOutLanguageWeight); + prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, + sessionId, inOutLanguageWeight); if (null != sugg) suggestions.addAll(sugg); } return suggestions; diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java index e0220e137..14c8bb6c3 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java @@ -444,7 +444,7 @@ public class DictionaryFacilitatorForSuggest { // TODO: Revise the way to fusion suggestion results. public SuggestionResults getSuggestionResults(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId, final ArrayList<SuggestedWordInfo> rawSuggestions) { final Dictionaries dictionaries = mDictionaries; @@ -455,7 +455,7 @@ public class DictionaryFacilitatorForSuggest { final Dictionary dictionary = dictionaries.getDict(dictType); if (null == dictionary) continue; final ArrayList<SuggestedWordInfo> dictionarySuggestions = - dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo, + dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId, languageWeight); if (null == dictionarySuggestions) continue; diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index e323f0ab2..629f3fd18 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -366,8 +366,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } @Override - public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId, final float[] inOutLanguageWeight) { reloadDictionaryIfRequired(); @@ -380,9 +380,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return null; } final ArrayList<SuggestedWordInfo> suggestions = - mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, - proximityInfo, blockOffensiveWords, additionalFeaturesOptions, - sessionId, inOutLanguageWeight); + mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, sessionId, + inOutLanguageWeight); if (mBinaryDictionary.isCorrupted()) { Log.i(TAG, "Dictionary (" + mDictName +") is corrupted. " + "Remove and regenerate it."); @@ -401,15 +401,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } @Override - public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { - return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight); - } - - @Override public boolean isValidWord(final String word) { reloadDictionaryIfRequired(); boolean lockAcquired = false; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1ccf5854a..5e45275f8 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -140,10 +140,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private final SubtypeState mSubtypeState = new SubtypeState(); // Object for reacting to adding/removing a dictionary pack. - private BroadcastReceiver mDictionaryPackInstallReceiver = + private final BroadcastReceiver mDictionaryPackInstallReceiver = new DictionaryPackInstallBroadcastReceiver(this); - private BroadcastReceiver mDictionaryDumpBroadcastReceiver = + private final BroadcastReceiver mDictionaryDumpBroadcastReceiver = new DictionaryDumpBroadcastReceiver(this); private AlertDialog mOptionsDialog; @@ -905,7 +905,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void onFinishInputViewInternal(final boolean finishingInput) { super.onFinishInputView(finishingInput); - mKeyboardSwitcher.onFinishInputView(); mKeyboardSwitcher.deallocateMemory(); // Remove pending messages related to update suggestions mHandler.cancelUpdateSuggestionStrip(); @@ -1388,7 +1387,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (!hasSuggestionStripView()) { return; } - mKeyboardSwitcher.onAutoCorrectionStateChanged(suggestedWords.mWillAutoCorrect); if (!onEvaluateInputViewShown()) { return; } @@ -1430,8 +1428,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { if (mInputLogic.mWordComposer.isComposingWord() || mInputLogic.mWordComposer.isBatchMode()) { - final String previousWord - = mInputLogic.mWordComposer.getPreviousWordForSuggestion(); + final PrevWordsInfo prevWordsInfo + = mInputLogic.mWordComposer.getPrevWordsInfoForSuggestion(); // TODO: this is for checking consistency with older versions. Remove this when // we are confident this is stable. // We're checking the previous word in the text field against the memorized previous @@ -1440,14 +1438,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final CharSequence rereadPrevWord = mInputLogic.getNthPreviousWordForSuggestion( currentSettings.mSpacingAndPunctuations, mInputLogic.mWordComposer.isComposingWord() ? 2 : 1); - if (!TextUtils.equals(previousWord, rereadPrevWord)) { + if (!TextUtils.equals(prevWordsInfo.mPrevWord, rereadPrevWord)) { throw new RuntimeException("Unexpected previous word: " - + previousWord + " <> " + rereadPrevWord); + + prevWordsInfo.mPrevWord + " <> " + rereadPrevWord); } } } mInputLogic.mSuggest.getSuggestedWords(mInputLogic.mWordComposer, - mInputLogic.mWordComposer.getPreviousWordForSuggestion(), + mInputLogic.mWordComposer.getPrevWordsInfoForSuggestion(), keyboard.getProximityInfo(), currentSettings.mBlockPotentiallyOffensive, currentSettings.mCorrectionEnabled, additionalFeaturesOptions, sessionId, sequenceNumber, callback); @@ -1631,7 +1629,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // boolean onKeyMultiple(final int keyCode, final int count, final KeyEvent event); // receive ringer mode change and network state change. - private BroadcastReceiver mConnectivityAndRingerModeChangeReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mConnectivityAndRingerModeChangeReceiver = + new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { final String action = intent.getAction(); @@ -1748,8 +1747,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @UsedForTesting /* package for test */ DistracterFilter createDistracterFilter() { - return DistracterFilterUtils.createDistracterFilter( - mInputLogic.mSuggest, mKeyboardSwitcher); + return DistracterFilterUtils.createDistracterFilter(this /* Context */, mKeyboardSwitcher); } public void dumpDictionaryForDebug(final String dictName) { diff --git a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java new file mode 100644 index 000000000..9d8543183 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +public class PrevWordsInfo { + // The previous word. May be null after resetting and before starting a new composing word, or + // when there is no context like at the start of text for example. It can also be set to null + // externally when the user enters a separator that does not let bigrams across, like a period + // or a comma. + public final String mPrevWord; + + public PrevWordsInfo(final String prevWord) { + mPrevWord = prevWord; + } +} diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java index 9f61d6c37..8f744bef8 100644 --- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java @@ -50,22 +50,14 @@ public final class ReadOnlyBinaryDictionary extends Dictionary { @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { - return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight); - } - - @Override - public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId, final float[] inOutLanguageWeight) { if (mLock.readLock().tryLock()) { try { - return mBinaryDictionary.getSuggestions(composer, prevWord, proximityInfo, - blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight); + return mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, sessionId, + inOutLanguageWeight); } finally { mLock.readLock().unlock(); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index db0a8a81c..e3759a586 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -71,17 +71,17 @@ public final class Suggest { } public void getSuggestedWords(final WordComposer wordComposer, - final String prevWordForBigram, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final boolean isCorrectionEnabled, final int[] additionalFeaturesOptions, final int sessionId, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { - LatinImeLogger.onStartSuggestion(prevWordForBigram); + LatinImeLogger.onStartSuggestion(prevWordsInfo.mPrevWord); if (wordComposer.isBatchMode()) { - getSuggestedWordsForBatchInput(wordComposer, prevWordForBigram, proximityInfo, + getSuggestedWordsForBatchInput(wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId, sequenceNumber, callback); } else { - getSuggestedWordsForTypingInput(wordComposer, prevWordForBigram, proximityInfo, + getSuggestedWordsForTypingInput(wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords, isCorrectionEnabled, additionalFeaturesOptions, sequenceNumber, callback); } @@ -90,12 +90,12 @@ public final class Suggest { // Retrieves suggestions for the typing input // and calls the callback function with the suggestions. private void getSuggestedWordsForTypingInput(final WordComposer wordComposer, - final String prevWordForBigram, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final boolean isCorrectionEnabled, final int[] additionalFeaturesOptions, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { - final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); final String typedWord = wordComposer.getTypedWord(); + final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWord); final String consideredWord = trailingSingleQuotesCount > 0 ? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount) : typedWord; @@ -108,7 +108,7 @@ public final class Suggest { rawSuggestions = null; } final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer, prevWordForBigram, proximityInfo, blockOffensiveWords, + wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, SESSION_TYPING, rawSuggestions); final boolean isFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); @@ -215,7 +215,7 @@ public final class Suggest { // Retrieves suggestions for the batch input // and calls the callback function with the suggestions. private void getSuggestedWordsForBatchInput(final WordComposer wordComposer, - final String prevWordForBigram, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { @@ -226,7 +226,7 @@ public final class Suggest { rawSuggestions = null; } final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer, prevWordForBigram, proximityInfo, blockOffensiveWords, + wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId, rawSuggestions); for (SuggestedWordInfo wordInfo : suggestionResults) { LatinImeLogger.onAddSuggestedWord(wordInfo.mWord, wordInfo.mSourceDict.mDictType); diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index ac6972928..227b42bde 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -46,11 +46,9 @@ public final class WordComposer { // The list of events that served to compose this string. private final ArrayList<Event> mEvents; private final InputPointers mInputPointers = new InputPointers(MAX_WORD_LENGTH); - // The previous word (before the composing word). Used as context for suggestions. May be null - // after resetting and before starting a new composing word, or when there is no context like - // at the start of text for example. It can also be set to null externally when the user - // enters a separator that does not let bigrams across, like a period or a comma. - private String mPreviousWordForSuggestion; + // The information of previous words (before the composing word). Must not be null. Used as + // context for suggestions. + private PrevWordsInfo mPrevWordsInfo; private String mAutoCorrection; private boolean mIsResumed; private boolean mIsBatchMode; @@ -87,7 +85,7 @@ public final class WordComposer { mIsBatchMode = false; mCursorPositionWithinWord = 0; mRejectedBatchModeSuggestion = null; - mPreviousWordForSuggestion = null; + mPrevWordsInfo = new PrevWordsInfo(null); refreshTypedWordCache(); } @@ -119,7 +117,7 @@ public final class WordComposer { mIsBatchMode = false; mCursorPositionWithinWord = 0; mRejectedBatchModeSuggestion = null; - mPreviousWordForSuggestion = null; + mPrevWordsInfo = new PrevWordsInfo(null); refreshTypedWordCache(); } @@ -149,7 +147,8 @@ public final class WordComposer { public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( final int[] destination) { // lastIndex is exclusive - final int lastIndex = mTypedWordCache.length() - trailingSingleQuotesCount(); + final int lastIndex = mTypedWordCache.length() + - StringUtils.getTrailingSingleQuotesCount(mTypedWordCache); if (lastIndex <= 0) { // The string is empty or contains only single quotes. return 0; @@ -308,7 +307,7 @@ public final class WordComposer { CoordinateUtils.yFromArray(coordinates, i))); } mIsResumed = true; - mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString(); + mPrevWordsInfo = new PrevWordsInfo(null == previousWord ? null : previousWord.toString()); } /** @@ -319,8 +318,8 @@ public final class WordComposer { return mTypedWordCache.toString(); } - public String getPreviousWordForSuggestion() { - return mPreviousWordForSuggestion; + public PrevWordsInfo getPrevWordsInfoForSuggestion() { + return mPrevWordsInfo; } /** @@ -331,15 +330,6 @@ public final class WordComposer { return mIsFirstCharCapitalized; } - public int trailingSingleQuotesCount() { - final int lastIndex = mTypedWordCache.length() - 1; - int i = lastIndex; - while (i >= 0 && mTypedWordCache.charAt(i) == Constants.CODE_SINGLE_QUOTE) { - --i; - } - return lastIndex - i; - } - /** * Whether or not all of the user typed chars are upper case * @return true if all user typed chars are upper case, false otherwise @@ -387,7 +377,7 @@ public final class WordComposer { public void setCapitalizedModeAndPreviousWordAtStartComposingTime(final int mode, final CharSequence previousWord) { mCapitalizedMode = mode; - mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString(); + mPrevWordsInfo = new PrevWordsInfo(null == previousWord ? null : previousWord.toString()); } /** @@ -438,7 +428,7 @@ public final class WordComposer { mCapsCount = 0; mDigitsCount = 0; mIsBatchMode = false; - mPreviousWordForSuggestion = committedWord.toString(); + mPrevWordsInfo = new PrevWordsInfo(committedWord.toString()); mCombinerChain.reset(); mEvents.clear(); mCodePointSize = 0; @@ -456,11 +446,11 @@ public final class WordComposer { // when the user inputs a separator that's not whitespace (including the case of the // double-space-to-period feature). public void discardPreviousWordForSuggestion() { - mPreviousWordForSuggestion = null; + mPrevWordsInfo = new PrevWordsInfo(null); } public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord, - final String previousWord) { + final PrevWordsInfo prevWordsInfo) { mEvents.clear(); Collections.copy(mEvents, lastComposedWord.mEvents); mInputPointers.set(lastComposedWord.mInputPointers); @@ -471,7 +461,7 @@ public final class WordComposer { mCursorPositionWithinWord = mCodePointSize; mRejectedBatchModeSuggestion = null; mIsResumed = true; - mPreviousWordForSuggestion = previousWord; + mPrevWordsInfo = prevWordsInfo; } public boolean isBatchMode() { diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index afacd085b..6ef505e76 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -138,11 +138,13 @@ public class PersonalizationHelper { } } dictionaryMap.clear(); - if (!FileUtils.deleteFilteredFiles( - context.getFilesDir(), new DictFilter(dictNamePrefix))) { + final File filesDir = context.getFilesDir(); + if (filesDir == null) { + Log.e(TAG, "context.getFilesDir() returned null."); + } + if (!FileUtils.deleteFilteredFiles(filesDir, new DictFilter(dictNamePrefix))) { Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: " - + context.getFilesDir().getAbsolutePath() + ", dictNamePrefix: " - + dictNamePrefix); + + filesDir.getAbsolutePath() + ", dictNamePrefix: " + dictNamePrefix); } } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java index ddda52d71..e951f5a89 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java @@ -23,6 +23,7 @@ import android.view.textservice.SentenceSuggestionsInfo; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.ArrayList; @@ -57,7 +58,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck final int offset = ssi.getOffsetAt(i); final int length = ssi.getLengthAt(i); final String subText = typedText.substring(offset, offset + length); - final String prevWord = currentWord; + final PrevWordsInfo prevWordsInfo = new PrevWordsInfo(currentWord); currentWord = subText; if (!subText.contains(AndroidSpellCheckerService.SINGLE_QUOTE)) { continue; @@ -73,7 +74,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck if (TextUtils.isEmpty(splitText)) { continue; } - if (mSuggestionsCache.getSuggestionsFromCache(splitText, prevWord) == null) { + if (mSuggestionsCache.getSuggestionsFromCache(splitText, prevWordsInfo) == null) { continue; } final int newLength = splitText.length(); @@ -148,7 +149,8 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck } else { prevWord = null; } - retval[i] = onGetSuggestionsInternal(textInfos[i], prevWord, suggestionsLimit); + final PrevWordsInfo prevWordsInfo = new PrevWordsInfo(prevWord); + retval[i] = onGetSuggestionsInternal(textInfos[i], prevWordsInfo, suggestionsLimit); retval[i].setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence()); } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 69d092751..cf26000d5 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -31,6 +31,7 @@ import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer; @@ -71,26 +72,26 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { new LruCache<String, SuggestionsParams>(MAX_CACHE_SIZE); // TODO: Support n-gram input - private static String generateKey(String query, String prevWord) { - if (TextUtils.isEmpty(query) || TextUtils.isEmpty(prevWord)) { + private static String generateKey(final String query, final PrevWordsInfo prevWordsInfo) { + if (TextUtils.isEmpty(query) || TextUtils.isEmpty(prevWordsInfo.mPrevWord)) { return query; } - return query + CHAR_DELIMITER + prevWord; + return query + CHAR_DELIMITER + prevWordsInfo.mPrevWord; } - // TODO: Support n-gram input - public SuggestionsParams getSuggestionsFromCache(String query, String prevWord) { - return mUnigramSuggestionsInfoCache.get(generateKey(query, prevWord)); + public SuggestionsParams getSuggestionsFromCache(String query, + final PrevWordsInfo prevWordsInfo) { + return mUnigramSuggestionsInfoCache.get(generateKey(query, prevWordsInfo)); } - // TODO: Support n-gram input public void putSuggestionsToCache( - String query, String prevWord, String[] suggestions, int flags) { + final String query, final PrevWordsInfo prevWordsInfo, + final String[] suggestions, final int flags) { if (suggestions == null || TextUtils.isEmpty(query)) { return; } mUnigramSuggestionsInfoCache.put( - generateKey(query, prevWord), new SuggestionsParams(suggestions, flags)); + generateKey(query, prevWordsInfo), new SuggestionsParams(suggestions, flags)); } public void clearCache() { @@ -259,11 +260,12 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { } protected SuggestionsInfo onGetSuggestionsInternal( - final TextInfo textInfo, final String prevWord, final int suggestionsLimit) { + final TextInfo textInfo, final PrevWordsInfo prevWordsInfo, + final int suggestionsLimit) { try { final String inText = textInfo.getText(); final SuggestionsParams cachedSuggestionsParams = - mSuggestionsCache.getSuggestionsFromCache(inText, prevWord); + mSuggestionsCache.getSuggestionsFromCache(inText, prevWordsInfo); if (cachedSuggestionsParams != null) { if (DBG) { Log.d(TAG, "Cache hit: " + inText + ", " + cachedSuggestionsParams.mFlags); @@ -325,9 +327,9 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { composer.setComposingWord(codePoints, coordinates, null /* previousWord */); // TODO: make a spell checker option to block offensive words or not final ArrayList<SuggestedWordInfo> suggestions = - dictInfo.mDictionary.getSuggestions(composer, prevWord, + dictInfo.mDictionary.getSuggestions(composer, prevWordsInfo, dictInfo.getProximityInfo(), true /* blockOffensiveWords */, - null /* additionalFeaturesOptions */, + null /* additionalFeaturesOptions */, 0 /* sessionId */, null /* inOutLanguageWeight */); if (suggestions != null) { for (final SuggestedWordInfo suggestion : suggestions) { @@ -369,7 +371,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() : 0); final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions); - mSuggestionsCache.putSuggestionsToCache(text, prevWord, result.mSuggestions, flags); + mSuggestionsCache.putSuggestionsToCache(text, prevWordsInfo, result.mSuggestions, + flags); return retval; } catch (RuntimeException e) { // Don't kill the keyboard if there is a bug in the spell checker diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java index c99264347..ba2e0c309 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java @@ -20,6 +20,7 @@ import android.util.Log; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.utils.CollectionUtils; @@ -52,9 +53,9 @@ public final class DictionaryPool extends LinkedBlockingQueue<DictAndKeyboard> { // TODO: this dummy dictionary should be a singleton in the Dictionary class. @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { + final int sessionId, final float[] inOutLanguageWeight) { return noSuggestions; } @Override diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java index a694bf47d..75075664f 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java @@ -20,6 +20,7 @@ import android.content.Context; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.ContactsBinaryDictionary; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; @@ -36,12 +37,12 @@ public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsB @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes, - final String prevWordForBigrams, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { + final int sessionId, final float[] inOutLanguageWeight) { synchronized (mLock) { - return super.getSuggestions(codes, prevWordForBigrams, proximityInfo, - blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight); + return super.getSuggestions(codes, prevWordsInfo, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, sessionId, inOutLanguageWeight); } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java index 1a6dd5818..f2d981a9d 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin.spellcheck; import android.content.Context; import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.UserBinaryDictionary; import com.android.inputmethod.latin.WordComposer; @@ -41,12 +42,12 @@ public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDic @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes, - final String prevWordForBigrams, final ProximityInfo proximityInfo, + final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, - final float[] inOutLanguageWeight) { + final int sessionId, final float[] inOutLanguageWeight) { synchronized (mLock) { - return super.getSuggestions(codes, prevWordForBigrams, proximityInfo, - blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight); + return super.getSuggestions(codes, prevWordsInfo, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, sessionId, inOutLanguageWeight); } } diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java index 0a0379982..a21953259 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java @@ -16,8 +16,15 @@ package com.android.inputmethod.latin.utils; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import android.content.Context; +import android.util.Log; + import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; import com.android.inputmethod.latin.SuggestedWords; @@ -29,6 +36,11 @@ import com.android.inputmethod.latin.WordComposer; * or user history dictionaries */ public class DistracterFilter { + private static final String TAG = DistracterFilter.class.getSimpleName(); + + private static final long TIMEOUT_TO_WAIT_LOADING_DICTIONARIES_IN_SECONDS = 120; + + private final Context mContext; private final Suggest mSuggest; private final Keyboard mKeyboard; @@ -42,13 +54,13 @@ public class DistracterFilter { /** * Create a DistracterFilter instance. * - * @param suggest an instance of Suggest which will be used to obtain a list of suggestions - * for a potential distracter + * @param context the context. * @param keyboard the keyboard that is currently being used. This information is needed * when calling mSuggest.getSuggestedWords(...) to obtain a list of suggestions. */ - public DistracterFilter(final Suggest suggest, final Keyboard keyboard) { - mSuggest = suggest; + public DistracterFilter(final Context context, final Keyboard keyboard) { + mContext = context; + mSuggest = new Suggest(); mKeyboard = keyboard; } @@ -66,29 +78,48 @@ public class DistracterFilter { return false; } + private void loadDictionariesForLocale(final Locale newlocale) throws InterruptedException { + mSuggest.mDictionaryFacilitator.resetDictionaries(mContext, newlocale, + false /* useContactsDict */, false /* usePersonalizedDicts */, + false /* forceReloadMainDictionary */, null /* listener */); + mSuggest.mDictionaryFacilitator.waitForLoadingMainDictionary( + TIMEOUT_TO_WAIT_LOADING_DICTIONARIES_IN_SECONDS, TimeUnit.SECONDS); + } + /** * Determine whether a word is a distracter to words in dictionaries. * - * @param prevWord the previous word, or null if none. + * @param prevWordsInfo the information of previous words. * @param testedWord the word that will be tested to see whether it is a distracter to words * in dictionaries. + * @param locale the locale of words. * @return true if testedWord is a distracter, otherwise false. */ - public boolean isDistracterToWordsInDictionaries(final String prevWord, - final String testedWord) { - if (mSuggest == null || mKeyboard == null) { + public boolean isDistracterToWordsInDictionaries(final PrevWordsInfo prevWordsInfo, + final String testedWord, final Locale locale) { + if (mKeyboard == null || locale == null) { return false; } + if (!locale.equals(mSuggest.mDictionaryFacilitator.getLocale())) { + // Reset dictionaries for the locale. + try { + loadDictionariesForLocale(locale); + } catch (final InterruptedException e) { + Log.e(TAG, "Interrupted while waiting for loading dicts in DistracterFilter", e); + return false; + } + } final WordComposer composer = new WordComposer(); final int[] codePoints = StringUtils.toCodePointArray(testedWord); final int[] coordinates; coordinates = mKeyboard.getCoordinates(codePoints); - composer.setComposingWord(codePoints, coordinates, prevWord); + composer.setComposingWord(codePoints, coordinates, prevWordsInfo.mPrevWord); - final int trailingSingleQuotesCount = composer.trailingSingleQuotesCount(); - final String consideredWord = trailingSingleQuotesCount > 0 ? testedWord.substring(0, - testedWord.length() - trailingSingleQuotesCount) : testedWord; + final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(testedWord); + final String consideredWord = trailingSingleQuotesCount > 0 ? + testedWord.substring(0, testedWord.length() - trailingSingleQuotesCount) : + testedWord; final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() { @Override @@ -103,7 +134,7 @@ public class DistracterFilter { } } }; - mSuggest.getSuggestedWords(composer, prevWord, mKeyboard.getProximityInfo(), + mSuggest.getSuggestedWords(composer, prevWordsInfo, mKeyboard.getProximityInfo(), true /* blockOffensiveWords */, true /* isCorrectionEnbaled */, null /* additionalFeaturesOptions */, 0 /* sessionId */, SuggestedWords.NOT_A_SEQUENCE_NUMBER, callback); diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java index df07f976c..8a711a24e 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUtils.java @@ -16,17 +16,18 @@ package com.android.inputmethod.latin.utils; +import android.content.Context; + import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.MainKeyboardView; -import com.android.inputmethod.latin.Suggest; public class DistracterFilterUtils { private DistracterFilterUtils() { // This utility class is not publicly instantiable. } - public static final DistracterFilter createDistracterFilter(final Suggest suggest, + public static final DistracterFilter createDistracterFilter(final Context context, final KeyboardSwitcher keyboardSwitcher) { final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView(); // TODO: Create Keyboard when mainKeyboardView is null. @@ -34,7 +35,7 @@ public class DistracterFilterUtils { // spellchecker's logic. final Keyboard keyboard = (mainKeyboardView != null) ? mainKeyboardView.getKeyboard() : null; - final DistracterFilter distracterFilter = new DistracterFilter(suggest, keyboard); + final DistracterFilter distracterFilter = new DistracterFilter(context, keyboard); return distracterFilter; } } diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java index 74e7db901..aaf4a4064 100644 --- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java +++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java @@ -20,6 +20,7 @@ import android.util.Log; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryFacilitatorForSuggest; +import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import java.util.ArrayList; @@ -85,7 +86,7 @@ public final class LanguageModelParam { final ArrayList<LanguageModelParam> languageModelParams = CollectionUtils.newArrayList(); final int N = tokens.size(); - String prevWord = null; + PrevWordsInfo prevWordsInfo = new PrevWordsInfo(null); for (int i = 0; i < N; ++i) { final String tempWord = tokens.get(i); if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) { @@ -102,7 +103,7 @@ public final class LanguageModelParam { + tempWord + "\""); } // Sentence terminator found. Split. - prevWord = null; + prevWordsInfo = new PrevWordsInfo(null); continue; } if (DEBUG_TOKEN) { @@ -110,19 +111,19 @@ public final class LanguageModelParam { } final LanguageModelParam languageModelParam = detectWhetherVaildWordOrNotAndGetLanguageModelParam( - prevWord, tempWord, timestamp, dictionaryFacilitator, + prevWordsInfo, tempWord, timestamp, dictionaryFacilitator, distracterFilter); if (languageModelParam == null) { continue; } languageModelParams.add(languageModelParam); - prevWord = languageModelParam.mTargetWord; + prevWordsInfo = new PrevWordsInfo(languageModelParam.mTargetWord); } return languageModelParams; } private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam( - final String prevWord, final String targetWord, final int timestamp, + final PrevWordsInfo prevWordsInfo, final String targetWord, final int timestamp, final DictionaryFacilitatorForSuggest dictionaryFacilitator, final DistracterFilter distracterFilter) { final Locale locale = dictionaryFacilitator.getLocale(); @@ -133,14 +134,14 @@ public final class LanguageModelParam { // distracterFilter in the following code. If targetWord is a distracter, // it should be filtered out. if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) { - return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp, + return createAndGetLanguageModelParamOfWord(prevWordsInfo, targetWord, timestamp, true /* isValidWord */, locale); } final String lowerCaseTargetWord = targetWord.toLowerCase(locale); if (dictionaryFacilitator.isValidWord(lowerCaseTargetWord, false /* ignoreCase */)) { // Add the lower-cased word. - return createAndGetLanguageModelParamOfWord(prevWord, lowerCaseTargetWord, + return createAndGetLanguageModelParamOfWord(prevWordsInfo, lowerCaseTargetWord, timestamp, true /* isValidWord */, locale); } @@ -150,26 +151,26 @@ public final class LanguageModelParam { // Adding such a word to dictonaries would interfere with entering in-dictionary words. For // example, adding "mot" to dictionaries might interfere with entering "not". // This kind of OOV should be filtered out. - if (distracterFilter.isDistracterToWordsInDictionaries(prevWord, targetWord)) { + if (distracterFilter.isDistracterToWordsInDictionaries(prevWordsInfo, targetWord, locale)) { return null; } - return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp, + return createAndGetLanguageModelParamOfWord(prevWordsInfo, targetWord, timestamp, false /* isValidWord */, locale); } private static LanguageModelParam createAndGetLanguageModelParamOfWord( - final String prevWord, final String targetWord, final int timestamp, + final PrevWordsInfo prevWordsInfo, final String targetWord, final int timestamp, final boolean isValidWord, final Locale locale) { final String word; if (StringUtils.getCapitalizationType(targetWord) == StringUtils.CAPITALIZE_FIRST - && prevWord == null && !isValidWord) { + && prevWordsInfo.mPrevWord == null && !isValidWord) { word = targetWord.toLowerCase(locale); } else { word = targetWord; } final int unigramProbability = isValidWord ? UNIGRAM_PROBABILITY_FOR_VALID_WORD : UNIGRAM_PROBABILITY_FOR_OOV_WORD; - if (prevWord == null) { + if (prevWordsInfo.mPrevWord == null) { if (DEBUG) { Log.d(TAG, "--- add unigram: current(" + (isValidWord ? "Valid" : "OOV") + ") = " + word); @@ -177,12 +178,12 @@ public final class LanguageModelParam { return new LanguageModelParam(word, unigramProbability, timestamp); } if (DEBUG) { - Log.d(TAG, "--- add bigram: prev = " + prevWord + ", current(" + Log.d(TAG, "--- add bigram: prev = " + prevWordsInfo.mPrevWord + ", current(" + (isValidWord ? "Valid" : "OOV") + ") = " + word); } final int bigramProbability = isValidWord ? BIGRAM_PROBABILITY_FOR_VALID_WORD : BIGRAM_PROBABILITY_FOR_OOV_WORD; - return new LanguageModelParam(prevWord, word, unigramProbability, + return new LanguageModelParam(prevWordsInfo.mPrevWord, word, unigramProbability, bigramProbability, timestamp); } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index 374badc19..73ac9a573 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -538,6 +538,15 @@ public final class StringUtils { ? casedText.codePointAt(0) : CODE_UNSPECIFIED; } + public static int getTrailingSingleQuotesCount(final CharSequence charSequence) { + final int lastIndex = charSequence.length() - 1; + int i = lastIndex; + while (i >= 0 && charSequence.charAt(i) == Constants.CODE_SINGLE_QUOTE) { + --i; + } + return lastIndex - i; + } + @UsedForTesting public static class Stringizer<E> { public String stringize(final E element) { |