Merge "Tell the text view we reset state on finish input"
diff --git a/java/res/values-mn/strings.xml b/java/res/values-mn/strings.xml
new file mode 100644
index 0000000..eb2ba85
--- /dev/null
+++ b/java/res/values-mn/strings.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2008, 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="english_ime_input_options" msgid="3909945612939668554">"Оруулах сонголтууд"</string>
+    <string name="english_ime_research_log" msgid="8492602295696577851">"Судалгааны протоколын командууд"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Харилцагчийн нэр хайх"</string>
+    <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Алдаа шалгагч нь таны харилцагчдын жагсаалтаас ашиглана"</string>
+    <string name="vibrate_on_keypress" msgid="5258079494276955460">"Товч дарахад чичрэх"</string>
+    <string name="sound_on_keypress" msgid="6093592297198243644">"Товч дарахад дуу гаргах"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Товч дарахад попап гарна"</string>
+    <string name="general_category" msgid="1859088467017573195">"Ерөнхий"</string>
+    <string name="correction_category" msgid="2236750915056607613">"Текст залруулалт"</string>
+    <string name="gesture_typing_category" msgid="497263612130532630">"Зангаагаар бичих"</string>
+    <string name="misc_category" msgid="6894192814868233453">"Бусад сонголтууд"</string>
+    <string name="advanced_settings" msgid="362895144495591463">"Дэлгэрэнгүй тохиргоо"</string>
+    <string name="advanced_settings_summary" msgid="4487980456152830271">"Экспертүүдэд зориулсан тохиргоо"</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Оруулах өөр арга руу шилжүүлэх"</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Хэл солих түлхүүрт өөр оруулах аргууд мөн багтсан байгаа"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"Хэл солих товч"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Оруулах хэл олныг идэвхжүүлсэн үед харуулах"</string>
+    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Гулсалт заагчийг харуулах"</string>
+    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Сэлгэх буюу Симбол товчуудаас гулсах үед нүдэнд харагдуулах"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Товчны попап арилах хугацаа"</string>
+    <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Хүлээхгүй"</string>
+    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Үндсэн"</string>
+    <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g>мс"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Харилцагчдын нэрс санал болгох"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Санал болгох, залруулахда Харилцагчдын нэрсээс ашиглах"</string>
+    <string name="use_double_space_period" msgid="8781529969425082860">"Давхар зайтай цэг"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Ардаа зайтай цэг оруулахын тулд Зай авах дээр давхар товшино уу"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"Автоматаар томруулах"</string>
+    <string name="auto_cap_summary" msgid="7934452761022946874">"Өгүүлбэр бүрийн эхний үгийн эхний үсгийг томруулах"</string>
+    <string name="edit_personal_dictionary" msgid="3996910038952940420">"Хувийн толь бичиг"</string>
+    <string name="configure_dictionaries_title" msgid="4238652338556902049">"Нэмэлт толь бичгүүд"</string>
+    <string name="main_dictionary" msgid="4798763781818361168">"Үндсэн толь бичиг"</string>
+    <string name="prefs_show_suggestions" msgid="8026799663445531637">"Залруулах санал болголтуудыг харуулах"</string>
+    <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Бичих явцад санал болгосон үгсийг харуулах"</string>
+    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Байнга харуулах"</string>
+    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Босоо горимд харуулах"</string>
+    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Байнга нуух"</string>
+    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Доромжилсон үгсийг хаах"</string>
+    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Доромжилсон үгсийг санал болгохгүй байх"</string>
+    <string name="auto_correction" msgid="7630720885194996950">"Авто-залруулга"</string>
+    <string name="auto_correction_summary" msgid="5625751551134658006">"Хоосон зай болон цэг таслал нь буруу бичсэн үгсийг автоматаар залруулна"</string>
+    <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Идэвхгүй"</string>
+    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Хүлээцтэй"</string>
+    <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Хүчтэй"</string>
+    <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Маш хүчтэй"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"Дараагийн-үг санал болгох"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"Өмнөх үгийг үг санал болгоход ашиглах"</string>
+    <string name="gesture_input" msgid="826951152254563827">"Зангаагаар бичихийг идэвхжүүлэх"</string>
+    <string name="gesture_input_summary" msgid="9180350639305731231">"Үсгүүд дээр гулсуулах замаар үг оруулах"</string>
+    <string name="gesture_preview_trail" msgid="3802333369335722221">"Зангасан мөрийг харуулах"</string>
+    <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Динамик хөвөгчөөр урьдчилан харах"</string>
+    <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Зангах явцад санал болгож буй үгийг харах"</string>
+    <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Хадгалагдсан"</string>
+    <string name="label_go_key" msgid="1635148082137219148">"Явах"</string>
+    <string name="label_next_key" msgid="362972844525672568">"Дараах"</string>
+    <string name="label_previous_key" msgid="1211868118071386787">"Өмнөх"</string>
+    <string name="label_done_key" msgid="2441578748772529288">"Дууссан"</string>
+    <string name="label_send_key" msgid="2815056534433717444">"Илгээх"</string>
+    <string name="label_pause_key" msgid="181098308428035340">"Пауз"</string>
+    <string name="label_wait_key" msgid="6402152600878093134">"Хүлээх"</string>
+    <string name="spoken_use_headphones" msgid="896961781287283493">"Нууц үгний товчнуудыг чангаар уншихыг сонсохын тулд чихэвчээ залгана уу."</string>
+    <string name="spoken_current_text_is" msgid="2485723011272583845">"Одоогийн текст %s"</string>
+    <string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст оруулаагүй"</string>
+    <string name="spoken_description_unknown" msgid="3197434010402179157">"Товчийн код %d"</string>
+    <string name="spoken_description_shift" msgid="244197883292549308">"Сэлгэх"</string>
+    <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Сэлгэхийг идэвхжүүлсэн (товшиж идэвхгүйжүүлнэ үү)"</string>
+    <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Томоор бичихийг асаасан (товшиж идэвхгүйжүүлнэ үү)"</string>
+    <string name="spoken_description_delete" msgid="8740376944276199801">"Устгах"</string>
+    <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Симбол"</string>
+    <string name="spoken_description_to_alpha" msgid="23129338819771807">"Үсэгнүүд"</string>
+    <string name="spoken_description_to_numeric" msgid="591752092685161732">"Тоонууд"</string>
+    <string name="spoken_description_settings" msgid="4627462689603838099">"Тохиргоо"</string>
+    <string name="spoken_description_tab" msgid="2667716002663482248">"Таб"</string>
+    <string name="spoken_description_space" msgid="2582521050049860859">"Хоосон зай"</string>
+    <string name="spoken_description_mic" msgid="615536748882611950">"Дуугаар оруулах"</string>
+    <string name="spoken_description_smiley" msgid="2256309826200113918">"Инээсэн царай"</string>
+    <string name="spoken_description_return" msgid="8178083177238315647">"Буцах"</string>
+    <string name="spoken_description_search" msgid="1247236163755920808">"Хайх"</string>
+    <string name="spoken_description_dot" msgid="40711082435231673">"Цэг"</string>
+    <string name="spoken_description_language_switch" msgid="5507091328222331316">"Хэл солих"</string>
+    <string name="spoken_description_action_next" msgid="8636078276664150324">"Дараах"</string>
+    <string name="spoken_description_action_previous" msgid="800872415009336208">"Өмнөх"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Сэлгэхийг идэвхжүүлсэн"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Томоор бичихийг идэвхжүүлсэн"</string>
+    <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Сэлгэхийг идэвхжүүлээгүй"</string>
+    <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Симбол төлөв"</string>
+    <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Үсэгнүүд төлөв"</string>
+    <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Утасны төлөв"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Утасны символ төлөв"</string>
+    <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Гарыг нуусан"</string>
+    <string name="announce_keyboard_mode" msgid="4729081055438508321">"<xliff:g id="MODE">%s</xliff:g> гарыг харуулж байна"</string>
+    <string name="keyboard_mode_date" msgid="3137520166817128102">"огноо"</string>
+    <string name="keyboard_mode_date_time" msgid="339593358488851072">"огноо болон цаг"</string>
+    <string name="keyboard_mode_email" msgid="6216248078128294262">"имэйл"</string>
+    <string name="keyboard_mode_im" msgid="1137405089766557048">"зурвас"</string>
+    <string name="keyboard_mode_number" msgid="7991623440699957069">"дугаар"</string>
+    <string name="keyboard_mode_phone" msgid="6851627527401433229">"утас"</string>
+    <string name="keyboard_mode_text" msgid="6479436687899701619">"текст"</string>
+    <string name="keyboard_mode_time" msgid="4381856885582143277">"цаг"</string>
+    <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Дуун оруулгын товч"</string>
+    <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Үндсэн гар дээр"</string>
+    <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Симбол гар дээр"</string>
+    <string name="voice_input_modes_off" msgid="3745699748218082014">"Хаах"</string>
+    <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мик үндсэн гар дээр"</string>
+    <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Мик симбол гар дээр"</string>
+    <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Дуун оруулах идэвхгүйжсэн"</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Оруулах аргуудын тохиргоо"</string>
+    <string name="language_selection_title" msgid="1651299598555326750">"Оруулах хэл"</string>
+    <string name="send_feedback" msgid="1780431884109392046">"Санал хүсэл илгээх"</string>
+    <string name="select_language" msgid="3693815588777926848">"Оруулах хэл"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Хадгалахын тулд дахин хүрнэ үү"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"Толь бичиг байна"</string>
+    <string name="prefs_enable_log" msgid="6620424505072963557">"Хэрэглэгчийн санал хүсэлтийг идэвхжүүлэх"</string>
+    <string name="prefs_description_log" msgid="7525225584555429211">"Ашиглалтын статистик болон гацалтын репортуудыг автоматаар илгээснээр энэ оруулах арга засагчийг сайжруулахад туслаарай"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"Гарын загвар"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"Англи (ИБ)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"Англи (АНУ)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"Испани (АНУ)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Англи (ИБ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Англи (АНУ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"Испани (АНУ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_no_language" msgid="141420857808801746">"Хэл байхгүй"</string>
+    <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Хэл байхгүй (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Хэл байхгүй (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Хэл байхгүй (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Хэл байхгүй (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Хэл байхгүй (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Хэл байхгүй (PC)"</string>
+    <string name="custom_input_styles_title" msgid="8429952441821251512">"Өөрийн оруулах загвар"</string>
+    <string name="add_style" msgid="6163126614514489951">"Загвар нэмэх"</string>
+    <string name="add" msgid="8299699805688017798">"Нэмэх"</string>
+    <string name="remove" msgid="4486081658752944606">"Устгах"</string>
+    <string name="save" msgid="7646738597196767214">"Хадгалах"</string>
+    <string name="subtype_locale" msgid="8576443440738143764">"Хэл"</string>
+    <string name="keyboard_layout_set" msgid="4309233698194565609">"Байршил"</string>
+    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Та өөрийн оруулах загварыг ашиглахаас өмнө идэвхжүүлэх шаардлагатай. Одоо идэвхжүүлэх үү?"</string>
+    <string name="enable" msgid="5031294444630523247">"Идэвхжүүлэх"</string>
+    <string name="not_now" msgid="6172462888202790482">"Одоо биш"</string>
+    <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ижилхэн оруулах загвар байна: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Ашиглалтын судалгааны горим"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Товч удаан дарах хугацааны тохиргоо"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Товч дарах чичиргээний хугацаа"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Товчны дууны хэмжээ"</string>
+    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Толь бичгийн гадны файлыг унших"</string>
+    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Татаж авсан фолдерт толь бичгийн файл байхгүй байна"</string>
+    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Суулгах толь бичгийн файлыг сонгоно уу"</string>
+    <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"<xliff:g id="LOCALE_NAME">%s</xliff:g>-д зориулсан энэ файлыг үнэхээр суулгах уу?"</string>
+    <string name="error" msgid="8940763624668513648">"Алдаа гарсан"</string>
+    <string name="button_default" msgid="3988017840431881491">"Үндсэн"</string>
+    <string name="setup_welcome_title" msgid="6112821709832031715">"Та <xliff:g id="APPLICATION_NAME">%s</xliff:g>-д тавтай морилно уу"</string>
+    <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Зангаагаар бичихээр"</string>
+    <string name="setup_start_action" msgid="8936036460897347708">"Эхлүүлэх"</string>
+    <string name="setup_next_action" msgid="371821437915144603">"Дараагийн алхам"</string>
+    <string name="setup_steps_title" msgid="6400373034871816182">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-г тохируулж байна"</string>
+    <string name="setup_step1_title" msgid="3147967630253462315">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-г идэвхжүүлэх"</string>
+    <string name="setup_step1_instruction" msgid="2578631936624637241">"Өөрийн Хэл &amp; оруулах тохиргоон дотроос \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\"-г сонгоно уу. Ингэснээр таны төхөөрөмж дээр ажиллах зөвшөөрлийг өгөх болно."</string>
+    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> таны Хэл &amp;amp оруулах тохиргоонд аль хэдийн идэвхжүүлсэн байгаа учир энэ алхам хийгдсэн. Дараагийн алхам руу!"</string>
+    <string name="setup_step1_action" msgid="4366513534999901728">"Тохиргоо дотроос идэвхжүүлэх"</string>
+    <string name="setup_step2_title" msgid="6860725447906690594">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> рүү шилжих"</string>
+    <string name="setup_step2_instruction" msgid="9141481964870023336">"Дараа нь \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\"-г өөрийн идэвхтэй текст-оруулах аргаар сонгоно уу."</string>
+    <string name="setup_step2_action" msgid="1660330307159824337">"Оруулах аргыг солих"</string>
+    <string name="setup_step3_title" msgid="3154757183631490281">"Баяр хүргэе, та бүгдийг нь тохируулчихлаа!"</string>
+    <string name="setup_step3_instruction" msgid="8025981829605426000">"Та одоо өөрийн дуртай апп-ууд дотроо <xliff:g id="APPLICATION_NAME">%s</xliff:g> ашиглан бичих болохоор боллоо."</string>
+    <string name="setup_step3_action" msgid="600879797256942259">"Нэмэлт хэлнүүдийг тохируулах"</string>
+    <string name="setup_finish_action" msgid="276559243409465389">"Дууссан"</string>
+    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Апп дүрсийг харуулах"</string>
+    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Эхлүүлэгч дээр аппликешний дүрсийг харуулах"</string>
+    <string name="app_name" msgid="6320102637491234792">"Толь бичгээг хангагч"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Толь бичгээг хангагч"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Толь бичгийн үйлчилгээ"</string>
+    <string name="download_description" msgid="6014835283119198591">"Толь бичгийн шинэчлэлтийн мэдээлэл"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Нэмэлт толь бичгүүд"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Толь бичиг байна"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Толь бичгийн тохиргоо"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Хэрэглэгчийн толь бичиг"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Хэрэглэгчийн толь"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Толь бичиг байна"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Одоо татаж байна"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Суулгасан"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Суулгасан, идэвхгүйжүүлсэн"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Толь бичгийн үйлчилгээнд холбогдоход алдаа гарлаа"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Толь бичиг байхгүй"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Дахин ачаалах"</string>
+    <string name="last_update" msgid="730467549913588780">"Сүүлд шинэчлэгдсэн"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Шинэчлэлтийг шалгаж байна"</string>
+    <string name="message_loading" msgid="8689096636874758814">"Ачаалж байна..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Үндсэн толь бичиг"</string>
+    <string name="cancel" msgid="6830980399865683324">"Цуцлах"</string>
+    <string name="install_dict" msgid="180852772562189365">"Суулгах"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Цуцлах"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Устгах"</string>
+    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Таны мобайль төхөөрөмж дээр сонгосон хэлэнд толь бичиг байна.&lt;br/&gt; Тус  <xliff:g id="LANGUAGE">%1$s</xliff:g> толь бичгийг &lt;b&gt;татаж аван&lt;/b&gt; зөв бичилтээ сайжруулахыг бид зөвлөж байна.&lt;br/&gt; &lt;br/&gt; Татаж авахад 3G сүлжээгээр нэг хоёр минут болно. Танд &lt;b&gt;хязгааргүй дата эрх&lt;/b&gt; байхгүй бол нэмэлт төлбөр гарч болно.&lt;br/&gt; Та дата эрхийнхээ талаар сайн мэдэхгүй байгаа бол Wi-Fi холболттой газар очин автоматаар татаж авахыг зөвлөж байна.&lt;br/&gt; &lt;br/&gt; Зөвлөмж: Та өөрийн мобайль төхөөрөмжийн &lt;b&gt;Тохиргоо&lt;/b&gt; цэсний &lt;b&gt;Хэл &amp; оруулах&lt;/b&gt; руу очиж толь бичиг татаж авах буюу устгаж болно."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Одоо татах (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi-р татаж авах"</string>
+    <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g> хэлний толь бичигтэй"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Шалгах болон татаж авахын тулд дарна уу"</string>
+    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Татаж байна: <xliff:g id="LANGUAGE">%1$s</xliff:g> хэлний санал болгох үгс удахгүй бэлэн болно."</string>
+    <string name="version_text" msgid="2715354215568469385">"Хувилбар <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+    <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Нэмэх"</string>
+    <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Толь бичигт нэмэх"</string>
+    <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Хэллэг"</string>
+    <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Илүү сонголтууд"</string>
+    <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Цөөн сонголт"</string>
+    <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"Тийм"</string>
+    <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Үг:"</string>
+    <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Товчилбор:"</string>
+    <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Хэл:"</string>
+    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Үг оруулна уу"</string>
+    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Зайлшгүй биш товчилбор"</string>
+    <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Үг засах"</string>
+    <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Засах"</string>
+    <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Устгах"</string>
+    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Таны хэрэглэгчийн толинд ямар ч үг алга байна. Нэмэх (+) товчинд хүрэн үг нэмнэ үү."</string>
+    <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Бүх хэлэнд"</string>
+    <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Өөр хэлүүд…"</string>
+    <string name="user_dict_settings_delete" msgid="110413335187193859">"Устгах"</string>
+    <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
index 5ab94a4..c5aca17 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
@@ -57,6 +57,11 @@
         super(context, attrs, defStyle);
     }
 
+    public void reset() {
+        mStatus = NOT_INITIALIZED;
+        mAnimateToStatus = NOT_INITIALIZED;
+    }
+
     @Override
     protected void onLayout(final boolean changed, final int left, final int top, final int right,
             final int bottom) {
@@ -64,9 +69,7 @@
         mInstallButton = (Button)findViewById(R.id.dict_install_button);
         mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
         mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
-        mInstallButton.setOnClickListener(mOnClickListener);
-        mCancelButton.setOnClickListener(mOnClickListener);
-        mDeleteButton.setOnClickListener(mOnClickListener);
+        setInternalOnClickListener(mOnClickListener);
         setButtonPositionWithoutAnimation(mStatus);
         if (mAnimateToStatus != NOT_INITIALIZED) {
             // We have been asked to animate before we were ready, so we took a note of it.
@@ -139,6 +142,12 @@
 
     public void setInternalOnClickListener(final OnClickListener listener) {
         mOnClickListener = listener;
+        if (null != mInstallButton) {
+            // Already laid out : do it now
+            mInstallButton.setOnClickListener(mOnClickListener);
+            mCancelButton.setOnClickListener(mOnClickListener);
+            mDeleteButton.setOnClickListener(mOnClickListener);
+        }
     }
 
     private ViewPropertyAnimator animateButton(final View button, final int direction) {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
index de3711c..5ad5900 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
@@ -16,8 +16,11 @@
 
 package com.android.inputmethod.dictionarypack;
 
+import android.view.View;
+
 import com.android.inputmethod.latin.CollectionUtils;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -37,6 +40,7 @@
     }
 
     private HashMap<String, State> mWordlistToState = CollectionUtils.newHashMap();
+    private ArrayList<View> mViewCache = CollectionUtils.newArrayList();
 
     public boolean isOpen(final String wordlistId) {
         final State state = mWordlistToState.get(wordlistId);
@@ -64,4 +68,16 @@
             state.mOpen = false;
         }
     }
+
+    public View findFirstOrphanedView() {
+        for (final View v : mViewCache) {
+            if (null == v.getParent()) return v;
+        }
+        return null;
+    }
+
+    public View addToCacheAndReturnView(final View view) {
+        mViewCache.add(view);
+        return view;
+    }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 6183223..1e93e7e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -222,7 +222,9 @@
                     refreshNetworkState();
 
                     removeAnyDictSettings(prefScreen);
+                    int i = 0;
                     for (Preference preference : prefList) {
+                        preference.setOrder(i++);
                         prefScreen.addPreference(preference);
                     }
                 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 03ed267..1511dbc 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -572,7 +572,8 @@
      * If several clients use the same metadata URL, we know to only download it once, and
      * dispatch the update process across all relevant clients when the download ends. This means
      * several clients may share a single download ID if they share a metadata URI.
-     * The dispatching is done in {@link UpdateHandler#downloadFinished(Context, Intent)}, which
+     * The dispatching is done in
+     * {@link UpdateHandler#downloadFinished(Context, android.content.Intent)}, which
      * finds out about the list of relevant clients by calling this method.
      *
      * @param context a context instance to open the databases
@@ -863,17 +864,20 @@
                                 r.getAsString(WORDLISTID_COLUMN),
                                 Integer.toString(STATUS_INSTALLED) },
                         null, null, null);
-                if (c.moveToFirst()) {
-                    // There should never be more than one file, but if there are, it's a bug
-                    // and we should remove them all. I think it might happen if the power of the
-                    // phone is suddenly cut during an update.
-                    final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
-                    do {
-                        Utils.l("Setting for removal", c.getString(filenameIndex));
-                        filenames.add(c.getString(filenameIndex));
-                    } while (c.moveToNext());
+                try {
+                    if (c.moveToFirst()) {
+                        // There should never be more than one file, but if there are, it's a bug
+                        // and we should remove them all. I think it might happen if the power of
+                        // the phone is suddenly cut during an update.
+                        final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
+                        do {
+                            Utils.l("Setting for removal", c.getString(filenameIndex));
+                            filenames.add(c.getString(filenameIndex));
+                        } while (c.moveToNext());
+                    }
+                } finally {
+                    c.close();
                 }
-
                 r.put(STATUS_COLUMN, STATUS_INSTALLED);
                 db.beginTransactionNonExclusive();
                 // Delete all old entries. There should never be any stalled entries, but if
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 451a0fb..a1031c2 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -98,6 +98,14 @@
         setSummary(getSummary(status));
     }
 
+    @Override
+    public View onCreateView(final ViewGroup parent) {
+        final View orphanedView = mInterfaceState.findFirstOrphanedView();
+        if (null != orphanedView) return orphanedView; // Will be sent to onBindView
+        final View newView = super.onCreateView(parent);
+        return mInterfaceState.addToCacheAndReturnView(newView);
+    }
+
     private String getSummary(final int status) {
         switch (status) {
             // If we are deleting the word list, for the user it's like it's already deleted.
@@ -209,6 +217,9 @@
 
         final ButtonSwitcher buttonSwitcher =
                 (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
+        // We need to clear the state of the button switcher, because we reuse views; if we didn't
+        // reset it would animate from whatever its old state was.
+        buttonSwitcher.reset();
         if (mInterfaceState.isOpen(mWordlistId)) {
             // The button is open.
             final int previousStatus = mInterfaceState.getStatus(mWordlistId);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index a9b58de..603e8d3 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -32,6 +32,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -319,20 +320,12 @@
                 // Try the next method.
             } finally {
                 // Ignore exceptions while closing files.
-                try {
-                    if (null != afd) afd.close();
-                    if (null != inputStream) inputStream.close();
-                    if (null != uncompressedStream) uncompressedStream.close();
-                    if (null != decryptedStream) decryptedStream.close();
-                    if (null != bufferedInputStream) bufferedInputStream.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "Exception while closing a file descriptor", e);
-                }
-                try {
-                    if (null != bufferedOutputStream) bufferedOutputStream.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "Exception while closing a file", e);
-                }
+                closeAssetFileDescriptorAndReportAnyException(afd);
+                closeCloseableAndReportAnyException(inputStream);
+                closeCloseableAndReportAnyException(uncompressedStream);
+                closeCloseableAndReportAnyException(decryptedStream);
+                closeCloseableAndReportAnyException(bufferedInputStream);
+                closeCloseableAndReportAnyException(bufferedOutputStream);
             }
         }
 
@@ -352,6 +345,26 @@
         }
     }
 
+    // Ideally the two following methods should be merged, but AssetFileDescriptor does not
+    // implement Closeable although it does implement #close(), and Java does not have
+    // structural typing.
+    private static void closeAssetFileDescriptorAndReportAnyException(
+            final AssetFileDescriptor file) {
+        try {
+            if (null != file) file.close();
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while closing a file", e);
+        }
+    }
+
+    private static void closeCloseableAndReportAnyException(final Closeable file) {
+        try {
+            if (null != file) file.close();
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while closing a file", e);
+        }
+    }
+
     /**
      * Queries a content provider for word list data for some locale and cache the returned files
      *
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index cbe9515..6c3c41a 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -53,10 +53,6 @@
     dictionary.cpp \
     dic_traverse_wrapper.cpp \
     digraph_utils.cpp \
-    proximity_info.cpp \
-    proximity_info_params.cpp \
-    proximity_info_state.cpp \
-    proximity_info_state_utils.cpp \
     unigram_dictionary.cpp \
     words_priority_queue.cpp \
     suggest/core/suggest.cpp \
@@ -64,6 +60,11 @@
         dic_node.cpp \
         dic_node_utils.cpp \
         dic_nodes_cache.cpp) \
+    $(addprefix suggest/core/layout/, \
+        proximity_info.cpp \
+        proximity_info_params.cpp \
+        proximity_info_state.cpp \
+        proximity_info_state_utils.cpp) \
     suggest/core/policy/weighting.cpp \
     suggest/core/session/dic_traverse_session.cpp \
     suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index dedb02a..e312aea 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -17,10 +17,11 @@
 #define LOG_TAG "LatinIME: jni: ProximityInfo"
 
 #include "com_android_inputmethod_keyboard_ProximityInfo.h"
+
 #include "defines.h"
 #include "jni.h"
 #include "jni_common.h"
-#include "proximity_info.h"
+#include "suggest/core/layout/proximity_info.h"
 
 namespace latinime {
 
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 0e9c292..03b3c60 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -162,7 +162,7 @@
     const jsize numberOfOptions = env->GetArrayLength(suggestOptions);
     int options[numberOfOptions];
     env->GetIntArrayRegion(suggestOptions, 0, numberOfOptions, options);
-    SuggestOptions givenOptions(options, numberOfOptions);
+    SuggestOptions givenSuggestOptions(options, numberOfOptions);
 
     // Output values
     /* By the way, let's check the output array length here to make sure */
@@ -190,12 +190,11 @@
     memset(outputTypes, 0, sizeof(outputTypes));
 
     int count;
-    if (givenOptions.isGesture() || inputSize > 0) {
+    if (givenSuggestOptions.isGesture() || inputSize > 0) {
         count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates,
                 times, pointerIds, inputCodePoints, inputSize, prevWordCodePoints,
-                prevWordCodePointsLength, commitPoint, givenOptions.isGesture(),
-                givenOptions.useFullEditDistance(), outputCodePoints, scores,
-                spaceIndices, outputTypes);
+                prevWordCodePointsLength, commitPoint, &givenSuggestOptions, outputCodePoints,
+                scores, spaceIndices, outputTypes);
     } else {
         count = dictionary->getBigrams(prevWordCodePoints, prevWordCodePointsLength,
                 inputCodePoints, inputSize, outputCodePoints, scores, outputTypes);
diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
index dfe3b09..08124ff 100644
--- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
+++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
@@ -34,12 +34,14 @@
     void *ts = reinterpret_cast<void *>(traverseSession);
     Dictionary *dict = reinterpret_cast<Dictionary *>(dictionary);
     if (!previousWord) {
-        DicTraverseWrapper::initDicTraverseSession(ts, dict, 0, 0);
+        DicTraverseWrapper::initDicTraverseSession(
+                ts, dict, 0 /* prevWord */, 0 /* prevWordLength*/, 0 /* suggestOptions */);
         return;
     }
     int prevWord[previousWordLength];
     env->GetIntArrayRegion(previousWord, 0, previousWordLength, prevWord);
-    DicTraverseWrapper::initDicTraverseSession(ts, dict, prevWord, previousWordLength);
+    DicTraverseWrapper::initDicTraverseSession(
+            ts, dict, prevWord, previousWordLength, 0 /* suggestOptions */);
 }
 
 static void latinime_releaseDicTraverseSession(JNIEnv *env, jclass clazz, jlong traverseSession) {
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 61bf3f6..e2ad557 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -21,8 +21,8 @@
 #include "char_utils.h"
 #include "correction.h"
 #include "defines.h"
-#include "proximity_info_state.h"
-#include "suggest_utils.h"
+#include "suggest/core/layout/proximity_info_state.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
 #include "suggest/policyimpl/utils/edit_distance.h"
 #include "suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h"
 
@@ -676,8 +676,8 @@
             if (i < adjustedProximityMatchedCount) {
                 multiplyIntCapped(typedLetterMultiplier, &finalFreq);
             }
-            const float factor =
-                    SuggestUtils::getLengthScalingFactor(static_cast<float>(squaredDistance));
+            const float factor = TouchPositionCorrectionUtils::getLengthScalingFactor(
+                    static_cast<float>(squaredDistance));
             if (factor > 0.0f) {
                 multiplyRate(static_cast<int>(factor * 100.0f), &finalFreq);
             } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) {
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index a9e9b48..75b4995 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -21,7 +21,7 @@
 
 #include "correction_state.h"
 #include "defines.h"
-#include "proximity_info_state.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/dic_traverse_wrapper.cpp b/native/jni/src/dic_traverse_wrapper.cpp
index 88ca9fa..ec8c62d 100644
--- a/native/jni/src/dic_traverse_wrapper.cpp
+++ b/native/jni/src/dic_traverse_wrapper.cpp
@@ -22,5 +22,5 @@
 void *(*DicTraverseWrapper::sDicTraverseSessionFactoryMethod)(JNIEnv *, jstring) = 0;
 void (*DicTraverseWrapper::sDicTraverseSessionReleaseMethod)(void *) = 0;
 void (*DicTraverseWrapper::sDicTraverseSessionInitMethod)(
-        void *, const Dictionary *const, const int *, const int) = 0;
+        void *, const Dictionary *const, const int *, const int, const SuggestOptions *const) = 0;
 } // namespace latinime
diff --git a/native/jni/src/dic_traverse_wrapper.h b/native/jni/src/dic_traverse_wrapper.h
index 1108a45..43b4c9a 100644
--- a/native/jni/src/dic_traverse_wrapper.h
+++ b/native/jni/src/dic_traverse_wrapper.h
@@ -22,6 +22,7 @@
 
 namespace latinime {
 class Dictionary;
+class SuggestOptions;
 // TODO: Remove
 class DicTraverseWrapper {
  public:
@@ -32,9 +33,11 @@
         return 0;
     }
     static void initDicTraverseSession(void *traverseSession, const Dictionary *const dictionary,
-            const int *prevWord, const int prevWordLength) {
+            const int *prevWord, const int prevWordLength,
+            const SuggestOptions *const suggestOptions) {
         if (sDicTraverseSessionInitMethod) {
-            sDicTraverseSessionInitMethod(traverseSession, dictionary, prevWord, prevWordLength);
+            sDicTraverseSessionInitMethod(
+                    traverseSession, dictionary, prevWord, prevWordLength, suggestOptions);
         }
     }
     static void releaseDicTraverseSession(void *traverseSession) {
@@ -46,7 +49,8 @@
         sDicTraverseSessionFactoryMethod = factoryMethod;
     }
     static void setTraverseSessionInitMethod(
-            void (*initMethod)(void *, const Dictionary *const, const int *, const int)) {
+            void (*initMethod)(void *, const Dictionary *const, const int *, const int,
+                    const SuggestOptions *const)) {
         sDicTraverseSessionInitMethod = initMethod;
     }
     static void setTraverseSessionReleaseMethod(void (*releaseMethod)(void *)) {
@@ -57,7 +61,7 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseWrapper);
     static void *(*sDicTraverseSessionFactoryMethod)(JNIEnv *, jstring);
     static void (*sDicTraverseSessionInitMethod)(
-            void *, const Dictionary *const, const int *, const int);
+            void *, const Dictionary *const, const int *, const int, const SuggestOptions *const);
     static void (*sDicTraverseSessionReleaseMethod)(void *);
 };
 } // namespace latinime
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index dadb2ba..d9ed0fe 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -25,6 +25,7 @@
 #include "binary_format.h"
 #include "defines.h"
 #include "dic_traverse_wrapper.h"
