Merge "Move some editing methods to RichInputConnection."
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index bd326a4..3957b01 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -98,7 +98,7 @@
 static const char QUOTE = '\'';
 
 inline bool Correction::isQuote(const unsigned short c) {
-    const unsigned short userTypedChar = mProximityInfo->getPrimaryCharAt(mInputIndex);
+    const unsigned short userTypedChar = mProximityInfoState.getPrimaryCharAt(mInputIndex);
     return (c == QUOTE && userTypedChar != QUOTE);
 }
 
@@ -283,7 +283,7 @@
 
 void Correction::addCharToCurrentWord(const int32_t c) {
     mWord[mOutputIndex] = c;
-    const unsigned short *primaryInputWord = mProximityInfo->getPrimaryInputWord();
+    const unsigned short *primaryInputWord = mProximityInfoState.getPrimaryInputWord();
     calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputLength,
             mWord, mOutputIndex + 1);
 }
@@ -335,19 +335,19 @@
         bool incremented = false;
         if (mLastCharExceeded && mInputIndex == mInputLength - 1) {
             // TODO: Do not check the proximity if EditDistance exceeds the threshold
-            const ProximityType matchId =
-                    mProximityInfo->getMatchedProximityId(mInputIndex, c, true, &proximityIndex);
+            const ProximityType matchId = mProximityInfoState.getMatchedProximityId(
+                    mInputIndex, c, true, &proximityIndex);
             if (isEquivalentChar(matchId)) {
                 mLastCharExceeded = false;
                 --mExcessiveCount;
                 mDistances[mOutputIndex] =
-                        mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
+                        mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
             } else if (matchId == NEAR_PROXIMITY_CHAR) {
                 mLastCharExceeded = false;
                 --mExcessiveCount;
                 ++mProximityCount;
-                mDistances[mOutputIndex] =
-                        mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
+                mDistances[mOutputIndex] = mProximityInfoState.getNormalizedSquaredDistance(
+                        mInputIndex, proximityIndex);
             }
             if (!isQuote(c)) {
                 incrementInputIndex();
@@ -388,7 +388,8 @@
 
     bool secondTransposing = false;
     if (mTransposedCount % 2 == 1) {
-        if (isEquivalentChar(mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+        if (isEquivalentChar(mProximityInfoState.getMatchedProximityId(
+                mInputIndex - 1, c, false))) {
             ++mTransposedCount;
             secondTransposing = true;
         } else if (mCorrectionStates[mOutputIndex].mExceeding) {
@@ -419,7 +420,7 @@
 
     ProximityType matchedProximityCharId = secondTransposing
             ? EQUIVALENT_CHAR
-            : mProximityInfo->getMatchedProximityId(
+            : mProximityInfoState.getMatchedProximityId(
                     mInputIndex, c, checkProximityChars, &proximityIndex);
 
     if (UNRELATED_CHAR == matchedProximityCharId
@@ -427,7 +428,7 @@
         if (canTryCorrection && mOutputIndex > 0
                 && mCorrectionStates[mOutputIndex].mProximityMatching
                 && mCorrectionStates[mOutputIndex].mExceeding
-                && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+                && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
                         mInputIndex, mWord[mOutputIndex - 1], false))) {
             if (DEBUG_CORRECTION
                     && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength)
@@ -446,7 +447,7 @@
             // Here, we are doing something equivalent to matchedProximityCharId,
             // but we already know that "excessive char correction" just happened
             // so that we just need to check "mProximityCount == 0".
-            matchedProximityCharId = mProximityInfo->getMatchedProximityId(
+            matchedProximityCharId = mProximityInfoState.getMatchedProximityId(
                     mInputIndex, c, mProximityCount == 0, &proximityIndex);
         }
     }
@@ -463,10 +464,10 @@
         if (mInputIndex < mInputLength - 1 && mOutputIndex > 0 && mTransposedCount > 0
                 && !mCorrectionStates[mOutputIndex].mTransposing
                 && mCorrectionStates[mOutputIndex - 1].mTransposing
-                && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+                && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
                         mInputIndex, mWord[mOutputIndex - 1], false))
                 && isEquivalentChar(
-                        mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+                        mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
             // Conversion t->e
             // Example:
             // occaisional -> occa   sional
@@ -478,7 +479,7 @@
                 && !mCorrectionStates[mOutputIndex].mTransposing
                 && mCorrectionStates[mOutputIndex - 1].mTransposing
                 && isEquivalentChar(
-                        mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+                        mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
             // Conversion t->s
             // Example:
             // chcolate -> chocolate
@@ -490,7 +491,7 @@
                 && mCorrectionStates[mOutputIndex].mProximityMatching
                 && mCorrectionStates[mOutputIndex].mSkipping
                 && isEquivalentChar(
-                        mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+                        mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
             // Conversion p->s
             // Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
             // proximity chars of "s", but it should rather be handled as a skipped char.
@@ -502,7 +503,7 @@
                 && mCorrectionStates[mOutputIndex].mSkipping
                 && mCorrectionStates[mOutputIndex].mAdditionalProximityMatching
                 && isProximityCharOrEquivalentChar(
-                        mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+                        mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
             // Conversion s->a
             incrementInputIndex();
             --mSkippedCount;
@@ -511,7 +512,7 @@
             mDistances[mOutputIndex] = ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO;
         } else if ((mExceeding || mTransposing) && mInputIndex - 1 < mInputLength
                 && isEquivalentChar(
-                        mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+                        mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
             // 1.2. Excessive or transpose correction
             if (mTransposing) {
                 ++mTransposedCount;
@@ -573,12 +574,12 @@
     } else if (isEquivalentChar(matchedProximityCharId)) {
         mMatching = true;
         ++mEquivalentCharCount;
-        mDistances[mOutputIndex] = mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
+        mDistances[mOutputIndex] = mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
     } else if (NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
         mProximityMatching = true;
         ++mProximityCount;
         mDistances[mOutputIndex] =
-                mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
+                mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, proximityIndex);
         if (DEBUG_CORRECTION
                 && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength)
                 && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0
@@ -662,7 +663,7 @@
     const int excessivePos = correction->getExcessivePos();
     const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER;
     const int fullWordMultiplier = correction->FULL_WORD_MULTIPLIER;
-    const ProximityInfo *proximityInfo = correction->mProximityInfo;
+    const ProximityInfoState *proximityInfoState = &correction->mProximityInfoState;
     const int skippedCount = correction->mSkippedCount;
     const int transposedCount = correction->mTransposedCount / 2;
     const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
@@ -685,7 +686,7 @@
     const bool skipped = skippedCount > 0;
 
     const int quoteDiffCount = max(0, getQuoteCount(word, outputLength)
-            - getQuoteCount(proximityInfo->getPrimaryInputWord(), inputLength));
+            - getQuoteCount(proximityInfoState->getPrimaryInputWord(), inputLength));
 
     // TODO: Calculate edit distance for transposed and excessive
     int ed = 0;
@@ -737,7 +738,7 @@
         multiplyIntCapped(matchWeight, &finalFreq);
     }
 
-    if (proximityInfo->getMatchedProximityId(0, word[0], true) == UNRELATED_CHAR) {
+    if (proximityInfoState->getMatchedProximityId(0, word[0], true) == UNRELATED_CHAR) {
         multiplyRate(FIRST_CHAR_DIFFERENT_DEMOTION_RATE, &finalFreq);
     }
 
@@ -763,7 +764,7 @@
     // Demotion for a word with excessive character
     if (excessiveCount > 0) {
         multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq);
-        if (!lastCharExceeded && !proximityInfo->existsAdjacentProximityChars(excessivePos)) {
+        if (!lastCharExceeded && !proximityInfoState->existsAdjacentProximityChars(excessivePos)) {
             if (DEBUG_DICT_FULL) {
                 AKLOGI("Double excessive demotion");
             }
@@ -774,8 +775,9 @@
     }
 
     const bool performTouchPositionCorrection =
-            CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfo->touchPositionCorrectionEnabled()
-                        && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0;
+            CALIBRATE_SCORE_BY_TOUCH_COORDINATES
+                    && proximityInfoState->touchPositionCorrectionEnabled()
+                    && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0;
     // Score calibration by touch coordinates is being done only for pure-fat finger typing error
     // cases.
     int additionalProximityCount = 0;
@@ -1145,5 +1147,4 @@
     const float weight = 1.0 - (float) distance / afterLength;
     return (score / maxScore) * weight;
 }
-
 } // namespace latinime
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 3300a84..60d7dc3 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -19,9 +19,10 @@
 
 #include <assert.h>
 #include <stdint.h>
-#include "correction_state.h"
 
+#include "correction_state.h"
 #include "defines.h"
+#include "proximity_info_state.h"
 
 namespace latinime {
 
@@ -178,6 +179,21 @@
         static const int FULL_WORD_MULTIPLIER = 2;
     };
 
+    // proximity info state
+    void initInputParams(const ProximityInfo *proximityInfo, const int32_t *inputCodes,
+            const int inputLength, const int *xCoordinates, const int *yCoordinates) {
+        mProximityInfoState.initInputParams(
+                proximityInfo, inputCodes, inputLength, xCoordinates, yCoordinates);
+    }
+
+    const unsigned short* getPrimaryInputWord() const {
+        return mProximityInfoState.getPrimaryInputWord();
+    }
+
+    unsigned short getPrimaryCharAt(const int index) const {
+        return mProximityInfoState.getPrimaryCharAt(index);
+    }
+
  private:
     inline void incrementInputIndex();
     inline void incrementOutputIndex();
@@ -240,7 +256,7 @@
     bool mExceeding;
     bool mTransposing;
     bool mSkipping;
-
+    ProximityInfoState mProximityInfoState;
 };
 } // namespace latinime
 #endif // LATINIME_CORRECTION_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 39b91d7..d1aa664 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -73,9 +73,6 @@
     copyOrFillZero(mSweetSpotRadii, sweetSpotRadii, KEY_COUNT * sizeof(mSweetSpotRadii[0]));
 
     initializeCodeToKeyIndex();
-    mProximityInfoState = new ProximityInfoState(this, MAX_PROXIMITY_CHARS_SIZE,
-            HAS_TOUCH_POSITION_CORRECTION_DATA, MOST_COMMON_KEY_WIDTH_SQUARE, mLocaleStr,
-            KEY_COUNT, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH, GRID_HEIGHT);
 }
 
 // Build the reversed look up table from the char code to the index in mKeyXCoordinates,
@@ -92,7 +89,6 @@
 
 ProximityInfo::~ProximityInfo() {
     delete[] mProximityCharsArray;
-    delete mProximityInfoState;
 }
 
 inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
@@ -203,12 +199,6 @@
     }
 }
 
-// TODO: remove
-void ProximityInfo::initInputParams(const int32_t *inputCodes, const int inputLength,
-        const int *xCoordinates, const int *yCoordinates) {
-    mProximityInfoState->initInputParams(inputCodes, inputLength, xCoordinates, yCoordinates);
-}
-
 int ProximityInfo::getKeyIndex(const int c) const {
     if (KEY_COUNT == 0) {
         // We do not have the coordinate data
@@ -220,47 +210,4 @@
     }
     return mCodeToKeyIndex[baseLowerC];
 }
-
-// TODO: remove
-inline const int* ProximityInfo::getProximityCharsAt(const int index) const {
-    return mProximityInfoState->getProximityCharsAt(index);
-}
-
-// TODO: remove
-unsigned short ProximityInfo::getPrimaryCharAt(const int index) const {
-    return mProximityInfoState->getPrimaryCharAt(index);
-}
-
-// TODO: remove
-bool ProximityInfo::existsCharInProximityAt(const int index, const int c) const {
-    return mProximityInfoState->existsCharInProximityAt(index, c);
-}
-
-// TODO: remove
-bool ProximityInfo::existsAdjacentProximityChars(const int index) const {
-    return mProximityInfoState->existsAdjacentProximityChars(index);
-}
-
-// TODO: remove
-ProximityType ProximityInfo::getMatchedProximityId(const int index,
-        const unsigned short c, const bool checkProximityChars, int *proximityIndex) const {
-    return mProximityInfoState->getMatchedProximityId(
-            index, c, checkProximityChars, proximityIndex);
-}
-
-// TODO: remove
-int ProximityInfo::getNormalizedSquaredDistance(
-        const int inputIndex, const int proximityIndex) const {
-    return mProximityInfoState->getNormalizedSquaredDistance(inputIndex, proximityIndex);
-}
-
-// TODO: remove
-const unsigned short* ProximityInfo::getPrimaryInputWord() const {
-    return mProximityInfoState->getPrimaryInputWord();
-}
-
-// TODO: remove
-bool ProximityInfo::touchPositionCorrectionEnabled() const {
-    return mProximityInfoState->touchPositionCorrectionEnabled();
-}
 } // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index a5ed57d..67f2f60 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -25,11 +25,9 @@
 namespace latinime {
 
 class Correction;
-class ProximityInfoState;
 
 class ProximityInfo {
  public:
-
     ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
             const int keyboardWidth, const int keyboardHeight, const int gridWidth,
             const int gridHeight, const int mostCommonkeyWidth,
@@ -68,21 +66,37 @@
     void calculateNearbyKeyCodes(
             const int x, const int y, const int32_t primaryKey, int *inputCodes) const;
 
-    ////////////////////////////////////
-    // Access to proximity info state //
-    // TODO: remove                   //
-    ////////////////////////////////////
-    void initInputParams(const int32_t *inputCodes, const int inputLength,
-            const int *xCoordinates, const int *yCoordinates);
-    const int* getProximityCharsAt(const int index) const;
-    unsigned short getPrimaryCharAt(const int index) const;
-    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 bool checkProximityChars, int *proximityIndex = 0) const;
-    const unsigned short* getPrimaryInputWord() const;
-    bool touchPositionCorrectionEnabled() const;
-    ////////////////////////////////////
+    bool hasTouchPositionCorrectionData() const {
+        return HAS_TOUCH_POSITION_CORRECTION_DATA;
+    }
+
+    int getMostCommonKeyWidthSquare() const {
+        return MOST_COMMON_KEY_WIDTH_SQUARE;
+    }
+
+    std::string getLocaleStr() const {
+        return mLocaleStr;
+    }
+
+    int getKeyCount() const {
+        return KEY_COUNT;
+    }
+
+    int getCellHeight() const {
+        return CELL_HEIGHT;
+    }
+
+    int getCellWidth() const {
+        return CELL_WIDTH;
+    }
+
+    int getGridWidth() const {
+        return GRID_WIDTH;
+    }
+
+    int getGridHeight() const {
+        return GRID_HEIGHT;
+    }
 
  private:
     // The max number of the keys in one keyboard layout
@@ -121,7 +135,6 @@
     float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
     int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
     // TODO: move to correction.h
-    ProximityInfoState *mProximityInfoState;
 };
 
 } // namespace latinime
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 4161afb..149299e 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -27,25 +27,41 @@
 #include "proximity_info_state.h"
 
 namespace latinime {
-void ProximityInfoState::initInputParams(const int32_t* inputCodes, const int inputLength,
+void ProximityInfoState::initInputParams(
+        const ProximityInfo* proximityInfo, const int32_t* inputCodes, const int inputLength,
         const int* xCoordinates, const int* yCoordinates) {
+    mProximityInfo = proximityInfo;
+    mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
+    mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare();
+    mLocaleStr = proximityInfo->getLocaleStr();
+    mKeyCount = proximityInfo->getKeyCount();
+    mCellHeight = proximityInfo->getCellHeight();
+    mCellWidth = proximityInfo->getCellWidth();
+    mGridHeight = proximityInfo->getGridWidth();
+    mGridWidth = proximityInfo->getGridHeight();
+    const int normalizedSquaredDistancesLength =
+            MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL;
+    for (int i = 0; i < normalizedSquaredDistancesLength; ++i) {
+        mNormalizedSquaredDistances[i] = NOT_A_DISTANCE;
+    }
+
     memset(mInputCodes, 0,
-            MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE * sizeof(mInputCodes[0]));
+            MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE_INTERNAL * sizeof(mInputCodes[0]));
 
     for (int i = 0; i < inputLength; ++i) {
         const int32_t primaryKey = inputCodes[i];
         const int x = xCoordinates[i];
         const int y = yCoordinates[i];
-        int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE];
+        int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL];
         mProximityInfo->calculateNearbyKeyCodes(x, y, primaryKey, proximities);
     }
 
     if (DEBUG_PROXIMITY_CHARS) {
         for (int i = 0; i < inputLength; ++i) {
             AKLOGI("---");
-            for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) {
-                int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
-                int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
+            for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) {
+                int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
+                int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
                 icc += 0;
                 icfjc += 0;
                 AKLOGI("--- (%d)%c,%c", i, icc, icfjc); AKLOGI("--- A<%d>,B<%d>", icc, icfjc);
@@ -54,8 +70,8 @@
     }
     mInputXCoordinates = xCoordinates;
     mInputYCoordinates = yCoordinates;
-    mTouchPositionCorrectionEnabled = HAS_TOUCH_POSITION_CORRECTION_DATA && xCoordinates
-            && yCoordinates;
+    mTouchPositionCorrectionEnabled =
+            mHasTouchPositionCorrectionData && xCoordinates && yCoordinates;
     mInputLength = inputLength;
     for (int i = 0; i < inputLength; ++i) {
         mPrimaryInputWord[i] = getPrimaryCharAt(i);
@@ -74,17 +90,17 @@
             a += 0;
             AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y);
         }
-        for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) {
+        for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityChars[j] > 0; ++j) {
             const int currentChar = proximityChars[j];
             const float squaredDistance =
                     hasInputCoordinates() ? calculateNormalizedSquaredDistance(
                             mProximityInfo->getKeyIndex(currentChar), i) :
                             NOT_A_DISTANCE_FLOAT;
             if (squaredDistance >= 0.0f) {
-                mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
+                mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] =
                         (int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
             } else {
-                mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
+                mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] =
                         (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO :
                                 PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
             }
@@ -94,4 +110,30 @@
         }
     }
 }
