Merge "Try to compensate for a race condition."
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index ff0458c..a66caa7 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -57,7 +57,7 @@
     <dimen name="mini_keyboard_vertical_correction">-0.330in</dimen>
     <!-- We use "inch", not "dip" because this value tries dealing with physical distance related
          to user's finger. -->
-    <dimen name="keyboard_vertical_correction">-0.05in</dimen>
+    <dimen name="keyboard_vertical_correction">0.0in</dimen>
 
     <fraction name="key_letter_ratio">55%</fraction>
     <fraction name="key_large_letter_ratio">65%</fraction>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index a70c795..b6adf63 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -41,7 +41,7 @@
     <!-- Label for "switch to phone numeric" key.  Must be short to fit on key! -->
     <string name="label_to_phone_numeric_key">123</string>
     <!-- Label for "switch to phone symbols" key.  Must be short to fit on key! -->
-    <string name="label_to_phone_symbols_key">\uff0a\uff03\uff08</string>
+    <string name="label_to_phone_symbols_key">\uff0a\uff03</string>
 
     <!-- Character for candidate divider (BOX DRAWINGS LIGHT VERTICAL) -->
     <string name="label_candidate_divider">\u2502</string>
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 221c1e3..5c4bf52 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -82,6 +82,19 @@
     <!-- Return key style -->
     <switch>
         <case
+            latin:mode="im"
+        >
+            <!-- Smiley key. -->
+            <key-style
+                latin:styleName="returnKeyStyle"
+                latin:keyLabel=":-)"
+                latin:keyOutputText=":-) "
+                latin:keyLabelOption="hasPopupHint"
+                latin:popupCharacters="@string/alternates_for_smiley"
+                latin:maxPopupKeyboardColumn="5"
+                latin:parentStyle="functionalKeyStyle" />
+        </case>
+        <case
             latin:imeAction="actionGo"
         >
             <key-style
@@ -139,14 +152,6 @@
         latin:code="@integer/key_space"
         latin:parentStyle="functionalKeyStyle" />
     <key-style
-        latin:styleName="smileyKeyStyle"
-        latin:keyLabel=":-)"
-        latin:keyOutputText=":-) "
-        latin:keyLabelOption="hasPopupHint"
-        latin:popupCharacters="@string/alternates_for_smiley"
-        latin:maxPopupKeyboardColumn="5"
-        latin:parentStyle="functionalKeyStyle" />
-    <key-style
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml
index 739cbc0..eb1e9b8 100644
--- a/java/res/xml/kbd_qwerty_row4.xml
+++ b/java/res/xml/kbd_qwerty_row4.xml
@@ -39,6 +39,9 @@
                     latin:keyWidth="50%p" />
                 <Key
                     latin:keyStyle="punctuationKeyStyle" />
+                <Key
+                    latin:keyStyle="returnKeyStyle"
+                    latin:keyWidth="fillRight" />
             </case>
             <!-- hasSettingsKey="true" or navigateAction="true" -->
             <default>
@@ -55,17 +58,6 @@
                 <Key
                     latin:keyStyle="punctuationKeyStyle"
                     latin:keyWidth="9.2%p" />
-            </default>
-        </switch>
-        <switch>
-            <case
-                latin:mode="im"
-            >
-                <Key
-                    latin:keyStyle="smileyKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </case>
-            <default>
                 <Key
                     latin:keyStyle="returnKeyStyle"
                     latin:keyWidth="fillRight" />
diff --git a/java/res/xml/kbd_symbols_row4.xml b/java/res/xml/kbd_symbols_row4.xml
index 534d183..864cf2b 100644
--- a/java/res/xml/kbd_symbols_row4.xml
+++ b/java/res/xml/kbd_symbols_row4.xml
@@ -39,6 +39,9 @@
                     latin:keyWidth="50%p" />
                 <Key
                     latin:keyStyle="punctuationKeyStyle" />
+                <Key
+                    latin:keyStyle="returnKeyStyle"
+                    latin:keyWidth="fillRight" />
             </case>
             <!-- hasSettingsKey="true" or navigateAction="true" -->
             <default>
@@ -55,17 +58,6 @@
                 <Key
                     latin:keyStyle="punctuationKeyStyle"
                     latin:keyWidth="9.2%p" />
-            </default>
-        </switch>
-        <switch>
-            <case
-                latin:mode="im"
-            >
-                <Key
-                    latin:keyStyle="smileyKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </case>
-            <default>
                 <Key
                     latin:keyStyle="returnKeyStyle"
                     latin:keyWidth="fillRight" />
diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml
index 11c2b00..9cb453f 100644
--- a/java/res/xml/kbd_symbols_shift_row4.xml
+++ b/java/res/xml/kbd_symbols_shift_row4.xml
@@ -42,6 +42,9 @@
                 <Key
                     latin:keyLabel="…"
                     latin:keyStyle="nonPasswordFunctionalKeyStyle" />
+                <Key
+                    latin:keyStyle="returnKeyStyle"
+                    latin:keyWidth="fillRight" />
             </case>
             <!-- hasSettingsKey="true" or navigateAction="true" -->
             <default>
@@ -62,17 +65,6 @@
                     latin:keyLabel="…"
                     latin:keyWidth="9.2%p"
                     latin:keyStyle="nonPasswordFunctionalKeyStyle" />
-            </default>
-        </switch>
-        <switch>
-            <case
-                latin:mode="im"
-            >
-                <Key
-                    latin:keyStyle="smileyKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </case>
-            <default>
                 <Key
                     latin:keyStyle="returnKeyStyle"
                     latin:keyWidth="fillRight" />
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 68868f1..5b34dd5 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -33,7 +33,6 @@
 import com.android.inputmethod.keyboard.internal.Row;
 import com.android.inputmethod.latin.R;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -292,13 +291,18 @@
             mY = y;
             mWidth = keyWidth - mGap;
 
-            final CharSequence[] popupCharacters = style.getTextArray(keyAttr,
-                    R.styleable.Keyboard_Key_popupCharacters);
+            CharSequence[] popupCharacters = style.getTextArray(
+                    keyAttr, R.styleable.Keyboard_Key_popupCharacters);
+            if (mKeyboard.mId.mPasswordInput) {
+                popupCharacters = PopupCharactersParser.filterOut(
+                        res, popupCharacters, PopupCharactersParser.NON_ASCII_FILTER);
+            }
             // In Arabic symbol layouts, we'd like to keep digits in popup characters regardless of
             // config_digit_popup_characters_enabled.
             if (mKeyboard.mId.isAlphabetKeyboard() && !res.getBoolean(
                     R.bool.config_digit_popup_characters_enabled)) {
-                mPopupCharacters = filterOutDigitPopupCharacters(popupCharacters);
+                mPopupCharacters = PopupCharactersParser.filterOut(
+                        res, popupCharacters, PopupCharactersParser.DIGIT_FILTER);
             } else {
                 mPopupCharacters = popupCharacters;
             }