+#include "suggest_options.h"
 #include "suggest/core/suggest.h"
 #include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
 #include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
@@ -53,13 +54,13 @@
 
 int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession,
         int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
-        int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint, bool isGesture,
-        bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices,
-        int *outputTypes) const {
+        int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
+        const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
+        int *spaceIndices, int *outputTypes) const {
     int result = 0;
-    if (isGesture) {
+    if (suggestOptions->isGesture()) {
         DicTraverseWrapper::initDicTraverseSession(
-                traverseSession, this, prevWordCodePoints, prevWordLength);
+                traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
         result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
                 ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
                 frequencies, spaceIndices, outputTypes);
@@ -70,7 +71,7 @@
     } else {
         if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
             DicTraverseWrapper::initDicTraverseSession(
-                    traverseSession, this, prevWordCodePoints, prevWordLength);
+                    traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
             result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
                     ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
                     outWords, frequencies, spaceIndices, outputTypes);
@@ -84,8 +85,8 @@
             mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
                     prevWordLength, &bigramMap, bigramFilter);
             result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
-                    inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance,
-                    outWords, frequencies, outputTypes);
+                    inputCodePoints, inputSize, &bigramMap, bigramFilter,
+                    suggestOptions->useFullEditDistance(), outWords, frequencies, outputTypes);
             return result;
         }
     }
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index edec83f..e6861a3 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -26,6 +26,7 @@
 class BigramDictionary;
 class ProximityInfo;
 class SuggestInterface;
