Merge "Move tools/makedict from platform/development to platform/packages/inputmethods/LatinIME"
diff --git a/java/res/drawable-land-mdpi/key_hint_at_holo.9.png b/java/res/drawable-land-mdpi/key_hint_at_holo.9.png
index 627e7a0..d1ea313 100644
--- a/java/res/drawable-land-mdpi/key_hint_at_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_at_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_at_large_holo.9.png b/java/res/drawable-land-mdpi/key_hint_at_large_holo.9.png
index 9569217..786bbc5 100644
--- a/java/res/drawable-land-mdpi/key_hint_at_large_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_at_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_exclamation_holo.9.png b/java/res/drawable-land-mdpi/key_hint_exclamation_holo.9.png
index 89c5aae..a14623d 100644
--- a/java/res/drawable-land-mdpi/key_hint_exclamation_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_exclamation_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_exclamation_large_holo.9.png b/java/res/drawable-land-mdpi/key_hint_exclamation_large_holo.9.png
index 932bcb9..ce52d3a 100644
--- a/java/res/drawable-land-mdpi/key_hint_exclamation_large_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_exclamation_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_question_holo.9.png b/java/res/drawable-land-mdpi/key_hint_question_holo.9.png
index 8373b69..2b71d74 100644
--- a/java/res/drawable-land-mdpi/key_hint_question_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_question_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_question_large_holo.9.png b/java/res/drawable-land-mdpi/key_hint_question_large_holo.9.png
index a9eaeea..0413368 100644
--- a/java/res/drawable-land-mdpi/key_hint_question_large_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_question_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_quote_holo.9.png b/java/res/drawable-land-mdpi/key_hint_quote_holo.9.png
index 01a3a9a..486e5e1 100644
--- a/java/res/drawable-land-mdpi/key_hint_quote_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_quote_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_quote_large_holo.9.png b/java/res/drawable-land-mdpi/key_hint_quote_large_holo.9.png
index 7cba264..4977031 100644
--- a/java/res/drawable-land-mdpi/key_hint_quote_large_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_quote_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/key_hint_underline_holo.9.png b/java/res/drawable-land-mdpi/key_hint_underline_holo.9.png
index a95a575..06f3efb 100644
--- a/java/res/drawable-land-mdpi/key_hint_underline_holo.9.png
+++ b/java/res/drawable-land-mdpi/key_hint_underline_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
index 8002da2..4e14655 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 506feec..9846137 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
index 9c34ccc..01a9139 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
index f33e4cb..024f576 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
index f6882c0..072b9d7 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
index e86eea7..12ebc9b 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
index a8375d4..15053ba 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png
index b4a50f2..73fdba4 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
index 4718865..ae3ada1 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png
index dc41d58..2ba416f 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/hint_popup_holo.9.png b/java/res/drawable-mdpi/hint_popup_holo.9.png
index c409cea..cfa17fd 100644
--- a/java/res/drawable-mdpi/hint_popup_holo.9.png
+++ b/java/res/drawable-mdpi/hint_popup_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_at_holo.9.png b/java/res/drawable-mdpi/key_hint_at_holo.9.png
index 627e7a0..d1ea313 100644
--- a/java/res/drawable-mdpi/key_hint_at_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_at_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_at_large_holo.9.png b/java/res/drawable-mdpi/key_hint_at_large_holo.9.png
index 9569217..786bbc5 100644
--- a/java/res/drawable-mdpi/key_hint_at_large_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_at_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_exclamation_holo.9.png b/java/res/drawable-mdpi/key_hint_exclamation_holo.9.png
index 89c5aae..a14623d 100644
--- a/java/res/drawable-mdpi/key_hint_exclamation_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_exclamation_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_exclamation_large_holo.9.png b/java/res/drawable-mdpi/key_hint_exclamation_large_holo.9.png
index 932bcb9..ce52d3a 100644
--- a/java/res/drawable-mdpi/key_hint_exclamation_large_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_exclamation_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_question_holo.9.png b/java/res/drawable-mdpi/key_hint_question_holo.9.png
index 8373b69..2b71d74 100644
--- a/java/res/drawable-mdpi/key_hint_question_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_question_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_question_large_holo.9.png b/java/res/drawable-mdpi/key_hint_question_large_holo.9.png
index a9eaeea..0413368 100644
--- a/java/res/drawable-mdpi/key_hint_question_large_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_question_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_quote_holo.9.png b/java/res/drawable-mdpi/key_hint_quote_holo.9.png
index 01a3a9a..486e5e1 100644
--- a/java/res/drawable-mdpi/key_hint_quote_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_quote_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_quote_large_holo.9.png b/java/res/drawable-mdpi/key_hint_quote_large_holo.9.png
index 7cba264..4977031 100644
--- a/java/res/drawable-mdpi/key_hint_quote_large_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_quote_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_underline_holo.9.png b/java/res/drawable-mdpi/key_hint_underline_holo.9.png
index a95a575..06f3efb 100644
--- a/java/res/drawable-mdpi/key_hint_underline_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_underline_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/key_hint_underline_large_holo.9.png b/java/res/drawable-mdpi/key_hint_underline_large_holo.9.png
index bef74c1..dbe1134 100644
--- a/java/res/drawable-mdpi/key_hint_underline_large_holo.9.png
+++ b/java/res/drawable-mdpi/key_hint_underline_large_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_background_holo.9.png b/java/res/drawable-mdpi/keyboard_background_holo.9.png
index 0ea57c0..34149a4 100644
--- a/java/res/drawable-mdpi/keyboard_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png
index 8cfd7cf..8c6ce6c 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png
index c5d938d..da192a6 100644
--- a/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/mic_slash_holo.png b/java/res/drawable-mdpi/mic_slash_holo.png
index 8108b6e..fc4108f 100644
--- a/java/res/drawable-mdpi/mic_slash_holo.png
+++ b/java/res/drawable-mdpi/mic_slash_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ok_cancel_holo.9.png b/java/res/drawable-mdpi/ok_cancel_holo.9.png
index 5eb078c..b6f1216 100644
--- a/java/res/drawable-mdpi/ok_cancel_holo.9.png
+++ b/java/res/drawable-mdpi/ok_cancel_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level0_holo.png b/java/res/drawable-mdpi/speak_now_level0_holo.png
index 2a4fbd8..29ec1b1 100644
--- a/java/res/drawable-mdpi/speak_now_level0_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level0_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level1_holo.png b/java/res/drawable-mdpi/speak_now_level1_holo.png
index dd35b18..df5d2fa 100644
--- a/java/res/drawable-mdpi/speak_now_level1_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level1_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level2_holo.png b/java/res/drawable-mdpi/speak_now_level2_holo.png
index e3e42c4..1e95ae6 100644
--- a/java/res/drawable-mdpi/speak_now_level2_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level2_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level3_holo.png b/java/res/drawable-mdpi/speak_now_level3_holo.png
index 7cf104e..3c6afd1 100644
--- a/java/res/drawable-mdpi/speak_now_level3_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level3_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level4_holo.png b/java/res/drawable-mdpi/speak_now_level4_holo.png
index baad6ca..e3100c7 100644
--- a/java/res/drawable-mdpi/speak_now_level4_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level4_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level5_holo.png b/java/res/drawable-mdpi/speak_now_level5_holo.png
index 34c161e..4bc8405 100644
--- a/java/res/drawable-mdpi/speak_now_level5_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level5_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/speak_now_level6_holo.png b/java/res/drawable-mdpi/speak_now_level6_holo.png
index e6b26d1..76bad8d 100644
--- a/java/res/drawable-mdpi/speak_now_level6_holo.png
+++ b/java/res/drawable-mdpi/speak_now_level6_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
index 9f1bfe8..d1d2d76 100644
--- a/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num0_holo.png b/java/res/drawable-mdpi/sym_keyboard_num0_holo.png
index 2bb2a8b..aa96c17 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num0_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num0_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num1_holo.png b/java/res/drawable-mdpi/sym_keyboard_num1_holo.png
index 0e05537..ee4b7ae 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num1_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num1_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num2_holo.png b/java/res/drawable-mdpi/sym_keyboard_num2_holo.png
index 3b2a550..e84dcbc 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num2_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num2_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num3_holo.png b/java/res/drawable-mdpi/sym_keyboard_num3_holo.png
index 0d829bf..55f04c0 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num3_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num3_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num4_holo.png b/java/res/drawable-mdpi/sym_keyboard_num4_holo.png
index d676a1c..18a744a 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num4_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num4_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num5_holo.png b/java/res/drawable-mdpi/sym_keyboard_num5_holo.png
index d47f2d5..348f1a9 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num5_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num5_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num6_holo.png b/java/res/drawable-mdpi/sym_keyboard_num6_holo.png
index 8e9138e..b94baa0 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num6_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num6_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num7_holo.png b/java/res/drawable-mdpi/sym_keyboard_num7_holo.png
index 7453b6b..f656141 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num7_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num7_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num8_holo.png b/java/res/drawable-mdpi/sym_keyboard_num8_holo.png
index b59885f..21884c8 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num8_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num8_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_num9_holo.png b/java/res/drawable-mdpi/sym_keyboard_num9_holo.png
index db465f7..3d09fc6 100644
--- a/java/res/drawable-mdpi/sym_keyboard_num9_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_num9_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_numbpound_holo.png b/java/res/drawable-mdpi/sym_keyboard_numbpound_holo.png
index 32f736c..d92c449 100644
--- a/java/res/drawable-mdpi/sym_keyboard_numbpound_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_numbpound_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_numbstar_holo.png b/java/res/drawable-mdpi/sym_keyboard_numbstar_holo.png
index 4fe9e6a..0792549 100644
--- a/java/res/drawable-mdpi/sym_keyboard_numbstar_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_numbstar_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-mdpi/sym_keyboard_return_holo.png
index 695a163..91122a8 100644
--- a/java/res/drawable-mdpi/sym_keyboard_return_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
index 8f5db5d..8678642 100644
--- a/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
index 0305827..836365b 100644
--- a/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-mdpi/sym_keyboard_smiley_holo.png
index 302ea0f..46b2f41 100644
--- a/java/res/drawable-mdpi/sym_keyboard_smiley_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_smiley_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-mdpi/sym_keyboard_space_holo.png
index ec21a4f..952c4ee 100644
--- a/java/res/drawable-mdpi/sym_keyboard_space_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_space_holo.png
Binary files differ
diff --git a/java/res/layout/candidate.xml b/java/res/layout/candidate.xml
index 37179d2..f2c4126 100644
--- a/java/res/layout/candidate.xml
+++ b/java/res/layout/candidate.xml
@@ -23,6 +23,7 @@
     android:layout_width="match_parent"
     android:layout_height="@dimen/candidate_strip_height"
     android:orientation="horizontal"
+    android:paddingRight="@dimen/candidate_padding"
 >
     <ImageView
         android:id="@+id/candidate_divider"
@@ -37,13 +38,23 @@
         android:id="@+id/candidate_word"
         android:layout_width="wrap_content"
         android:layout_height="@dimen/candidate_strip_height"
-        android:minWidth="@dimen/candidate_min_touchable_width"
+        android:minWidth="@dimen/candidate_min_width"
         android:textSize="@dimen/candidate_text_size"
         android:textColor="@color/candidate_normal"
         android:background="@drawable/btn_candidate"
         android:focusable="true"
         android:clickable="true"
         android:gravity="center_vertical|center_horizontal"
-        android:paddingLeft="12dip"
-        android:paddingRight="12dip" />
+        android:paddingLeft="@dimen/candidate_padding" />
+    <TextView
+        android:id="@+id/candidate_debug_info"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        android:textSize="10dip"
+        android:textColor="#ff808080"
+        android:focusable="false"
+        android:clickable="false"
+        android:gravity="bottom"
+        android:paddingLeft="4dip" />
 </LinearLayout>
diff --git a/java/res/values-xlarge/bools.xml b/java/res/values-xlarge/bools.xml
index abacfa1..9fb670c 100644
--- a/java/res/values-xlarge/bools.xml
+++ b/java/res/values-xlarge/bools.xml
@@ -21,6 +21,7 @@
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="default_popup_preview">false</bool>
     <bool name="config_enable_show_settings_key_option">false</bool>
+    <bool name="config_enable_show_subtype_settings">false</bool>
     <bool name="config_enable_show_voice_key_option">false</bool>
     <bool name="config_candidate_highlight_font_color_enabled">false</bool>
 </resources>
diff --git a/java/res/values-xlarge/dimens.xml b/java/res/values-xlarge/dimens.xml
index dbdfa96..07d5f09 100644
--- a/java/res/values-xlarge/dimens.xml
+++ b/java/res/values-xlarge/dimens.xml
@@ -44,5 +44,7 @@
 
     <dimen name="candidate_strip_height">46dip</dimen>
     <dimen name="candidate_strip_padding">15.0mm</dimen>
