Merge "Update AOSP dictionaries." into jb-mr1-dev
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 5eb0f08..4388a27 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -24,7 +24,7 @@
     <string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
     <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string>
-    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya wasiliani"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya unaowasiliana nao"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e99e956..38025e8 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -389,7 +389,7 @@
         }
     }
 
-    public int getManualCapsMode() {
+    public int getKeyboardShiftMode() {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
             return WordComposer.CAPS_MODE_OFF;
@@ -400,6 +400,8 @@
             return WordComposer.CAPS_MODE_MANUAL_SHIFT_LOCKED;
         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
             return WordComposer.CAPS_MODE_MANUAL_SHIFTED;
+        case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+            return WordComposer.CAPS_MODE_AUTO_SHIFTED;
         default:
             return WordComposer.CAPS_MODE_OFF;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index b39f2ba..472f74b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -105,7 +105,7 @@
     private static final String TAG = KeyboardView.class.getSimpleName();
 
     // XML attributes
-    private final KeyVisualAttributes mKeyVisualAttributes;
+    protected final KeyVisualAttributes mKeyVisualAttributes;
     private final int mKeyLabelHorizontalPadding;
     private final float mKeyHintLetterPadding;
     private final float mKeyPopupHintLetterPadding;
@@ -733,6 +733,7 @@
         return width;
     }
 
+    // TODO: Remove this method.
     public float getLabelWidth(final String label, final Paint paint) {
         paint.getTextBounds(label, 0, label.length(), mTextBounds);
         return mTextBounds.width();
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index ccf6932..d0f7cb2 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -180,8 +180,9 @@
 
     static final class BogusMoveEventDetector {
         // Move these thresholds to resource.
-        private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.70f; // in keyWidth
-        private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.50f; // in keyWidth
+        // These thresholds' unit is a diagonal length of a key.
+        private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.53f;
+        private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.14f;
 
         private int mAccumulatedDistanceThreshold;
         private int mRadiusThreshold;
@@ -191,10 +192,11 @@
         private int mActualDownX;
         private int mActualDownY;
 
-        public void setKeyboardGeometry(final int keyWidth) {
+        public void setKeyboardGeometry(final int keyWidth, final int keyHeight) {
+            final float keyDiagonal = (float)Math.hypot(keyWidth, keyHeight);
             mAccumulatedDistanceThreshold = (int)(
-                    keyWidth * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD);
-            mRadiusThreshold = (int)(keyWidth * BOGUS_MOVE_RADIUS_THRESHOLD);
+                    keyDiagonal * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD);
+            mRadiusThreshold = (int)(keyDiagonal * BOGUS_MOVE_RADIUS_THRESHOLD);
         }
 
         public void onActualDownEvent(final int x, final int y) {
@@ -210,8 +212,12 @@
             mAccumulatedDistanceFromDownKey += distance;
         }
 
-        public boolean hasTraveledLongDistance() {
-            return mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold;
+        public boolean hasTraveledLongDistance(final int x, final int y) {
+            final int dx = Math.abs(x - mActualDownX);
+            final int dy = Math.abs(y - mActualDownY);
+            // A bogus move event should be a horizontal movement. A vertical movement might be
+            // a sloppy typing and should be ignored.
+            return dx >= dy && mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold;
         }
 
         /* package */ int getDistanceFromDownEvent(final int x, final int y) {
@@ -514,7 +520,9 @@
         }
         mKeyDetector = keyDetector;
         mKeyboard = keyDetector.getKeyboard();
-        mGestureStrokeWithPreviewPoints.setKeyboardGeometry(mKeyboard.mMostCommonKeyWidth);
+        final int keyWidth = mKeyboard.mMostCommonKeyWidth;
+        final int keyHeight = mKeyboard.mMostCommonKeyHeight;
+        mGestureStrokeWithPreviewPoints.setKeyboardGeometry(keyWidth);
         final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
         if (newKey != mCurrentKey) {
             if (mDrawingProxy != null) {
@@ -522,9 +530,8 @@
             }
             // Keep {@link #mCurrentKey} that comes from previous keyboard.
         }
-        final int keyWidth = mKeyboard.mMostCommonKeyWidth;
         mPhantonSuddenMoveThreshold = (int)(keyWidth * PHANTOM_SUDDEN_MOVE_THRESHOLD);
-        mBogusMoveEventDetector.setKeyboardGeometry(keyWidth);
+        mBogusMoveEventDetector.setKeyboardGeometry(keyWidth, keyHeight);
     }
 
     @Override
@@ -962,11 +969,13 @@
                             && sTimeRecorder.isInFastTyping(eventTime)
                             && mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) {
                         if (DEBUG_MODE) {
+                            final float keyDiagonal = (float)Math.hypot(
+                                    mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight);
                             final float radiusRatio =
-                                    (float)mBogusMoveEventDetector.getDistanceFromDownEvent(x, y)
-                                    / mKeyboard.mMostCommonKeyWidth;
+                                    mBogusMoveEventDetector.getDistanceFromDownEvent(x, y)
+                                    / keyDiagonal;
                             Log.w(TAG, String.format("[%d] onMoveEvent:"
-                                    + " bogus down-move-up event (raidus=%.2f keyWidth) is "
+                                    + " bogus down-move-up event (raidus=%.2f key diagonal) is "
                                     + " translated to up[%d,%d,%s]/down[%d,%d,%s] events",
                                     mPointerId, radiusRatio,
                                     lastX, lastY, Keyboard.printableCode(oldKey.mCode),
@@ -1146,24 +1155,24 @@
             final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y);
             if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) {
                 if (DEBUG_MODE) {
-                    final int keyWidth = mKeyboard.mMostCommonKeyWidth;
-                    final float distanceToEdgeRatio = (float)distanceFromKeyEdgeSquared
-                            / (keyWidth * keyWidth);
+                    final float distanceToEdgeRatio = (float)Math.sqrt(distanceFromKeyEdgeSquared)
+                            / mKeyboard.mMostCommonKeyWidth;
                     Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
-                            +" %.2f keyWidth from key edge",
+                            +" %.2f key width from key edge",
                             mPointerId, distanceToEdgeRatio));
                 }
                 return true;
             }
             if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput
                     && sTimeRecorder.isInFastTyping(eventTime)
-                    && mBogusMoveEventDetector.hasTraveledLongDistance()) {
+                    && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) {
                 if (DEBUG_MODE) {
+                    final float keyDiagonal = (float)Math.hypot(
+                            mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight);
                     final float lengthFromDownRatio =
-                            (float)mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey
-                            / mKeyboard.mMostCommonKeyWidth;
+                            mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey / keyDiagonal;
                     Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
-                            + " %.2f keyWidth from virtual down point",
+                            + " %.2f key diagonal from virtual down point",
                             mPointerId, lengthFromDownRatio));
                 }
                 return true;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d98966e..c1b1751 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1119,8 +1119,8 @@
 
     // Factor in auto-caps and manual caps and compute the current caps mode.
     private int getActualCapsMode() {
-        final int manual = mKeyboardSwitcher.getManualCapsMode();
-        if (manual != WordComposer.CAPS_MODE_OFF) return manual;
+        final int keyboardShiftMode = mKeyboardSwitcher.getKeyboardShiftMode();
+        if (keyboardShiftMode != WordComposer.CAPS_MODE_AUTO_SHIFTED) return keyboardShiftMode;
         final int auto = getCurrentAutoCapsState();
         if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) {
             return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED;
@@ -1429,6 +1429,12 @@
             // The following is necessary for the case where the user typed something but didn't
             // manual pick it and didn't input any separator.
             mSpaceState = SPACE_STATE_PHANTOM;
+        } else {
+            final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+            if (Constants.NOT_A_CODE != codePointBeforeCursor
+                    && !Character.isWhitespace(codePointBeforeCursor)) {
+                mSpaceState = SPACE_STATE_PHANTOM;
+            }
         }
         mConnection.endBatchEdit();
         mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode());