+class SuggestOptions;
 class UnigramDictionary;
 
 class Dictionary {
@@ -54,9 +55,9 @@
 
     int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates,
             int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints, int inputSize,
-            int *prevWordCodePoints, int prevWordLength, int commitPoint, bool isGesture,
-            bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices,
-            int *outputTypes) const;
+            int *prevWordCodePoints, int prevWordLength, int commitPoint,
+            const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
+            int *spaceIndices, int *outputTypes) const;
 
     int getBigrams(const int *word, int length, int *inputCodePoints, int inputSize, int *outWords,
             int *frequencies, int *outputTypes) const;
diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h
deleted file mode 100644
index 4cbb127..0000000
--- a/native/jni/src/geometry_utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_GEOMETRY_UTILS_H
-#define LATINIME_GEOMETRY_UTILS_H
-
-#include <cmath>
-
-#include "defines.h"
-
-#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
-        ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
-
-namespace latinime {
-
-static inline float SQUARE_FLOAT(const float x) { return x * x; }
-
-static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
-    const int dx = x1 - x2;
-    const int dy = y1 - y2;
-    if (dx == 0 && dy == 0) return 0.0f;
-    return atan2f(static_cast<float>(dy), static_cast<float>(dx));
-}
-
-static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
-    const float deltaA = fabsf(a1 - a2);
-    const float diff = ROUND_FLOAT_10000(deltaA);
-    if (diff > M_PI_F) {
-        const float normalizedDiff = 2.0f * M_PI_F - diff;
-        return ROUND_FLOAT_10000(normalizedDiff);
-    }
-    return diff;
-}
-
-static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
-        const int y2) {
-    return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
-}
-} // namespace latinime
-#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 5357c37..4fe4bad 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -22,8 +22,8 @@
 #include "dic_node_utils.h"
 #include "dic_node_vector.h"
 #include "multi_bigram_map.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/suggest/core/layout/geometry_utils.h b/native/jni/src/suggest/core/layout/geometry_utils.h
