aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.pngbin951 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.pngbin846 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.pngbin1448 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.pngbin1312 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.pngbin1010 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.pngbin807 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.pngbin796 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.pngbin486 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.pngbin873 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.pngbin1020 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.pngbin880 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.pngbin673 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.pngbin619 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.pngbin941 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.pngbin878 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.pngbin678 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.pngbin610 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.pngbin563 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.pngbin399 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.pngbin642 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.pngbin695 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.pngbin619 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.pngbin1271 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.pngbin1141 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.pngbin2095 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.pngbin1872 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.pngbin1336 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.pngbin1073 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.pngbin1024 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.pngbin523 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.pngbin1186 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.pngbin1427 -> 0 bytes
-rw-r--r--java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.pngbin1192 -> 0 bytes
-rw-r--r--java/res/values-en/whitelist.xml4
-rw-r--r--java/res/values-ru/donottranslate-altchars.xml1
-rw-r--r--java/res/values-sw600dp-land/dimens.xml2
-rw-r--r--java/res/values-sw600dp/dimens.xml10
-rw-r--r--java/res/values/attrs.xml3
-rw-r--r--java/res/values/donottranslate-altchars.xml1
-rw-r--r--java/res/values/styles.xml10
-rw-r--r--java/res/xml-sw600dp/kbd_key_styles.xml4
-rw-r--r--java/res/xml-sw600dp/kbd_qwerty_row4.xml1
-rw-r--r--java/res/xml-sw600dp/kbd_rows_symbols.xml1
-rw-r--r--java/res/xml-sw600dp/kbd_rows_symbols_shift.xml1
-rw-r--r--java/res/xml/kbd_rows_russian.xml2
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java108
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java6
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java27
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java27
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java7
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java1
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java21
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java29
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java34
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java84
-rw-r--r--native/src/correction.cpp244
-rw-r--r--native/src/correction.h17
-rw-r--r--native/src/correction_state.h34
-rw-r--r--native/src/unigram_dictionary.cpp25
61 files changed, 395 insertions, 321 deletions
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 223fcfb3a..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index c9d3d749b..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 5ed614a59..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 00168b272..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 980547e37..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 868eec332..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 27d2b7d1b..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index d89bddae9..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index e11d854e4..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index 0eb4aa244..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index b53456a99..000000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 66111eefa..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index 5420161b7..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 182133727..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 3c8166682..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 6e3d718b2..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index ea2f0e967..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 9c08b5a17..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index dac90bb87..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 79f3735ef..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index b1678f03e..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 58142fa6d..000000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index df64bbe9b..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index 13f78c480..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 7e0f1ae07..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 8c1395edf..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index a4068eae4..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 4cb37cdfc..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 481d889ab..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index 4bfbf6651..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 1ea57c5cb..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index 597be7d92..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 58fd48b4a..000000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/values-en/whitelist.xml b/java/res/values-en/whitelist.xml
index 9395f4c88..4078b4db4 100644
--- a/java/res/values-en/whitelist.xml
+++ b/java/res/values-en/whitelist.xml
@@ -31,8 +31,8 @@
<item>I\'ll</item>
<item>255</item>
- <item>thisd</item>
- <item>this\'d</item>
+ <item>lets</item>
+ <item>let\'s</item>
</string-array>
</resources>
diff --git a/java/res/values-ru/donottranslate-altchars.xml b/java/res/values-ru/donottranslate-altchars.xml
index 2da8b8469..2a24e563e 100644
--- a/java/res/values-ru/donottranslate-altchars.xml
+++ b/java/res/values-ru/donottranslate-altchars.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="alternates_for_cyrillic_e">5,ё</string>
<string name="alternates_for_cyrillic_soft_sign">ъ</string>
+ <string name="alternates_for_cyrillic_ha">ъ</string>
</resources>
diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml
index c75fcc0d1..1d26338c5 100644
--- a/java/res/values-sw600dp-land/dimens.xml
+++ b/java/res/values-sw600dp-land/dimens.xml
@@ -44,7 +44,7 @@
<dimen name="key_label_horizontal_padding">18dip</dimen>
<fraction name="key_letter_ratio">45%</fraction>
- <fraction name="key_large_letter_ratio">45%</fraction>
+ <fraction name="key_large_letter_ratio">48%</fraction>
<fraction name="key_label_ratio">32%</fraction>
<fraction name="key_hint_letter_ratio">23%</fraction>
<fraction name="key_hint_label_ratio">34%</fraction>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index 20876a202..942bc726f 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -53,12 +53,12 @@
<dimen name="key_hint_letter_padding">3dp</dimen>
<dimen name="key_uppercase_letter_padding">3dp</dimen>
- <fraction name="key_letter_ratio">37%</fraction>
- <fraction name="key_large_letter_ratio">37%</fraction>
- <fraction name="key_label_ratio">22%</fraction>
+ <fraction name="key_letter_ratio">42%</fraction>
+ <fraction name="key_large_letter_ratio">45%</fraction>
+ <fraction name="key_label_ratio">25%</fraction>
<fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">26%</fraction>
- <fraction name="key_uppercase_letter_ratio">25%</fraction>
+ <fraction name="key_hint_label_ratio">28%</fraction>
+ <fraction name="key_uppercase_letter_ratio">26%</fraction>
<fraction name="key_preview_text_ratio">50%</fraction>
<dimen name="key_preview_height">15.0mm</dimen>
<dimen name="key_preview_offset">0.1in</dimen>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 172ca2f25..4cabe93a8 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -107,10 +107,11 @@
</declare-styleable>
<declare-styleable name="CandidateView">
- <attr name="autoCorrectHighlight" format="integer">
+ <attr name="suggestionStripOption" format="integer">
<flag name="autoCorrectBold" value="0x01" />
<flag name="autoCorrectUnderline" value="0x02" />
<flag name="autoCorrectInvert" value="0x04" />
+ <flag name="validTypedWordBold" value="0x08" />
</attr>
<attr name="colorTypedWord" format="color" />
<attr name="colorAutoCorrect" format="color" />
diff --git a/java/res/values/donottranslate-altchars.xml b/java/res/values/donottranslate-altchars.xml
index fbde4b9ba..acd4b3725 100644
--- a/java/res/values/donottranslate-altchars.xml
+++ b/java/res/values/donottranslate-altchars.xml
@@ -44,6 +44,7 @@
<string name="alternates_for_scandinavia_row2_11"></string>
<string name="alternates_for_cyrillic_e"></string>
<string name="alternates_for_cyrillic_soft_sign"></string>
+ <string name="alternates_for_cyrillic_ha"></string>
<string name="alternates_for_currency_dollar">¢,£,€,¥,₱</string>
<string name="alternates_for_currency_euro">¢,£,$,¥,₱</string>
<string name="alternates_for_currency_pound">¢,$,€,¥,₱</string>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 8145d0510..cb9edb0b8 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -85,7 +85,7 @@
<item name="android:background">@drawable/candidate_feedback_background</item>
</style>
<style name="CandidateViewStyle" parent="SuggestionsStripBackgroundStyle">
- <item name="autoCorrectHighlight">autoCorrectBold</item>
+ <item name="suggestionStripOption">autoCorrectBold</item>
<item name="colorTypedWord">#FFFFFFFF</item>
<item name="colorAutoCorrect">#FFFCAE00</item>
<item name="colorSuggested">#FFFCAE00</item>
@@ -188,10 +188,10 @@
<item name="android:background">@drawable/keyboard_popup_panel_background_holo</item>
</style>
<style name="CandidateViewStyle.IceCreamSandwich" parent="SuggestionsStripBackgroundStyle.IceCreamSandwich">
- <item name="autoCorrectHighlight">autoCorrectBold</item>
- <item name="colorTypedWord">#FFFFFFFF</item>
- <item name="colorAutoCorrect">#FF3DC8FF</item>
- <item name="colorSuggested">#FFFFFFFF</item>
+ <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
+ <item name="colorTypedWord">#FFBCBEC0</item>
+ <item name="colorAutoCorrect">#FF0099CC</item>
+ <item name="colorSuggested">#FFA7A9AC</item>
<item name="candidateCountInStrip">@integer/candidate_count_in_strip</item>
<item name="centerCandidatePercentile">@integer/center_candidate_percentile</item>
</style>
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 05b683707..15a3d1df5 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -96,25 +96,21 @@
latin:styleName="toSymbolKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
latin:parentStyle="functionalKeyStyle" />
<key-style
latin:styleName="toAlphaKeyStyle"
latin:code="@integer/key_switch_alpha_symbol"
latin:keyLabel="@string/label_to_alpha_key"
- latin:keyLabelOption="fontNormal"
latin:parentStyle="functionalKeyStyle" />
<key-style
latin:styleName="toMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
- latin:keyLabelOption="fontNormal"
latin:parentStyle="functionalKeyStyle" />
<key-style
latin:styleName="backFromMoreSymbolKeyStyle"
latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
latin:parentStyle="functionalKeyStyle" />
<key-style
latin:styleName="comKeyStyle"
diff --git a/java/res/xml-sw600dp/kbd_qwerty_row4.xml b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
index f22b69f73..4c978cb2c 100644
--- a/java/res/xml-sw600dp/kbd_qwerty_row4.xml
+++ b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
@@ -26,7 +26,6 @@
>
<Key
latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
latin:keyWidth="13.0%p" />
<Key
latin:keyStyle="tabKeyStyle" />
diff --git a/java/res/xml-sw600dp/kbd_rows_symbols.xml b/java/res/xml-sw600dp/kbd_rows_symbols.xml
index 4f6a9bc31..420e46cce 100644
--- a/java/res/xml-sw600dp/kbd_rows_symbols.xml
+++ b/java/res/xml-sw600dp/kbd_rows_symbols.xml
@@ -147,7 +147,6 @@
>
<Key
latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
latin:keyWidth="13.0%p" />
<Key
latin:keyStyle="tabKeyStyle" />
diff --git a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
index 1dca8c47e..2909acb6f 100644
--- a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
+++ b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
@@ -133,7 +133,6 @@
>
<Key
latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
latin:keyWidth="13.0%p" />
<Key
latin:keyStyle="tabKeyStyle" />
diff --git a/java/res/xml/kbd_rows_russian.xml b/java/res/xml/kbd_rows_russian.xml
index 3aeb52bcc..0c7a23754 100644
--- a/java/res/xml/kbd_rows_russian.xml
+++ b/java/res/xml/kbd_rows_russian.xml
@@ -69,7 +69,7 @@
latin:popupCharacters="0" />
<Key
latin:keyLabel="х"
- latin:popupCharacters="@string/alternates_for_cyrillic_soft_sign"
+ latin:popupCharacters="@string/alternates_for_cyrillic_ha"
latin:keyWidth="fillRight" />
</Row>
<Row
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index d0a2f864c..2e4988fb0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -113,14 +113,6 @@ public class KeyboardId {
false, F2KEY_MODE_NONE, false, false, false);
}
- public KeyboardId cloneWithNewGeometry(int orientation, int width) {
- if (mWidth == width)
- return this;
- return new KeyboardId(mXmlName, mXmlId, mLocale, orientation, width, mMode, mAttribute,
- mHasSettingsKey, mF2KeyMode, mClobberSettingsKey, mShortcutKeyEnabled,
- mHasShortcutKey);
- }
-
public int getXmlId() {
return mXmlId;
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 21477a992..8bf82807a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.InflateException;
@@ -39,7 +39,6 @@ import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
import java.lang.ref.SoftReference;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
@@ -78,9 +77,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private KeyboardId mCurrentId;
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
- // TODO: Remove this cache object when {@link DisplayMetrics} has actual window width excluding
- // system navigation bar.
- private WindowWidthCache mWindowWidthCache;
private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState();
@@ -105,77 +101,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
- private static class WindowWidthCache {
- private final InputMethodService mService;
- private final Resources mResources;
- private final boolean mIsRegistered[] = new boolean[Configuration.ORIENTATION_SQUARE + 1];
- private final int mWidth[] = new int[Configuration.ORIENTATION_SQUARE + 1];
-
- public WindowWidthCache(InputMethodService service) {
- mService = service;
- mResources = service.getResources();
-
- Arrays.fill(mIsRegistered, false);
- Arrays.fill(mWidth, 0);
- }
-
- private int getCurrentWindowWidth() {
- return mService.getWindow().getWindow().getDecorView().getWidth();
- }
-
- public int getWidth(Configuration conf) {
- final int orientation = conf.orientation;
- try {
- final int width = mWidth[orientation];
- if (mIsRegistered[orientation] || width > 0) {
- // Return registered or cached window width for this orientation.
- return width;
- }
- // Fall through
- } catch (IndexOutOfBoundsException e) {
- Log.w(TAG, "unknwon orientation value " + orientation);
- // Fall through
- }
-
- // Return screen width as default window width.
- return mResources.getDisplayMetrics().widthPixels;
- }
-
- public int getWidthOnSizeChanged(Configuration conf) {
- final int orientation = conf.orientation;
- try {
- if (mIsRegistered[orientation]) {
- // Return registered window width for this orientation.
- return mWidth[orientation];
- }
-
- // Cache the current window width without registering.
- final int width = getCurrentWindowWidth();
- mWidth[orientation] = width;
- return width;
- } catch (IndexOutOfBoundsException e) {
- Log.w(TAG, "unknwon orientation value " + orientation);
- return 0;
- }
- }
-
- public void registerWidth() {
- final int orientation = mResources.getConfiguration().orientation;
- try {
- if (!mIsRegistered[orientation]) {
- final int width = getCurrentWindowWidth();
- if (width > 0) {
- // Register current window width.
- mWidth[orientation] = width;
- mIsRegistered[orientation] = true;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- Log.w(TAG, "unknwon orientation value " + orientation);
- }
- }
- }
-
public class KeyboardLayoutState {
private boolean mIsValid;
private boolean mIsAlphabetMode;
@@ -247,7 +172,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mResources = ims.getResources();
mPrefs = prefs;
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- mWindowWidthCache = new WindowWidthCache(ims);
setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
prefs.registerOnSharedPreferenceChangeListener(this);
}
@@ -298,26 +222,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mIsAutoCorrectionActive = false;
}
- public void registerWindowWidth() {
- mWindowWidthCache.registerWidth();
- }
-
- @SuppressWarnings("unused")
- public void onSizeChanged(int w, int h, int oldw, int oldh) {
- // TODO: This hack should be removed when display metric returns a proper width.
- // Until then, the behavior of KeyboardSwitcher is suboptimal on a device that has a
- // vertical system navigation bar in landscape screen orientation, for instance.
- final Configuration conf = mResources.getConfiguration();
- final int width = mWindowWidthCache.getWidthOnSizeChanged(conf);
- // If the window width hasn't fixed yet or keyboard doesn't exist, nothing to do with.
- if (width == 0 || mCurrentId == null)
- return;
- // Reload keyboard with new width.
- final KeyboardId newId = mCurrentId.cloneWithNewGeometry(conf.orientation, width);
- mInputMethodService.mHandler.postRestoreKeyboardLayout();
- setKeyboard(getKeyboard(newId));
- }
-
private void setKeyboard(final Keyboard keyboard) {
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
mKeyboardView.setKeyboard(keyboard);
@@ -402,7 +306,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
break;
}
- final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled(editorInfo);
+ final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
final boolean noMicrophone = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
|| Utils.inPrivateImeOptions(
@@ -416,10 +320,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
final Configuration conf = mResources.getConfiguration();
+ final DisplayMetrics dm = mResources.getDisplayMetrics();
return new KeyboardId(
mResources.getResourceEntryName(xmlId), xmlId, mSubtypeSwitcher.getInputLocale(),
- conf.orientation, mWindowWidthCache.getWidth(conf), mode, editorInfo,
+ conf.orientation, dm.widthPixels, mode, editorInfo,
hasSettingsKey, f2KeyMode, noSettingsKey, voiceKeyEnabled, hasShortcutKey);
}
@@ -545,9 +450,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private void setAutomaticTemporaryUpperCase() {
if (mKeyboardView == null) return;
final Keyboard keyboard = mKeyboardView.getKeyboard();
- if (keyboard != null) {
- keyboard.setAutomaticTemporaryUpperCase();
- }
+ if (keyboard == null) return;
+ keyboard.setAutomaticTemporaryUpperCase();
mKeyboardView.invalidateAllKeys();
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index 12aadcb5c..e0c6bbbb2 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -266,12 +266,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
return mKeyTimerHandler;
}
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // TODO: Should notify InputMethodService instead?
- KeyboardSwitcher.getInstance().onSizeChanged(w, h, oldw, oldh);
- }
-
/**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard.
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 18df797f0..5d2dab0a9 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -214,6 +214,13 @@ class BinaryDictionaryGetter {
}
/**
+ * Returns the id of the main dict for a specified locale.
+ */
+ private static String getMainDictId(final Locale locale) {
+ return locale.toString();
+ }
+
+ /**
* Returns a list of file addresses for a given locale, trying relevant methods in order.
*
* Tries to get binary dictionaries from various sources, in order:
@@ -234,12 +241,18 @@ class BinaryDictionaryGetter {
BinaryDictionaryFileDumper.cacheDictionariesFromContentProvider(locale, context);
final File[] cachedDictionaryList = getCachedDictionaryList(locale, context);
+ final String mainDictId = getMainDictId(locale);
+
final DictPackSettings dictPackSettings = new DictPackSettings(context);
+ boolean foundMainDict = false;
final ArrayList<AssetFileAddress> fileList = new ArrayList<AssetFileAddress>();
// cachedDictionaryList may not be null, see doc for getCachedDictionaryList
for (final File f : cachedDictionaryList) {
final String wordListId = getWordListIdFromFileName(f.getName());
+ if (wordListId.equals(mainDictId)) {
+ foundMainDict = true;
+ }
if (!dictPackSettings.isWordListActive(wordListId)) continue;
if (f.canRead()) {
fileList.add(AssetFileAddress.makeFromFileName(f.getPath()));
@@ -248,14 +261,14 @@ class BinaryDictionaryGetter {
}
}
- if (!fileList.isEmpty()) {
- return fileList;
+ if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) {
+ final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
+ locale);
+ if (null != fallbackAsset) {
+ fileList.add(fallbackAsset);
+ }
}
- // If the list is empty, fall through and return the fallback
- final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
- locale);
- if (null == fallbackAsset) return null;
- return Arrays.asList(fallbackAsset);
+ return fileList;
}
}
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index f499bc0bb..d46b4b5b5 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -272,9 +272,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
private static final int AUTO_CORRECT_BOLD = 0x01;
private static final int AUTO_CORRECT_UNDERLINE = 0x02;
private static final int AUTO_CORRECT_INVERT = 0x04;
+ private static final int VALID_TYPED_WORD_BOLD = 0x08;
private final TextPaint mPaint;
- private final int mAutoCorrectHighlight;
+ private final int mSuggestionStripOption;
private final ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
@@ -285,7 +286,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
super(words, dividers, infos);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle);
- mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0);
+ mSuggestionStripOption = a.getInt(R.styleable.CandidateView_suggestionStripOption, 0);
mColorTypedWord = a.getColor(R.styleable.CandidateView_colorTypedWord, 0);
mColorAutoCorrect = a.getColor(R.styleable.CandidateView_colorAutoCorrect, 0);
mColorSuggestedCandidate = a.getColor(R.styleable.CandidateView_colorSuggested, 0);
@@ -313,15 +314,23 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
return mColorTypedWord;
}
- private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) {
- if (!isAutoCorrect)
+ private CharSequence getStyledCandidateWord(SuggestedWords suggestions, int pos) {
+ final CharSequence word = suggestions.getWord(pos);
+ final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
+ final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid;
+ if (!isAutoCorrect && !isTypedWordValid)
return word;
+
final int len = word.length();
final Spannable spannedWord = new SpannableString(word);
- if ((mAutoCorrectHighlight & AUTO_CORRECT_BOLD) != 0)
+ final int option = mSuggestionStripOption;
+ if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
+ || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- if ((mAutoCorrectHighlight & AUTO_CORRECT_UNDERLINE) != 0)
+ }
+ if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
return spannedWord;
}
@@ -370,7 +379,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
}
public CharSequence getInvertedText(CharSequence text) {
- if ((mAutoCorrectHighlight & AUTO_CORRECT_INVERT) == 0)
+ if ((mSuggestionStripOption & AUTO_CORRECT_INVERT) == 0)
return null;
final int len = text.length();
final Spannable word = new SpannableString(text);
@@ -457,9 +466,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mTexts.clear();
final int count = Math.min(suggestions.size(), countInStrip);
for (int pos = 0; pos < count; pos++) {
- final CharSequence word = suggestions.getWord(pos);
- final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
- final CharSequence styled = getStyledCandidateWord(word, isAutoCorrect);
+ final CharSequence styled = getStyledCandidateWord(suggestions, pos);
mTexts.add(styled);
}
for (int pos = count; pos < countInStrip; pos++) {
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 39b4f63a5..ffd204dac 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -42,9 +42,9 @@ public class DictionaryFactory {
* @param context application context for reading resources
* @param locale the locale for which to create the dictionary
* @param fallbackResId the id of the resource to use as a fallback if no pack is found
- * @return an initialized instance of Dictionary
+ * @return an initialized instance of DictionaryCollection
*/
- public static Dictionary createDictionaryFromManager(Context context, Locale locale,
+ public static DictionaryCollection createDictionaryFromManager(Context context, Locale locale,
int fallbackResId) {
if (null == locale) {
Log.e(TAG, "No locale defined for dictionary");
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 35d1541ff..9f4777f5a 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -127,7 +127,7 @@ public class ExpandableDictionary extends Dictionary {
if (!mUpdatingDictionary) {
mUpdatingDictionary = true;
mRequiresReload = false;
- new LoadDictionaryTask().execute();
+ new LoadDictionaryTask().start();
}
}
@@ -541,14 +541,13 @@ public class ExpandableDictionary extends Dictionary {
mRoots = new NodeArray();
}
- private class LoadDictionaryTask extends AsyncTask<Void, Void, Void> {
+ private class LoadDictionaryTask extends Thread {
@Override
- protected Void doInBackground(Void... v) {
+ public void run() {
loadDictionaryAsync();
synchronized (mUpdatingLock) {
mUpdatingDictionary = false;
}
- return null;
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a932f03ac..afbdd36a9 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -2027,7 +2027,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onPress(int primaryCode, boolean withSliding) {
final KeyboardSwitcher switcher = mKeyboardSwitcher;
- switcher.registerWindowWidth();
if (switcher.isVibrateAndSoundFeedbackRequired()) {
vibrate();
playKeyClick(primaryCode);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4c2627be3..87a713f5c 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -53,7 +53,7 @@ import java.util.Locale;
public class Settings extends InputMethodSettingsActivity
implements SharedPreferences.OnSharedPreferenceChangeListener,
DialogInterface.OnDismissListener, OnPreferenceClickListener {
- private static final String TAG = "Settings";
+ private static final String TAG = Settings.class.getSimpleName();
public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
public static final String PREF_VIBRATE_ON = "vibrate_on";
@@ -182,8 +182,9 @@ public class Settings extends InputMethodSettingsActivity
mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
final boolean defaultShowSettingsKey = res.getBoolean(
R.bool.config_default_show_settings_key);
- mShowSettingsKey = prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY,
- defaultShowSettingsKey);
+ mShowSettingsKey = isShowSettingsKeyOption(res)
+ ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
+ : defaultShowSettingsKey;
final String voiceModeMain = res.getString(R.string.voice_mode_main);
final String voiceModeOff = res.getString(R.string.voice_mode_off);
final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain);
@@ -292,7 +293,12 @@ public class Settings extends InputMethodSettingsActivity
return builder.setIsPunctuationSuggestions().build();
}
- public boolean isSettingsKeyEnabled(EditorInfo attribute) {
+ public static boolean isShowSettingsKeyOption(final Resources resources) {
+ return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
+
+ }
+
+ public boolean isSettingsKeyEnabled() {
return mShowSettingsKey;
}
@@ -386,9 +392,7 @@ public class Settings extends InputMethodSettingsActivity
final PreferenceGroup textCorrectionGroup =
(PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY);
- final boolean showSettingsKeyOption = res.getBoolean(
- R.bool.config_enable_show_settings_key_option);
- if (!showSettingsKeyOption) {
+ if (!Values.isShowSettingsKeyOption(res)) {
generalSettings.removePreference(mShowSettingsKeyPreference);
}
@@ -445,8 +449,7 @@ public class Settings extends InputMethodSettingsActivity
if (null == mKeyPreviewPopupDismissDelay.getValue()) {
mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
}
- mKeyPreviewPopupDismissDelay.setEnabled(
- Settings.Values.isKeyPreviewPopupEnabled(prefs, res));
+ mKeyPreviewPopupDismissDelay.setEnabled(Values.isKeyPreviewPopupEnabled(prefs, res));
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index c3caae448..e3cb6987a 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -404,7 +404,7 @@ public class Suggest implements Dictionary.WordCallback {
if (typedWord != null) {
mSuggestions.add(0, typedWordString);
}
- removeDupes(mSuggestions);
+ Utils.removeDupes(mSuggestions);
if (DBG) {
double normalizedScore = mAutoCorrection.getNormalizedScore();
@@ -431,33 +431,6 @@ public class Suggest implements Dictionary.WordCallback {
return new SuggestedWords.Builder().addWords(mSuggestions, null);
}
- private static void removeDupes(final ArrayList<CharSequence> suggestions) {
- if (suggestions.size() < 2) return;
- int i = 1;
- // Don't cache suggestions.size(), since we may be removing items
- while (i < suggestions.size()) {
- final CharSequence cur = suggestions.get(i);
- // Compare each candidate with each previous candidate
- for (int j = 0; j < i; j++) {
- CharSequence previous = suggestions.get(j);
- if (TextUtils.equals(cur, previous)) {
- removeFromSuggestions(suggestions, i);
- i--;
- break;
- }
- }
- i++;
- }
- }
-
- private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions,
- final int index) {
- final CharSequence garbage = suggestions.remove(index);
- if (garbage instanceof StringBuilder) {
- StringBuilderPool.recycle((StringBuilder)garbage);
- }
- }
-
public boolean hasAutoCorrection() {
return mAutoCorrection.hasAutoCorrection();
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 1a6260a4e..36fbfd951 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -32,6 +32,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.text.InputType;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
@@ -735,4 +736,37 @@ public class Utils {
return retval;
}
}
+
+ /**
+ * Remove duplicates from an array of strings.
+ *
+ * This method will always keep the first occurence of all strings at their position
+ * in the array, removing the subsequent ones.
+ */
+ public static void removeDupes(final ArrayList<CharSequence> suggestions) {
+ if (suggestions.size() < 2) return;
+ int i = 1;
+ // Don't cache suggestions.size(), since we may be removing items
+ while (i < suggestions.size()) {
+ final CharSequence cur = suggestions.get(i);
+ // Compare each candidate with each previous candidate
+ for (int j = 0; j < i; j++) {
+ CharSequence previous = suggestions.get(j);
+ if (TextUtils.equals(cur, previous)) {
+ removeFromSuggestions(suggestions, i);
+ i--;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
+ private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions,
+ final int index) {
+ final CharSequence garbage = suggestions.remove(index);
+ if (garbage instanceof StringBuilder) {
+ StringBuilderPool.recycle((StringBuilder)garbage);
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 649774d78..502ebb52a 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -23,6 +23,7 @@ import android.service.textservice.SpellCheckerService.Session;
import android.util.Log;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
+import android.text.TextUtils;
import com.android.inputmethod.compat.ArraysCompatUtils;
import com.android.inputmethod.keyboard.Key;
@@ -30,10 +31,13 @@ import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.Dictionary.DataType;
import com.android.inputmethod.latin.Dictionary.WordCallback;
+import com.android.inputmethod.latin.DictionaryCollection;
import com.android.inputmethod.latin.DictionaryFactory;
+import com.android.inputmethod.latin.UserDictionary;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.WordComposer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
@@ -48,9 +52,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private static final boolean DBG = false;
private static final int POOL_SIZE = 2;
- private final static String[] emptyArray = new String[0];
+ private final static String[] EMPTY_STRING_ARRAY = new String[0];
+ private final static SuggestionsInfo EMPTY_SUGGESTIONS_INFO =
+ new SuggestionsInfo(0, EMPTY_STRING_ARRAY);
private Map<String, DictionaryPool> mDictionaryPools =
Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
+ private Map<String, Dictionary> mUserDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, Dictionary>());
@Override
public Session createSession() {
@@ -59,14 +67,15 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private static class SuggestionsGatherer implements WordCallback {
private final int DEFAULT_SUGGESTION_LENGTH = 16;
- private final String[] mSuggestions;
+ private final ArrayList<CharSequence> mSuggestions;
private final int[] mScores;
private final int mMaxLength;
private int mLength = 0;
+ private boolean mSeenSuggestions = false;
SuggestionsGatherer(final int maxLength) {
mMaxLength = maxLength;
- mSuggestions = new String[mMaxLength];
+ mSuggestions = new ArrayList<CharSequence>(maxLength + 1);
mScores = new int[mMaxLength];
}
@@ -78,30 +87,37 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// if it doesn't. See documentation for binarySearch.
final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
+ mSeenSuggestions = true;
if (mLength < mMaxLength) {
final int copyLen = mLength - insertIndex;
++mLength;
System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen);
- System.arraycopy(mSuggestions, insertIndex, mSuggestions, insertIndex + 1, copyLen);
+ mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
} else {
if (insertIndex == 0) return true;
System.arraycopy(mScores, 1, mScores, 0, insertIndex);
- System.arraycopy(mSuggestions, 1, mSuggestions, 0, insertIndex);
+ mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
+ mSuggestions.remove(0);
}
mScores[insertIndex] = score;
- mSuggestions[insertIndex] = new String(word, wordOffset, wordLength);
return true;
}
public String[] getGatheredSuggestions() {
- if (0 == mLength) return null;
+ if (!mSeenSuggestions) return null;
+ if (0 == mLength) return EMPTY_STRING_ARRAY;
- final String[] results = new String[mLength];
- for (int i = mLength - 1; i >= 0; --i) {
- results[mLength - i - 1] = mSuggestions[i];
+ if (DBG) {
+ if (mLength != mSuggestions.size()) {
+ Log.e(TAG, "Suggestion size is not the same as stored mLength");
+ }
}
- return results;
+ Collections.reverse(mSuggestions);
+ Utils.removeDupes(mSuggestions);
+ // This returns a String[], while toArray() returns an Object[] which cannot be cast
+ // into a String[].
+ return mSuggestions.toArray(EMPTY_STRING_ARRAY);
}
}
@@ -109,9 +125,14 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
public boolean onUnbind(final Intent intent) {
final Map<String, DictionaryPool> oldPools = mDictionaryPools;
mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
+ final Map<String, Dictionary> oldUserDictionaries = mUserDictionaries;
+ mUserDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
for (DictionaryPool pool : oldPools.values()) {
pool.close();
}
+ for (Dictionary dict : oldUserDictionaries.values()) {
+ dict.close();
+ }
return false;
}
@@ -129,18 +150,29 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo();
final Resources resources = getResources();
final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
- final Dictionary dictionary =
+ final DictionaryCollection dictionaryCollection =
DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId);
- return new DictAndProximity(dictionary, proximityInfo);
+ final String localeStr = locale.toString();
+ Dictionary userDict = mUserDictionaries.get(localeStr);
+ if (null == userDict) {
+ userDict = new UserDictionary(this, localeStr);
+ mUserDictionaries.put(localeStr, userDict);
+ }
+ dictionaryCollection.addDictionary(userDict);
+ return new DictAndProximity(dictionaryCollection, proximityInfo);
}
private class AndroidSpellCheckerSession extends Session {
// Immutable, but need the locale which is not available in the constructor yet
DictionaryPool mDictionaryPool;
+ // Likewise
+ Locale mLocale;
@Override
public void onCreate() {
- mDictionaryPool = getDictionaryPool(getLocale());
+ final String localeString = getLocale();
+ mDictionaryPool = getDictionaryPool(localeString);
+ mLocale = Utils.constructLocaleFromString(localeString);
}
// Note : this must be reentrant
@@ -154,6 +186,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final int suggestionsLimit) {
final String text = textInfo.getText();
+ if (TextUtils.isEmpty(text)) return EMPTY_SUGGESTIONS_INFO;
+
final SuggestionsGatherer suggestionsGatherer =
new SuggestionsGatherer(suggestionsLimit);
final WordComposer composer = new WordComposer();
@@ -178,12 +212,32 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
dictInfo.mProximityInfo);
isInDict = dictInfo.mDictionary.isValidWord(text);
+ if (!isInDict && Character.isUpperCase(text.codePointAt(0))) {
+ // If the first char is not uppercase, then the word is either all lower case,
+ // in which case we already tested it, or mixed case, in which case we don't
+ // want to test a lower-case version of it. Hence the test above.
+ // Also note that by isEmpty() test at the top of the method codePointAt(0) is
+ // guaranteed to be there.
+ final int len = text.codePointCount(0, text.length());
+ int capsCount = 1;
+ for (int i = 1; i < len; ++i) {
+ if (1 != capsCount && i != capsCount) break;
+ if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
+ }
+ // We know the first char is upper case. So we want to test if either everything
+ // else is lower case, or if everything else is upper case. If the string is
+ // exactly one char long, then we will arrive here with capsCount 0, and this is
+ // correct, too.
+ if (1 == capsCount || len == capsCount) {
+ isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
+ }
+ }
if (!mDictionaryPool.offer(dictInfo)) {
Log.e(TAG, "Can't re-insert a dictionary into its pool");
}
} catch (InterruptedException e) {
// I don't think this can happen.
- return new SuggestionsInfo(0, new String[0]);
+ return EMPTY_SUGGESTIONS_INFO;
}
final String[] suggestions = suggestionsGatherer.getGatheredSuggestions();
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index 99412b211..fb160149d 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -56,17 +56,22 @@ void Correction::initCorrectionState(
const int rootPos, const int childCount, const bool traverseAll) {
latinime::initCorrectionState(mCorrectionStates, rootPos, childCount, traverseAll);
// TODO: remove
+ mCorrectionStates[0].mTransposedPos = mTransposedPos;
+ mCorrectionStates[0].mExcessivePos = mExcessivePos;
mCorrectionStates[0].mSkipPos = mSkipPos;
}
void Correction::setCorrectionParams(const int skipPos, const int excessivePos,
const int transposedPos, const int spaceProximityPos, const int missingSpacePos) {
// TODO: remove
+ mTransposedPos = transposedPos;
+ mExcessivePos = excessivePos;
mSkipPos = skipPos;
// TODO: remove
+ mCorrectionStates[0].mTransposedPos = transposedPos;
+ mCorrectionStates[0].mExcessivePos = excessivePos;
mCorrectionStates[0].mSkipPos = skipPos;
- mExcessivePos = excessivePos;
- mTransposedPos = transposedPos;
+
mSpaceProximityPos = spaceProximityPos;
mMissingSpacePos = missingSpacePos;
}
@@ -107,12 +112,23 @@ bool Correction::initProcessState(const int outputIndex) {
--(mCorrectionStates[outputIndex].mChildCount);
mInputIndex = mCorrectionStates[outputIndex].mInputIndex;
mNeedsToTraverseAllNodes = mCorrectionStates[outputIndex].mNeedsToTraverseAllNodes;
+
mProximityCount = mCorrectionStates[outputIndex].mProximityCount;
+ mTransposedCount = mCorrectionStates[outputIndex].mTransposedCount;
+ mExcessiveCount = mCorrectionStates[outputIndex].mExcessiveCount;
mSkippedCount = mCorrectionStates[outputIndex].mSkippedCount;
+ mLastCharExceeded = mCorrectionStates[outputIndex].mLastCharExceeded;
+
+ mTransposedPos = mCorrectionStates[outputIndex].mTransposedPos;
+ mExcessivePos = mCorrectionStates[outputIndex].mExcessivePos;
mSkipPos = mCorrectionStates[outputIndex].mSkipPos;
- mSkipping = false;
- mProximityMatching = false;
+
mMatching = false;
+ mProximityMatching = false;
+ mTransposing = false;
+ mExceeding = false;
+ mSkipping = false;
+
return true;
}
@@ -150,12 +166,23 @@ void Correction::incrementOutputIndex() {
mCorrectionStates[mOutputIndex].mSiblingPos = mCorrectionStates[mOutputIndex - 1].mSiblingPos;
mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex;
mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes;
+
mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount;
+ mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount;
+ mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount;
mCorrectionStates[mOutputIndex].mSkippedCount = mSkippedCount;
- mCorrectionStates[mOutputIndex].mSkipping = mSkipping;
+
mCorrectionStates[mOutputIndex].mSkipPos = mSkipPos;
+ mCorrectionStates[mOutputIndex].mTransposedPos = mTransposedPos;
+ mCorrectionStates[mOutputIndex].mExcessivePos = mExcessivePos;
+
+ mCorrectionStates[mOutputIndex].mLastCharExceeded = mLastCharExceeded;
+
mCorrectionStates[mOutputIndex].mMatching = mMatching;
mCorrectionStates[mOutputIndex].mProximityMatching = mProximityMatching;
+ mCorrectionStates[mOutputIndex].mTransposing = mTransposing;
+ mCorrectionStates[mOutputIndex].mExceeding = mExceeding;
+ mCorrectionStates[mOutputIndex].mSkipping = mSkipping;
}
void Correction::startToTraverseAllNodes() {
@@ -183,102 +210,138 @@ Correction::CorrectionType Correction::processSkipChar(
Correction::CorrectionType Correction::processCharAndCalcState(
const int32_t c, const bool isTerminal) {
- CorrectionType currentStateType = NOT_ON_TERMINAL;
- // This has to be done for each virtual char (this forwards the "inputIndex" which
- // is the index in the user-inputted chars, as read by proximity chars.
- if (mExcessivePos == mOutputIndex && mInputIndex < mInputLength - 1) {
- incrementInputIndex();
+
+ if (mNeedsToTraverseAllNodes || isQuote(c)) {
+ if (mLastCharExceeded > 0 && mInputIndex == mInputLength - 1
+ && mProximityInfo->getMatchedProximityId(mInputIndex, c, false)
+ == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ mLastCharExceeded = false;
+ --mExcessiveCount;
+ }
+ return processSkipChar(c, isTerminal);
+ }
+
+ if (mExcessivePos >= 0) {
+ if (mExcessiveCount == 0 && mExcessivePos < mOutputIndex) {
+ mExcessivePos = mOutputIndex;
+ }
+ if (mExcessivePos < mInputLength - 1) {
+ mExceeding = mExcessivePos == mInputIndex;
+ }
}
- bool skip = false;
if (mSkipPos >= 0) {
if (mSkippedCount == 0 && mSkipPos < mOutputIndex) {
if (DEBUG_DICT) {
assert(mSkipPos == mOutputIndex - 1);
}
- ++mSkipPos;
+ mSkipPos = mOutputIndex;
}
- skip = mSkipPos == mOutputIndex;
- mSkipping = true;
+ mSkipping = mSkipPos == mOutputIndex;
}
- if (mNeedsToTraverseAllNodes || isQuote(c)) {
- return processSkipChar(c, isTerminal);
- } else {
- int inputIndexForProximity = mInputIndex;
+ if (mTransposedPos >= 0) {
+ if (mTransposedCount == 0 && mTransposedPos < mOutputIndex) {
+ mTransposedPos = mOutputIndex;
+ }
+ if (mTransposedPos < mInputLength - 1) {
+ mTransposing = mInputIndex == mTransposedPos;
+ }
+ }
- if (mTransposedPos >= 0) {
- if (mInputIndex == mTransposedPos) {
- ++inputIndexForProximity;
- }
- if (mInputIndex == (mTransposedPos + 1)) {
- --inputIndexForProximity;
- }
+ bool secondTransposing = false;
+ if (mTransposedCount % 2 == 1) {
+ if (mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false)
+ == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ ++mTransposedCount;
+ secondTransposing = true;
+ } else if (mCorrectionStates[mOutputIndex].mExceeding) {
+ --mTransposedCount;
+ ++mExcessiveCount;
+ incrementInputIndex();
+ } else {
+ --mTransposedCount;
+ return UNRELATED;
}
+ }
- // TODO: sum counters
- const bool checkProximityChars =
- !(mSkippedCount > 0 || mExcessivePos >= 0 || mTransposedPos >= 0);
- int matchedProximityCharId = mProximityInfo->getMatchedProximityId(
- inputIndexForProximity, c, checkProximityChars);
-
- if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
- if (skip && mProximityCount == 0) {
- // Skip this letter and continue deeper
- ++mSkippedCount;
- return processSkipChar(c, isTerminal);
- } else if (checkProximityChars
- && inputIndexForProximity > 0
- && mCorrectionStates[mOutputIndex].mProximityMatching
- && mCorrectionStates[mOutputIndex].mSkipping
- && mProximityInfo->getMatchedProximityId(
- inputIndexForProximity - 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
- // Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
- // proximity chars of "s", but it should rather be handled as a skipped char.
- ++mSkippedCount;
- --mProximityCount;
- return processSkipChar(c, isTerminal);
+ // TODO: sum counters
+ const bool checkProximityChars =
+ !(mSkippedCount > 0 || mExcessivePos >= 0 || mTransposedPos >= 0);
+ const int matchedProximityCharId = secondTransposing
+ ? ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR
+ : mProximityInfo->getMatchedProximityId(mInputIndex, c, checkProximityChars);
+
+ if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
+ if (mInputIndex - 1 < mInputLength && (mExceeding || mTransposing)
+ && mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false)
+ == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ if (mTransposing) {
+ ++mTransposedCount;
} else {
- return UNRELATED;
+ ++mExcessiveCount;
+ incrementInputIndex();
}
- } else if (ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
- // If inputIndex is greater than mInputLength, that means there is no
- // proximity chars. So, we don't need to check proximity.
- mMatching = true;
- } else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
- mProximityMatching = true;
- incrementProximityCount();
+ } else if (mSkipping && mProximityCount == 0) {
+ // Skip this letter and continue deeper
+ ++mSkippedCount;
+ return processSkipChar(c, isTerminal);
+ } else if (checkProximityChars
+ && mInputIndex > 0
+ && mCorrectionStates[mOutputIndex].mProximityMatching
+ && mCorrectionStates[mOutputIndex].mSkipping
+ && mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false)
+ == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ // Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
+ // proximity chars of "s", but it should rather be handled as a skipped char.
+ ++mSkippedCount;
+ --mProximityCount;
+ return processSkipChar(c, isTerminal);
+ } else {
+ return UNRELATED;
}
+ } else if (secondTransposing
+ || ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
+ // If inputIndex is greater than mInputLength, that means there is no
+ // proximity chars. So, we don't need to check proximity.
+ mMatching = true;
+ } else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
+ mProximityMatching = true;
+ incrementProximityCount();
+ }
- mWord[mOutputIndex] = c;
+ mWord[mOutputIndex] = c;
- const bool isSameAsUserTypedLength = mInputLength
- == getInputIndex() + 1
- || (mExcessivePos == mInputLength - 1
- && getInputIndex() == mInputLength - 2);
- if (isSameAsUserTypedLength && isTerminal) {
- mTerminalInputIndex = mInputIndex;
- mTerminalOutputIndex = mOutputIndex;
- currentStateType = ON_TERMINAL;
- }
- // Start traversing all nodes after the index exceeds the user typed length
- if (isSameAsUserTypedLength) {
- startToTraverseAllNodes();
- }
+ mLastCharExceeded = mExcessiveCount == 0 && mSkippedCount == 0
+ && mProximityCount == 0 && mTransposedCount == 0
+ // TODO: remove this line once excessive correction is conmibned to others.
+ && mExcessivePos >= 0 && (mInputIndex == mInputLength - 2);
+ const bool isSameAsUserTypedLength = (mInputLength == mInputIndex + 1) || mLastCharExceeded;
+ if (mLastCharExceeded) {
+ ++mExcessiveCount;
+ }
- // Finally, we are ready to go to the next character, the next "virtual node".
- // We should advance the input index.
- // We do this in this branch of the 'if traverseAllNodes' because we are still matching
- // characters to input; the other branch is not matching them but searching for
- // completions, this is why it does not have to do it.
- incrementInputIndex();
+ // Start traversing all nodes after the index exceeds the user typed length
+ if (isSameAsUserTypedLength) {
+ startToTraverseAllNodes();
}
+ // Finally, we are ready to go to the next character, the next "virtual node".
+ // We should advance the input index.
+ // We do this in this branch of the 'if traverseAllNodes' because we are still matching
+ // characters to input; the other branch is not matching them but searching for
+ // completions, this is why it does not have to do it.
+ incrementInputIndex();
// Also, the next char is one "virtual node" depth more than this char.
incrementOutputIndex();
- return currentStateType;
+ if (isSameAsUserTypedLength && isTerminal) {
+ mTerminalInputIndex = mInputIndex - 1;
+ mTerminalOutputIndex = mOutputIndex - 1;
+ return ON_TERMINAL;
+ } else {
+ return NOT_ON_TERMINAL;
+ }
}
Correction::~Correction() {
@@ -395,20 +458,33 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER;
const int fullWordMultiplier = correction->FULL_WORD_MULTIPLIER;
const ProximityInfo *proximityInfo = correction->mProximityInfo;
- const int skipCount = correction->mSkippedCount;
+ const int skippedCount = correction->mSkippedCount;
+ const int transposedCount = correction->mTransposedCount;
+ const int excessiveCount = correction->mExcessiveCount;
const int proximityMatchedCount = correction->mProximityCount;
- if (skipCount >= inputLength || inputLength == 0) {
+ const bool lastCharExceeded = correction->mLastCharExceeded;
+ if (skippedCount >= inputLength || inputLength == 0) {
+ return -1;
+ }
+
+ // TODO: remove
+ if (transposedPos >= 0 && transposedCount == 0) {
return -1;
}
- const bool sameLength = (excessivePos == inputLength - 1) ? (inputLength == inputIndex + 2)
- : (inputLength == inputIndex + 1);
+ // TODO: remove
+ if (excessivePos >= 0 && excessiveCount == 0) {
+ return -1;
+ }
+
+ const bool sameLength = lastCharExceeded ? (inputLength == inputIndex + 2)
+ : (inputLength == inputIndex + 1);
// TODO: use mExcessiveCount
int matchCount = inputLength - correction->mProximityCount - (excessivePos >= 0 ? 1 : 0);
const unsigned short* word = correction->mWord;
- const bool skipped = skipCount > 0;
+ const bool skipped = skippedCount > 0;
const int quoteDiffCount = max(0, getQuoteCount(word, outputIndex + 1)
- getQuoteCount(proximityInfo->getPrimaryInputWord(), inputLength));
@@ -417,6 +493,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
int matchWeight;
int ed = 0;
int adJustedProximityMatchedCount = proximityMatchedCount;
+
+ // TODO: Optimize this.
if (excessivePos < 0 && transposedPos < 0 && (proximityMatchedCount > 0 || skipped)) {
const unsigned short* primaryInputWord = proximityInfo->getPrimaryInputWord();
ed = editDistance(editDistanceTable, primaryInputWord,
@@ -475,7 +553,7 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
}
- const int errorCount = proximityMatchedCount + skipCount;
+ const int errorCount = proximityMatchedCount + skippedCount;
multiplyRate(
100 - CORRECTION_COUNT_RATE_DEMOTION_RATE_BASE * errorCount / inputLength, &finalFreq);
diff --git a/native/src/correction.h b/native/src/correction.h
index 871a04251..3cd600cf0 100644
--- a/native/src/correction.h
+++ b/native/src/correction.h
@@ -113,8 +113,6 @@ private:
int mMaxEditDistance;
int mMaxDepth;
int mInputLength;
- int mExcessivePos;
- int mTransposedPos;
int mSpaceProximityPos;
int mMissingSpacePos;
int mTerminalInputIndex;
@@ -126,15 +124,26 @@ private:
CorrectionState mCorrectionStates[MAX_WORD_LENGTH_INTERNAL];
// The following member variables are being used as cache values of the correction state.
+ bool mNeedsToTraverseAllNodes;
int mOutputIndex;
int mInputIndex;
+
int mProximityCount;
+ int mExcessiveCount;
+ int mTransposedCount;
int mSkippedCount;
+
+ int mTransposedPos;
+ int mExcessivePos;
int mSkipPos;
- bool mNeedsToTraverseAllNodes;
+
+ bool mLastCharExceeded;
+
bool mMatching;
- bool mSkipping;
bool mProximityMatching;
+ bool mExceeding;
+ bool mTransposing;
+ bool mSkipping;
class RankingAlgorithm {
public:
diff --git a/native/src/correction_state.h b/native/src/correction_state.h
index 267deda9b..93f8a8aab 100644
--- a/native/src/correction_state.h
+++ b/native/src/correction_state.h
@@ -28,12 +28,25 @@ struct CorrectionState {
int mSiblingPos;
uint16_t mChildCount;
uint8_t mInputIndex;
+
uint8_t mProximityCount;
+ uint8_t mTransposedCount;
+ uint8_t mExcessiveCount;
uint8_t mSkippedCount;
+
+ int8_t mTransposedPos;
+ int8_t mExcessivePos;
int8_t mSkipPos; // should be signed
+
+ // TODO: int?
+ bool mLastCharExceeded;
+
bool mMatching;
+ bool mTransposing;
+ bool mExceeding;
bool mSkipping;
bool mProximityMatching;
+
bool mNeedsToTraverseAllNodes;
};
@@ -43,14 +56,27 @@ inline static void initCorrectionState(CorrectionState *state, const int rootPos
state->mParentIndex = -1;
state->mChildCount = childCount;
state->mInputIndex = 0;
- state->mProximityCount = 0;
state->mSiblingPos = rootPos;
+ state->mNeedsToTraverseAllNodes = traverseAll;
+
+ state->mTransposedPos = -1;
+ state->mExcessivePos = -1;
+ state->mSkipPos = -1;
+
+
+ state->mProximityCount = 0;
+ state->mTransposedCount = 0;
+ state->mExcessiveCount = 0;
state->mSkippedCount = 0;
+
+ state->mLastCharExceeded = false;
+
state->mMatching = false;
- state->mSkipping = false;
state->mProximityMatching = false;
- state->mNeedsToTraverseAllNodes = traverseAll;
- state->mSkipPos = -1;
+ state->mTransposing = false;
+ state->mExceeding = false;
+ state->mSkipping = false;
+
}
} // namespace latinime
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 6bc350505..805e1cbb7 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -194,34 +194,27 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
PROF_START(2);
// Suggestion with missing character
- LOGI("--- Suggest missing characters");
+ if (DEBUG_DICT) {
+ LOGI("--- Suggest missing characters");
+ }
getSuggestionCandidates(0, -1, -1);
PROF_END(2);
PROF_START(3);
// Suggestion with excessive character
- if (SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER
- && mInputLength >= MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION) {
- for (int i = 0; i < codesSize; ++i) {
- if (DEBUG_DICT) {
- LOGI("--- Suggest excessive characters %d", i);
- }
- getSuggestionCandidates(-1, i, -1);
- }
+ if (DEBUG_DICT) {
+ LOGI("--- Suggest excessive characters");
}
+ getSuggestionCandidates(-1, 0, -1);
PROF_END(3);
PROF_START(4);
// Suggestion with transposed characters
// Only suggest words that length is mInputLength
- if (SUGGEST_WORDS_WITH_TRANSPOSED_CHARACTERS) {
- for (int i = 0; i < codesSize; ++i) {
- if (DEBUG_DICT) {
- LOGI("--- Suggest transposed characters %d", i);
- }
- getSuggestionCandidates(-1, -1, i);
- }
+ if (DEBUG_DICT) {
+ LOGI("--- Suggest transposed characters");
}
+ getSuggestionCandidates(-1, -1, 0);
PROF_END(4);
PROF_START(5);