+
+float ProximityInfoState::calculateNormalizedSquaredDistance(
+        const int keyIndex, const int inputIndex) const {
+    if (keyIndex == NOT_AN_INDEX) {
+        return NOT_A_DISTANCE_FLOAT;
+    }
+    if (!mProximityInfo->hasSweetSpotData(keyIndex)) {
+        return NOT_A_DISTANCE_FLOAT;
+    }
+    if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) {
+        return NOT_A_DISTANCE_FLOAT;
+    }
+    const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(
+            keyIndex, inputIndex);
+    const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex));
+    return squaredDistance / squaredRadius;
+}
+
+float ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter(
+        const int keyIndex, const int inputIndex) const {
+    const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex);
+    const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex);
+    const float inputX = (float)mInputXCoordinates[inputIndex];
+    const float inputY = (float)mInputYCoordinates[inputIndex];
+    return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
+}
 } // namespace latinime
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 8113171..3a98d9b 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -22,6 +22,7 @@
 #include <string>
 
 #include "additional_proximity_chars.h"
+#include "char_utils.h"
 #include "defines.h"
 
 namespace latinime {
@@ -33,8 +34,6 @@
     static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
     static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
             1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
-    // The max number of the keys in one keyboard layout
-    static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64;
     // The upper limit of the char code in mCodeToKeyIndex
     static const int MAX_CHAR_CODE = 127;
     static const float NOT_A_DISTANCE_FLOAT = -1.0f;
@@ -43,39 +42,15 @@
     /////////////////////////////////////////
     // Defined in proximity_info_state.cpp //
     /////////////////////////////////////////
-    void initInputParams(const int32_t* inputCodes, const int inputLength,
-           const int* xCoordinates, const int* yCoordinates);
+    void initInputParams(
+            const ProximityInfo* proximityInfo, const int32_t* inputCodes, const int inputLength,
+            const int* xCoordinates, const int* yCoordinates);
 
     /////////////////////////////////////////
     // Defined here                        //
     /////////////////////////////////////////
-    // TODO: Move the constructor to initInputParams
-    ProximityInfoState(ProximityInfo* proximityInfo, const int maxProximityCharsSize,
-            const bool hasTouchPositionCorrectionData, const int mostCommonKeyWidthSquare,
-            const std::string localeStr, const int keyCount, const int cellHeight,
-            const int cellWidth, const int gridHeight, const int gridWidth)
-            : mProximityInfo(proximityInfo),
-              MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize),
-              HAS_TOUCH_POSITION_CORRECTION_DATA(hasTouchPositionCorrectionData),
-              MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidthSquare),
-              LOCALE_STR(localeStr),
-              KEY_COUNT(keyCount),
-              CELL_HEIGHT(cellHeight),
-              CELL_WIDTH(cellWidth),
-              GRID_HEIGHT(gridHeight),
-              GRID_WIDTH(gridWidth),
-              mInputXCoordinates(0),
-              mInputYCoordinates(0),
-              mTouchPositionCorrectionEnabled(false) {
-        const int normalizedSquaredDistancesLength =
-                MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL;
-        for (int i = 0; i < normalizedSquaredDistancesLength; ++i) {
-            mNormalizedSquaredDistances[i] = NOT_A_DISTANCE;
-        }
-    }
-
     inline const int* getProximityCharsAt(const int index) const {
-        return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE);
+        return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
     }
 
     inline unsigned short getPrimaryCharAt(const int index) const {
@@ -85,7 +60,7 @@
     inline bool 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) {
+        while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) {
             if (chars[i++] == c) {
                 return true;
             }
@@ -120,7 +95,7 @@
     // 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.
     inline ProximityType getMatchedProximityId(const int index,
-            const unsigned short c, const bool checkProximityChars, int *proximityIndex) const {
+            const unsigned short c, const bool checkProximityChars, int *proximityIndex = 0) const {
         const int *currentChars = getProximityCharsAt(index);
         const int firstChar = currentChars[0];
         const unsigned short baseLowerC = toBaseLowerCase(c);
@@ -141,7 +116,7 @@
 
         // Not an exact nor an accent-alike match: search the list of close keys
         int j = 1;
-        while (j < MAX_PROXIMITY_CHARS_SIZE
+        while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
                 && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
             const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
             if (matched) {
@@ -152,10 +127,10 @@
             }
             ++j;
         }
-        if (j < MAX_PROXIMITY_CHARS_SIZE
+        if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
                 && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
             ++j;
-            while (j < MAX_PROXIMITY_CHARS_SIZE
+            while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
                     && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
                 const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
                 if (matched) {
@@ -174,7 +149,8 @@
 
     inline int getNormalizedSquaredDistance(
             const int inputIndex, const int proximityIndex) const {
-        return mNormalizedSquaredDistances[inputIndex * MAX_PROXIMITY_CHARS_SIZE + proximityIndex];
+        return mNormalizedSquaredDistances[
+                inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex];
     }
 
     inline const unsigned short* getPrimaryInputWord() const {
@@ -186,38 +162,23 @@
     }
 
  private:
-    inline float square(const float x) const { return x * x; }
+    /////////////////////////////////////////
+    // Defined in proximity_info_state.cpp //
+    /////////////////////////////////////////
+    float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
 
-    float calculateNormalizedSquaredDistance(
-            const int keyIndex, const int inputIndex) const {
-        if (keyIndex == NOT_AN_INDEX) {
-            return NOT_A_DISTANCE_FLOAT;
-        }
-        if (!mProximityInfo->hasSweetSpotData(keyIndex)) {
-            return NOT_A_DISTANCE_FLOAT;
-        }
-        if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) {
-            return NOT_A_DISTANCE_FLOAT;
-        }
-        const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(
-                keyIndex, inputIndex);
-        const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex));
-        return squaredDistance / squaredRadius;
-    }
+    float calculateSquaredDistanceFromSweetSpotCenter(
+            const int keyIndex, const int inputIndex) const;
+
+    /////////////////////////////////////////
+    // Defined here                        //
+    /////////////////////////////////////////
+    inline float square(const float x) const { return x * x; }
 
     bool hasInputCoordinates() const {
         return mInputXCoordinates && mInputYCoordinates;
     }
 
-    float calculateSquaredDistanceFromSweetSpotCenter(
-            const int keyIndex, const int inputIndex) const {
-        const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex);
-        const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex);
-        const float inputX = (float)mInputXCoordinates[inputIndex];
-        const float inputY = (float)mInputYCoordinates[inputIndex];
-        return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
-    }
-
     bool sameAsTyped(const unsigned short *word, int length) const {
         if (length != mInputLength) {
             return false;
@@ -227,23 +188,22 @@
             if ((unsigned int) *inputCodes != (unsigned int) *word) {
                 return false;
             }
-            inputCodes += MAX_PROXIMITY_CHARS_SIZE;
+            inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
             word++;
         }
         return true;
     }
 