new file mode 100644
index 0000000..b667df6
--- /dev/null
+++ b/native/jni/src/suggest/core/layout/geometry_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_GEOMETRY_UTILS_H
+#define LATINIME_GEOMETRY_UTILS_H
+
+#include <cmath>
+
+#include "defines.h"
+
+#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
+        ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
+
+namespace latinime {
+
+class GeometryUtils {
+ public:
+    static inline float SQUARE_FLOAT(const float x) { return x * x; }
+
+    static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
+        const int dx = x1 - x2;
+        const int dy = y1 - y2;
+        if (dx == 0 && dy == 0) return 0.0f;
+        return atan2f(static_cast<float>(dy), static_cast<float>(dx));
+    }
+
+    static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
+        const float deltaA = fabsf(a1 - a2);
+        const float diff = ROUND_FLOAT_10000(deltaA);
+        if (diff > M_PI_F) {
+            const float normalizedDiff = 2.0f * M_PI_F - diff;
+            return ROUND_FLOAT_10000(normalizedDiff);
+        }
+        return diff;
+    }
+
+    static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
+            const int y2) {
+        return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(GeometryUtils);
+};
+} // namespace latinime
+#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
similarity index 95%
rename from native/jni/src/proximity_info.cpp
rename to native/jni/src/suggest/core/layout/proximity_info.cpp
index 88d670d..d5ef2d8 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info.h"
+
 #include <cstring>
 #include <cmath>
 