@@ -402,36 +406,6 @@
         return (mLabelOption & LABEL_OPTION_HAS_HINT_LABEL) != 0;
     }
 
-    private static boolean isDigitPopupCharacter(CharSequence label) {
-        return label != null && label.length() == 1 && Character.isDigit(label.charAt(0));
-    }
-
-    private static CharSequence[] filterOutDigitPopupCharacters(CharSequence[] popupCharacters) {
-        if (popupCharacters == null || popupCharacters.length < 1)
-            return null;
-        if (popupCharacters.length == 1 && isDigitPopupCharacter(
-                PopupCharactersParser.getLabel(popupCharacters[0].toString())))
-            return null;
-        ArrayList<CharSequence> filtered = null;
-        for (int i = 0; i < popupCharacters.length; i++) {
-            final CharSequence popupSpec = popupCharacters[i];
-            if (isDigitPopupCharacter(PopupCharactersParser.getLabel(popupSpec.toString()))) {
-                if (filtered == null) {
-                    filtered = new ArrayList<CharSequence>();
-                    for (int j = 0; j < i; j++)
-                        filtered.add(popupCharacters[j]);
-                }
-            } else if (filtered != null) {
-                filtered.add(popupSpec);
-            }
-        }
-        if (filtered == null)
-            return popupCharacters;
-        if (filtered.size() == 0)
-            return null;
-        return filtered.toArray(new CharSequence[filtered.size()]);
-    }
-
     public Drawable getIcon() {
         return mIcon;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java b/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
index 8276f5d..032489e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
@@ -23,6 +23,8 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.latin.R;
 
+import java.util.ArrayList;
+
 /**
  * String parser of popupCharacters attribute of Key.
  * The string is comma separated texts each of which represents one popup key.
@@ -182,4 +184,54 @@
             super(message);
         }
     }
+
+    public interface CodeFilter {
+        public boolean shouldFilterOut(int code);
+    }
+
+    public static final CodeFilter DIGIT_FILTER = new CodeFilter() {
+        @Override
+        public boolean shouldFilterOut(int code) {
+            return Character.isDigit(code);
+        }
+    };
+
+    public static final CodeFilter NON_ASCII_FILTER = new CodeFilter() {
+        @Override
+        public boolean shouldFilterOut(int code) {
+            return code < 0x20 || code > 0x7e;
+        }
+    };
+
+    public static CharSequence[] filterOut(Resources res, CharSequence[] popupCharacters,
+            CodeFilter filter) {
+        if (popupCharacters == null || popupCharacters.length < 1) {
+            return null;
+        }
+        if (popupCharacters.length == 1
+                && filter.shouldFilterOut(getCode(res, popupCharacters[0].toString()))) {
+            return null;
+        }
+        ArrayList<CharSequence> filtered = null;
+        for (int i = 0; i < popupCharacters.length; i++) {
+            final CharSequence popupSpec = popupCharacters[i];
+            if (filter.shouldFilterOut(getCode(res, popupSpec.toString()))) {
+                if (filtered == null) {
+                    filtered = new ArrayList<CharSequence>();
+                    for (int j = 0; j < i; j++) {
+                        filtered.add(popupCharacters[j]);
+                    }
+                }
+            } else if (filtered != null) {
+                filtered.add(popupSpec);
+            }
+        }
+        if (filtered == null) {
+            return popupCharacters;
+        }
+        if (filtered.size() == 0) {
+            return null;
+        }
+        return filtered.toArray(new CharSequence[filtered.size()]);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6348018..bdcbfbc 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -557,7 +557,7 @@
         // If orientation changed while predicting, commit the change
         if (conf.orientation != mDisplayOrientation) {
             mHandler.startOrientationChanging(mDisplayWidth, mDisplayHeight);
-            InputConnection ic = getCurrentInputConnection();
+            final InputConnection ic = getCurrentInputConnection();
             commitTyped(ic);
             if (ic != null) ic.finishComposingText(); // For voice input
             if (isShowingOptionDialog())
@@ -1013,7 +1013,7 @@
                         event.getAction(), event.getKeyCode(), event.getRepeatCount(),
                         event.getDeviceId(), event.getScanCode(),
                         KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
-                InputConnection ic = getCurrentInputConnection();
+                final InputConnection ic = getCurrentInputConnection();
                 if (ic != null)
                     ic.sendKeyEvent(newEvent);
                 return true;
@@ -1023,12 +1023,12 @@
         return super.onKeyUp(keyCode, event);
     }
 
-    public void commitTyped(InputConnection inputConnection) {
+    public void commitTyped(final InputConnection ic) {
         if (!mHasUncommittedTypedChars) return;
         mHasUncommittedTypedChars = false;
         if (mComposingStringBuilder.length() > 0) {
-            if (inputConnection != null) {
-                inputConnection.commitText(mComposingStringBuilder, 1);
+            if (ic != null) {
+                ic.commitText(mComposingStringBuilder, 1);
             }
             mCommittedLength = mComposingStringBuilder.length();
             TextEntryState.acceptedTyped(mComposingStringBuilder);
@@ -1039,7 +1039,7 @@
     }
 
     public boolean getCurrentAutoCapsState() {
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         EditorInfo ei = getCurrentInputEditorInfo();
         if (mSettingsValues.mAutoCap && ic != null && ei != null
                 && ei.inputType != InputType.TYPE_NULL) {
@@ -1063,25 +1063,13 @@
         }
     }
 
-    private static boolean canBeFollowedByPeriod(final int codePoint) {
-        // TODO: Check again whether there really ain't a better way to check this.
-        // TODO: This should probably be language-dependant...
-        return Character.isLetterOrDigit(codePoint)
-                || codePoint == Keyboard.CODE_SINGLE_QUOTE
-                || codePoint == Keyboard.CODE_DOUBLE_QUOTE
-                || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
-                || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
-                || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
-                || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
-    }
-
     private void maybeDoubleSpace() {
         if (mCorrectionMode == Suggest.CORRECTION_NONE) return;
         final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return;
         final CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
         if (lastThree != null && lastThree.length() == 3
-                && canBeFollowedByPeriod(lastThree.charAt(0))
+                && Utils.canBeFollowedByPeriod(lastThree.charAt(0))
                 && lastThree.charAt(1) == Keyboard.CODE_SPACE
                 && lastThree.charAt(2) == Keyboard.CODE_SPACE
                 && mHandler.isAcceptingDoubleSpaces()) {
@@ -1097,10 +1085,8 @@
         }
     }
 
-    private void maybeRemovePreviousPeriod(CharSequence text) {
-        final InputConnection ic = getCurrentInputConnection();
-        if (ic == null) return;
-
+    // "ic" must not null
+    private void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) {
         // When the text's first character is '.', remove the previous period
         // if there is one.
         CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
@@ -1239,12 +1225,12 @@
     @Override
     public void onTextInput(CharSequence text) {
         mVoiceProxy.commitVoiceInput();
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return;
         mRecorrection.abortRecorrection(false);
         ic.beginBatchEdit();
         commitTyped(ic);
-        maybeRemovePreviousPeriod(text);
+        maybeRemovePreviousPeriod(ic, text);
         ic.commitText(text, 1);
         ic.endBatchEdit();
         mKeyboardSwitcher.updateShiftState();
@@ -1294,14 +1280,14 @@
 
         TextEntryState.backspace();
         if (TextEntryState.isUndoCommit()) {
-            revertLastWord(deleteChar);
+            revertLastWord(ic);
             ic.endBatchEdit();
             return;
         }
         if (justReplacedDoubleSpace) {
-            if (revertDoubleSpace()) {
-              ic.endBatchEdit();
-              return;
+            if (revertDoubleSpace(ic)) {
+                ic.endBatchEdit();
+                return;
             }
         }
 
@@ -1316,7 +1302,7 @@
                 // different behavior only in the case of picking the first
                 // suggestion (typed word).  It's intentional to have made this
                 // inconsistent with backspacing after selecting other suggestions.
-                revertLastWord(true /* deleteChar */);
+                revertLastWord(ic);
             } else {
                 sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
                 if (mDeleteCount > DELETE_ACCELERATE_AT) {
@@ -1399,7 +1385,7 @@
             }
             mComposingStringBuilder.append((char) code);
             mWordComposer.add(code, keyCodes, x, y);
-            InputConnection ic = getCurrentInputConnection();
+            final InputConnection ic = getCurrentInputConnection();
             if (ic != null) {
                 // If it's the first letter, make note of auto-caps state
                 if (mWordComposer.size() == 1) {
@@ -1664,15 +1650,15 @@
                 mSettingsValues.mWordSeparators);
 
         final boolean recorrecting = TextEntryState.isRecorrecting();
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         if (ic != null) {
             ic.beginBatchEdit();
         }
         if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null
                 && index >= 0 && index < mApplicationSpecifiedCompletions.length) {
-            CompletionInfo ci = mApplicationSpecifiedCompletions[index];
             if (ic != null) {
-                ic.commitCompletion(ci);
+                final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
+                ic.commitCompletion(completionInfo);
             }
             mCommittedLength = suggestion.length();
             if (mCandidateView != null) {
@@ -1784,10 +1770,10 @@
      * Commits the chosen word to the text field and saves it for later retrieval.
      */
     private void commitBestWord(CharSequence bestWord) {
-        KeyboardSwitcher switcher = mKeyboardSwitcher;
+        final KeyboardSwitcher switcher = mKeyboardSwitcher;
         if (!switcher.isKeyboardAvailable())
             return;
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         if (ic != null) {
             mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators);
             SuggestedWords suggestedWords = mCandidateView.getSuggestions();
@@ -1879,7 +1865,7 @@
     }
 
     public boolean isCursorTouchingWord() {
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return false;
         CharSequence toLeft = ic.getTextBeforeCursor(1, 0);
         CharSequence toRight = ic.getTextAfterCursor(1, 0);
@@ -1896,36 +1882,33 @@
         return false;
     }
 
-    private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) {
+    // "ic" must not null
+    private boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) {
         CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0);
         return TextUtils.equals(text, beforeText);
     }
 
-    private void revertLastWord(boolean deleteChar) {
+    // "ic" must not null
+    private void revertLastWord(final InputConnection ic) {
         if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) {
             sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
             return;
         }
 
-        final InputConnection ic = getCurrentInputConnection();
-        final CharSequence punctuation = ic.getTextBeforeCursor(1, 0);
-        if (deleteChar) ic.deleteSurroundingText(1, 0);
-        final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
-        final int toDeleteLength = (!TextUtils.isEmpty(textToTheLeft)
-                && mSettingsValues.isWordSeparator(textToTheLeft.charAt(0)))
-                ? mCommittedLength - 1 : mCommittedLength;
-        ic.deleteSurroundingText(toDeleteLength, 0);
+        final CharSequence separator = ic.getTextBeforeCursor(1, 0);
+        ic.deleteSurroundingText(mCommittedLength + 1 /* separator */, 0);
 
-        // Re-insert punctuation only when the deleted character was word separator and the
-        // composing text wasn't equal to the auto-corrected text.
-        if (deleteChar
-                && !TextUtils.isEmpty(punctuation)
-                && mSettingsValues.isWordSeparator(punctuation.charAt(0))
-                && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) {
+        // Re-insert "separator" only when the deleted character was word separator and the
+        // composing text wasn't equal to the auto-corrected text which can be found before
+        // the cursor.
+        if (!TextUtils.isEmpty(separator)
+                && mSettingsValues.isWordSeparator(separator.charAt(0))
+                && !TextUtils.equals(mComposingStringBuilder,
+                        ic.getTextBeforeCursor(mCommittedLength, 0))) {
             ic.commitText(mComposingStringBuilder, 1);
             TextEntryState.acceptedTyped(mComposingStringBuilder);
-            ic.commitText(punctuation, 1);
-            TextEntryState.typedCharacter(punctuation.charAt(0), true,
+            ic.commitText(separator, 1);
+            TextEntryState.typedCharacter(separator.charAt(0), true,
                     WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
             // Clear composing text
             mComposingStringBuilder.setLength(0);
@@ -1938,9 +1921,9 @@
         mHandler.postUpdateSuggestions();
     }
 
-    private boolean revertDoubleSpace() {
+    // "ic" must not null
+    private boolean revertDoubleSpace(final InputConnection ic) {
         mHandler.cancelDoubleSpacesTimer();
-        final InputConnection ic = getCurrentInputConnection();
         // Here we test whether we indeed have a period and a space before us. This should not
         // be needed, but it's there just in case something went wrong.
         final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 23ef1a0..16a2b0e 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -190,6 +190,18 @@
         }
     }
 
+    public static boolean canBeFollowedByPeriod(final int codePoint) {
+        // TODO: Check again whether there really ain't a better way to check this.
+        // TODO: This should probably be language-dependant...
+        return Character.isLetterOrDigit(codePoint)
+                || codePoint == Keyboard.CODE_SINGLE_QUOTE
+                || codePoint == Keyboard.CODE_DOUBLE_QUOTE
+                || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
+                || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
+                || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
+                || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
+    }
+
     /* package */ static class RingCharBuffer {
         private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
         private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
diff --git a/native/Android.mk b/native/Android.mk
index bc246a9..04819e4 100644
--- a/native/Android.mk
+++ b/native/Android.mk
@@ -8,15 +8,13 @@
 # To suppress compiler warnings for unused variables/functions used for debug features etc.
 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function
 
-# Use the new dictionary format
-LOCAL_CFLAGS += -DNEW_DICTIONARY_FORMAT
-
 LOCAL_SRC_FILES := \
     jni/com_android_inputmethod_keyboard_ProximityInfo.cpp \
     jni/com_android_inputmethod_latin_BinaryDictionary.cpp \
     jni/jni_common.cpp \
     src/bigram_dictionary.cpp \
     src/char_utils.cpp \
+    src/correction_state.cpp \
     src/dictionary.cpp \
     src/proximity_info.cpp \
     src/unigram_dictionary.cpp
diff --git a/native/src/correction_state.cpp b/native/src/correction_state.cpp
new file mode 100644
index 0000000..aa5efce
--- /dev/null
+++ b/native/src/correction_state.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#define LOG_TAG "LatinIME: correction_state.cpp"
+
+#include "correction_state.h"
+
+namespace latinime {
+
+CorrectionState::CorrectionState() {
+}
+
+void CorrectionState::setCorrectionParams(const ProximityInfo *pi, const int inputLength,
+        const int skipPos, const int excessivePos, const int transposedPos) {
+    mProximityInfo = pi;
+    mSkipPos = skipPos;
+    mExcessivePos = excessivePos;
+    mTransposedPos = transposedPos;
+}
+
+void CorrectionState::checkState() {
+    if (DEBUG_DICT) {
+        int inputCount = 0;
+        if (mSkipPos >= 0) ++inputCount;
+        if (mExcessivePos >= 0) ++inputCount;
+        if (mTransposedPos >= 0) ++inputCount;
+        // TODO: remove this assert
+        assert(inputCount <= 1);
+    }
+}
+
+CorrectionState::~CorrectionState() {
+}
+
+} // namespace latinime
diff --git a/native/src/correction_state.h b/native/src/correction_state.h
new file mode 100644
index 0000000..5b73925
--- /dev/null
+++ b/native/src/correction_state.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef LATINIME_CORRECTION_STATE_H
+#define LATINIME_CORRECTION_STATE_H
+
+#include <stdint.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+class ProximityInfo;
+
+class CorrectionState {
+public:
+    CorrectionState();
+    void setCorrectionParams(const ProximityInfo *pi, const int inputLength, const int skipPos,
+        const int excessivePos, const int transposedPos);
+    void checkState();
+    virtual ~CorrectionState();
+    int getSkipPos() const {
+        return mSkipPos;
+    }
+    int getExcessivePos() const {
+        return mExcessivePos;
+    }
+    int getTransposedPos() const {
+        return mTransposedPos;
+    }
+private:
+    const ProximityInfo *mProximityInfo;
+    int mInputLength;
+    int mSkipPos;
+    int mExcessivePos;
+    int mTransposedPos;
+};
+} // namespace latinime
+#endif // LATINIME_CORRECTION_INFO_H
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index c45393f..bed92cf 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -78,7 +78,7 @@
     return getProximityCharsAt(index)[0];
 }
 
-bool ProximityInfo::existsCharInProximityAt(const int index, const int c) const {
+inline bool ProximityInfo::existsCharInProximityAt(const int index, const int c) const {
     const int *chars = getProximityCharsAt(index);
     int i = 0;
     while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE) {
@@ -114,8 +114,10 @@
 // in their list. The non-accented version of the character should be considered
 // "close", but not the other keys close to the non-accented version.
 ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(
-        const int index, const unsigned short c, const int skipPos,
-        const int excessivePos, const int transposedPos) const {
+        const int index, const unsigned short c, CorrectionState *correctionState) const {
+    const int skipPos = correctionState->getSkipPos();
+    const int excessivePos = correctionState->getExcessivePos();
+    const int transposedPos = correctionState->getTransposedPos();
     const int *currentChars = getProximityCharsAt(index);
     const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c);
 
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index 435a601..b28191d 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -23,6 +23,8 @@
 
 namespace latinime {
 
+class CorrectionState;
+
 class ProximityInfo {
 public:
     typedef enum {                             // Used as a return value for character comparison
@@ -42,8 +44,7 @@
     bool existsCharInProximityAt(const int index, const int c) const;
     bool existsAdjacentProximityChars(const int index) const;
     ProximityType getMatchedProximityId(
-            const int index, const unsigned short c, const int skipPos,
-            const int excessivePos, const int transposedPos) const;
+            const int index, const unsigned short c, CorrectionState *correctionState) const;
     bool sameAsTyped(const unsigned short *word, int length) const;
 private:
     int getStartIndexFromCoordinates(const int x, const int y) const;
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index bccd37a..f0bb384 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -24,9 +24,7 @@
 #include "dictionary.h"
 #include "unigram_dictionary.h"
 
-#ifdef NEW_DICTIONARY_FORMAT
 #include "binary_format.h"
-#endif // NEW_DICTIONARY_FORMAT
 
 namespace latinime {
 
@@ -39,28 +37,23 @@
 UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultiplier,
         int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars,
         const bool isLatestDictVersion)
-#ifndef NEW_DICTIONARY_FORMAT
-    : DICT_ROOT(streamStart),
-#else // NEW_DICTIONARY_FORMAT
     : DICT_ROOT(streamStart + NEW_DICTIONARY_HEADER_SIZE),
-#endif // NEW_DICTIONARY_FORMAT
     MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords),
     MAX_PROXIMITY_CHARS(maxProximityChars), IS_LATEST_DICT_VERSION(isLatestDictVersion),
     TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier),
-#ifndef NEW_DICTIONARY_FORMAT
-    ROOT_POS(isLatestDictVersion ? DICTIONARY_HEADER_SIZE : 0),
-#else // NEW_DICTIONARY_FORMAT
       // TODO : remove this variable.
     ROOT_POS(0),
-#endif // NEW_DICTIONARY_FORMAT
     BYTES_IN_ONE_CHAR(MAX_PROXIMITY_CHARS * sizeof(int)),
     MAX_UMLAUT_SEARCH_DEPTH(DEFAULT_MAX_UMLAUT_SEARCH_DEPTH) {
     if (DEBUG_DICT) {
         LOGI("UnigramDictionary - constructor");
     }
+    mCorrectionState = new CorrectionState();
 }
 
-UnigramDictionary::~UnigramDictionary() {}
+UnigramDictionary::~UnigramDictionary() {
+    delete mCorrectionState;
+}
 
 static inline unsigned int getCodesBufferSize(const int* codes, const int codesSize,
         const int MAX_PROXIMITY_CHARS) {
@@ -362,6 +355,8 @@
         assert(excessivePos < mInputLength);
         assert(missingPos < mInputLength);
     }
+    mCorrectionState->setCorrectionParams(mProximityInfo, mInputLength, skipPos, excessivePos,
+            transposedPos);
     int rootPosition = ROOT_POS;
     // Get the number of children of root, then increment the position
     int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
@@ -389,8 +384,8 @@
             // depth will never be greater than maxDepth because in that case,
             // needsToTraverseChildrenNodes should be false
             const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, outputIndex,
-                    maxDepth, traverseAllNodes, matchWeight, inputIndex, diffs, skipPos,
-                    excessivePos, transposedPos, nextLetters, nextLettersSize, &childCount,
+                    maxDepth, traverseAllNodes, matchWeight, inputIndex, diffs,
+                    nextLetters, nextLettersSize, mCorrectionState, &childCount,
                     &firstChildPos, &traverseAllNodes, &matchWeight, &inputIndex, &diffs,
                     &siblingPos, &outputIndex);
             // Update next sibling pos
@@ -521,8 +516,12 @@
 }
 
 inline int UnigramDictionary::calculateFinalFreq(const int inputIndex, const int depth,
-        const int matchWeight, const int skipPos, const int excessivePos, const int transposedPos,
-        const int freq, const bool sameLength) const {
+        const int matchWeight, const int freq, const bool sameLength,
+        CorrectionState *correctionState) const {
+    const int skipPos = correctionState->getSkipPos();
+    const int excessivePos = correctionState->getExcessivePos();
+    const int transposedPos = correctionState->getTransposedPos();
+
     // TODO: Demote by edit distance
     int finalFreq = freq * matchWeight;
     if (skipPos >= 0) {
@@ -587,16 +586,16 @@
 
 inline void UnigramDictionary::onTerminal(unsigned short int* word, const int depth,
         const uint8_t* const root, const uint8_t flags, const int pos,
-        const int inputIndex, const int matchWeight, const int skipPos,
-        const int excessivePos, const int transposedPos, const int freq, const bool sameLength,
-        int* nextLetters, const int nextLettersSize) {
+        const int inputIndex, const int matchWeight, const int freq, const bool sameLength,
+        int* nextLetters, const int nextLettersSize, CorrectionState *correctionState) {
+    const int skipPos = correctionState->getSkipPos();
 
     const bool isSameAsTyped = sameLength ? mProximityInfo->sameAsTyped(word, depth + 1) : false;
     if (isSameAsTyped) return;
 
     if (depth >= MIN_SUGGEST_DEPTH) {
-        const int finalFreq = calculateFinalFreq(inputIndex, depth, matchWeight, skipPos,
-                excessivePos, transposedPos, freq, sameLength);
+        const int finalFreq = calculateFinalFreq(inputIndex, depth, matchWeight,
+                freq, sameLength, correctionState);
         if (!isSameAsTyped)
             addWord(word, depth + 1, finalFreq);
     }
@@ -647,282 +646,6 @@
     return true;
 }
 
-#ifndef NEW_DICTIONARY_FORMAT
-// The following functions will be entirely replaced with new implementations.
-void UnigramDictionary::getWordsOld(const int initialPos, const int inputLength, const int skipPos,
-        const int excessivePos, const int transposedPos,int *nextLetters,
-        const int nextLettersSize) {
-    int initialPosition = initialPos;
-    const int count = Dictionary::getCount(DICT_ROOT, &initialPosition);
-    getWordsRec(count, initialPosition, 0,
-            min(inputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH),
-            mInputLength <= 0, 1, 0, 0, skipPos, excessivePos, transposedPos, nextLetters,
-            nextLettersSize);
-}
-
-void UnigramDictionary::getWordsRec(const int childrenCount, const int pos, const int depth,
-        const int maxDepth, const bool traverseAllNodes, const int matchWeight,
-        const int inputIndex, const int diffs, const int skipPos, const int excessivePos,
-        const int transposedPos, int *nextLetters, const int nextLettersSize) {
-    int siblingPos = pos;
-    for (int i = 0; i < childrenCount; ++i) {
-        int newCount;
-        int newChildPosition;
-        bool newTraverseAllNodes;
-        int newMatchRate;
-        int newInputIndex;
-        int newDiffs;
-        int newSiblingPos;
-        int newOutputIndex;
-        const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, depth, maxDepth,
-                traverseAllNodes, matchWeight, inputIndex, diffs,
-                skipPos, excessivePos, transposedPos,
-                nextLetters, nextLettersSize,
-                &newCount, &newChildPosition, &newTraverseAllNodes, &newMatchRate,
-                &newInputIndex, &newDiffs, &newSiblingPos, &newOutputIndex);
-        siblingPos = newSiblingPos;
-
-        if (needsToTraverseChildrenNodes) {
-            getWordsRec(newCount, newChildPosition, newOutputIndex, maxDepth, newTraverseAllNodes,
-                    newMatchRate, newInputIndex, newDiffs, skipPos, excessivePos, transposedPos,
-                    nextLetters, nextLettersSize);
-        }
-    }
-}
-
-inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex,
-        const int inputLength, unsigned short *word) {
-    int pos = ROOT_POS;
-    int count = Dictionary::getCount(DICT_ROOT, &pos);
-    int maxFreq = 0;
-    int depth = 0;
-    unsigned short newWord[MAX_WORD_LENGTH_INTERNAL];
-    bool terminal = false;
-
-    mStackChildCount[0] = count;
-    mStackSiblingPos[0] = pos;
-
-    while (depth >= 0) {
-        if (mStackChildCount[depth] > 0) {
-            --mStackChildCount[depth];
-            int firstChildPos;
-            int newFreq;
-            int siblingPos = mStackSiblingPos[depth];
-            const bool needsToTraverseChildrenNodes = processCurrentNodeForExactMatch(siblingPos,
-                    startInputIndex, depth, newWord, &firstChildPos, &count, &terminal, &newFreq,
-                    &siblingPos);
-            mStackSiblingPos[depth] = siblingPos;
-            if (depth == (inputLength - 1)) {
-                // Traverse sibling node
-                if (terminal) {
-                    if (newFreq > maxFreq) {
-                        for (int i = 0; i < inputLength; ++i) word[i] = newWord[i];
-                        if (DEBUG_DICT && DEBUG_NODE) {
-#ifdef FLAG_DBG
-                            char s[inputLength + 1];
-                            for (int i = 0; i < inputLength; ++i) s[i] = word[i];
-                            s[inputLength] = 0;
-                            LOGI("New missing space word found: %d > %d (%s), %d, %d",
-                                    newFreq, maxFreq, s, inputLength, depth);
-#endif
-                        }
-                        maxFreq = newFreq;
-                    }
-                }
-            } else if (needsToTraverseChildrenNodes) {
-                // Traverse children nodes
-                ++depth;
-                mStackChildCount[depth] = count;
-                mStackSiblingPos[depth] = firstChildPos;
-            }
-        } else {
-            // Traverse parent node
-            --depth;
-        }
-    }
-
-    word[inputLength] = 0;
-    return maxFreq;
-}
-
-inline bool UnigramDictionary::processCurrentNodeForExactMatch(const int firstChildPos,
-        const int startInputIndex, const int depth, unsigned short *word, int *newChildPosition,
-        int *newCount, bool *newTerminal, int *newFreq, int *siblingPos) {
-    const int inputIndex = startInputIndex + depth;
-    unsigned short c;
-    *siblingPos = Dictionary::setDictionaryValues(DICT_ROOT, IS_LATEST_DICT_VERSION, firstChildPos,
-            &c, newChildPosition, newTerminal, newFreq);
-    const unsigned int inputC = mProximityInfo->getPrimaryCharAt(inputIndex);
-    if (DEBUG_DICT) {
-        assert(inputC <= U_SHORT_MAX);
-    }
-    const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c);
-    const bool matched = (inputC == baseLowerC || inputC == c);
-    const bool hasChild = *newChildPosition != 0;
-    if (matched) {
-        word[depth] = c;
-        if (DEBUG_DICT && DEBUG_NODE) {
-            LOGI("Node(%c, %c)<%d>, %d, %d", inputC, c, matched, hasChild, *newFreq);
-            if (*newTerminal) {
-                LOGI("Terminal %d", *newFreq);
-            }
-        }
-        if (hasChild) {
-            *newCount = Dictionary::getCount(DICT_ROOT, newChildPosition);
-            return true;
-        } else {
-            return false;
-        }
-    } else {
-        // If this node is not user typed character, this method treats this word as unmatched.
-        // Thus newTerminal shouldn't be true.
-        *newTerminal = false;
-        return false;
-    }
-}
-
-// TODO: use uint32_t instead of unsigned short
-bool UnigramDictionary::isValidWord(unsigned short *word, int length) {
-    if (IS_LATEST_DICT_VERSION) {
-        return (getBigramPosition(DICTIONARY_HEADER_SIZE, word, 0, length) != NOT_VALID_WORD);
-    } else {
-        return (getBigramPosition(0, word, 0, length) != NOT_VALID_WORD);
-    }
-}
-
-
-// Require strict exact match.
-int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offset,
-        int length) const {
-    // returns address of bigram data of that word
-    // return -99 if not found
-
-    int count = Dictionary::getCount(DICT_ROOT, &pos);
-    unsigned short currentChar = (unsigned short) word[offset];
-    for (int j = 0; j < count; j++) {
-        unsigned short c = Dictionary::getChar(DICT_ROOT, &pos);
-        int terminal = Dictionary::getTerminal(DICT_ROOT, &pos);
-        int childPos = Dictionary::getAddress(DICT_ROOT, &pos);
-        if (c == currentChar) {
-            if (offset == length - 1) {
-                if (terminal) {
-                    return (pos+1);
-                }
-            } else {
-                if (childPos != 0) {
-                    int t = getBigramPosition(childPos, word, offset + 1, length);
-                    if (t > 0) {
-                        return t;
-                    }
-                }
-            }
-        }
-        if (terminal) {
-            Dictionary::getFreq(DICT_ROOT, IS_LATEST_DICT_VERSION, &pos);
-        }
-        // There could be two instances of each alphabet - upper and lower case. So continue
-        // looking ...
-    }
-    return NOT_VALID_WORD;
-}
-
-// The following functions will be modified.
-inline bool UnigramDictionary::processCurrentNode(const int initialPos, const int initialDepth,
-        const int maxDepth, const bool initialTraverseAllNodes, int matchWeight, int inputIndex,
-        const int initialDiffs, const int skipPos, const int excessivePos, const int transposedPos,
-        int *nextLetters, const int nextLettersSize, int *newCount, int *newChildPosition,
-        bool *newTraverseAllNodes, int *newMatchRate, int *newInputIndex, int *newDiffs,
-        int *nextSiblingPosition, int *nextOutputIndex) {
-    if (DEBUG_DICT) {
-        int inputCount = 0;
-        if (skipPos >= 0) ++inputCount;
-        if (excessivePos >= 0) ++inputCount;
-        if (transposedPos >= 0) ++inputCount;
-        assert(inputCount <= 1);
-    }
-    unsigned short c;
-    int childPosition;
-    bool terminal;
-    int freq;
-    bool isSameAsUserTypedLength = false;
-
-    const int pos = initialPos;
-    const int depth = initialDepth;
-    const int traverseAllNodes = initialTraverseAllNodes;
-    const int diffs = initialDiffs;
-
-    const uint8_t flags = 0; // No flags for now
-
-    if (excessivePos == depth && inputIndex < mInputLength - 1) ++inputIndex;
-
-    *nextSiblingPosition = Dictionary::setDictionaryValues(DICT_ROOT, IS_LATEST_DICT_VERSION, pos,
-            &c, &childPosition, &terminal, &freq);
-    *nextOutputIndex = depth + 1;
-
-    const bool needsToTraverseChildrenNodes = childPosition != 0;
-
-    // If we are only doing traverseAllNodes, no need to look at the typed characters.
-    if (traverseAllNodes || needsToSkipCurrentNode(c, inputIndex, skipPos, depth)) {
-        mWord[depth] = c;
-        if (traverseAllNodes && terminal) {
-            onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight, skipPos,
-                       excessivePos, transposedPos, freq, false, nextLetters, nextLettersSize);
-        }
-        if (!needsToTraverseChildrenNodes) return false;
-        *newTraverseAllNodes = traverseAllNodes;
-        *newMatchRate = matchWeight;
-        *newDiffs = diffs;
-        *newInputIndex = inputIndex;
-    } else {
-        int inputIndexForProximity = inputIndex;
-
-        if (transposedPos >= 0) {
-            if (inputIndex == transposedPos) ++inputIndexForProximity;
-            if (inputIndex == (transposedPos + 1)) --inputIndexForProximity;
-        }
-
-        ProximityInfo::ProximityType matchedProximityCharId = mProximityInfo->getMatchedProximityId(
-                inputIndexForProximity, c, skipPos, excessivePos, transposedPos);
-        if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) return false;
-        mWord[depth] = c;
-        // If inputIndex is greater than mInputLength, that means there is no
-        // proximity chars. So, we don't need to check proximity.
-        if (ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
-            multiplyIntCapped(TYPED_LETTER_MULTIPLIER, &matchWeight);
-        }
-        bool isSameAsUserTypedLength = mInputLength == inputIndex + 1
-                || (excessivePos == mInputLength - 1 && inputIndex == mInputLength - 2);
-        if (isSameAsUserTypedLength && terminal) {
-            onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight, skipPos,
-                    excessivePos, transposedPos, freq, true, nextLetters, nextLettersSize);
-        }
-        if (!needsToTraverseChildrenNodes) return false;
-        // Start traversing all nodes after the index exceeds the user typed length
-        *newTraverseAllNodes = isSameAsUserTypedLength;
-        *newMatchRate = matchWeight;
-        *newDiffs = diffs
-                + ((ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) ? 1 : 0);
-        *newInputIndex = inputIndex + 1;
-    }
-    // Optimization: Prune out words that are too long compared to how much was typed.
-    if (depth >= maxDepth || *newDiffs > mMaxEditDistance) {
-        return false;
-    }
-
-    // If inputIndex is greater than mInputLength, that means there are no proximity chars.
-    // TODO: Check if this can be isSameAsUserTypedLength only.
-    if (isSameAsUserTypedLength || mInputLength <= *newInputIndex) {
-        *newTraverseAllNodes = true;
-    }
-    // get the count of nodes and increment childAddress.
-    *newCount = Dictionary::getCount(DICT_ROOT, &childPosition);
-    *newChildPosition = childPosition;
-    if (DEBUG_DICT) assert(needsToTraverseChildrenNodes);
-    return needsToTraverseChildrenNodes;
-}
-
-#else // NEW_DICTIONARY_FORMAT
-
 // Wrapper for getMostFrequentWordLikeInner, which matches it to the previous
 // interface.
 inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex,