-    // TODO: const
-    ProximityInfo *mProximityInfo;
-    const int MAX_PROXIMITY_CHARS_SIZE;
-    const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
-    const int MOST_COMMON_KEY_WIDTH_SQUARE;
-    const std::string LOCALE_STR;
-    const int KEY_COUNT;
-    const int CELL_HEIGHT;
-    const int CELL_WIDTH;
-    const int GRID_HEIGHT;
-    const int GRID_WIDTH;
+    // const
+    const ProximityInfo *mProximityInfo;
+    bool mHasTouchPositionCorrectionData;
+    int mMostCommonKeyWidthSquare;
+    std::string mLocaleStr;
+    int mKeyCount;
+    int mCellHeight;
+    int mCellWidth;
+    int mGridHeight;
+    int mGridWidth;
 
     const int *mInputXCoordinates;
     const int *mInputYCoordinates;
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 157e47d..27196f4 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -103,7 +103,7 @@
         const bool useFullEditDistance, const int *codesSrc,
         const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
         WordsPriorityQueuePool *queuePool,
-        const digraph_t* const digraphs, const unsigned int digraphsSize) {
+        const digraph_t* const digraphs, const unsigned int digraphsSize) const {
 
     const int startIndex = codesDest - codesBuffer;
     if (currentDepth < MAX_DIGRAPH_SEARCH_DEPTH) {
@@ -173,7 +173,7 @@
         WordsPriorityQueuePool *queuePool, Correction *correction, const int *xcoordinates,
         const int *ycoordinates, const int *codes, const int codesSize,
         const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
-        const bool useFullEditDistance, unsigned short *outWords, int *frequencies) {
+        const bool useFullEditDistance, unsigned short *outWords, int *frequencies) const {
 
     queuePool->clearAll();
     Correction* masterCorrection = correction;
@@ -205,17 +205,17 @@
     PROF_START(20);
     if (DEBUG_DICT) {
         float ns = queuePool->getMasterQueue()->getHighestNormalizedScore(
-                proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0);
+                correction->getPrimaryInputWord(), codesSize, 0, 0, 0);
         ns += 0;
         AKLOGI("Max normalized score = %f", ns);
     }
     const int suggestedWordsCount =
             queuePool->getMasterQueue()->outputSuggestions(
-                    proximityInfo->getPrimaryInputWord(), codesSize, frequencies, outWords);
+                    correction->getPrimaryInputWord(), codesSize, frequencies, outWords);
 
     if (DEBUG_DICT) {
         float ns = queuePool->getMasterQueue()->getHighestNormalizedScore(
-                proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0);
+                correction->getPrimaryInputWord(), codesSize, 0, 0, 0);
         ns += 0;
         AKLOGI("Returning %d words", suggestedWordsCount);
         /// Print the returned words