@@ -22,10 +24,9 @@
 #include "additional_proximity_chars.h"
 #include "char_utils.h"
 #include "defines.h"
-#include "geometry_utils.h"
 #include "jni.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 
@@ -58,7 +59,7 @@
           MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
           MOST_COMMON_KEY_HEIGHT(mostCommonKeyHeight),
           NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE(1.0f +
-                  SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
+                  GeometryUtils::SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
                           static_cast<float>(mostCommonKeyWidth))),
           CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
           CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
@@ -150,7 +151,7 @@
     const float touchY = static_cast<float>(y);
     const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
     return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
-            / SQUARE_FLOAT(keyWidth);
+            / GeometryUtils::SQUARE_FLOAT(keyWidth);
 }
 
 int ProximityInfo::getCodePointOf(const int keyIndex) const {
@@ -173,7 +174,7 @@
     for (int i = 0; i < KEY_COUNT; i++) {
         mKeyKeyDistancesG[i][i] = 0;
         for (int j = i + 1; j < KEY_COUNT; j++) {
-            mKeyKeyDistancesG[i][j] = getDistanceInt(
+            mKeyKeyDistancesG[i][j] = GeometryUtils::getDistanceInt(
                     mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
             mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
         }
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/suggest/core/layout/proximity_info.h
similarity index 98%
rename from native/jni/src/proximity_info.h
rename to native/jni/src/suggest/core/layout/proximity_info.h
index deb9ae0..6d2ddd4 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/suggest/core/layout/proximity_info.h
@@ -20,7 +20,7 @@
 #include "defines.h"
 #include "hash_map_compat.h"
 #include "jni.h"
-#include "proximity_info_utils.h"
+#include "suggest/core/layout/proximity_info_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
similarity index 98%
rename from native/jni/src/proximity_info_params.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_params.cpp
index 2675d9e..0e887f7 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
@@ -15,7 +15,7 @@
  */
 
 #include "defines.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/suggest/core/layout/proximity_info_params.h
similarity index 100%
rename from native/jni/src/proximity_info_params.h
rename to native/jni/src/suggest/core/layout/proximity_info_params.h
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
similarity index 98%
rename from native/jni/src/proximity_info_state.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_state.cpp
index cc5b736..fb57174 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info_state.h"
+
 #include <cstring> // for memset() and memcpy()
 #include <sstream> // for debug prints
 #include <vector>
@@ -21,10 +23,9 @@
 #define LOG_TAG "LatinIME: proximity_info_state.cpp"
 
 #include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/suggest/core/layout/proximity_info_state.h
similarity index 98%
rename from native/jni/src/proximity_info_state.h
rename to native/jni/src/suggest/core/layout/proximity_info_state.h
index bbe8af2..fd09307 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.h
@@ -23,8 +23,8 @@
 #include "char_utils.h"
 #include "defines.h"
 #include "hash_map_compat.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
similarity index 95%
rename from native/jni/src/proximity_info_state_utils.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
index 359673c..6f88833 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info_state_utils.h"
+
 #include <cmath>
 #include <cstring> // for memset()
 #include <sstream> // for debug prints
 #include <vector>
 
 #include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 
@@ -103,12 +104,12 @@
             const int time = times ? times[i] : -1;
 
             if (i > 1) {
-                const float prevAngle = getAngle(
+                const float prevAngle = GeometryUtils::getAngle(
                         inputXCoordinates[i - 2], inputYCoordinates[i - 2],
                         inputXCoordinates[i - 1], inputYCoordinates[i - 1]);
-                const float currentAngle = getAngle(
+                const float currentAngle = GeometryUtils::getAngle(
                         inputXCoordinates[i - 1], inputYCoordinates[i - 1], x, y);
-                sumAngle += getAngleDiff(prevAngle, currentAngle);
+                sumAngle += GeometryUtils::getAngleDiff(prevAngle, currentAngle);
             }
 
             if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time,
@@ -157,7 +158,8 @@
     const float sweetSpotCenterY = proximityInfo->getSweetSpotCenterYAt(keyIndex);
     const float inputX = static_cast<float>((*sampledInputXs)[inputIndex]);
     const float inputY = static_cast<float>((*sampledInputYs)[inputIndex]);
-    return SQUARE_FLOAT(inputX - sweetSpotCenterX) + SQUARE_FLOAT(inputY - sweetSpotCenterY);
+    return GeometryUtils::SQUARE_FLOAT(inputX - sweetSpotCenterX)
+            + GeometryUtils::SQUARE_FLOAT(inputY - sweetSpotCenterY);
 }
 
 /* static */ float ProximityInfoStateUtils::calculateNormalizedSquaredDistance(
@@ -174,7 +176,8 @@
     }
     const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(proximityInfo,
             sampledInputXs, sampledInputYs, keyIndex, inputIndex);
-    const float squaredRadius = SQUARE_FLOAT(proximityInfo->getSweetSpotRadiiAt(keyIndex));
+    const float squaredRadius = GeometryUtils::SQUARE_FLOAT(
+            proximityInfo->getSweetSpotRadiiAt(keyIndex));
     return squaredDistance / squaredRadius;
 }
 
@@ -285,7 +288,7 @@
             if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) {
                 break;
             }
-            length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+            length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
                     xCoordinates[j + 1], yCoordinates[j + 1]);
             duration += times[j + 1] - times[j];
         }
@@ -296,7 +299,7 @@
                 break;
             }
             // TODO: use mSampledLengthCache instead?