@@ -1081,16 +804,15 @@
 // given level, as output into newCount when traversing this level's parent.
 inline bool UnigramDictionary::processCurrentNode(const int initialPos, const int initialDepth,
         const int maxDepth, const bool initialTraverseAllNodes, int matchWeight, int inputIndex,
-        const int initialDiffs, const int skipPos, const int excessivePos, const int transposedPos,
-        int *nextLetters, const int nextLettersSize, int *newCount, int *newChildrenPosition,
+        const int initialDiffs, int *nextLetters, const int nextLettersSize,
+        CorrectionState *correctionState, int *newCount, int *newChildrenPosition,
         bool *newTraverseAllNodes, int *newMatchRate, int *newInputIndex, int *newDiffs,
         int *nextSiblingPosition, int *newOutputIndex) {
+    const int skipPos = correctionState->getSkipPos();
+    const int excessivePos = correctionState->getExcessivePos();
+    const int transposedPos = correctionState->getTransposedPos();
     if (DEBUG_DICT) {
-        int inputCount = 0;
-        if (skipPos >= 0) ++inputCount;
-        if (excessivePos >= 0) ++inputCount;
-        if (transposedPos >= 0) ++inputCount;
-        assert(inputCount <= 1);
+        correctionState->checkState();
     }
     int pos = initialPos;
     int depth = initialDepth;
@@ -1146,8 +868,8 @@
                 // The frequency should be here, because we come here only if this is actually
                 // a terminal node, and we are on its last char.
                 const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
-                onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight, skipPos,
-                           excessivePos, transposedPos, freq, false, nextLetters, nextLettersSize);
+                onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight,
+                        freq, false, nextLetters, nextLettersSize, mCorrectionState);
             }
             if (!hasChildren) {
                 // If we don't have children here, that means we finished processing all
@@ -1170,7 +892,7 @@
             }
 
             int matchedProximityCharId = mProximityInfo->getMatchedProximityId(
-                    inputIndexForProximity, c, skipPos, excessivePos, transposedPos);
+                    inputIndexForProximity, c, mCorrectionState);
             if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
                 // We found that this is an unrelated character, so we should give up traversing
                 // this node and its children entirely.