@@ -235,7 +235,8 @@
 void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
         const int *xcoordinates, const int *ycoordinates, const int *codes,
         const int inputLength, const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
-        const bool useFullEditDistance, Correction *correction, WordsPriorityQueuePool *queuePool) {
+        const bool useFullEditDistance, Correction *correction,
+        WordsPriorityQueuePool *queuePool) const {
 
     PROF_OPEN;
     PROF_START(0);
@@ -259,7 +260,7 @@
     WordsPriorityQueue* masterQueue = queuePool->getMasterQueue();
     if (masterQueue->size() > 0) {
         float nsForMaster = masterQueue->getHighestNormalizedScore(
-                proximityInfo->getPrimaryInputWord(), inputLength, 0, 0, 0);
+                correction->getPrimaryInputWord(), inputLength, 0, 0, 0);
         hasAutoCorrectionCandidate = (nsForMaster > START_TWO_WORDS_CORRECTION_THRESHOLD);
     }
     PROF_END(4);
@@ -288,11 +289,11 @@
                 const unsigned short* word = sw->mWord;
                 const int wordLength = sw->mWordLength;
                 float ns = Correction::RankingAlgorithm::calcNormalizedScore(
-                        proximityInfo->getPrimaryInputWord(), i, word, wordLength, score);
+                        correction->getPrimaryInputWord(), i, word, wordLength, score);
                 ns += 0;
                 AKLOGI("--- TOP SUB WORDS for %d --- %d %f [%d]", i, score, ns,
                         (ns > TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD));