+    <dimen name="candidate_min_width">0.3in</dimen>
+    <dimen name="candidate_padding">12dip</dimen>
     <dimen name="candidate_text_size">22dip</dimen>
 </resources>
diff --git a/java/res/values/bools.xml b/java/res/values/bools.xml
index 84b0fe1..8742676 100644
--- a/java/res/values/bools.xml
+++ b/java/res/values/bools.xml
@@ -31,6 +31,7 @@
     <bool name="default_recorrection_enabled">true</bool>
     <bool name="config_long_press_comma_for_settings_enabled">true</bool>
     <bool name="config_enable_show_settings_key_option">true</bool>
+    <bool name="config_enable_show_subtype_settings">true</bool>
     <bool name="config_enable_show_voice_key_option">true</bool>
     <bool name="config_candidate_highlight_font_color_enabled">true</bool>
 </resources>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 456d9ad..0bb0e33 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -32,14 +32,14 @@
     <integer name="config_long_press_key_timeout">400</integer>
     <integer name="config_long_press_shift_key_timeout">1200</integer>
     <integer name="config_multi_tap_key_timeout">800</integer>
-    <string-array name="auto_complete_threshold_values">
-        <!-- Off, When auto completing setting is Off, this value is not used. -->
+    <string-array name="auto_correction_threshold_values">
+        <!-- Off, When auto correction setting is Off, this value is not used. -->
         <item></item>
         <!-- Modest : Suggestion whose normalized score is greater than this value
-             will be subject to auto-completion. -->
+             will be subject to auto-correction. -->
         <item>0.22</item>
         <!-- Aggressive : Suggestion whose normalized score is greater than this value
-             will be subject to auto-completion. -->
+             will be subject to auto-correction. -->
         <item>0</item>
     </string-array>
 </resources>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 27d324b..41d6384 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -49,6 +49,8 @@
     <dimen name="candidate_strip_height">42dip</dimen>
     <dimen name="candidate_strip_fading_edge_length">63dip</dimen>
     <dimen name="candidate_strip_padding">0dip</dimen>
+    <dimen name="candidate_min_width">0.3in</dimen>
+    <dimen name="candidate_padding">0dip</dimen>
     <dimen name="candidate_text_size">18dip</dimen>
     <dimen name="spacebar_vertical_correction">4dip</dimen>
     <!-- If the screen height in landscape is larger than the below value, then the keyboard
@@ -57,5 +59,4 @@
     <dimen name="bubble_pointer_offset">22dip</dimen>
 
     <dimen name="key_hysteresis_distance">0.05in</dimen>
-    <dimen name="candidate_min_touchable_width">0.3in</dimen>
 </resources>
diff --git a/java/res/values/donottranslate-altchars.xml b/java/res/values/donottranslate-altchars.xml
index 41c498e..de4250e 100644
--- a/java/res/values/donottranslate-altchars.xml
+++ b/java/res/values/donottranslate-altchars.xml
@@ -43,4 +43,14 @@
     <string name="alternates_for_scandinavia_row2_11"></string>
     <string name="alternates_for_cyrillic_e"></string>
     <string name="alternates_for_cyrillic_soft_sign"></string>
+    <!-- popular web domains for the locale - most popular, displayed on the keyboard -->
+    <string name="popular_domain_0">".com"</string>
+    <!-- popular web domains for the locale - item 1, displayed in the popup -->
+    <string name="popular_domain_1">".net"</string>
+    <!-- popular web domains for the locale - item 2, displayed in the popup -->
+    <string name="popular_domain_2">".org"</string>
+    <!-- popular web domains for the locale - item 3, displayed in the popup -->
+    <string name="popular_domain_3">".gov"</string>
+    <!-- popular web domains for the locale - item 4, displayed in the popup -->
+    <string name="popular_domain_4">".edu"</string>
 </resources>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 453e188..5703729 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -27,31 +27,93 @@
 
     <!-- Option values to show/hide the settings key in onscreen keyboard -->
     <!-- Automatically decide to show or hide the settings key -->
-    <string name="settings_key_mode_auto" translatable="false">0</string>
+    <string name="settings_key_mode_auto">0</string>
     <!-- Always show the settings key -->
-    <string name="settings_key_mode_always_show" translatable="false">1</string>
+    <string name="settings_key_mode_always_show">1</string>
     <!-- Always hide the settings key -->
-    <string name="settings_key_mode_always_hide" translatable="false">2</string>
+    <string name="settings_key_mode_always_hide">2</string>
+    <!-- Array of the settings key mode values -->
+    <string-array name="settings_key_modes_values">
+        <item>@string/settings_key_mode_auto</item>
+        <item>@string/settings_key_mode_always_show</item>
+        <item>@string/settings_key_mode_always_hide</item>
+    </string-array>
+    <!-- Array of the settings key modes -->
+    <string-array name="settings_key_modes">
+        <item>@string/settings_key_mode_auto_name</item>
+        <item>@string/settings_key_mode_always_show_name</item>
+        <item>@string/settings_key_mode_always_hide_name</item>
+    </string-array>
 
     <!--  Always show the suggestion strip -->
-    <string name="prefs_suggestion_visibility_show_value" translatable="false">0</string>
+    <string name="prefs_suggestion_visibility_show_value">0</string>
     <!--  Show the suggestion strip only on portrait mode -->
-    <string name="prefs_suggestion_visibility_show_only_portrait_value" translatable="false">1</string>
+    <string name="prefs_suggestion_visibility_show_only_portrait_value">1</string>
     <!--  Always hide the suggestion strip -->
-    <string name="prefs_suggestion_visibility_hide_value" translatable="false">2</string>
+    <string name="prefs_suggestion_visibility_hide_value">2</string>
     <!--  Default value of the visibility of the suggestion strip -->
-    <string name="prefs_suggestion_visibility_default_value" translatable="false">0</string>
+    <string name="prefs_suggestion_visibility_default_value">0</string>
+    <!--  Option to show/hide the suggestion strip -->
+    <string-array name="prefs_suggestion_visibility_values">
+       <item>@string/prefs_suggestion_visibility_show_value</item>
+       <item>@string/prefs_suggestion_visibility_show_only_portrait_value</item>
+       <item>@string/prefs_suggestion_visibility_hide_value</item>
+    </string-array>
+    <string-array name="prefs_suggestion_visibilities">
+       <item>@string/prefs_suggestion_visibility_show_name</item>
+       <item>@string/prefs_suggestion_visibility_show_only_portrait_name</item>
+       <item>@string/prefs_suggestion_visibility_hide_name</item>
+    </string-array>
+
+    <string name="auto_correction_threshold_mode_index_off">0</string>
+    <string name="auto_correction_threshold_mode_index_modest">1</string>
+    <string name="auto_correction_threshold_mode_index_aggeressive">2</string>
+    <string-array name="auto_correction_threshold_mode_indexes">
+      <item>@string/auto_correction_threshold_mode_index_off</item>
+      <item>@string/auto_correction_threshold_mode_index_modest</item>
+      <item>@string/auto_correction_threshold_mode_index_aggeressive</item>
+    </string-array>
+    <string-array name="auto_correction_threshold_modes">
+      <item>@string/auto_correction_threshold_mode_off</item>
+      <item>@string/auto_correction_threshold_mode_modest</item>
+      <item>@string/auto_correction_threshold_mode_aggeressive</item>
+    </string-array>
+
+    <string name="voice_mode_main">0</string>
+    <string name="voice_mode_symbols">1</string>
+    <string name="voice_mode_off">2</string>
+    <string-array name="voice_input_modes_values">
+        <item>@string/voice_mode_main</item>
+        <item>@string/voice_mode_symbols</item>
+        <item>@string/voice_mode_off</item>
+    </string-array>
+    <!-- Array of Voice Input modes -->
+    <string-array name="voice_input_modes">
+        <item>@string/voice_input_modes_main_keyboard</item>
+        <item>@string/voice_input_modes_symbols_keyboard</item>
+        <item>@string/voice_input_modes_off</item>
+    </string-array>
+    <!-- Array of Voice Input modes summary -->
+    <string-array name="voice_input_modes_summary">
+        <item>@string/voice_input_modes_summary_main_keyboard</item>
+        <item>@string/voice_input_modes_summary_symbols_keyboard</item>
+        <item>@string/voice_input_modes_summary_off</item>
+    </string-array>
+
+    <!-- Title for Latin keyboard debug settings activity / dialog -->
+    <string name="english_ime_debug_settings">Android keyboard Debug settings</string>
+    <string name="prefs_debug_mode">Debug Mode</string>
 
     <!-- Keyboard theme names -->
-    <string name="layout_basic" translatable="false">Basic</string>
-    <string name="layout_high_contrast" translatable="false">Basic (High Contrast)</string>
-    <string name="layout_stone_bold"  translatable="false">Stone (bold)</string>
-    <string name="layout_stone_normal"  translatable="false">Stone (normal)</string>
-    <string name="layout_gingerbread"  translatable="false">Gingerbread</string>
-    <string name="layout_honeycomb"  translatable="false">Honeycomb</string>
+    <string name="layout_basic">Basic</string>
+    <string name="layout_high_contrast">Basic (High Contrast)</string>
+    <string name="layout_stone_bold">Stone (bold)</string>
+    <string name="layout_stone_normal">Stone (normal)</string>
+    <string name="layout_gingerbread">Gingerbread</string>
+    <string name="layout_honeycomb">Honeycomb</string>
 
     <!-- For keyboard theme switcher dialog -->
-    <string-array name="keyboard_layout_modes" translatable="false">
+    <string-array name="keyboard_layout_modes">
         <item>@string/layout_basic</item>
         <item>@string/layout_high_contrast</item>
         <item>@string/layout_stone_normal</item>
@@ -59,7 +121,7 @@
         <item>@string/layout_gingerbread</item>
         <item>@string/layout_honeycomb</item>
     </string-array>
-    <string-array name="keyboard_layout_modes_values" translatable="false">
+    <string-array name="keyboard_layout_modes_values">
         <item>0</item>
         <item>1</item>
         <item>2</item>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index da315df..c244ad2 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -34,182 +34,54 @@
     <!-- Option to control whether or not to show a popup with a larger font on each key press. -->
     <string name="popup_on_keypress">Popup on keypress</string>
 
-    <!-- Option to enable using nearby keys when correcting/predicting -->
-    <string name="hit_correction">Correct typing errors</string>
-    
-    <!-- Description for hit_correction  -->
-    <string name="hit_correction_summary">Enable input error correction</string>
-    
-    <!-- Option to enable using nearby keys when correcting/predicting in landscape-->
-    <string name="hit_correction_land">Landscape input errors</string>
-    
-    <!-- Description for hit_correction in landscape -->
-    <string name="hit_correction_land_summary">Enable input error correction</string>
-    
-    <!-- Option to automatically correct word on hitting space -->
-    <string name="auto_correction">Word suggestions</string> 
-    
-    <!-- Description for auto_correction -->
-    <string name="auto_correction_summary">Automatically correct the previous word</string>
-	
-    <!-- Option to enable text prediction -->
-    <string name="prediction">Word suggestions</string>
     <!-- Category title for text prediction -->
     <string name="prediction_category">Word suggestion settings</string>
-    <!-- Description for text prediction -->
-    <string name="prediction_summary">Enable auto completion while typing</string>
-	
-    <!-- Dialog title for auto complete choices -->
-    <string name="auto_complete_dialog_title">Auto completion</string>
-    
-    <!-- Option to enable text prediction in landscape -->
-    <string name="prediction_landscape">Increase text field size</string> 
-    <!-- Description for text prediction -->
-    <string name="prediction_landscape_summary">Hide word suggestions in landscape view</string>
 	
     <!-- Option to enable auto capitalization of sentences -->
     <string name="auto_cap">Auto-capitalization</string> 
-    <!-- Description for auto cap -->
-    <string name="auto_cap_summary">Capitalize the start of a sentence</string>
-    <!-- Option to enable auto punctuate -->
-    <string name="auto_punctuate">Auto-punctuate</string> 
-    <!-- Description for auto punctuate -->
-    <string name="auto_punctuate_summary"></string>
-    
+
     <!-- Option to enable quick fixes -->
     <string name="quick_fixes">Quick fixes</string>
     <!-- Description for quick fixes -->
     <string name="quick_fixes_summary">Corrects commonly typed mistakes</string>
-    
+
     <!-- Option to enable showing suggestions -->
     <string name="prefs_show_suggestions">Show suggestions</string>
     <!-- Description for show suggestions -->
     <string name="prefs_show_suggestions_summary">Display suggested words while typing</string>
-    <!--  Option to show/hide the suggestion strip -->
-    <string-array name="prefs_suggestion_visibility_values" translatable="false">
-       <item>@string/prefs_suggestion_visibility_show_value</item>
-       <item>@string/prefs_suggestion_visibility_show_only_portrait_value</item>
-       <item>@string/prefs_suggestion_visibility_hide_value</item>
-    </string-array>
     <string name="prefs_suggestion_visibility_show_name">Always show</string>
     <string name="prefs_suggestion_visibility_show_only_portrait_name">Show on portrait mode</string>
     <string name="prefs_suggestion_visibility_hide_name">Always hide</string>