@@ -1197,8 +919,8 @@
                     || (excessivePos == mInputLength - 1 && inputIndex == mInputLength - 2);
             if (isSameAsUserTypedLength && isTerminal) {
                 const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
-                onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight, skipPos,
-                        excessivePos, transposedPos, freq, true, nextLetters, nextLettersSize);
+                onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight,
+                        freq, true, nextLetters, nextLettersSize, mCorrectionState);
             }
             // This character matched the typed character (enough to traverse the node at least)
             // so we just evaluated it. Now we should evaluate this virtual node's children - that
@@ -1276,6 +998,4 @@
     return true;
 }
 
-#endif // NEW_DICTIONARY_FORMAT
-
 } // namespace latinime
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index 97198ef..41e3818 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -18,6 +18,7 @@
 #define LATINIME_UNIGRAM_DICTIONARY_H
 
 #include <stdint.h>
+#include "correction_state.h"
 #include "defines.h"
 #include "proximity_info.h"
 
@@ -30,7 +31,6 @@
 class UnigramDictionary {
 
 public:
-#ifdef NEW_DICTIONARY_FORMAT
 
     // Mask and flags for children address type selection.
     static const int MASK_GROUP_ADDRESS_TYPE = 0xC0;
@@ -62,21 +62,16 @@
     static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
     static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
     static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
-#endif // NEW_DICTIONARY_FORMAT
 
     UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultipler,
             int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars,
             const bool isLatestDictVersion);