-                DUMP_WORD(proximityInfo->getPrimaryInputWord(), i);
+                DUMP_WORD(correction->getPrimaryInputWord(), i);
                 DUMP_WORD(word, wordLength);
             }
         }
@@ -300,12 +301,13 @@
 }
 
 void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xCoordinates,
-        const int *yCoordinates, const int *codes, const int inputLength, Correction *correction) {
+        const int *yCoordinates, const int *codes, const int inputLength,
+        Correction *correction) const {
     if (DEBUG_DICT) {
         AKLOGI("initSuggest");
         DUMP_WORD_INT(codes, inputLength);
     }
-    proximityInfo->initInputParams(codes, inputLength, xCoordinates, yCoordinates);
+    correction->initInputParams(proximityInfo, codes, inputLength, xCoordinates, yCoordinates);
     const int maxDepth = min(inputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
     correction->initCorrection(proximityInfo, inputLength, maxDepth);
 }
@@ -317,7 +319,7 @@
         const int *xcoordinates, const int *ycoordinates, const int *codes,
         const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
         const bool useFullEditDistance, const int inputLength,
-        Correction *correction, WordsPriorityQueuePool *queuePool) {
+        Correction *correction, WordsPriorityQueuePool *queuePool) const {
     initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, inputLength, correction);
     getSuggestionCandidates(useFullEditDistance, inputLength, bigramMap, bigramFilter, correction,
             queuePool, true /* doAutoCompletion */, DEFAULT_MAX_ERRORS, FIRST_WORD_INDEX);