-    <string-array name="prefs_suggestion_visibilities" translatable="false">
-       <item>@string/prefs_suggestion_visibility_show_name</item>
-       <item>@string/prefs_suggestion_visibility_show_only_portrait_name</item>
-       <item>@string/prefs_suggestion_visibility_hide_name</item>
-    </string-array>
 
     <!-- Option to show/hide the settings key -->
     <string name="prefs_settings_key">Show settings key</string>
-    <!-- Array of the settings key mode values -->
-    <string-array name="settings_key_modes_values" translatable="false">
-        <item>@string/settings_key_mode_auto</item>
-        <item>@string/settings_key_mode_always_show</item>
-        <item>@string/settings_key_mode_always_hide</item>
-    </string-array>
     <!-- Option to automatically decide to show/hide the settings key -->
     <string name="settings_key_mode_auto_name">Automatic</string>
     <!-- Option to always show the settings key -->
     <string name="settings_key_mode_always_show_name">Always show</string>
     <!-- Option to always hide the settings key -->
     <string name="settings_key_mode_always_hide_name">Always hide</string>
-    <!-- Array of the settings key modes -->
-    <string-array name="settings_key_modes">
-        <item>@string/settings_key_mode_auto_name</item>
-        <item>@string/settings_key_mode_always_show_name</item>
-        <item>@string/settings_key_mode_always_hide_name</item>
-    </string-array>
 
-    <!-- Option to decide the auto completion threshold score -->
-    <!-- Option to enable auto completion -->
-    <string name="auto_complete">Auto-complete</string>
-    <!-- Description for auto completion -->
-    <string name="auto_complete_summary">Spacebar and punctuation automatically insert highlighted word</string>
-    <string name="auto_completion_threshold_mode_value_off" translatable="false">0</string>
-    <string name="auto_completion_threshold_mode_value_modest" translatable="false">1</string>
-    <string name="auto_completion_threshold_mode_value_aggeressive" translatable="false">2</string>
-    <string-array name="auto_completion_threshold_mode_values" translatable="false">
-      <item>@string/auto_completion_threshold_mode_value_off</item>
-      <item>@string/auto_completion_threshold_mode_value_modest</item>
-      <item>@string/auto_completion_threshold_mode_value_aggeressive</item>
-    </string-array>
-    <!-- Option to disable auto completion. -->
-    <string name="auto_completion_threshold_mode_off">Off</string>
+    <!-- Option to decide the auto correction threshold score -->
+    <!-- Option to enable auto correction -->
+    <string name="auto_correction">Auto correction</string>
+    <!-- Description for auto correction -->
+    <string name="auto_correction_summary">Spacebar and punctuation automatically insert highlighted word</string>
+    <!-- Option to disable auto correction. -->
+    <string name="auto_correction_threshold_mode_off">Off</string>
     <!-- Option to use modest auto completion. -->
-    <string name="auto_completion_threshold_mode_modest">Modest</string>
+    <string name="auto_correction_threshold_mode_modest">Modest</string>
     <!-- Option to use aggressive auto completion. -->
-    <string name="auto_completion_threshold_mode_aggeressive">Aggressive</string>
-    <string-array name="auto_completion_threshold_modes">
-      <item>@string/auto_completion_threshold_mode_off</item>
-      <item>@string/auto_completion_threshold_mode_modest</item>
-      <item>@string/auto_completion_threshold_mode_aggeressive</item>
-    </string-array>
+    <string name="auto_correction_threshold_mode_aggeressive">Aggressive</string>
 
     <!-- Option to enable bigram completion -->
     <string name="bigram_suggestion">Bigram Suggestions</string>
     <!-- Description for auto completion -->
     <string name="bigram_suggestion_summary">Use previous word to improve suggestion</string>
 
-    <!-- Array of prediction modes -->
-    <string-array name="prediction_modes">
-        <item>None</item>
-        <item>Basic</item>
-        <item>Advanced</item>
-    </string-array>
-    
-    <!-- Don't translate -->
-    <string name="prediction_none" translatable="false">0</string>
-    <!-- Don't translate -->
-    <string name="prediction_basic" translatable="false">1</string>
-    <!-- Don't translate -->
-    <string name="prediction_full"  translatable="false">2</string>
-
-    <string-array name="prediction_modes_values" translatable="false">
-        <item>@string/prediction_none</item>
-        <item>@string/prediction_basic</item>
-        <item>@string/prediction_full</item>
-    </string-array>
-
     <!-- Indicates that a word has been added to the dictionary -->
     <string name="added_word"><xliff:g id="word">%s</xliff:g> : Saved</string>
     
-    <!-- Tip to long press on keys -->
-    <string name="tip_long_press">Hold a key down to see accents (ø, ö, etc.)</string>
-    <!-- Tip to dismiss keyboard -->
-    <string name="tip_dismiss">Press the back key \u21B6 to close the keyboard at any point</string>
-    <!-- Tip to press ?123 to access numbers and symbols -->
-    <string name="tip_access_symbols">Access numbers and symbols</string>    
-    <!-- Tip to long press on typed word to add to dictionary -->
-    <string name="tip_add_to_dictionary">Press and hold the left-most word to add it to the dictionary
-        </string>
-        
-    <!-- Instruction to touch the bubble to continue -->
-    <string name="touch_to_continue">Touch this hint to continue »</string>
-    
-    <!-- Instruction to touch the bubble to start typing -->
-    <string name="touch_to_finish">Touch here to close this hint and start typing!</string>
-    
-    <!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
-    <string name="tip_to_open_keyboard"><b>The keyboard opens any time you touch a text field</b></string>
-    
-    <!-- Tutorial tip 2 - Touch and hold a key to view accents (examples) -->
-    <string name="tip_to_view_accents"><b>Touch &amp; hold a key to view accents\n(ø, ö, ô, ó, and so on)</b>
-    </string>
-    
-    <!-- Tutorial tip 3 - How to switch to number/symbol keyboard -->
-    <string name="tip_to_open_symbols"><b>Switch to numbers and symbols by touching this key</b></string>
-    
-    <!-- Tutorial tip 4 - How to switch back to alphabet keyboard -->
-    <string name="tip_to_close_symbols"><b>Go back to letters by touching this key again</b></string>
-    
-    <!-- Tutorial tip 5 - How to launch keyboard settings -->
-    <string name="tip_to_launch_settings"><b>Touch &amp; hold this key to change keyboard settings, like auto complete</b></string>
-    
-    <!-- Tutorial tip 6 - Done with the tutorial -->
-    <string name="tip_to_start_typing"><b>Try it!</b></string>
-    
-    
     <!-- Label for soft enter key when it performs GO action.  Must be short to fit on key! -->
     <string name="label_go_key">Go</string>
     <!-- Label for soft enter key when it performs NEXT action.  Must be short to fit on key! -->
@@ -308,62 +180,14 @@
     <!-- Preferences item for enabling speech input -->
     <string name="voice_input">Voice input</string>
 
-    <!-- Array of Voice Input modes -->
-    <string-array name="voice_input_modes">
-        <item>On main keyboard</item>
-        <item>On symbols keyboard</item>
-        <item>Off</item>
-    </string-array>
-
-    <!-- Don't translate -->
-    <string name="voice_mode_main" translatable="false">0</string>
-    <!-- Don't translate -->
-    <string name="voice_mode_symbols" translatable="false">1</string>
-    <!-- Don't translate -->
-    <string name="voice_mode_off"  translatable="false">2</string>
-
-    <string-array name="voice_input_modes_values" translatable="false">
-        <item>@string/voice_mode_main</item>
-        <item>@string/voice_mode_symbols</item>
-        <item>@string/voice_mode_off</item>
-    </string-array>
-
-    <!-- Array of Voice Input modes summary -->
-    <string-array name="voice_input_modes_summary">
-        <item>Mic on main keyboard</item>
-        <item>Mic on symbols keyboard</item>
-        <item>Voice input is disabled</item>
-    </string-array>
-
-    <!-- Press the "enter" key after the user speaks. Option on settings.-->
-    <string name="auto_submit">Auto submit after voice</string>
-
-    <!-- Press the "enter" key after the user speaks. Summary of option in settings.-->
-    <string name="auto_submit_summary">Automatically press enter when searching or going to the next field.</string>
-
-    <!-- IME Tutorial screen (ROMAN) --><skip />
-    <!-- appears above image showing the user to click on a TextView to show the IME -->
-    <string name="open_the_keyboard"><font size="17"><b>Open the keyboard\n</b></font><font size="3">\n</font>Touch any text field.</string>
-
-    <!-- appears above the image showing the back button used to close the keyboard -->
-    <string name="close_the_keyboard"><font size="17"><b>Close the keyboard\n</b></font><font size="3">\n</font>Press the Back key.</string>
-
-    <!-- appears above image showing how to use touch and hold -->
-    <string name="touch_and_hold"><font size="17"><b>Touch \u0026 hold a key for options\n</b></font><font size="3">\n</font>Access punctuation and accents.</string>
-
-    <!-- appears above image showing how to access keyboard settings -->
-    <string name="keyboard_settings"><font size="17"><b>Keyboard settings\n</b></font><font size="3">\n</font>Touch \u0026 hold the <b>\?123\</b> key.</string>
-
-    <!-- popular web domains for the locale - most popular, displayed on the keyboard -->
-    <string name="popular_domain_0">".com"</string>
-    <!-- popular web domains for the locale - item 1, displayed in the popup -->
-    <string name="popular_domain_1">".net"</string>
-    <!-- popular web domains for the locale - item 2, displayed in the popup -->
-    <string name="popular_domain_2">".org"</string>
-    <!-- popular web domains for the locale - item 3, displayed in the popup -->
-    <string name="popular_domain_3">".gov"</string>
-    <!-- popular web domains for the locale - item 4, displayed in the popup -->
-    <string name="popular_domain_4">".edu"</string>
+    <!-- Voice Input modes -->
+    <string name="voice_input_modes_main_keyboard">On main keyboard</string>
+    <string name="voice_input_modes_symbols_keyboard">On symbols keyboard</string>
+    <string name="voice_input_modes_off">Off</string>
+    <!-- Voice Input modes summary -->
+    <string name="voice_input_modes_summary_main_keyboard">Mic on main keyboard</string>
+    <string name="voice_input_modes_summary_symbols_keyboard">Mic on symbols keyboard</string>
+    <string name="voice_input_modes_summary_off">Voice input is disabled</string>
 
     <!-- Menu item for launching Input method picker -->
     <string name="selectInputMethod">Select input method</string>
@@ -391,8 +215,6 @@
     <!-- Description for keyboard theme switcher -->
     <string name="keyboard_layout">Keyboard Theme</string>
 
-    <string name="subtype_mode_keyboard">keyboard</string>
-    <string name="subtype_mode_voice">voice</string>
     <string name="subtype_mode_cs_keyboard">Czech Keyboard</string>
     <string name="subtype_mode_da_keyboard">Danish Keyboard</string>
     <string name="subtype_mode_de_keyboard">German Keyboard</string>
@@ -428,9 +250,6 @@
     <string name="subtype_mode_zh_CN_voice">Chinese (China) Voice</string>
     <string name="subtype_mode_zh_TW_voice">Chinese (Taiwan) Voice</string>
 
-    <!-- Title for Latin keyboard debug settings activity / dialog -->
-    <string name="english_ime_debug_settings" translatable="false">Android keyboard Debug settings</string>
-    <string name="prefs_debug_mode" translatable="false">Debug Mode</string>
     <!-- Title of an option for usability study mode -->
     <string name="prefs_usability_study_mode">Usability Study Mode</string>
 </resources>
diff --git a/java/res/xml-xlarge/kbd_key_styles.xml b/java/res/xml-xlarge/kbd_key_styles.xml
index 8a1f6ff..9ff3340 100644
--- a/java/res/xml-xlarge/kbd_key_styles.xml
+++ b/java/res/xml-xlarge/kbd_key_styles.xml
@@ -153,9 +153,9 @@
         latin:isSticky="true" />
     <key-style
         latin:styleName="comKeyStyle"
-        latin:keyLabel=".com"
+        latin:keyLabel="@string/popular_domain_0"
         latin:keyLabelOption="fontNormal"
-        latin:keyOutputText=".com"
+        latin:keyOutputText="@string/popular_domain_0"
         latin:keyHintIcon="@drawable/hint_popup_holo"
         latin:popupKeyboard="@xml/popup_domains" />
 </merge>