-#ifndef NEW_DICTIONARY_FORMAT
-    bool isValidWord(unsigned short *word, int length);
-#else // NEW_DICTIONARY_FORMAT
     bool isValidWord(const uint16_t* const inWord, const int length) const;
-#endif // NEW_DICTIONARY_FORMAT
     int getBigramPosition(int pos, unsigned short *word, int offset, int length) const;
     int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codes, const int codesSize, const int flags,
             unsigned short *outWords, int *frequencies);
-    ~UnigramDictionary();
+    virtual ~UnigramDictionary();
 
 private:
     void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
@@ -99,42 +94,25 @@
             const int secondWordStartPos, const int secondWordLength, const bool isSpaceProximity);
     bool getMissingSpaceWords(const int inputLength, const int missingSpacePos);
     bool getMistypedSpaceWords(const int inputLength, const int spaceProximityPos);
-    int calculateFinalFreq(const int inputIndex, const int depth, const int snr, const int skipPos,
-            const int excessivePos, const int transposedPos, const int freq,
-            const bool sameLength) const;
+    int calculateFinalFreq(const int inputIndex, const int depth, const int snr,
+            const int freq, const bool sameLength, CorrectionState *correctionState) const;
     void onTerminal(unsigned short int* word, const int depth,
             const uint8_t* const root, const uint8_t flags, const int pos,
-            const int inputIndex, const int matchWeight, const int skipPos,
-            const int excessivePos, const int transposedPos, const int freq, const bool sameLength,
-            int *nextLetters, const int nextLettersSize);
+            const int inputIndex, const int matchWeight, const int freq, const bool sameLength,
+            int* nextLetters, const int nextLettersSize, CorrectionState *correctionState);
     bool needsToSkipCurrentNode(const unsigned short c,
             const int inputIndex, const int skipPos, const int depth);
     // Process a node by considering proximity, missing and excessive character
     bool processCurrentNode(const int initialPos, const int initialDepth,
-            const int maxDepth, const bool initialTraverseAllNodes, const int snr, int inputIndex,
-            const int initialDiffs, const int skipPos, const int excessivePos,
-            const int transposedPos, int *nextLetters, const int nextLettersSize, int *newCount,
-            int *newChildPosition, bool *newTraverseAllNodes, int *newSnr, int*newInputIndex,
-            int *newDiffs, int *nextSiblingPosition, int *nextOutputIndex);
+            const int maxDepth, const bool initialTraverseAllNodes, int matchWeight, int inputIndex,
+            const int initialDiffs, int *nextLetters, const int nextLettersSize,
+            CorrectionState *correctionState, int *newCount, int *newChildPosition,
+            bool *newTraverseAllNodes, int *newMatchRate, int *newInputIndex, int *newDiffs,
+            int *nextSiblingPosition, int *nextOutputIndex);
     int getMostFrequentWordLike(const int startInputIndex, const int inputLength,
             unsigned short *word);