@@ -326,7 +328,7 @@
 void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance,
         const int inputLength, const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
         Correction *correction, WordsPriorityQueuePool *queuePool,
-        const bool doAutoCompletion, const int maxErrors, const int currentWordIndex) {
+        const bool doAutoCompletion, const int maxErrors, const int currentWordIndex) const {
     uint8_t totalTraverseCount = correction->pushAndGetTotalTraverseCount();
     if (DEBUG_DICT) {
         AKLOGI("Traverse count %d", totalTraverseCount);
@@ -374,7 +376,7 @@
 inline void UnigramDictionary::onTerminal(const int probability,
         const TerminalAttributes& terminalAttributes, Correction *correction,
         WordsPriorityQueuePool *queuePool, const bool addToMasterQueue,
-        const int currentWordIndex) {
+        const int currentWordIndex) const {
     const int inputIndex = correction->getInputIndex();
     const bool addToSubQueue = inputIndex < SUB_QUEUE_MAX_COUNT;
 
@@ -430,7 +432,7 @@
         const bool hasAutoCorrectionCandidate, const int currentWordIndex,
         const int inputWordStartPos, const int inputWordLength,
         const int outputWordStartPos, const bool isSpaceProximity, int *freqArray,
-        int*wordLengthArray, unsigned short* outputWord, int *outputWordLength) {
+        int*wordLengthArray, unsigned short* outputWord, int *outputWordLength) const {
     if (inputWordLength > MULTIPLE_WORDS_SUGGESTION_MAX_WORD_LENGTH) {
         return FLAG_MULTIPLE_SUGGEST_ABORT;
     }
@@ -479,11 +481,12 @@
     initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes,
             inputLength, correction);
 
+    unsigned short word[MAX_WORD_LENGTH_INTERNAL];
     int freq = getMostFrequentWordLike(
-            inputWordStartPos, inputWordLength, proximityInfo, mWord);
+            inputWordStartPos, inputWordLength, correction, word);
     if (freq > 0) {
         nextWordLength = inputWordLength;
-        tempOutputWord = mWord;
+        tempOutputWord = word;
     } else if (!hasAutoCorrectionCandidate) {
         if (inputWordStartPos > 0) {
             const int offset = inputWordStartPos;
@@ -510,7 +513,7 @@
         }
         int score = 0;
         const float ns = queue->getHighestNormalizedScore(
-                proximityInfo->getPrimaryInputWord(), inputWordLength,
+                correction->getPrimaryInputWord(), inputWordLength,
                 &tempOutputWord, &score, &nextWordLength);
         if (DEBUG_DICT) {
             AKLOGI("NS(%d) = %f, Score = %d", currentWordIndex, ns, score);
@@ -577,7 +580,7 @@
         Correction *correction, WordsPriorityQueuePool* queuePool,
         const bool hasAutoCorrectionCandidate, const int startInputPos, const int startWordIndex,
         const int outputWordLength, int *freqArray, int* wordLengthArray,
-        unsigned short* outputWord) {
+        unsigned short* outputWord) const {
     if (startWordIndex >= (MULTIPLE_WORDS_SUGGESTION_MAX_WORDS - 1)) {
         // Return if the last word index
         return;
@@ -656,7 +659,7 @@
         const int *xcoordinates, const int *ycoordinates, const int *codes,
         const bool useFullEditDistance, const int inputLength,
         Correction *correction, WordsPriorityQueuePool* queuePool,
-        const bool hasAutoCorrectionCandidate) {
+        const bool hasAutoCorrectionCandidate) const {
     if (inputLength >= MAX_WORD_LENGTH) return;
     if (DEBUG_DICT) {
         AKLOGI("--- Suggest multiple words");
@@ -678,11 +681,11 @@
 // Wrapper for getMostFrequentWordLikeInner, which matches it to the previous
 // interface.
 inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex,
-        const int inputLength, ProximityInfo *proximityInfo, unsigned short *word) {
+        const int inputLength, Correction *correction, unsigned short *word) const {
     uint16_t inWord[inputLength];
 
     for (int i = 0; i < inputLength; ++i) {
-        inWord[i] = (uint16_t)proximityInfo->getPrimaryCharAt(startInputIndex + i);
+        inWord[i] = (uint16_t)correction->getPrimaryCharAt(startInputIndex + i);
     }
     return getMostFrequentWordLikeInner(inWord, inputLength, word);
 }
@@ -751,21 +754,24 @@
 // Will find the highest frequency of the words like the one passed as an argument,
 // that is, everything that only differs by case/accents.
 int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWord,
-        const int length, short unsigned int* outWord) {
+        const int length, short unsigned int* outWord) const {
     int32_t newWord[MAX_WORD_LENGTH_INTERNAL];
     int depth = 0;
     int maxFreq = -1;
     const uint8_t* const root = DICT_ROOT;
+    int stackChildCount[MAX_WORD_LENGTH_INTERNAL];
+    int stackInputIndex[MAX_WORD_LENGTH_INTERNAL];
+    int stackSiblingPos[MAX_WORD_LENGTH_INTERNAL];
 
     int startPos = 0;
-    mStackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos);
-    mStackInputIndex[0] = 0;
-    mStackSiblingPos[0] = startPos;
+    stackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos);
+    stackInputIndex[0] = 0;
+    stackSiblingPos[0] = startPos;
     while (depth >= 0) {
-        const int charGroupCount = mStackChildCount[depth];
-        int pos = mStackSiblingPos[depth];
+        const int charGroupCount = stackChildCount[depth];
+        int pos = stackSiblingPos[depth];
         for (int charGroupIndex = charGroupCount - 1; charGroupIndex >= 0; --charGroupIndex) {
-            int inputIndex = mStackInputIndex[depth];
+            int inputIndex = stackInputIndex[depth];
             const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos);
             // Test whether all chars in this group match with the word we are searching for. If so,
             // we want to traverse its children (or if the length match, evaluate its frequency).
@@ -785,15 +791,15 @@
             // anyway, so don't traverse unless inputIndex < length.
             if (isAlike && (-1 != childrenNodePos) && (inputIndex < length)) {
                 // Save position for this depth, to get back to this once children are done
-                mStackChildCount[depth] = charGroupIndex;
-                mStackSiblingPos[depth] = siblingPos;
+                stackChildCount[depth] = charGroupIndex;
+                stackSiblingPos[depth] = siblingPos;
                 // Prepare stack values for next depth
                 ++depth;
                 int childrenPos = childrenNodePos;
-                mStackChildCount[depth] =
+                stackChildCount[depth] =
                         BinaryFormat::getGroupCountAndForwardPointer(root, &childrenPos);
-                mStackSiblingPos[depth] = childrenPos;
-                mStackInputIndex[depth] = inputIndex;
+                stackSiblingPos[depth] = childrenPos;
+                stackInputIndex[depth] = inputIndex;
                 pos = childrenPos;
                 // Go to the next depth level.
                 ++depth;
@@ -848,7 +854,7 @@
 inline bool UnigramDictionary::processCurrentNode(const int initialPos,
         const std::map<int, int> *bigramMap, const uint8_t *bigramFilter, Correction *correction,
         int *newCount, int *newChildrenPosition, int *nextSiblingPosition,
-        WordsPriorityQueuePool *queuePool, const int currentWordIndex) {
+        WordsPriorityQueuePool *queuePool, const int currentWordIndex) const {
     if (DEBUG_DICT) {
         correction->checkState();
     }
diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h
index a1a8299..1b26eff 100644
--- a/native/jni/src/unigram_dictionary.h
+++ b/native/jni/src/unigram_dictionary.h
@@ -81,7 +81,7 @@
             Correction *correction, const int *xcoordinates, const int *ycoordinates,
             const int *codes, const int codesSize, const std::map<int, int> *bigramMap,
             const uint8_t *bigramFilter, const bool useFullEditDistance, unsigned short *outWords,
-            int *frequencies);
+            int *frequencies) const;
     virtual ~UnigramDictionary();
 
  private:
@@ -89,7 +89,7 @@
             const int *ycoordinates, const int *codes, const int inputLength,
             const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
             const bool useFullEditDistance, Correction *correction,
-            WordsPriorityQueuePool *queuePool);
+            WordsPriorityQueuePool *queuePool) const;
     int getDigraphReplacement(const int *codes, const int i, const int codesSize,
             const digraph_t* const digraphs, const unsigned int digraphsSize) const;
     void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo,
@@ -99,37 +99,36 @@
         const bool useFullEditDistance, const int* codesSrc, const int codesRemain,
         const int currentDepth, int* codesDest, Correction *correction,
         WordsPriorityQueuePool* queuePool, const digraph_t* const digraphs,
-        const unsigned int digraphsSize);
+        const unsigned int digraphsSize) const;
     void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
