Merge "Actually add shortcut-only entries."
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 54d842f..df61689 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -225,12 +225,13 @@
             keyboard.setAutomaticTemporaryUpperCase();
         } else {
             final boolean shifted = (shiftMode == MANUAL_SHIFT);
+            // TODO: Remove duplicated logic in KeyboardState#setShifted
             // On non-distinct multi touch panel device, we should also turn off the shift locked
             // state when shift key is pressed to go to normal mode.
             // On the other hand, on distinct multi touch panel device, turning off the shift
             // locked state with shift key pressing is handled by onReleaseShift().
             if (!hasDistinctMultitouch() && !shifted && mState.isShiftLocked()) {
-                keyboard.setShiftLocked(false);
+                setShiftLocked(false);
             }
             keyboard.setShifted(shifted);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 42f069c..609593e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -166,21 +166,29 @@
         if (DEBUG_STATE) {
             Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode));
         }
+        // TODO: Remove this hack in conjunction with duplicated logic below.
+        boolean needsToTurnOffShiftLockedLater = false;
         if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) {
             mKeyboardShiftState.setAutomaticTemporaryUpperCase();
         } else {
-            // TODO: Duplicated logic in KeyboardSwitcher#setShifted()
+            // TODO: Remove duplicated logic in KeyboardSwitcher#setShifted()
             final boolean shifted = (shiftMode == SwitchActions.MANUAL_SHIFT);
             // On non-distinct multi touch panel device, we should also turn off the shift locked
             // state when shift key is pressed to go to normal mode.
             // On the other hand, on distinct multi touch panel device, turning off the shift
             // locked state with shift key pressing is handled by onReleaseShift().
             if (!mHasDistinctMultitouch && !shifted && mKeyboardShiftState.isShiftLocked()) {
-                mKeyboardShiftState.setShiftLocked(false);
+                // Setting shift lock state should be delayed after
+                // mSwitchActions.setShifted(shiftMode) is called, because in that call the state
+                // is referenced.
+                needsToTurnOffShiftLockedLater = true;
             }
             mKeyboardShiftState.setShifted(shifted);
         }
         mSwitchActions.setShifted(shiftMode);
+        if (needsToTurnOffShiftLockedLater) {
+            mKeyboardShiftState.setShiftLocked(false);
+        }
     }
 
     private void setShiftLocked(boolean shiftLocked) {
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index 43ab3f5..75831b6 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -168,8 +168,8 @@
     const int outputIndex = mTerminalOutputIndex;
     const int inputIndex = mTerminalInputIndex;
     *wordLength = outputIndex + 1;
-    if (mProximityInfo->sameAsTyped(mWord, outputIndex + 1) || outputIndex < MIN_SUGGEST_DEPTH) {
-        return -1;
+    if (outputIndex < MIN_SUGGEST_DEPTH) {
+        return NOT_A_FREQUENCY;
     }
 
     *word = mWord;
diff --git a/native/src/defines.h b/native/src/defines.h
index 48f92d8..ce3f85a 100644
--- a/native/src/defines.h
+++ b/native/src/defines.h
@@ -172,6 +172,7 @@
 #define EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO -2
 #define PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO -3
 #define NOT_A_INDEX -1
+#define NOT_A_FREQUENCY -1
 
 #define KEYCODE_SPACE ' '
 
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 85e7e9b..69e3200 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -335,7 +335,7 @@
     int wordLength;
     unsigned short* wordPointer;
     const int finalFreq = correction->getFinalFreq(freq, &wordPointer, &wordLength);
-    if (finalFreq >= 0) {
+    if (finalFreq != NOT_A_FREQUENCY) {
         if (!terminalAttributes.isShortcutOnly()) {
             if (addToMasterQueue) {
                 addWord(wordPointer, wordLength, finalFreq, masterQueue);
diff --git a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
index b47b025..918b1ca 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
@@ -647,7 +647,8 @@
                     }
                     if (currentGroup.mFrequency >= 0)
                         return new Word(mCurrentString.toString(), currentGroup.mFrequency,
-                                currentGroup.mShortcutTargets, currentGroup.mBigrams);
+                                currentGroup.mShortcutTargets, currentGroup.mBigrams,
+                                currentGroup.mIsShortcutOnly);
                 } else {
                     mPositions.removeLast();
                     currentPos = mPositions.getLast();
diff --git a/tools/makedict/src/com/android/inputmethod/latin/Word.java b/tools/makedict/src/com/android/inputmethod/latin/Word.java
index 561b21b..cf6116f 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/Word.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/Word.java
@@ -28,16 +28,18 @@
 public class Word implements Comparable<Word> {
     final String mWord;
     final int mFrequency;
+    final boolean mIsShortcutOnly;
     final ArrayList<WeightedString> mShortcutTargets;
     final ArrayList<WeightedString> mBigrams;
 
     public Word(final String word, final int frequency,
             final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams) {
+            final ArrayList<WeightedString> bigrams, final boolean isShortcutOnly) {
         mWord = word;
         mFrequency = frequency;
         mShortcutTargets = shortcutTargets;
         mBigrams = bigrams;
+        mIsShortcutOnly = isShortcutOnly;
     }
 
     /**
diff --git a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
index 58e7f29..77c5366 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
@@ -45,6 +45,7 @@
     private static final String SHORTCUT_TAG = "shortcut";
     private static final String FREQUENCY_ATTR = "f";
     private static final String WORD_ATTR = "word";
+    private static final String SHORTCUT_ONLY_ATTR = "shortcutOnly";
 
     private static final int SHORTCUT_ONLY_DEFAULT_FREQ = 1;
 
@@ -275,9 +276,11 @@
         }
         // TODO: use an XMLSerializer if this gets big
         destination.write("<wordlist format=\"2\">\n");
+        destination.write("<!-- Warning: there is no code to read this format yet. -->\n");
         for (Word word : set) {
             destination.write("  <" + WORD_TAG + " " + WORD_ATTR + "=\"" + word.mWord + "\" "
-                    + FREQUENCY_ATTR + "=\"" + word.mFrequency + "\">");
+                    + FREQUENCY_ATTR + "=\"" + word.mFrequency + "\" " + SHORTCUT_ONLY_ATTR
+                    + "=\"" + word.mIsShortcutOnly + "\">");
             if (null != word.mShortcutTargets) {
                 destination.write("\n");
                 for (WeightedString target : word.mShortcutTargets) {