-#ifndef NEW_DICTIONARY_FORMAT
-    void getWordsRec(const int childrenCount, const int pos, const int depth, const int maxDepth,
-            const bool traverseAllNodes, const int snr, const int inputIndex, const int diffs,
-            const int skipPos, const int excessivePos, const int transposedPos, int *nextLetters,
-            const int nextLettersSize);
-    // Keep getWordsOld for comparing performance between getWords and getWordsOld
-    void getWordsOld(const int initialPos, const int inputLength, const int skipPos,
-            const int excessivePos, const int transposedPos, int *nextLetters,
-            const int nextLettersSize);
-    // Process a node by considering missing space
-    bool processCurrentNodeForExactMatch(const int firstChildPos,
-            const int startInputIndex, const int depth, unsigned short *word,
-            int *newChildPosition, int *newCount, bool *newTerminal, int *newFreq, int *siblingPos);
-#else // NEW_DICTIONARY_FORMAT
     int getMostFrequentWordLikeInner(const uint16_t* const inWord, const int length,
             short unsigned int* outWord);
-#endif // NEW_DICTIONARY_FORMAT
 
     const uint8_t* const DICT_ROOT;
     const int MAX_WORD_LENGTH;
@@ -158,7 +136,8 @@
 
     int *mFrequencies;
     unsigned short *mOutputChars;