-            length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+            length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
                     xCoordinates[j + 1], yCoordinates[j + 1]);
             duration += times[j + 1] - times[j];
         }
@@ -349,7 +352,7 @@
     const int y1 = (*sampledInputYs)[index0];
     const int x2 = (*sampledInputXs)[index1];
     const int y2 = (*sampledInputYs)[index1];
-    return getAngle(x1, y1, x2, y2);
+    return GeometryUtils::getAngle(x1, y1, x2, y2);
 }
 
 // Calculating point to key distance for all near keys and returning the distance between
@@ -411,9 +414,9 @@
     }
 
     const int baseSampleRate = mostCommonKeyWidth;
-    const int distPrev = getDistanceInt(sampledInputXs->back(), sampledInputYs->back(),
-            (*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2])
-                    * ProximityInfoParams::DISTANCE_BASE_SCALE;
+    const int distPrev = GeometryUtils::getDistanceInt(sampledInputXs->back(),
+            sampledInputYs->back(), (*sampledInputXs)[size - 2],
+            (*sampledInputYs)[size - 2]) * ProximityInfoParams::DISTANCE_BASE_SCALE;
     float score = 0.0f;
 
     // Location
@@ -425,10 +428,11 @@
         score += ProximityInfoParams::LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE;
     }
     // Angle
