Increase target size of preferred letters while typing.

This increases the chance of hitting the correct letter when typing a word
that exists in the dictionary, rather than only correct it after the fact.
It is most effective after 2 or 3 letters of a word have been typed and gets
more accurate with more typed letters in the word.

If 2 adjacent letters have similar probabilities of occuring, then there is no
hit correction applied.
diff --git a/dictionary/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/dictionary/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 3076085..3dda062 100644
--- a/dictionary/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/dictionary/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -89,7 +89,7 @@
 static int latinime_BinaryDictionary_getSuggestions(
         JNIEnv *env, jobject object, jint dict, jintArray inputArray, jint arraySize,
         jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxWords,
-        jint maxAlternatives, jint skipPos)
+        jint maxAlternatives, jint skipPos, jintArray nextLettersArray, jint nextLettersSize)
 {
     Dictionary *dictionary = (Dictionary*) dict;
     if (dictionary == NULL)
@@ -98,13 +98,16 @@
     int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
     int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
     jchar *outputChars = env->GetCharArrayElements(outputArray, NULL);
+    int *nextLetters = nextLettersArray != NULL ? env->GetIntArrayElements(nextLettersArray, NULL)
+            : NULL;
 
     int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars, frequencies,
-            maxWordLength, maxWords, maxAlternatives, skipPos);
+            maxWordLength, maxWords, maxAlternatives, skipPos, nextLetters, nextLettersSize);
     
     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
+    env->ReleaseIntArrayElements(nextLettersArray, nextLetters, 0);
     
     return count;
 }
@@ -136,7 +139,7 @@
     {"openNative",           "(Landroid/content/res/AssetManager;Ljava/lang/String;II)I",
                                           (void*)latinime_BinaryDictionary_open},
     {"closeNative",          "(I)V",            (void*)latinime_BinaryDictionary_close},
-    {"getSuggestionsNative", "(I[II[C[IIIII)I",  (void*)latinime_BinaryDictionary_getSuggestions},
+    {"getSuggestionsNative", "(I[II[C[IIIII[II)I",  (void*)latinime_BinaryDictionary_getSuggestions},
     {"isValidWordNative",    "(I[CI)Z",         (void*)latinime_BinaryDictionary_isValidWord}
 };
 
diff --git a/dictionary/src/dictionary.cpp b/dictionary/src/dictionary.cpp
index 306aff5..6e6f441 100644
--- a/dictionary/src/dictionary.cpp
+++ b/dictionary/src/dictionary.cpp
@@ -49,7 +49,8 @@
 }
 
 int Dictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
-        int maxWordLength, int maxWords, int maxAlternatives, int skipPos)
+        int maxWordLength, int maxWords, int maxAlternatives, int skipPos,
+        int *nextLetters, int nextLettersSize)
 {
     int suggWords;
     mFrequencies = frequencies;
@@ -61,6 +62,8 @@
     mMaxWords = maxWords;
     mSkipPos = skipPos;
     mMaxEditDistance = mInputLength < 5 ? 2 : mInputLength / 2;
+    mNextLettersFrequencies = nextLetters;
+    mNextLettersSize = nextLettersSize;
 
     getWordsRec(0, 0, mInputLength * 3, false, 1, 0, 0);
 
@@ -68,9 +71,27 @@
     suggWords = 0;
     while (suggWords < mMaxWords && mFrequencies[suggWords] > 0) suggWords++;
     if (DEBUG_DICT) LOGI("Returning %d words", suggWords);
+
+    if (DEBUG_DICT) {
+        LOGI("Next letters: ");
+        for (int k = 0; k < nextLettersSize; k++) {
+            if (mNextLettersFrequencies[k] > 0) {
+                LOGI("%c = %d,", k, mNextLettersFrequencies[k]);
+            }
+        }
+        LOGI("\n");
+    }
     return suggWords;
 }
 
+void
+Dictionary::registerNextLetter(unsigned short c)
+{
+    if (c < mNextLettersSize) {
+        mNextLettersFrequencies[c]++;
+    }
+}
+
 unsigned short
 Dictionary::getChar(int *pos)
 {
@@ -210,6 +231,9 @@
             mWord[depth] = c;
             if (terminal) {
                 addWord(mWord, depth + 1, freq * snr);
+                if (depth >= mInputLength && mSkipPos < 0) {
+                    registerNextLetter(mWord[mInputLength]);
+                }
             }
             if (childrenAddress != 0) {
                 getWordsRec(childrenAddress, depth + 1, maxDepth,
diff --git a/dictionary/src/dictionary.h b/dictionary/src/dictionary.h
index a12c035..3749f3d 100644
--- a/dictionary/src/dictionary.h
+++ b/dictionary/src/dictionary.h
@@ -32,7 +32,8 @@
 public:
     Dictionary(void *dict, int typedLetterMultipler, int fullWordMultiplier);
     int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
-        int maxWordLength, int maxWords, int maxAlternatives, int skipPos);
+            int maxWordLength, int maxWords, int maxAlternatives, int skipPos,
+            int *nextLetters, int nextLettersSize);
     bool isValidWord(unsigned short *word, int length);
     void setAsset(void *asset) { mAsset = asset; }
     void *getAsset() { return mAsset; }
@@ -53,6 +54,7 @@
     void getWordsRec(int pos, int depth, int maxDepth, bool completion, int frequency,
             int inputIndex, int diffs);
     bool isValidWordRec(int pos, unsigned short *word, int offset, int length);
+    void registerNextLetter(unsigned short c);
 
     unsigned char *mDict;
     void *mAsset;
@@ -70,6 +72,8 @@
 
     int mFullWordMultiplier;
     int mTypedLetterMultiplier;
+    int *mNextLettersFrequencies;
+    int mNextLettersSize;
 };
 
 // ----------------------------------------------------------------------------