-    const ProximityInfo *mProximityInfo;
+    ProximityInfo *mProximityInfo;
+    CorrectionState *mCorrectionState;
     int mInputLength;
     // MAX_WORD_LENGTH_INTERNAL must be bigger than MAX_WORD_LENGTH
     unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];
diff --git a/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
index 99bcc61..7af566b 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
@@ -18,6 +18,7 @@
 import com.android.inputmethod.latin.tests.R;
 
 import android.content.res.AssetFileDescriptor;
+import android.content.res.Configuration;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -38,7 +39,7 @@
         final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
         mHelper = new SuggestHelper(
                 getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
-                createKeyboardId(Locale.US));
+                createKeyboardId(Locale.US, Configuration.ORIENTATION_PORTRAIT));
         loadString(R.raw.testtext);
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/SuggestTests.java b/tests/src/com/android/inputmethod/latin/SuggestTests.java
index 6e9a127..cf45580 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestTests.java
@@ -19,6 +19,7 @@
 import com.android.inputmethod.latin.tests.R;
 
 import android.content.res.AssetFileDescriptor;
+import android.content.res.Configuration;
 
 import java.util.Locale;
 
@@ -31,7 +32,7 @@
         final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
         mHelper = new SuggestHelper(
                 getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
-                createKeyboardId(Locale.US));
+                createKeyboardId(Locale.US, Configuration.ORIENTATION_PORTRAIT));
         mHelper.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java