-            const int *ycoordinates, const int *codes, const int codesSize, Correction *correction);
+            const int *ycoordinates, const int *codes, const int codesSize,
+            Correction *correction) const;
     void getOneWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
             const int *ycoordinates, const int *codes, const std::map<int, int> *bigramMap,
             const uint8_t *bigramFilter, const bool useFullEditDistance, const int inputLength,
-            Correction *correction, WordsPriorityQueuePool* queuePool);
+            Correction *correction, WordsPriorityQueuePool* queuePool) const;
     void getSuggestionCandidates(
             const bool useFullEditDistance, const int inputLength,
             const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
             Correction *correction, WordsPriorityQueuePool* queuePool, const bool doAutoCompletion,
-            const int maxErrors, const int currentWordIndex);
+            const int maxErrors, const int currentWordIndex) const;
     void getSplitMultipleWordsSuggestions(ProximityInfo *proximityInfo,
             const int *xcoordinates, const int *ycoordinates, const int *codes,
             const bool useFullEditDistance, const int inputLength,
             Correction *correction, WordsPriorityQueuePool* queuePool,
-            const bool hasAutoCorrectionCandidate);
+            const bool hasAutoCorrectionCandidate) const;
     void onTerminal(const int freq, const TerminalAttributes& terminalAttributes,
             Correction *correction, WordsPriorityQueuePool *queuePool, const bool addToMasterQueue,
-            const int currentWordIndex);
-    bool needsToSkipCurrentNode(const unsigned short c,
-            const int inputIndex, const int skipPos, const int depth);
+            const int currentWordIndex) const;
     // Process a node by considering proximity, missing and excessive character
     bool processCurrentNode(const int initialPos, const std::map<int, int> *bigramMap,
             const uint8_t *bigramFilter, Correction *correction, int *newCount,
             int *newChildPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool,
-            const int currentWordIndex);
+            const int currentWordIndex) const;
     int getMostFrequentWordLike(const int startInputIndex, const int inputLength,
-            ProximityInfo *proximityInfo, unsigned short *word);
+            Correction *correction, unsigned short *word) const;
     int getMostFrequentWordLikeInner(const uint16_t* const inWord, const int length,
-            short unsigned int *outWord);
+            short unsigned int *outWord) const;
     int getSubStringSuggestion(
             ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates,
             const int *codes, const bool useFullEditDistance, Correction *correction,
@@ -137,14 +136,14 @@
             const bool hasAutoCorrectionCandidate, const int currentWordIndex,
             const int inputWordStartPos, const int inputWordLength,
             const int outputWordStartPos, const bool isSpaceProximity, int *freqArray,
-            int *wordLengthArray, unsigned short* outputWord, int *outputWordLength);
+            int *wordLengthArray, unsigned short* outputWord, int *outputWordLength) const;
     void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo,
             const int *xcoordinates, const int *ycoordinates, const int *codes,
             const bool useFullEditDistance, const int inputLength,
             Correction *correction, WordsPriorityQueuePool* queuePool,
             const bool hasAutoCorrectionCandidate, const int startPos, const int startWordIndex,
             const int outputWordLength, int *freqArray, int* wordLengthArray,
-            unsigned short* outputWord);
+            unsigned short* outputWord) const;
 
     const uint8_t* const DICT_ROOT;
     const int MAX_WORD_LENGTH;
@@ -158,12 +157,6 @@
 
     static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
     static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
-
-    // Still bundled members
-    unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
-    int mStackChildCount[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
-    int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
-    int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
 };
 } // namespace latinime