-    const float angle1 = getAngle(x, y, sampledInputXs->back(), sampledInputYs->back());
-    const float angle2 = getAngle(sampledInputXs->back(), sampledInputYs->back(),
+    const float angle1 = GeometryUtils::getAngle(x, y, sampledInputXs->back(),
+            sampledInputYs->back());
+    const float angle2 = GeometryUtils::getAngle(sampledInputXs->back(), sampledInputYs->back(),
             (*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2]);
-    const float angleDiff = getAngleDiff(angle1, angle2);
+    const float angleDiff = GeometryUtils::getAngleDiff(angle1, angle2);
 
     // Save corner
     if (distPrev > baseSampleRate * ProximityInfoParams::CORNER_CHECK_DISTANCE_THRESHOLD_SCALE
@@ -472,13 +476,13 @@
         }
         // Check if the last point should be skipped.
         if (isLastPoint && size > 0) {
-            if (getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
+            if (GeometryUtils::getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
                     * ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE < mostCommonKeyWidth) {
                 // This point is not used because it's too close to the previous point.
                 if (DEBUG_GEO_FULL) {
                     AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, "
                            "width = %d", size, x, y, sampledInputXs->back(),
-                           sampledInputYs->back(), getDistanceInt(
+                           sampledInputYs->back(), GeometryUtils::getDistanceInt(
                                    x, y, sampledInputXs->back(), sampledInputYs->back()),
                            mostCommonKeyWidth
                                    / ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE);
@@ -499,7 +503,7 @@
     // Pushing point information.
     if (size > 0) {
         sampledLengthCache->push_back(
-                sampledLengthCache->back() + getDistanceInt(
+                sampledLengthCache->back() + GeometryUtils::getDistanceInt(
                         x, y, sampledInputXs->back(), sampledInputYs->back()));
     } else {
         sampledLengthCache->push_back(0);
@@ -540,7 +544,8 @@
     while (start > 0 && tempBeelineDistance < lookupRadius) {
         tempTime += times[start] - times[start - 1];
         --start;
-        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[start], yCoordinates[start]);
+        tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[start],
+                yCoordinates[start]);
     }
     // Exclusive unless this is an edge point
     if (start > 0 && start < actualInputIndex) {
@@ -553,7 +558,8 @@
     while (end < (inputSize - 1) && tempBeelineDistance < lookupRadius) {
         tempTime += times[end + 1] - times[end];
         ++end;
-        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[end], yCoordinates[end]);
+        tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[end],
+                yCoordinates[end]);
     }
     // Exclusive unless this is an edge point
     if (end > actualInputIndex && end < (inputSize - 1)) {
@@ -571,7 +577,7 @@
     const int y2 = yCoordinates[start];
     const int x3 = xCoordinates[end];
     const int y3 = yCoordinates[end];
-    const int beelineDistance = getDistanceInt(x2, y2, x3, y3);
+    const int beelineDistance = GeometryUtils::getDistanceInt(x2, y2, x3, y3);
     int adjustedStartTime = times[start];
     if (start == 0 && actualInputIndex == 0 && inputSize > 1) {
         adjustedStartTime += ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS;
@@ -613,7 +619,7 @@
     }
     const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index - 1, index);
     const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index, index + 1);
-    const float directionDiff = getAngleDiff(previousDirection, nextDirection);
+    const float directionDiff = GeometryUtils::getAngleDiff(previousDirection, nextDirection);
     return directionDiff;
 }
 
@@ -636,7 +642,7 @@
     }
     const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index0, index1);
     const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index1, index2);
-    return getAngleDiff(previousDirection, nextDirection);
+    return GeometryUtils::getAngleDiff(previousDirection, nextDirection);
 }
 
 // This function basically converts from a length to an edit distance. Accordingly, it's obviously
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
similarity index 100%
rename from native/jni/src/proximity_info_state_utils.h
rename to native/jni/src/suggest/core/layout/proximity_info_state_utils.h
diff --git a/native/jni/src/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h
similarity index 94%
rename from native/jni/src/proximity_info_utils.h
rename to native/jni/src/suggest/core/layout/proximity_info_utils.h
index 71c97e3..2204fd9 100644
--- a/native/jni/src/proximity_info_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h
@@ -22,8 +22,8 @@
 #include "additional_proximity_chars.h"
 #include "char_utils.h"
 #include "defines.h"
-#include "geometry_utils.h"
 #include "hash_map_compat.h"
+#include "suggest/core/layout/geometry_utils.h"
 
 namespace latinime {
 class ProximityInfoUtils {
@@ -87,7 +87,7 @@
 
     static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2,
             const float y2) {
-        return SQUARE_FLOAT(x1 - x2) + SQUARE_FLOAT(y1 - y2);
+        return GeometryUtils::SQUARE_FLOAT(x1 - x2) + GeometryUtils::SQUARE_FLOAT(y1 - y2);
     }
 
     static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y,
@@ -98,7 +98,8 @@
         const float ray2y = y2 - y1;
 
         const float dotProduct = ray1x * ray2x + ray1y * ray2y;
-        const float lineLengthSqr = SQUARE_FLOAT(ray2x) + SQUARE_FLOAT(ray2y);
+        const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x)
+                + GeometryUtils::SQUARE_FLOAT(ray2y);
         const float projectionLengthSqr = dotProduct / lineLengthSqr;
 
         float projectionX;
@@ -121,12 +122,14 @@
      public:
         NormalDistribution(const float u, const float sigma)
                 : mU(u), mSigma(sigma),
-                  mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))),
-                  mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {}
+                  mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F
+                          * GeometryUtils::SQUARE_FLOAT(sigma))),
+                  mPreComputedExponentPart(-1.0f / (2.0f * GeometryUtils::SQUARE_FLOAT(sigma))) {}
 
         float getProbabilityDensity(const float x) const {
             const float shiftedX = x - mU;
-            return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX));
+            return mPreComputedNonExpPart
+                    * expf(mPreComputedExponentPart * GeometryUtils::SQUARE_FLOAT(shiftedX));
         }
 
      private:
diff --git a/native/jni/src/suggest_utils.h b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
similarity index 91%
rename from native/jni/src/suggest_utils.h
rename to native/jni/src/suggest/core/layout/touch_position_correction_utils.h
index e053dd6..e7a8cae 100644
--- a/native/jni/src/suggest_utils.h
+++ b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef LATINIME_SUGGEST_UTILS_H
-#define LATINIME_SUGGEST_UTILS_H
+#ifndef LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
+#define LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
 
 #include "defines.h"
 #include "proximity_info_params.h"
 
 namespace latinime {
-class SuggestUtils {
+class TouchPositionCorrectionUtils {
  public:
     // TODO: (OLD) Remove
     static float getLengthScalingFactor(const float normalizedSquaredDistance) {
@@ -82,7 +82,7 @@
         }
     }
  private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestUtils);
+    DISALLOW_IMPLICIT_CONSTRUCTORS(TouchPositionCorrectionUtils);
 };
 } // namespace latinime
-#endif // LATINIME_SUGGEST_UTILS_H
+#endif // LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index 6408f01..f9f1c09 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -34,10 +34,11 @@
 
 // TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
 static void initSessionInstance(void *traverseSession, const Dictionary *const dictionary,
-        const int *prevWord, const int prevWordLength) {
+        const int *prevWord, const int prevWordLength,
+        const SuggestOptions *const suggestOptions) {
     if (traverseSession) {
         DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
-        tSession->init(dictionary, prevWord, prevWordLength);
+        tSession->init(dictionary, prevWord, prevWordLength, suggestOptions);
     }
 }
 
@@ -62,10 +63,11 @@
 static TraverseSessionFactoryRegisterer traverseSessionFactoryRegisterer;
 
 void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
-        int prevWordLength) {
+        int prevWordLength, const SuggestOptions *const suggestOptions) {
     mDictionary = dictionary;
     mMultiWordCostMultiplier = BinaryFormat::getMultiWordCostMultiplier(mDictionary->getDict(),
             mDictionary->getDictSize());
+    mSuggestOptions = suggestOptions;
     if (!prevWord) {
         mPrevWordPos = NOT_VALID_WORD;
         return;
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index d88be5b..c774eae 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -23,19 +23,20 @@
 #include "defines.h"
 #include "jni.h"
 #include "multi_bigram_map.h"
-#include "proximity_info_state.h"
 #include "suggest/core/dicnode/dic_nodes_cache.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
 class Dictionary;
 class ProximityInfo;
+class SuggestOptions;
 
 class DicTraverseSession {
  public:
     AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
             : mPrevWordPos(NOT_VALID_WORD), mProximityInfo(0),
-              mDictionary(0), mDicNodesCache(), mMultiBigramMap(),
+              mDictionary(0), mSuggestOptions(0), mDicNodesCache(), mMultiBigramMap(),
               mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
               mMultiWordCostMultiplier(1.0f) {
         // NOTE: mProximityInfoStates is an array of instances.
@@ -45,7 +46,8 @@
     // Non virtual inline destructor -- never inherit this class
     AK_FORCE_INLINE ~DicTraverseSession() {}
 
-    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength);
+    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength,
+            const SuggestOptions *const suggestOptions);
     // TODO: Remove and merge into init
     void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
             const int inputSize, const int *const inputXs, const int *const inputYs,
@@ -61,6 +63,7 @@
     // getters and setters
     //--------------------
     const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
+    const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
     int getPrevWordPos() const { return mPrevWordPos; }
     // TODO: REMOVE
     void setPrevWordPos(int pos) { mPrevWordPos = pos; }
@@ -167,6 +170,7 @@
     int mPrevWordPos;
     const ProximityInfo *mProximityInfo;
     const Dictionary *mDictionary;
+    const SuggestOptions *mSuggestOptions;
 
     DicNodesCache mDicNodesCache;
     // Temporary cache for bigram frequencies
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index a187948..8fe8fbc 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -19,11 +19,11 @@
 #include "char_utils.h"
 #include "dictionary.h"
 #include "digraph_utils.h"
-#include "proximity_info.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_priority_queue.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
 #include "suggest/core/dictionary/shortcut_utils.h"
+#include "suggest/core/layout/proximity_info.h"
 #include "suggest/core/policy/scoring.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/policy/weighting.h"
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index 12110d5..b212fe1 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -21,9 +21,9 @@
 
 #include "char_utils.h"
 #include "defines.h"
-#include "proximity_info_state.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/layout/proximity_info_state.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/session/dic_traverse_session.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 3938c0e..cb6abd5 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -18,8 +18,8 @@
 #define LATINIME_TYPING_WEIGHTING_H
 
 #include "defines.h"
-#include "suggest_utils.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
 #include "suggest/core/policy/weighting.h"
 #include "suggest/core/session/dic_traverse_session.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
@@ -74,7 +74,7 @@
         // the keyboard (like accented letters)
         const float normalizedSquaredLength = traverseSession->getProximityInfoState(0)
                 ->getPointToKeyLength(pointIndex, dicNode->getNodeCodePoint());
-        const float normalizedDistance = SuggestUtils::getSweetSpotFactor(
+        const float normalizedDistance = TouchPositionCorrectionUtils::getSweetSpotFactor(
                 traverseSession->isTouchPositionCorrectionEnabled(), normalizedSquaredLength);
         const float weightedDistance = ScoringParams::DISTANCE_WEIGHT_LENGTH * normalizedDistance;
 
diff --git a/native/jni/src/suggest_options.h b/native/jni/src/suggest_options.h
index 1bed47c..1b21aaf 100644
--- a/native/jni/src/suggest_options.h
+++ b/native/jni/src/suggest_options.h
@@ -23,6 +23,9 @@
 
 class SuggestOptions{
  public:
+    SuggestOptions(const int *const options, const int length)
+            : mOptions(options), mLength(length) {}
+
     AK_FORCE_INLINE bool isGesture() const {
         return getBoolOption(IS_GESTURE);
     }
@@ -31,14 +34,20 @@
         return getBoolOption(USE_FULL_EDIT_DISTANCE);
     }
 
-    SuggestOptions(const int *const options, const int length)
-            : mOptions(options), mLength(length) {}
+    AK_FORCE_INLINE bool getAdditionalFeaturesBoolOption(const int key) const {
+        return getBoolOption(key + ADDITIONAL_FEATURES_OPTIONS);
+    }
 
  private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestOptions);
+
     // Need to update com.android.inputmethod.latin.NativeSuggestOptions when you add, remove or
     // reorder options.
     static const int IS_GESTURE = 0;
     static const int USE_FULL_EDIT_DISTANCE = 1;
+    // Additional features options are stored after the other options and used as setting values of
+    // experimental features.
+    static const int ADDITIONAL_FEATURES_OPTIONS = 2;
 
     const int *const mOptions;
     const int mLength;
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index a672294..08cd7b7 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -23,7 +23,7 @@
 #include "defines.h"
 #include "dictionary.h"
 #include "digraph_utils.h"
-#include "proximity_info.h"
+#include "suggest/core/layout/proximity_info.h"
 #include "terminal_attributes.h"
 #include "unigram_dictionary.h"
 #include "words_priority_queue.h"