index 7d61d00..058a3e7 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java
@@ -20,6 +20,7 @@
 import android.content.res.Configuration;
 import android.test.AndroidTestCase;
 import android.text.TextUtils;
+import android.util.DisplayMetrics;
 import android.view.inputmethod.EditorInfo;
 
 import com.android.inputmethod.keyboard.KeyboardId;
@@ -37,12 +38,22 @@
         mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir);
     }
 
-    protected KeyboardId createKeyboardId(Locale locale) {
-        final int displayWidth = getContext().getResources().getDisplayMetrics().widthPixels;
+    protected KeyboardId createKeyboardId(Locale locale, int orientation) {
+        final DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
+        final int width;
+        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            width = Math.max(dm.widthPixels, dm.heightPixels);
+        } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+            width = Math.min(dm.widthPixels, dm.heightPixels);
+        } else {
+            fail("Orientation should be ORIENTATION_LANDSCAPE or ORIENTATION_PORTRAIT: "
+                    + "orientation=" + orientation);
+            return null;
+        }
         return new KeyboardId(locale.toString() + " keyboard",
-                com.android.inputmethod.latin.R.xml.kbd_qwerty, locale,
-                Configuration.ORIENTATION_LANDSCAPE, displayWidth, KeyboardId.MODE_TEXT,
-                new EditorInfo(), false, KeyboardId.F2KEY_MODE_NONE, false, false, false);
+                com.android.inputmethod.latin.R.xml.kbd_qwerty, locale, orientation, width,
+                KeyboardId.MODE_TEXT, new EditorInfo(), false, KeyboardId.F2KEY_MODE_NONE,
+                false, false, false);
     }
 
     protected InputStream openTestRawResource(int resIdInTest) {
diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
index 9bd8538..0b97e41 100644
--- a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
+++ b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
@@ -15,9 +15,10 @@
  */
 
 package com.android.inputmethod.latin;
-import com.android.inputmethod.latin.tests.R;
-
 import android.content.res.AssetFileDescriptor;
+import android.content.res.Configuration;
+
+import com.android.inputmethod.latin.tests.R;
 
 import java.util.Locale;
 
@@ -34,7 +35,8 @@
         final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
         mHelper = new UserBigramSuggestHelper(
                 getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
-                MAX_DATA, DELETE_DATA, createKeyboardId(Locale.US));
+                MAX_DATA, DELETE_DATA,
+                createKeyboardId(Locale.US, Configuration.ORIENTATION_PORTRAIT));
     }
 
     /************************** Tests ************************/