@@ -1564,6 +1570,7 @@
         // We have a TLD (or something that looks like this): make sure we don't add
         // a space even if currently in phantom mode.
         mSpaceState = SPACE_STATE_NONE;
+        // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code
         final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0);
         if (lastOne != null && lastOne.length() == 1
                 && lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
@@ -2284,6 +2291,7 @@
             // This is a stopgap solution to avoid leaving a high surrogate alone in a text view.
             // In the future, we need to deprecate deteleSurroundingText() and have a surrogate
             // pair-friendly way of deleting characters in InputConnection.
+            // TODO: use getCodePointBeforeCursor instead to improve performance
             final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0);
             if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
                 mConnection.deleteSurroundingText(1, 0);
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index b27db57..2144136 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -235,7 +235,14 @@
                 hasSpaceBefore);
     }
 
+    public int getCodePointBeforeCursor() {
+        if (mCommittedTextBeforeComposingText.length() < 1) return Constants.NOT_A_CODE;
+        return Character.codePointBefore(mCommittedTextBeforeComposingText,
+                mCommittedTextBeforeComposingText.length());
+    }
+
     public CharSequence getTextBeforeCursor(final int i, final int j) {
+        // TODO: use mCommittedTextBeforeComposingText if possible to improve performance
         mIC = mParent.getCurrentInputConnection();
         if (null != mIC) return mIC.getTextBeforeCursor(i, j);
         return null;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index e9bf0fa..4e9fd19 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -51,10 +51,11 @@
             super();
         }
 
+        // TODO: Remove {@link MoreSuggestionsView} argument.
         public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth,
                 final int minWidth, final int maxRow, final MoreSuggestionsView view) {
             clearKeys();
-            final Resources res = view.getContext().getResources();
+            final Resources res = view.getResources();
             mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
             mDividerWidth = mDivider.getIntrinsicWidth();
             final int padding = (int) res.getDimension(
@@ -181,6 +182,7 @@
             load(xmlId, keyboard.mId);
             mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
 
+            mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
             final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
                     mPaneView);
             mFromPos = fromPos;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 9b9a354..03a2e73 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -105,6 +105,10 @@
         }
     }
 
+    public void updateKeyboardGeometry(final int keyHeight) {
+        mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
+    }
+
     @Override
     public void setKeyboard(Keyboard keyboard) {
         super.setKeyboard(keyboard);
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 49d044f..e3649bd 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -798,7 +798,8 @@
             // into inputIndex if there is a match.
             const bool isAlike = testCharGroupForContinuedLikeness(flags, root, pos, inWord,
                     inputIndex, inputSize, newWord, &inputIndex, &pos);
-            if (isAlike && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) {
+            if (isAlike && (!(BinaryFormat::FLAG_IS_NOT_A_WORD & flags))
+                    && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) {
                 const int frequency = BinaryFormat::readFrequencyWithoutMovingPointer(root, pos);
                 onTerminalWordLike(frequency, newWord, inputIndex, outWord, &maxFreq);
             }