diff --git a/java/res/xml-xlarge/kbd_symbols.xml b/java/res/xml-xlarge/kbd_symbols.xml
index f5d0c4c..f78af8a 100644
--- a/java/res/xml-xlarge/kbd_symbols.xml
+++ b/java/res/xml-xlarge/kbd_symbols.xml
@@ -137,10 +137,6 @@
             latin:popupKeyboard="@xml/kbd_popup_template"
             latin:popupCharacters="≥»›" />
         <Key
-            latin:keyLabel="[" />
-        <Key
-            latin:keyLabel="]" />
-        <Key
             latin:keyLabel="="
             latin:popupKeyboard="@xml/kbd_popup_template"
             latin:popupCharacters="≠≈" />
@@ -149,6 +145,10 @@
         <Key
             latin:keyLabel=";" />
         <Key
+            latin:keyLabel="," />
+        <Key
+            latin:keyLabel="." />
+        <Key
             latin:keyLabel="!"
             latin:popupKeyboard="@xml/kbd_popup_template"
             latin:popupCharacters="¡" />
diff --git a/java/res/xml-xlarge/kbd_symbols_shift.xml b/java/res/xml-xlarge/kbd_symbols_shift.xml
index 99f48eb..f3fbf36 100644
--- a/java/res/xml-xlarge/kbd_symbols_shift.xml
+++ b/java/res/xml-xlarge/kbd_symbols_shift.xml
@@ -121,9 +121,9 @@
         <Key
             latin:keyLabel="â„…" />
         <Key
-            latin:keyLabel="," />
+            latin:keyLabel="[" />
         <Key
-            latin:keyLabel="." />
+            latin:keyLabel="]" />
         <Key
             latin:keyLabel="¡" />
         <Key
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 85612b0..47b3b45 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -73,6 +73,7 @@
     <!-- TODO: Filter subtypes by IME in SubtypeEnabler -->
     <!-- TODO: Maybe use this only for phone? -->
     <PreferenceScreen
+            android:key="subtype_settings"
             android:title="@string/language_selection_title"
             android:summary="@string/language_selection_summary">
         <intent
@@ -102,13 +103,13 @@
             />
 
         <ListPreference
-            android:key="auto_completion_threshold"
-            android:title="@string/auto_complete"
-            android:summary="@string/auto_complete_summary"
+            android:key="auto_correction_threshold"
+            android:title="@string/auto_correction"
+            android:summary="@string/auto_correction_summary"
             android:persistent="true"
-            android:entryValues="@array/auto_completion_threshold_mode_values"
-            android:entries="@array/auto_completion_threshold_modes"
-            android:defaultValue="@string/auto_completion_threshold_mode_value_modest"
+            android:entryValues="@array/auto_correction_threshold_mode_indexes"
+            android:entries="@array/auto_correction_threshold_modes"
+            android:defaultValue="@string/auto_correction_threshold_mode_index_modest"
             />
 
         <CheckBoxPreference
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 51e878c..cd57db3 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -74,9 +74,9 @@
     private int mMode = KeyboardId.MODE_TEXT; /* default value */
     private int mImeOptions;
     private boolean mIsSymbols;
-    /** mIsAutoCompletionActive indicates that auto completed word will be input instead of
+    /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
      * what user actually typed. */
-    private boolean mIsAutoCompletionActive;
+    private boolean mIsAutoCorrectionActive;
     private boolean mVoiceKeyEnabled;
     private boolean mVoiceButtonOnPrimary;
     private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
@@ -197,7 +197,7 @@
             Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT  id=" + id);
         }
 
-        keyboard.onAutoCompletionStateChanged(mIsAutoCompletionActive);
+        keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
         keyboard.setShifted(false);
         return keyboard;
     }
@@ -617,12 +617,12 @@
                 ? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE;
     }
 
-    public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
-        if (isAutoCompletion != mIsAutoCompletionActive) {
+    public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
+        if (isAutoCorrection != mIsAutoCorrectionActive) {
             LatinKeyboardView keyboardView = getInputView();
-            mIsAutoCompletionActive = isAutoCompletion;
+            mIsAutoCorrectionActive = isAutoCorrection;
             keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard())
-                    .onAutoCompletionStateChanged(isAutoCompletion));
+                    .onAutoCorrectionStateChanged(isAutoCorrection));
         }
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index 8087f03..0a42857 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -45,7 +45,7 @@
     private static final int SPACE_LED_LENGTH_PERCENT = 80;
 
     private Drawable mShiftLockPreviewIcon;
-    private Drawable mSpaceAutoCompletionIndicator;
+    private Drawable mSpaceAutoCorrectionIndicator;
     private final Drawable mButtonArrowLeftIcon;
     private final Drawable mButtonArrowRightIcon;
     private final int mSpaceBarTextShadowColor;
@@ -89,7 +89,7 @@
         }
         mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
         setDefaultBounds(mShiftLockPreviewIcon);
-        mSpaceAutoCompletionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led);
+        mSpaceAutoCorrectionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led);
         mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
         mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
         sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
@@ -100,22 +100,22 @@
     /**
      * @return a key which should be invalidated.
      */
-    public Key onAutoCompletionStateChanged(boolean isAutoCompletion) {
-        updateSpaceBarForLocale(isAutoCompletion);
+    public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) {
+        updateSpaceBarForLocale(isAutoCorrection);
         return mSpaceKey;
     }
 
-    private void updateSpaceBarForLocale(boolean isAutoCompletion) {
+    private void updateSpaceBarForLocale(boolean isAutoCorrection) {
         final Resources res = mRes;
         // If application locales are explicitly selected.
         if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {
             mSpaceKey.setIcon(new BitmapDrawable(res,
-                    drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion)));
+                    drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
         } else {
             // sym_keyboard_space_led can be shared with Black and White symbol themes.
-            if (isAutoCompletion) {
+            if (isAutoCorrection) {
                 mSpaceKey.setIcon(new BitmapDrawable(res,
-                        drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion)));
+                        drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
             } else {
                 mSpaceKey.setIcon(mSpaceIcon);
             }
@@ -173,7 +173,7 @@
     }
 
     @SuppressWarnings("unused")
-    private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) {
+    private Bitmap drawSpaceBar(int opacity, boolean isAutoCorrection) {
         final int width = mSpaceKey.mWidth;
         final int height = mSpaceIcon.getIntrinsicHeight();
         final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -212,13 +212,13 @@
         }
 
         // Draw the spacebar icon at the bottom
-        if (isAutoCompletion) {
+        if (isAutoCorrection) {
             final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
-            final int iconHeight = mSpaceAutoCompletionIndicator.getIntrinsicHeight();
+            final int iconHeight = mSpaceAutoCorrectionIndicator.getIntrinsicHeight();
             int x = (width - iconWidth) / 2;
             int y = height - iconHeight;
-            mSpaceAutoCompletionIndicator.setBounds(x, y, x + iconWidth, y + iconHeight);
-            mSpaceAutoCompletionIndicator.draw(canvas);
+            mSpaceAutoCorrectionIndicator.setBounds(x, y, x + iconWidth, y + iconHeight);
+            mSpaceAutoCorrectionIndicator.draw(canvas);
         } else {
             final int iconWidth = mSpaceIcon.getIntrinsicWidth();
             final int iconHeight = mSpaceIcon.getIntrinsicHeight();
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 03ba119..784077a 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -43,11 +43,9 @@
 import android.widget.TextView;
 
 import java.util.ArrayList;
-import java.util.List;
 
 public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
     private LatinIME mService;
-    private final ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
     private final ArrayList<View> mWords = new ArrayList<View>();
 
     private final TextView mPreviewText;
@@ -64,27 +62,12 @@
     private final CharacterStyle mInvertedForegroundColorSpan;
     private final CharacterStyle mInvertedBackgroundColorSpan;
 
-    private boolean mShowingCompletions;
+    private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
     private boolean mShowingAutoCorrectionInverted;
-
     private boolean mShowingAddToDictionary;
 
     private final UiHandler mHandler = new UiHandler();
 
-    private static class UpdateSuggestionsArgs {
-        public final List<CharSequence> mSuggestions;
-        public final boolean mCompletions;
-        public final boolean mTypedWordValid;
-        public final boolean mHaveMinimalSuggestion;
-        public UpdateSuggestionsArgs(List<CharSequence> suggestions, boolean completions,
-                boolean typedWordValid, boolean haveMinimalSuggestion) {
-            mSuggestions = suggestions;
-            mCompletions = completions;
-            mTypedWordValid = typedWordValid;
-            mHaveMinimalSuggestion = haveMinimalSuggestion;
-        }
-    }
-
     private class UiHandler extends Handler {
         private static final int MSG_HIDE_PREVIEW = 0;
         private static final int MSG_UPDATE_SUGGESTION = 1;
@@ -99,9 +82,7 @@
                 hidePreview();
                 break;
             case MSG_UPDATE_SUGGESTION:
-                UpdateSuggestionsArgs args = (UpdateSuggestionsArgs)msg.obj;
-                updateSuggestions(args.mSuggestions, args.mCompletions, args.mTypedWordValid,
-                        args.mHaveMinimalSuggestion);
+                updateSuggestions((SuggestedWords)msg.obj);
                 break;
             }
         }
@@ -115,11 +96,9 @@
             removeMessages(MSG_HIDE_PREVIEW);
         }
 
-        public void postUpdateSuggestions(List<CharSequence> suggestions, boolean completions,
-                boolean typedWordValid, boolean haveMinimalSuggestion) {
+        public void postUpdateSuggestions(SuggestedWords suggestions) {
             cancelUpdateSuggestions();
-            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION, new UpdateSuggestionsArgs(
-                    suggestions, completions, typedWordValid, haveMinimalSuggestion)),
+            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION, suggestions),
                     DELAY_UPDATE_SUGGESTION);
         }
 
@@ -167,7 +146,7 @@
                 tv.setOnLongClickListener(this);
             ImageView divider = (ImageView)v.findViewById(R.id.candidate_divider);
             // Do not display divider of first candidate.
-            divider.setVisibility(i == 0 ? View.GONE : View.VISIBLE);
+            divider.setVisibility(i == 0 ? GONE : VISIBLE);
             mWords.add(v);
         }
 
@@ -182,44 +161,35 @@
         mService = listener;
     }
 
-    public void setSuggestions(List<CharSequence> suggestions, boolean completions,
-            boolean typedWordValid, boolean haveMinimalSuggestion) {
-        // Don't update suggestions when there is zero or only one suggestion found.
-        if (suggestions != null && suggestions.size() <= 1)
+    public void setSuggestions(SuggestedWords suggestions) {
+        // Don't update suggestions when there is only one suggestion found.
+        // Empty (size zero) suggestions will be passed in order to clear candidate view.
+        if (suggestions == null || suggestions.size() == 1)
             return;
         if (mShowingAutoCorrectionInverted) {
-            mHandler.postUpdateSuggestions(suggestions, completions, typedWordValid,
-                    haveMinimalSuggestion);
+            mHandler.postUpdateSuggestions(suggestions);
         } else {
-            updateSuggestions(suggestions, completions, typedWordValid, haveMinimalSuggestion);
+            updateSuggestions(suggestions);
         }
     }
 
-    private void updateSuggestions(List<CharSequence> suggestions, boolean completions,
-            boolean typedWordValid, boolean haveMinimalSuggestion) {
+    private void updateSuggestions(SuggestedWords suggestions) {
         clear();
-        if (suggestions != null) {
-            int insertCount = Math.min(suggestions.size(), MAX_SUGGESTIONS);
-            for (CharSequence suggestion : suggestions) {
-                mSuggestions.add(suggestion);
-                if (--insertCount == 0)
-                    break;
-            }
-        }
-
-        final int count = mSuggestions.size();
-        boolean existsAutoCompletion = false;
-
+        mSuggestions = suggestions;
+        final int count = suggestions.size();
+        final Object[] debugInfo = suggestions.mDebugInfo;
         for (int i = 0; i < count; i++) {
-            CharSequence suggestion = mSuggestions.get(i);
-            if (suggestion == null) continue;
-            final int wordLength = suggestion.length();
+            CharSequence word = suggestions.getWord(i);
+            if (word == null) continue;
+            final int wordLength = word.length();
 
             final View v = mWords.get(i);
             final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
+            final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info);
             tv.setTextColor(mColorNormal);
-            if (haveMinimalSuggestion
-                    && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) {
+            if (suggestions.mHasMinimalSuggestion
+                    && ((i == 1 && !suggestions.mTypedWordValid) ||
+                            (i == 0 && suggestions.mTypedWordValid))) {
                 final CharacterStyle style;
                 if (mConfigCandidateHighlightFontColorEnabled) {
                     style = BOLD_SPAN;
@@ -227,10 +197,9 @@
                 } else {
                     style = UNDERLINE_SPAN;
                 }
-                final Spannable word = new SpannableString(suggestion);
-                word.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-                suggestion = word;
-                existsAutoCompletion = true;
+                final Spannable spannedWord = new SpannableString(word);
+                spannedWord.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+                word = spannedWord;
             } else if (i != 0 || (wordLength == 1 && count > 1)) {
                 // HACK: even if i == 0, we use mColorOther when this
                 // suggestion's length is 1
@@ -239,16 +208,18 @@
                 if (mConfigCandidateHighlightFontColorEnabled)
                     tv.setTextColor(mColorOther);
             }
-            tv.setText(suggestion);
+            tv.setText(word);
             tv.setClickable(true);
+            if (debugInfo != null && i < debugInfo.length && debugInfo[i] != null
+                    && !TextUtils.isEmpty(debugInfo[i].toString())) {
+                dv.setText(debugInfo[i].toString());
+                dv.setVisibility(VISIBLE);
+            } else {
+                dv.setVisibility(GONE);
+            }
             addView(v);
         }
 
-        mShowingCompletions = completions;
-        // TODO: Move this call back to LatinIME
-        if (mConfigCandidateHighlightFontColorEnabled)
-            mService.onAutoCompletionStateChanged(existsAutoCompletion);
-
         scrollTo(0, getScrollY());
         requestLayout();
     }
@@ -267,15 +238,19 @@
         mShowingAutoCorrectionInverted = true;
     }
 
+    public boolean isConfigCandidateHighlightFontColorEnabled() {
+        return mConfigCandidateHighlightFontColorEnabled;
+    }
+
     public boolean isShowingAddToDictionaryHint() {
         return mShowingAddToDictionary;
     }
 
     public void showAddToDictionaryHint(CharSequence word) {
-        ArrayList<CharSequence> suggestions = new ArrayList<CharSequence>();
-        suggestions.add(word);
-        suggestions.add(getContext().getText(R.string.hint_add_to_dictionary));
-        setSuggestions(suggestions, false, false, false);
+        SuggestedWords.Builder builder = new SuggestedWords.Builder()
+                .addWord(word)
+                .addWord(getContext().getText(R.string.hint_add_to_dictionary));
+        setSuggestions(builder.build());
         mShowingAddToDictionary = true;
         // Disable R.string.hint_add_to_dictionary button
         TextView tv = (TextView)getChildAt(1).findViewById(R.id.candidate_word);
@@ -288,14 +263,11 @@
         return true;
     }
 
-    /* package */ List<CharSequence> getSuggestions() {
+    public SuggestedWords getSuggestions() {
         return mSuggestions;
     }
 
     public void clear() {
-        // Don't call mSuggestions.clear() because it's being used for logging
-        // in LatinIME.pickSuggestionManually().
-        mSuggestions.clear();
         mShowingAddToDictionary = false;
         mShowingAutoCorrectionInverted = false;
         removeAllViews();
@@ -337,7 +309,7 @@
     @Override
     public boolean onLongClick(View view) {
         int index = (Integer) view.getTag();
-        CharSequence word = mSuggestions.get(index);
+        CharSequence word = mSuggestions.getWord(index);
         if (word.length() < 2)
             return false;
         addToDictionary(word);
@@ -347,12 +319,12 @@
     @Override
     public void onClick(View view) {
         int index = (Integer) view.getTag();
-        CharSequence word = mSuggestions.get(index);
+        CharSequence word = mSuggestions.getWord(index);
         if (mShowingAddToDictionary && index == 0) {
             addToDictionary(word);
         } else {
-            if (!mShowingCompletions) {
-                TextEntryState.acceptedSuggestion(mSuggestions.get(0), word);
+            if (!mSuggestions.mIsApplicationSpecifiedCompletions) {
+                TextEntryState.acceptedSuggestion(mSuggestions.getWord(0), word);
             }
             mService.pickSuggestionManually(index, word);
         }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 99b6c73..243306a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -63,6 +63,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -77,7 +78,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Locale;
 
 /**
@@ -120,7 +120,7 @@
     private View mCandidateViewContainer;
     private CandidateView mCandidateView;
     private Suggest mSuggest;
-    private CompletionInfo[] mCompletions;
+    private CompletionInfo[] mApplicationSpecifiedCompletions;
 
     private AlertDialog mOptionsDialog;
 
@@ -142,7 +142,7 @@
     private CharSequence mBestWord;
     private boolean mPredicting;
     private boolean mPredictionOn;
-    private boolean mCompletionOn;
+    private boolean mApplicationSpecifiedCompletionOn;
     private boolean mHasDictionary;
     private boolean mAutoSpace;
     private boolean mJustAddedAutoSpace;
@@ -162,7 +162,7 @@
     // Keep track of the last selection range to decide if we need to show word alternatives
     private int mLastSelectionStart;
     private int mLastSelectionEnd;
-    private List<CharSequence> mSuggestPuncList;
+    private SuggestedWords mSuggestPuncList;
 
     // Input type is such that we should not auto-correct
     private boolean mInputTypeNoAutoCorrect;
@@ -212,7 +212,7 @@
             return mChosenWord;
         }
 
-        public abstract List<CharSequence> getAlternatives();
+        public abstract SuggestedWords.Builder getAlternatives();
     }
 
     public class TypedWordAlternatives extends WordAlternatives {
@@ -233,7 +233,7 @@
         }
 
         @Override
-        public List<CharSequence> getAlternatives() {
+        public SuggestedWords.Builder getAlternatives() {
             return getTypedSuggestions(word);
         }
     }
@@ -394,7 +394,7 @@
 
         int[] dictionaries = getDictionary(orig);
         mSuggest = new Suggest(this, dictionaries);
-        loadAndSetAutoCompletionThreshold(prefs);
+        loadAndSetAutoCorrectionThreshold(prefs);
         if (mUserDictionary != null) mUserDictionary.close();
         mUserDictionary = new UserDictionary(this, locale);
         if (mContactsDictionary == null) {
@@ -520,8 +520,8 @@
         mVoiceConnector.resetVoiceStates(isPasswordVariation(variation));
         mInputTypeNoAutoCorrect = false;
         mPredictionOn = false;
-        mCompletionOn = false;
-        mCompletions = null;
+        mApplicationSpecifiedCompletionOn = false;
+        mApplicationSpecifiedCompletions = null;
         mEnteredText = null;
 
         final int mode;
@@ -580,7 +580,7 @@
                 }
                 if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
                     mPredictionOn = false;
-                    mCompletionOn = isFullscreenMode();
+                    mApplicationSpecifiedCompletionOn = isFullscreenMode();
                 }
                 break;
             default:
@@ -603,7 +603,8 @@
 
         setCandidatesViewShownInternal(isCandidateStripVisible(),
                 false /* needsInputViewShown */ );
-        updateSuggestions();
+        // Delay updating suggestions because keyboard input view may not be shown at this point.
+        mHandler.postUpdateSuggestions();
 
         // If the dictionary is not big enough, don't auto correct
         mHasDictionary = mSuggest.hasMainDictionary();
@@ -633,7 +634,7 @@
         if (isSuggestionShown() && isPredictionOn()) {
             // First get the cursor position. This is required by setOldSuggestions(), so that
             // it can pass the correct range to setComposingRegion(). At this point, we don't
-            // have valid values for mLastSelectionStart/Stop because onUpdateSelection() has
+            // have valid values for mLastSelectionStart/End because onUpdateSelection() has
             // not been called yet.
             ExtractedTextRequest etr = new ExtractedTextRequest();
             etr.token = 0; // anything is fine here
@@ -655,7 +656,7 @@
         super.onFinishInput();
 
         LatinImeLogger.commit();
-        onAutoCompletionStateChanged(false);
+        mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
 
         mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
 
@@ -790,7 +791,7 @@
     @Override
     public void hideWindow() {
         LatinImeLogger.commit();
-        onAutoCompletionStateChanged(false);
+        mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
 
         if (TRACE) Debug.stopMethodTracing();
         if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
@@ -804,27 +805,28 @@
     }
 
     @Override
-    public void onDisplayCompletions(CompletionInfo[] completions) {
+    public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) {
         if (DEBUG) {
             Log.i("foo", "Received completions:");
-            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
-                Log.i("foo", "  #" + i + ": " + completions[i]);
+            final int count = (applicationSpecifiedCompletions != null)
+                    ? applicationSpecifiedCompletions.length : 0;
+            for (int i = 0; i < count; i++) {
+                Log.i("foo", "  #" + i + ": " + applicationSpecifiedCompletions[i]);
             }
         }
-        if (mCompletionOn) {
-            mCompletions = completions;
-            if (completions == null) {
+        if (mApplicationSpecifiedCompletionOn) {
+            mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
+            if (applicationSpecifiedCompletions == null) {
                 clearSuggestions();
                 return;
             }
 
-            List<CharSequence> stringList = new ArrayList<CharSequence>();
-            for (int i = 0; i < completions.length; i++) {
-                CompletionInfo ci = completions[i];
-                if (ci != null) stringList.add(ci.getText());
-            }
+            SuggestedWords.Builder builder = new SuggestedWords.Builder()
+                    .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions)
+                    .setTypedWordValid(true)
+                    .setHasMinimalSuggestion(true);
             // When in fullscreen mode, show completions generated by the application
-            setSuggestions(stringList, true, true, true);
+            setSuggestions(builder.build());
             mBestWord = null;
             setCandidatesViewShown(true);
         }
@@ -1293,7 +1295,7 @@
 
         boolean pickedDefault = false;
         // Handle separator
-        InputConnection ic = getCurrentInputConnection();
+        final InputConnection ic = getCurrentInputConnection();
         if (ic != null) {
             ic.beginBatchEdit();
             abortCorrection(false);
@@ -1338,7 +1340,11 @@
             CharSequence typedWord = mWord.getTypedWord();
             TextEntryState.backToAcceptedDefault(typedWord);
             if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
-                // TODO: Will call InputConnection.commitCorrection() here.
+                if (ic != null) {
+                    CorrectionInfo correctionInfo = new CorrectionInfo(
+                            mLastSelectionEnd - typedWord.length(), typedWord, mBestWord);
+                    ic.commitCorrection(correctionInfo);
+                }
                 if (mCandidateView != null)
                     mCandidateView.onAutoCorrectionInverted(mBestWord);
             }
@@ -1382,7 +1388,7 @@
     }
 
     private boolean isShowingPunctuationList() {
-        return mSuggestPuncList.equals(mCandidateView.getSuggestions());
+        return mSuggestPuncList == mCandidateView.getSuggestions();
     }
 
     private boolean isSuggestionShown() {
@@ -1394,8 +1400,9 @@
     private boolean isCandidateStripVisible() {
         boolean forceVisible = mCandidateView.isShowingAddToDictionaryHint()
                 || TextEntryState.isCorrecting();
-        return forceVisible || (isSuggestionShown()
-                && (isPredictionOn() || mCompletionOn || isShowingPunctuationList()));
+        return forceVisible || (
+                isSuggestionShown() && (isPredictionOn() || mApplicationSpecifiedCompletionOn
+                        || isShowingPunctuationList()));
     }
 
     public void switchToKeyboardView() {
@@ -1422,22 +1429,20 @@
     }
 
     public void clearSuggestions() {
-        setSuggestions(null, false, false, false);
+        setSuggestions(SuggestedWords.EMPTY);
     }
 
-    public void setSuggestions(
-            List<CharSequence> suggestions,
-            boolean completions,
-            boolean typedWordValid,
-            boolean haveMinimalSuggestion) {
-
+    public void setSuggestions(SuggestedWords words) {
         if (mVoiceConnector.getAndResetIsShowingHint()) {
              setCandidatesView(mCandidateViewContainer);
         }
 
         if (mCandidateView != null) {
-            mCandidateView.setSuggestions(
-                    suggestions, completions, typedWordValid, haveMinimalSuggestion);
+            mCandidateView.setSuggestions(words);
+            if (mCandidateView.isConfigCandidateHighlightFontColorEnabled()) {
+                mKeyboardSwitcher.onAutoCorrectionStateChanged(
+                        words.hasWordAboveAutoCorrectionScoreThreshold());
+            }
         }
     }
 
@@ -1457,16 +1462,15 @@
         showSuggestions(mWord);
     }
 
-    private List<CharSequence> getTypedSuggestions(WordComposer word) {
-        List<CharSequence> stringList = mSuggest.getSuggestions(
-                mKeyboardSwitcher.getInputView(), word, false, null);
-        return stringList;
+    private SuggestedWords.Builder getTypedSuggestions(WordComposer word) {
+        return mSuggest.getSuggestedWordBuilder(mKeyboardSwitcher.getInputView(), word, null);
     }
 
     private void showCorrections(WordAlternatives alternatives) {
         mKeyboardSwitcher.setPreferredLetters(null);
-        List<CharSequence> stringList = alternatives.getAlternatives();
-        showSuggestions(stringList, alternatives.getOriginalWord(), false, false);
+        SuggestedWords.Builder builder = alternatives.getAlternatives();
+        builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
+        showSuggestions(builder.build(), alternatives.getOriginalWord());
     }
 
     private void showSuggestions(WordComposer word) {
@@ -1474,10 +1478,8 @@
         // TODO Maybe need better way of retrieving previous word
         CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
                 mWordSeparators);
-        List<CharSequence> stringList = mSuggest.getSuggestions(
-                mKeyboardSwitcher.getInputView(), word, false, prevWord);
-        // long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT!
-        // Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime));
+        SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
+                mKeyboardSwitcher.getInputView(), word, prevWord);
 
         int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
         mKeyboardSwitcher.setPreferredLetters(nextLettersFrequencies);
@@ -1497,15 +1499,15 @@
         correctionAvailable &= !word.isMostlyCaps();
         correctionAvailable &= !TextEntryState.isCorrecting();
 
-        showSuggestions(stringList, typedWord, typedWordValid, correctionAvailable);
+        builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(correctionAvailable);
+        showSuggestions(builder.build(), typedWord);
     }
 
-    private void showSuggestions(List<CharSequence> stringList, CharSequence typedWord,
-            boolean typedWordValid, boolean correctionAvailable) {
-        setSuggestions(stringList, false, typedWordValid, correctionAvailable);
-        if (stringList.size() > 0) {
-            if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
-                mBestWord = stringList.get(1);
+    private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
+        setSuggestions(suggestedWords);
+        if (suggestedWords.size() > 0) {
+            if (suggestedWords.hasAutoCorrectionWord()) {
+                mBestWord = suggestedWords.getWord(1);
             } else {
                 mBestWord = typedWord;
             }
@@ -1534,7 +1536,7 @@
     }
 
     public void pickSuggestionManually(int index, CharSequence suggestion) {
-        List<CharSequence> suggestions = mCandidateView.getSuggestions();
+        SuggestedWords suggestions = mCandidateView.getSuggestions();
         mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators);
 
         final boolean correcting = TextEntryState.isCorrecting();
@@ -1542,9 +1544,9 @@
         if (ic != null) {
             ic.beginBatchEdit();
         }
-        if (mCompletionOn && mCompletions != null && index >= 0
-                && index < mCompletions.length) {
-            CompletionInfo ci = mCompletions[index];
+        if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null
+                && index >= 0 && index < mApplicationSpecifiedCompletions.length) {
+            CompletionInfo ci = mApplicationSpecifiedCompletions[index];
             if (ic != null) {
                 ic.commitCompletion(ci);
             }
@@ -1565,7 +1567,7 @@
             // Word separators are suggested before the user inputs something.
             // So, LatinImeLogger logs "" as a user's input.
             LatinImeLogger.logOnManualSuggestion(
-                    "", suggestion.toString(), index, suggestions);
+                    "", suggestion.toString(), index, suggestions.mWords);
             final char primaryCode = suggestion.charAt(0);
             onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE,
                     KeyboardView.NOT_A_TOUCH_COORDINATE);
@@ -1583,7 +1585,7 @@
             addToBigramDictionary(suggestion, 1);
         }
         LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(),
-                index, suggestions);
+                index, suggestions.mWords);
         TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
         // Follow it with a space
         if (mAutoSpace && !correcting) {
@@ -1655,7 +1657,7 @@
                 break;
             }
         }
-        // If we didn't find a match, at least suggest completions
+        // If we didn't find a match, at least suggest corrections.
         if (foundWord == null
                 && (mSuggest.isValidWord(touching.mWord)
                         || mSuggest.isValidWord(touching.mWord.toString().toLowerCase()))) {
@@ -1718,7 +1720,7 @@
 
     private void setPunctuationSuggestions() {
         setCandidatesViewShown(isCandidateStripVisible());
-        setSuggestions(mSuggestPuncList, false, false, false);
+        setSuggestions(mSuggestPuncList);
     }
 
     private void addToDictionaries(CharSequence suggestion, int frequencyDelta) {
@@ -2043,7 +2045,7 @@
 
         mAutoCorrectEnabled = isAutoCorrectEnabled(prefs);
         mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs);
-        loadAndSetAutoCompletionThreshold(prefs);
+        loadAndSetAutoCorrectionThreshold(prefs);
 
         mVoiceConnector.loadSettings(attribute, prefs);
 
@@ -2054,50 +2056,47 @@
     }
 
     /**
-     *  load Auto completion threshold from SharedPreferences,
-     *  and modify mSuggest's threshold.
+     *  Load Auto correction threshold from SharedPreferences, and modify mSuggest's threshold.
      */
-    private void loadAndSetAutoCompletionThreshold(SharedPreferences sp) {
+    private void loadAndSetAutoCorrectionThreshold(SharedPreferences sp) {
         // When mSuggest is not initialized, cannnot modify mSuggest's threshold.
         if (mSuggest == null) return;
-        // When auto completion setting is turned off, the threshold is ignored.
+        // When auto correction setting is turned off, the threshold is ignored.
         if (!isAutoCorrectEnabled(sp)) return;
 
-        final String currentAutoCompletionSetting = sp.getString(
-                Settings.PREF_AUTO_COMPLETION_THRESHOLD,
-                mResources.getString(R.string.auto_completion_threshold_mode_value_modest));
-        final String[] autoCompletionThresholdValues = mResources.getStringArray(
-                R.array.auto_complete_threshold_values);
-        // When autoCompletionThreshold is greater than 1.0,
-        // auto completion is virtually turned off.
-        double autoCompletionThreshold = Double.MAX_VALUE;
+        final String currentAutoCorrectionSetting = sp.getString(
+                Settings.PREF_AUTO_CORRECTION_THRESHOLD,
+                mResources.getString(R.string.auto_correction_threshold_mode_index_modest));
+        final String[] autoCorrectionThresholdValues = mResources.getStringArray(
+                R.array.auto_correction_threshold_values);
+        // When autoCrrectionThreshold is greater than 1.0, auto correction is virtually turned off.
+        double autoCorrectionThreshold = Double.MAX_VALUE;
         try {
-            final int arrayIndex = Integer.valueOf(currentAutoCompletionSetting);
-            if (arrayIndex >= 0 && arrayIndex < autoCompletionThresholdValues.length) {
-                autoCompletionThreshold = Double.parseDouble(
-                        autoCompletionThresholdValues[arrayIndex]);
+            final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
+            if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
+                autoCorrectionThreshold = Double.parseDouble(
+                        autoCorrectionThresholdValues[arrayIndex]);
             }
         } catch (NumberFormatException e) {
-            // Whenever the threshold settings are correct,
-            // never come here.
-            autoCompletionThreshold = Double.MAX_VALUE;
-            Log.w(TAG, "Cannot load auto completion threshold setting."
-                    + " currentAutoCompletionSetting: " + currentAutoCompletionSetting
-                    + ", autoCompletionThresholdValues: "
-                    + Arrays.toString(autoCompletionThresholdValues));
+            // Whenever the threshold settings are correct, never come here.
+            autoCorrectionThreshold = Double.MAX_VALUE;
+            Log.w(TAG, "Cannot load auto correction threshold setting."
+                    + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
+                    + ", autoCorrectionThresholdValues: "
+                    + Arrays.toString(autoCorrectionThresholdValues));
         }
         // TODO: This should be refactored :
-        //           setAutoCompleteThreshold should be called outside of this method.
-        mSuggest.setAutoCompleteThreshold(autoCompletionThreshold);
+        //           setAutoCorrectionThreshold should be called outside of this method.
+        mSuggest.setAutoCorrectionThreshold(autoCorrectionThreshold);
     }
 
     private boolean isAutoCorrectEnabled(SharedPreferences sp) {
-        final String currentAutoCompletionSetting = sp.getString(
-                Settings.PREF_AUTO_COMPLETION_THRESHOLD,
-                mResources.getString(R.string.auto_completion_threshold_mode_value_modest));
-        final String autoCompletionOff = mResources.getString(
-                R.string.auto_completion_threshold_mode_value_off);
-        return !currentAutoCompletionSetting.equals(autoCompletionOff);
+        final String currentAutoCorrectionSetting = sp.getString(
+                Settings.PREF_AUTO_CORRECTION_THRESHOLD,
+                mResources.getString(R.string.auto_correction_threshold_mode_index_modest));
+        final String autoCorrectionOff = mResources.getString(
+                R.string.auto_correction_threshold_mode_index_off);
+        return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
     }
 
     private boolean isBigramSuggestionEnabled(SharedPreferences sp) {
@@ -2106,13 +2105,17 @@
     }
 
     private void initSuggestPuncList() {
-        mSuggestPuncList = new ArrayList<CharSequence>();
-        mSuggestPuncs = mResources.getString(R.string.suggested_punctuations);
-        if (mSuggestPuncs != null) {
-            for (int i = 0; i < mSuggestPuncs.length(); i++) {
-                mSuggestPuncList.add(mSuggestPuncs.subSequence(i, i + 1));
+        if (mSuggestPuncs != null || mSuggestPuncList != null)
+            return;
+        SuggestedWords.Builder builder = new SuggestedWords.Builder();
+        String puncs = mResources.getString(R.string.suggested_punctuations);
+        if (puncs != null) {
+            for (int i = 0; i < puncs.length(); i++) {
+                builder.addWord(puncs.subSequence(i, i + 1));
             }
         }
+        mSuggestPuncList = builder.build();
+        mSuggestPuncs = puncs;
     }
 
     private boolean isSuggestedPunctuation(int code) {
@@ -2167,7 +2170,7 @@
         p.println("  mPredicting=" + mPredicting);
         p.println("  mAutoCorrectOn=" + mAutoCorrectOn);
         p.println("  mAutoSpace=" + mAutoSpace);
-        p.println("  mCompletionOn=" + mCompletionOn);
+        p.println("  mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn);
         p.println("  TextEntryState.state=" + TextEntryState.getState());
         p.println("  mSoundOn=" + mSoundOn);
         p.println("  mVibrateOn=" + mVibrateOn);
@@ -2192,10 +2195,6 @@
         System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
     }
 
-    public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
-        mKeyboardSwitcher.onAutoCompletionStateChanged(isAutoCompletion);
-    }
-
     @Override
     public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
         SubtypeSwitcher.getInstance().updateSubtype(subtype);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 9c7c5aa..3f604a3 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -53,11 +53,12 @@
     public static final String PREF_VOICE_SETTINGS_KEY = "voice_mode";
     public static final String PREF_INPUT_LANGUAGE = "input_language";
     public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
+    public static final String PREF_SUBTYPES = "subtype_settings";
 
     public static final String PREF_PREDICTION_SETTINGS_KEY = "prediction_settings";
     public static final String PREF_QUICK_FIXES = "quick_fixes";
     public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
-    public static final String PREF_AUTO_COMPLETION_THRESHOLD = "auto_completion_threshold";
+    public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
     public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion";
 
     // Dialog ids
@@ -66,7 +67,7 @@
     private CheckBoxPreference mQuickFixes;
     private ListPreference mVoicePreference;
     private ListPreference mSettingsKeyPreference;
-    private ListPreference mAutoCompletionThreshold;
+    private ListPreference mAutoCorrectionThreshold;
     private CheckBoxPreference mBigramSuggestion;
     private boolean mVoiceOn;
 
@@ -77,11 +78,11 @@
     private boolean mOkClicked = false;
     private String mVoiceModeOff;
 
-    private void ensureConsistencyOfAutoCompletionSettings() {
-        final String autoCompletionOff = getResources().getString(
-                R.string.auto_completion_threshold_mode_value_off);
-        final String currentSetting = mAutoCompletionThreshold.getValue();
-        mBigramSuggestion.setEnabled(!currentSetting.equals(autoCompletionOff));
+    private void ensureConsistencyOfAutoCorrectionSettings() {
+        final String autoCorrectionOff = getResources().getString(
+                R.string.auto_correction_threshold_mode_index_off);
+        final String currentSetting = mAutoCorrectionThreshold.getValue();
+        mBigramSuggestion.setEnabled(!currentSetting.equals(autoCorrectionOff));
     }
     @Override
     protected void onCreate(Bundle icicle) {
@@ -98,9 +99,9 @@
                 .equals(mVoiceModeOff));
         mLogger = VoiceInputLogger.getLogger(this);
 
-        mAutoCompletionThreshold = (ListPreference) findPreference(PREF_AUTO_COMPLETION_THRESHOLD);
+        mAutoCorrectionThreshold = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
         mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS);
-        ensureConsistencyOfAutoCompletionSettings();
+        ensureConsistencyOfAutoCorrectionSettings();
 
         final boolean showSettingsKeyOption = getResources().getBoolean(
                 R.bool.config_enable_show_settings_key_option);
@@ -119,6 +120,12 @@
             getPreferenceScreen().removePreference(
                     getPreferenceScreen().findPreference(PREF_VIBRATE_ON));
         }
+
+        final boolean showSubtypeSettings = getResources().getBoolean(
+                R.bool.config_enable_show_subtype_settings);
+        if (!showSubtypeSettings) {
+            getPreferenceScreen().removePreference(findPreference(PREF_SUBTYPES));
+        }
     }
 
     @Override
@@ -155,7 +162,7 @@
                 showVoiceConfirmation();
             }
         }
-        ensureConsistencyOfAutoCompletionSettings();
+        ensureConsistencyOfAutoCorrectionSettings();
         mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
                 .equals(mVoiceModeOff));
         updateVoiceModeSummary();
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index a6df187..a30ec15 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -25,12 +25,10 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 
 /**
  * This class loads a dictionary and provides a list of suggestions for a given sequence of 
  * characters. This includes corrections and completions.
- * @hide pending API Council Approval
  */
 public class Suggest implements Dictionary.WordCallback {
 
@@ -83,7 +81,7 @@
 
     private boolean mAutoTextEnabled;
 
-    private double mAutoCompleteThreshold;
+    private double mAutoCorrectionThreshold;
     private int[] mPriorities = new int[mPrefMaxSuggestions];
     private int[] mBigramPriorities = new int[PREF_MAX_BIGRAMS];
 
@@ -97,7 +95,6 @@
     ArrayList<CharSequence> mBigramSuggestions  = new ArrayList<CharSequence>();
     private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
     private boolean mHaveCorrection;
-    private CharSequence mOriginalWord;
     private String mLowerOriginalWord;
 
     // TODO: Remove these member variables by passing more context to addWord() callback method
@@ -166,8 +163,8 @@
         mUserBigramDictionary = userBigramDictionary;
     }
 
-    public void setAutoCompleteThreshold(double threshold) {
-        mAutoCompleteThreshold = threshold;
+    public void setAutoCorrectionThreshold(double threshold) {
+        mAutoCorrectionThreshold = threshold;
     }
 
     /**
@@ -191,15 +188,21 @@
     }
 
     /**
-     * Returns a list of words that match the list of character codes passed in.
-     * This list will be overwritten the next time this function is called.
+     * Returns a object which represents suggested words that match the list of character codes
+     * passed in. This object contents will be overwritten the next time this function is called.
      * @param view a view for retrieving the context for AutoText
      * @param wordComposer contains what is currently being typed
      * @param prevWordForBigram previous word (used only for bigram)
-     * @return list of suggestions.
+     * @return suggested words object.
      */
-    public List<CharSequence> getSuggestions(View view, WordComposer wordComposer, 
-            boolean includeTypedWordIfValid, CharSequence prevWordForBigram) {
+    public SuggestedWords getSuggestions(View view, WordComposer wordComposer,
+            CharSequence prevWordForBigram) {
+        return getSuggestedWordBuilder(view, wordComposer, prevWordForBigram).build();
+    }
+
+    // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
+    public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
+            CharSequence prevWordForBigram) {
         LatinImeLogger.onStartSuggestion(prevWordForBigram);
         mHaveCorrection = false;
         mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
@@ -209,13 +212,13 @@
         Arrays.fill(mNextLettersFrequencies, 0);
 
         // Save a lowercase version of the original word
-        mOriginalWord = wordComposer.getTypedWord();
-        if (mOriginalWord != null) {
-            final String mOriginalWordString = mOriginalWord.toString();
-            mOriginalWord = mOriginalWordString;
-            mLowerOriginalWord = mOriginalWordString.toLowerCase();
+        CharSequence typedWord = wordComposer.getTypedWord();
+        if (typedWord != null) {
+            final String typedWordString = typedWord.toString();
+            typedWord = typedWordString;
+            mLowerOriginalWord = typedWordString.toLowerCase();
             // Treating USER_TYPED as UNIGRAM suggestion for logging now.
-            LatinImeLogger.onAddSuggestedWord(mOriginalWordString, Suggest.DIC_USER_TYPED,
+            LatinImeLogger.onAddSuggestedWord(typedWordString, Suggest.DIC_USER_TYPED,
                     Dictionary.DataType.UNIGRAM);
         } else {
             mLowerOriginalWord = "";
@@ -273,7 +276,7 @@
                     mContactsDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
                 }
 
-                if (mSuggestions.size() > 0 && isValidWord(mOriginalWord)
+                if (mSuggestions.size() > 0 && isValidWord(typedWord)
                         && (mCorrectionMode == CORRECTION_FULL
                         || mCorrectionMode == CORRECTION_FULL_BIGRAM)) {
                     mHaveCorrection = true;
@@ -285,19 +288,19 @@
                 // TODO: when the normalized score of the first suggestion is nearly equals to
                 //       the normalized score of the second suggestion, behave less aggressive.
                 final double normalizedScore = Utils.calcNormalizedScore(
-                        mOriginalWord, mSuggestions.get(0), mPriorities[0]);
+                        typedWord, mSuggestions.get(0), mPriorities[0]);
                 if (LatinImeLogger.sDBG) {
-                    Log.d(TAG, "Normalized " + mOriginalWord + "," + mSuggestions.get(0) + ","
+                    Log.d(TAG, "Normalized " + typedWord + "," + mSuggestions.get(0) + ","
                             + mPriorities[0] + normalizedScore
-                            + "(" + mAutoCompleteThreshold + ")");
+                            + "(" + mAutoCorrectionThreshold + ")");
                 }
-                if (normalizedScore >= mAutoCompleteThreshold) {
+                if (normalizedScore >= mAutoCorrectionThreshold) {
                     mHaveCorrection = true;
                 }
             }
         }
-        if (mOriginalWord != null) {
-            mSuggestions.add(0, mOriginalWord.toString());
+        if (typedWord != null) {
+            mSuggestions.add(0, typedWord.toString());
         }
         if (mAutoTextEnabled) {
             int i = 0;
@@ -342,7 +345,7 @@
             }
         }
         removeDupes();
-        return mSuggestions;
+        return new SuggestedWords.Builder().setWords(mSuggestions);
     }
 
     public int[] getNextLettersFrequencies() {
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
new file mode 100644
index 0000000..0bb7c66
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.view.inputmethod.CompletionInfo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SuggestedWords {
+    public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, null);
+
+    public final List<CharSequence> mWords;
+    public final boolean mIsApplicationSpecifiedCompletions;
+    public final boolean mTypedWordValid;
+    public final boolean mHasMinimalSuggestion;
+    public final Object[] mDebugInfo;
+
+    private SuggestedWords(List<CharSequence> words, boolean isApplicationSpecifiedCompletions,
+            boolean typedWordValid, boolean hasMinamlSuggestion, Object[] debugInfo) {
+        if (words != null) {
+            mWords = words;
+        } else {
+            mWords = Collections.emptyList();
+        }
+        mIsApplicationSpecifiedCompletions = isApplicationSpecifiedCompletions;
+        mTypedWordValid = typedWordValid;
+        mHasMinimalSuggestion = hasMinamlSuggestion;
+        mDebugInfo = debugInfo;
+    }
+
+    public int size() {
+        return mWords.size();
+    }
+
+    public CharSequence getWord(int pos) {
+        return mWords.get(pos);
+    }
+
+    public boolean hasAutoCorrectionWord() {
+        return mHasMinimalSuggestion && size() > 1 && !mTypedWordValid;
+    }
+
+    public boolean hasWordAboveAutoCorrectionScoreThreshold() {
+        return mHasMinimalSuggestion && ((size() > 1 && !mTypedWordValid) || mTypedWordValid);
+    }
+
+    public static class Builder {
+        private List<CharSequence> mWords;
+        private boolean mIsCompletions;
+        private boolean mTypedWordVallid;
+        private boolean mHasMinimalSuggestion;
+        private Object[] mDebugInfo;
+
+        public Builder() {
+            // Nothing to do here.
+        }
+
+        public Builder setWords(List<CharSequence> words) {
+            mWords = words;
+            return this;
+        }
+
+        public Builder setDebugInfo(Object[] debuginfo) {
+            mDebugInfo = debuginfo;
+            return this;
+        }
+
+        public Builder addWord(int pos, CharSequence word) {
+            if (mWords == null)
+                mWords = new ArrayList<CharSequence>();
+            mWords.add(pos, word);
+            return this;
+        }
+
+        public Builder addWord(CharSequence word) {
+            if (mWords == null)
+                mWords = new ArrayList<CharSequence>();
+            mWords.add(word);
+            return this;
+        }
+
+        public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) {
+            for (CompletionInfo info : infos)
+                addWord(info.getText());
+            mIsCompletions = true;
+            return this;
+        }
+
+        public Builder setTypedWordValid(boolean typedWordValid) {
+            mTypedWordVallid = typedWordValid;
+            return this;
+        }
+
+        public Builder setHasMinimalSuggestion(boolean hasMinamlSuggestion) {
+            mHasMinimalSuggestion = hasMinamlSuggestion;
+            return this;
+        }
+
+        public CharSequence getWord(int pos) {
+            return mWords.get(pos);
+        }
+
+        public SuggestedWords build() {
+            return new SuggestedWords(mWords, mIsCompletions, mTypedWordVallid,
+                    mHasMinimalSuggestion, mDebugInfo);
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 7a94ae4..e03f564 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
+import android.net.Uri;
 import android.provider.UserDictionary.Words;
 
 public class UserDictionary extends ExpandableDictionary {
@@ -80,7 +81,7 @@
      * @TODO use a higher or float range for frequency
      */
     @Override
-    public synchronized void addWord(String word, int frequency) {
+    public synchronized void addWord(final String word, final int frequency) {
         // Force load the dictionary here synchronously
         if (getRequiresReload()) loadDictionaryAsync();
         // Safeguard against adding long words. Can cause stack overflow.
@@ -99,7 +100,22 @@
         new Thread("addWord") {
             @Override
             public void run() {
-                contentResolver.insert(Words.CONTENT_URI, values);
+                Cursor cursor = contentResolver.query(Words.CONTENT_URI, PROJECTION,
+                        "word=? and ((locale IS NULL) or (locale=?))",
+                        new String[] { word, mLocale }, null);
+                if (cursor != null && cursor.moveToFirst()) {
+                    String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE));
+                    // If locale is null, we will not override the entry.
+                    if (locale != null && locale.equals(mLocale.toString())) {
+                        long id = cursor.getLong(cursor.getColumnIndex(Words._ID));
+                        Uri uri = Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id));
+                        // Update the entry with new frequency value.
+                        contentResolver.update(uri, values, null, null);
+                    }
+                } else {
+                    // Insert new entry.
+                    contentResolver.insert(Words.CONTENT_URI, values);
+                }
             }
         }.start();
 
diff --git a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
index 2052d93..c532a0b 100644
--- a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
+++ b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
@@ -22,6 +22,7 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SharedPreferencesCompat;
 import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.SuggestedWords;
 
 import android.app.AlertDialog;
 import android.content.Context;
@@ -424,17 +425,20 @@
         if (mWordToSuggestions.containsKey(selectedWord)) {
             mShowingVoiceSuggestions = true;
             List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
+            SuggestedWords.Builder builder = new SuggestedWords.Builder();
             // If the first letter of touching is capitalized, make all the suggestions
             // start with a capital letter.
             if (Character.isUpperCase(touching.mWord.charAt(0))) {
-                for (int i = 0; i < suggestions.size(); i++) {
-                    String origSugg = (String) suggestions.get(i);
-                    String capsSugg = origSugg.toUpperCase().charAt(0)
-                            + origSugg.subSequence(1, origSugg.length()).toString();
-                    suggestions.set(i, capsSugg);
+                for (CharSequence word : suggestions) {
+                    String str = word.toString();
+                    word = Character.toUpperCase(str.charAt(0)) + str.substring(1);
+                    builder.addWord(word);
                 }
+            } else {
+                builder.setWords(suggestions);
             }
-            mContext.setSuggestions(suggestions, false, true, true);
+            builder.setTypedWordValid(true).setHasMinimalSuggestion(true);
+            mContext.setSuggestions(builder.build());
             mContext.setCandidatesViewShown(true);
             return true;
         }
diff --git a/native/src/defines.h b/native/src/defines.h
index 52191be..73394ce 100644
--- a/native/src/defines.h
+++ b/native/src/defines.h
@@ -67,6 +67,7 @@
 #define WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE 75
 #define WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE 80
 #define WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE 75
+#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
 #define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
 
 // This should be greater than or equal to MAX_WORD_LENGTH defined in BinaryDictionary.java
@@ -75,7 +76,10 @@
 
 #define MAX_DEPTH_MULTIPLIER 3
 
-#define MIN_SUGGEST_DEPTH 2
+// Minimum suggest depth for one word for all cases except for missing space suggestions.
+#define MIN_SUGGEST_DEPTH 1
+#define MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION 3
+#define MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION 3
 
 #define min(a,b) ((a)<(b)?(a):(b))
 
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 7ecf1c9..f679001 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -45,24 +45,25 @@
         int *frequencies, int *nextLetters, int nextLettersSize)
 {
     initSuggestions(codes, codesSize, outWords, frequencies);
+    if (DEBUG_DICT) assert(codesSize == mInputLength);
+
     const int MAX_DEPTH = min(mInputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
-    getSuggestionCandidates(codesSize, -1, -1, -1, nextLetters, nextLettersSize, MAX_DEPTH);
+    getSuggestionCandidates(-1, -1, -1, nextLetters, nextLettersSize, MAX_DEPTH);
 
     // Suggestion with missing character
     if (SUGGEST_WORDS_WITH_MISSING_CHARACTER) {
         for (int i = 0; i < codesSize; ++i) {
             if (DEBUG_DICT) LOGI("--- Suggest missing characters %d", i);
-            getSuggestionCandidates(codesSize, i, -1, -1, NULL, 0, MAX_DEPTH);
+            getSuggestionCandidates(i, -1, -1, NULL, 0, MAX_DEPTH);
         }
     }
 
     // Suggestion with excessive character
-    if (SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER && mInputLength > MIN_SUGGEST_DEPTH) {
+    if (SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER
+            && mInputLength >= MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION) {
         for (int i = 0; i < codesSize; ++i) {
-            if (existsAdjacentProximityChars(i, codesSize)) {
-                if (DEBUG_DICT) LOGI("--- Suggest excessive characters %d", i);
-                getSuggestionCandidates(codesSize, -1, i, -1, NULL, 0, MAX_DEPTH);
-            }
+            if (DEBUG_DICT) LOGI("--- Suggest excessive characters %d", i);
+            getSuggestionCandidates(-1, i, -1, NULL, 0, MAX_DEPTH);
         }
     }
 
@@ -71,12 +72,13 @@
     if (SUGGEST_WORDS_WITH_TRANSPOSED_CHARACTERS) {
         for (int i = 0; i < codesSize; ++i) {
             if (DEBUG_DICT) LOGI("--- Suggest transposed characters %d", i);
-            getSuggestionCandidates(codesSize, -1, -1, i, NULL, 0, mInputLength - 1);
+            getSuggestionCandidates(-1, -1, i, NULL, 0, mInputLength - 1);
         }
     }
 
     // Suggestions with missing space
-    if (SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER && mInputLength > MIN_SUGGEST_DEPTH) {
+    if (SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER
+            && mInputLength >= MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION) {
         for (int i = 1; i < codesSize; ++i) {
             if (DEBUG_DICT) LOGI("--- Suggest missing space characters %d", i);
             getMissingSpaceWords(mInputLength, i);
@@ -196,13 +198,15 @@
 static const char QUOTE = '\'';
 static const char SPACE = ' ';
 
-void UnigramDictionary::getSuggestionCandidates(const int inputLength, const int skipPos,
+void UnigramDictionary::getSuggestionCandidates(const int skipPos,
         const int excessivePos, const int transposedPos, int *nextLetters,
         const int nextLettersSize, const int maxDepth) {
-    if (DEBUG_DICT) LOGI("getSuggestionCandidates %d", maxDepth);
-    if (DEBUG_DICT) assert(transposedPos + 1 < inputLength);
-    if (DEBUG_DICT) assert(excessivePos < inputLength);
-    if (DEBUG_DICT) assert(missingPos < inputLength);
+    if (DEBUG_DICT) {
+        LOGI("getSuggestionCandidates %d", maxDepth);
+        assert(transposedPos + 1 < mInputLength);
+        assert(excessivePos < mInputLength);
+        assert(missingPos < mInputLength);
+    }
     int rootPosition = ROOT_POS;
     // Get the number of child of root, then increment the position
     int childCount = Dictionary::getCount(DICT, &rootPosition);
@@ -321,41 +325,46 @@
     }
 }
 
-inline void UnigramDictionary::onTerminalWhenUserTypedLengthIsGreaterThanInputLength(
-        unsigned short *word, const int inputLength, const int depth, const int snr,
-        int *nextLetters, const int nextLettersSize, const int skipPos, const int excessivePos,
-        const int transposedPos, const int freq) {
-    int finalFreq = freq * snr;
+inline int UnigramDictionary::calculateFinalFreq(const int inputIndex, const int snr,
+        const int skipPos, const int excessivePos, const int transposedPos, const int freq,
+        const bool sameLength) {
     // TODO: Demote by edit distance
+    int finalFreq = freq * snr;
     if (skipPos >= 0) finalFreq = finalFreq * WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE / 100;
-    if (excessivePos >= 0) finalFreq = finalFreq
-            * WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE / 100;
     if (transposedPos >= 0) finalFreq = finalFreq
             * WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE / 100;
+    if (excessivePos >= 0) {
+        finalFreq = finalFreq * WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE / 100;
+        if (!existsAdjacentProximityChars(inputIndex, mInputLength)) {
+            finalFreq = finalFreq
+                    * WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE / 100;
+        }
+    }
+    if (sameLength && skipPos < 0) finalFreq *= FULL_WORD_MULTIPLIER;
+    return finalFreq;
+}
 
+inline void UnigramDictionary::onTerminalWhenUserTypedLengthIsGreaterThanInputLength(
+        unsigned short *word, const int inputIndex, const int depth, const int snr,
+        int *nextLetters, const int nextLettersSize, const int skipPos, const int excessivePos,
+        const int transposedPos, const int freq) {
+    const int finalFreq = calculateFinalFreq(inputIndex, snr, skipPos, excessivePos, transposedPos,
+            freq, false);
     if (depth >= MIN_SUGGEST_DEPTH) addWord(word, depth + 1, finalFreq);
-    if (depth >= inputLength && skipPos < 0) {
+    if (depth >= mInputLength && skipPos < 0) {
         registerNextLetter(mWord[mInputLength], nextLetters, nextLettersSize);
     }
 }
 
 inline void UnigramDictionary::onTerminalWhenUserTypedLengthIsSameAsInputLength(
-        unsigned short *word, const int depth, const int snr, const int skipPos,
-        const int excessivePos, const int transposedPos, const int freq, const int addedWeight) {
-    if (!sameAsTyped(word, depth + 1)) {
-        int finalFreq = freq * snr * addedWeight;
-        // TODO: Demote by edit distance
-        if (skipPos >= 0) finalFreq = finalFreq * WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE / 100;
-        if (excessivePos >= 0) finalFreq = finalFreq
-                * WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE / 100;
-        if (transposedPos >= 0) finalFreq = finalFreq
-                * WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE / 100;
-
-        // Proximity collection will promote a word of the same length as
-        // what user typed.
-        if (skipPos < 0) finalFreq *= FULL_WORD_MULTIPLIER;
-        if (depth >= MIN_SUGGEST_DEPTH) addWord(word, depth + 1, finalFreq);
-    }
+        unsigned short *word, const int inputIndex, const int depth, const int snr,
+        const int skipPos, const int excessivePos, const int transposedPos, const int freq,
+        const int addedWeight) {
+    if (sameAsTyped(word, depth + 1)) return;
+    const int finalFreq = calculateFinalFreq(inputIndex, snr * addedWeight, skipPos,
+            excessivePos, transposedPos, freq, true);
+    // Proximity collection will promote a word of the same length as what user typed.
+    if (depth >= MIN_SUGGEST_DEPTH) addWord(word, depth + 1, finalFreq);
 }
 
 inline bool UnigramDictionary::needsToSkipCurrentNode(const unsigned short c,
@@ -437,7 +446,7 @@
     if (traverseAllNodes || needsToSkipCurrentNode(c, inputIndex, skipPos, depth)) {
         mWord[depth] = c;
         if (traverseAllNodes && terminal) {
-            onTerminalWhenUserTypedLengthIsGreaterThanInputLength(mWord, mInputLength, depth,
+            onTerminalWhenUserTypedLengthIsGreaterThanInputLength(mWord, inputIndex, depth,
                     snr, nextLetters, nextLettersSize, skipPos, excessivePos, transposedPos, freq);
         }
         if (!needsToTraverseChildrenNodes) return false;
@@ -462,7 +471,7 @@
         const int addedWeight = matchedProximityCharId == 0 ? TYPED_LETTER_MULTIPLIER : 1;
         const bool isSameAsUserTypedLength = mInputLength == inputIndex + 1;
         if (isSameAsUserTypedLength && terminal) {
-            onTerminalWhenUserTypedLengthIsSameAsInputLength(mWord, depth, snr,
+            onTerminalWhenUserTypedLengthIsSameAsInputLength(mWord, inputIndex, depth, snr,
                     skipPos, excessivePos, transposedPos, freq, addedWeight);
         }
         if (!needsToTraverseChildrenNodes) return false;
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index abfdb8d..445ff7a 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -31,7 +31,7 @@
 
 private:
     void initSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies);
-    void getSuggestionCandidates(const int inputLength, const int skipPos, const int excessivePos,
+    void getSuggestionCandidates(const int skipPos, const int excessivePos,
             const int transposedPos, int *nextLetters, const int nextLettersSize,
             const int maxDepth);
     void getVersionNumber();
@@ -52,13 +52,15 @@
             const int excessivePos, const int transposedPos, int *nextLetters,
             const int nextLettersSize);
     void registerNextLetter(unsigned short c, int *nextLetters, int nextLettersSize);
+    int calculateFinalFreq(const int inputIndex, const int snr, const int skipPos,
+            const int excessivePos, const int transposedPos, const int freq, const bool sameLength);
     void onTerminalWhenUserTypedLengthIsGreaterThanInputLength(unsigned short *word,
-            const int mInputLength, const int depth, const int snr, int *nextLetters,
+            const int inputIndex, const int depth, const int snr, int *nextLetters,
             const int nextLettersSize, const int skipPos, const int excessivePos,
             const int transposedPos, const int freq);
-    void onTerminalWhenUserTypedLengthIsSameAsInputLength(unsigned short *word, const int depth,
-            const int snr, const int skipPos, const int excessivePos, const int transposedPos,
-            const int freq, const int addedWeight);
+    void onTerminalWhenUserTypedLengthIsSameAsInputLength(unsigned short *word,
+            const int inputIndex, const int depth, const int snr, const int skipPos,
+            const int excessivePos, const int transposedPos, const int freq, const int addedWeight);
     bool needsToSkipCurrentNode(const unsigned short c,
             const int inputIndex, const int skipPos, const int depth);
     int getMatchedProximityId(const int *currentChars, const unsigned short c, const int skipPos,
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 932098a..7254520 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -116,30 +116,30 @@
         return word;
     }
 
-    private boolean isDefaultSuggestion(List<CharSequence> suggestions, CharSequence word) {
+    private boolean isDefaultSuggestion(SuggestedWords suggestions, CharSequence word) {
         // Check if either the word is what you typed or the first alternative
         return suggestions.size() > 0 &&
                 (/*TextUtils.equals(suggestions.get(0), word) || */
-                  (suggestions.size() > 1 && TextUtils.equals(suggestions.get(1), word)));
+                  (suggestions.size() > 1 && TextUtils.equals(suggestions.getWord(1), word)));
     }
 
     boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) {
         WordComposer word = createWordComposer(typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
         return isDefaultSuggestion(suggestions, expected);
     }
 
     boolean isDefaultCorrection(CharSequence typed, CharSequence expected) {
         WordComposer word = createWordComposer(typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
         return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection();
     }
 
     boolean isASuggestion(CharSequence typed, CharSequence expected) {
         WordComposer word = createWordComposer(typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
         for (int i = 1; i < suggestions.size(); i++) {
-            if (TextUtils.equals(suggestions.get(i), expected)) return true;
+            if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
         }
         return false;
     }
@@ -147,7 +147,7 @@
     private void getBigramSuggestions(CharSequence previous, CharSequence typed) {
         if (!TextUtils.isEmpty(previous) && (typed.length() > 1)) {
             WordComposer firstChar = createWordComposer(Character.toString(typed.charAt(0)));
-            mSuggest.getSuggestions(null, firstChar, false, previous);
+            mSuggest.getSuggestions(null, firstChar, previous);
         }
     }
 
@@ -155,7 +155,7 @@
             CharSequence expected) {
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
         return isDefaultSuggestion(suggestions, expected);
     }
 
@@ -163,7 +163,7 @@
             CharSequence expected) {
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
         return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection();
     }
 
@@ -171,9 +171,9 @@
             CharSequence expected) {
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
-        List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous);
+        SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
         for (int i = 1; i < suggestions.size(); i++) {
-            if (TextUtils.equals(suggestions.get(i), expected)) return true;
+            if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
         }
         return false;
     }
@@ -189,7 +189,7 @@
         flushUserBigrams();
         if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) {
             WordComposer firstChar = createWordComposer(Character.toString(typed));
-            mSuggest.getSuggestions(null, firstChar, false, previous);
+            mSuggest.getSuggestions(null, firstChar, previous);
             boolean reloading = mUserBigram.reloadDictionaryIfRequired();
             if (reloading) mUserBigram.waitForDictionaryLoading();
             mUserBigram.getBigrams(firstChar, previous, mSuggest, null);