aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/color/emoji_tab_label_color_lxx.xml33
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.pngbin506 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lxx.9.pngbin0 -> 135 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin639 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lxx.9.pngbin0 -> 130 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.pngbin972 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin537 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin655 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lxx.9.pngbin0 -> 138 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1440 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin670 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lxx.9.pngbin0 -> 130 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.pngbin505 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.pngbin301 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.pngbin835 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin517 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lxx.9.png (renamed from java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lmp.9.png)bin272 -> 272 bytes
-rw-r--r--java/res/drawable-hdpi/btn_suggestion_pressed.9.pngbin1234 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_background_lmp.9.png)bin2147 -> 2147 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_left_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_left_background_lmp.9.png)bin2105 -> 2105 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lmp.9.png)bin2164 -> 2164 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_more_background_lmp.9.png)bin2225 -> 2225 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_right_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_right_background_lmp.9.png)bin2061 -> 2061 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lmp.9.png)bin2133 -> 2133 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_popup_panel_background_lxx.9.png (renamed from java/res/drawable-hdpi/keyboard_popup_panel_background_lmp.9.png)bin871 -> 871 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.pngbin778 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.pngbin458 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lxx.9.pngbin0 -> 120 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin453 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lxx.9.pngbin0 -> 114 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.pngbin849 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin380 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin468 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lxx.9.pngbin0 -> 124 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1293 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin458 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lxx.9.pngbin0 -> 114 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.pngbin454 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.pngbin258 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.pngbin717 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin368 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lxx.9.png (renamed from java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lmp.9.png)bin222 -> 222 bytes
-rw-r--r--java/res/drawable-mdpi/btn_suggestion_pressed.9.pngbin11006 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_background_lmp.9.png)bin1353 -> 1353 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_left_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_left_background_lmp.9.png)bin1305 -> 1305 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lmp.9.png)bin1425 -> 1425 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_more_background_lmp.9.png)bin1454 -> 1454 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_right_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_right_background_lmp.9.png)bin1314 -> 1314 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lmp.9.png)bin1427 -> 1427 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_popup_panel_background_lxx.9.png (renamed from java/res/drawable-mdpi/keyboard_popup_panel_background_lmp.9.png)bin589 -> 589 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.pngbin590 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.pngbin571 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lxx.9.pngbin0 -> 153 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin787 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lxx.9.pngbin0 -> 149 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.pngbin1007 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin657 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin848 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.pngbin0 -> 159 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1486 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin867 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.pngbin0 -> 149 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.pngbin548 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.pngbin359 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.pngbin860 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin634 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lxx.9.png (renamed from java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lmp.9.png)bin323 -> 323 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_suggestion_pressed.9.pngbin1266 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_background_lmp.9.png)bin3316 -> 3316 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lmp.9.png)bin3169 -> 3169 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lmp.9.png)bin3374 -> 3374 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lmp.9.png)bin3525 -> 3525 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lmp.9.png)bin3218 -> 3218 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lmp.9.png)bin3424 -> 3424 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_popup_panel_background_lxx.9.png (renamed from java/res/drawable-xhdpi/keyboard_popup_panel_background_lmp.9.png)bin1246 -> 1246 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.pngbin942 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lxx.9.pngbin0 -> 180 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.pngbin1998 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lxx.9.pngbin0 -> 182 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.pngbin1861 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.pngbin2073 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.pngbin0 -> 186 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.pngbin2091 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.pngbin0 -> 182 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.pngbin1799 -> 0 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lxx.9.png (renamed from java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lmp.9.png)bin1261 -> 1261 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_background_lmp.9.png)bin5251 -> 5251 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lmp.9.png)bin5862 -> 5862 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lmp.9.png)bin5920 -> 5920 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lmp.9.png)bin5450 -> 5450 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lmp.9.png)bin5981 -> 5981 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lmp.9.png)bin6060 -> 6060 bytes
-rw-r--r--java/res/drawable-xxhdpi/keyboard_popup_panel_background_lxx.9.png (renamed from java/res/drawable-xxhdpi/keyboard_popup_panel_background_lmp.9.png)bin2732 -> 2732 bytes
-rw-r--r--java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.pngbin1566 -> 0 bytes
-rw-r--r--java/res/drawable/btn_keyboard_key_functional_lxx.xml (renamed from java/res/drawable/btn_keyboard_key_functional_lmp.xml)4
-rw-r--r--java/res/drawable/btn_keyboard_key_ics.xml6
-rw-r--r--java/res/drawable/btn_keyboard_key_klp.xml6
-rw-r--r--java/res/drawable/btn_keyboard_key_lxx.xml (renamed from java/res/drawable/btn_keyboard_key_lmp.xml)24
-rw-r--r--java/res/drawable/btn_keyboard_key_popup_lxx.xml (renamed from java/res/drawable/btn_keyboard_key_popup_lmp.xml)2
-rw-r--r--java/res/drawable/btn_keyboard_spacebar_lxx.xml (renamed from java/res/drawable/btn_keyboard_spacebar_lmp.xml)4
-rw-r--r--java/res/drawable/btn_suggestion_lxx.xml (renamed from java/res/drawable/btn_suggestion_lmp.xml)2
-rw-r--r--java/res/drawable/keyboard_key_feedback_lxx.xml (renamed from java/res/drawable/keyboard_key_feedback_lmp.xml)12
-rw-r--r--java/res/layout/emoji_keyboard_page.xml2
-rw-r--r--java/res/layout/emoji_palettes_view.xml6
-rw-r--r--java/res/values-km-rKH/strings.xml18
-rw-r--r--java/res/values/attrs.xml15
-rw-r--r--java/res/values/colors.xml18
-rw-r--r--java/res/values/config-common.xml2
-rw-r--r--java/res/values/keyboard-icons-lxx.xml (renamed from java/res/values/keyboard-icons-lmp.xml)2
-rw-r--r--java/res/values/themes-common.xml7
-rw-r--r--java/res/values/themes-ics.xml6
-rw-r--r--java/res/values/themes-klp.xml6
-rw-r--r--java/res/values/themes-lxx.xml (renamed from java/res/values/themes-lmp.xml)100
-rw-r--r--java/src/com/android/inputmethod/event/CombinerChain.java8
-rw-r--r--java/src/com/android/inputmethod/event/MyanmarReordering.java30
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardTheme.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java18
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java24
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/DynamicGridKeyboard.java (renamed from java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java)7
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java358
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java (renamed from java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java)6
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java (renamed from java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java)4
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java (renamed from java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java)7
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java146
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java (renamed from java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java)524
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java1
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java17
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java15
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java10
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java6
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilter.java94
-rw-r--r--java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java3
-rw-r--r--native/jni/CleanupNativeFileList.mk1
-rw-r--r--native/jni/NativeFileList.mk22
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp24
-rw-r--r--native/jni/src/suggest/core/dictionary/property/word_property.cpp15
-rw-r--r--native/jni/src/suggest/core/result/suggestion_results.cpp33
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/Readme.txt1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.cpp290
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h93
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.cpp224
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h122
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h110
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h47
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.cpp171
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h74
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h90
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.cpp199
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h101
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h86
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.cpp50
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h122
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.cpp111
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h73
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h118
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.cpp155
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h152
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.cpp81
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h84
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.cpp109
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h79
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.cpp429
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h145
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp475
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h168
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.cpp39
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h52
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.cpp301
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h140
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.cpp90
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h57
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp16
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp14
-rw-r--r--native/jni/src/utils/char_utils.cpp3
-rw-r--r--native/jni/src/utils/char_utils.h7
-rw-r--r--native/jni/src/utils/jni_data_utils.cpp24
-rw-r--r--native/jni/src/utils/jni_data_utils.h37
-rw-r--r--tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java16
-rw-r--r--tests/src/com/android/inputmethod/latin/DistracterFilterTest.java73
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java12
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java13
-rw-r--r--tests/src/com/android/inputmethod/latin/LatinImeStressTests.java6
-rw-r--r--tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java6
190 files changed, 5822 insertions, 770 deletions
diff --git a/java/res/color/emoji_tab_label_color_lxx.xml b/java/res/color/emoji_tab_label_color_lxx.xml
new file mode 100644
index 000000000..c2710d365
--- /dev/null
+++ b/java/res/color/emoji_tab_label_color_lxx.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_focused="true"
+ android:color="@color/key_text_color_holo" />
+ <item
+ android:state_pressed="true"
+ android:color="@color/key_text_color_holo" />
+ <item
+ android:state_selected="true"
+ android:color="@color/key_text_color_holo" />
+ <item
+ android:color="@color/key_text_inactive_color_lxx" />
+</selector>
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index bc130cab6..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lxx.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
new file mode 100644
index 000000000..44308bfd8
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
deleted file mode 100644
index 814e40235..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lxx.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
new file mode 100644
index 000000000..674783d7d
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index af5ea6bd2..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 90abe3940..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
deleted file mode 100644
index 48eeb3f54..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
new file mode 100644
index 000000000..96b625bd6
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index fc7ba2aeb..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
deleted file mode 100644
index 71e0683cd..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
new file mode 100644
index 000000000..20e53c2e5
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index 005c4e498..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index 9a07acd91..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index be420a7af..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 6768241a7..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lmp.9.png b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lxx.9.png
index 10f8e97e4..10f8e97e4 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lmp.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_suggestion_pressed.9.png b/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 7acceaee7..000000000
--- a/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx.9.png
index be394151a..be394151a 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_lxx.9.png
index 9fa6d0003..9fa6d0003 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lxx.9.png
index c73269b7e..c73269b7e 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx.9.png
index fffd4021e..fffd4021e 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_lxx.9.png
index 61c23c19b..61c23c19b 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lxx.9.png
index 827d74363..827d74363 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_background_lmp.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_background_lxx.9.png
index f9dd3b8b1..f9dd3b8b1 100644
--- a/java/res/drawable-hdpi/keyboard_popup_panel_background_lmp.9.png
+++ b/java/res/drawable-hdpi/keyboard_popup_panel_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 3c5469403..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index 49329f094..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lxx.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
new file mode 100644
index 000000000..837df83ce
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
deleted file mode 100644
index b7b2dca43..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lxx.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
new file mode 100644
index 000000000..977265214
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index c6876f76e..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 4a92b80dd..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
deleted file mode 100644
index 72125a065..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
new file mode 100644
index 000000000..d21363316
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index 2bb7b64f4..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
deleted file mode 100644
index 82413d4cc..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
new file mode 100644
index 000000000..6d20c540b
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index f5ce40cf6..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index ca73b9249..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index 73f2006d4..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 049385984..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lmp.9.png b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lxx.9.png
index ee0aae28b..ee0aae28b 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lmp.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_suggestion_pressed.9.png b/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 02b4e9a53..000000000
--- a/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx.9.png
index 625490b1f..625490b1f 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_lxx.9.png
index 427c87061..427c87061 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lxx.9.png
index ea757296d..ea757296d 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx.9.png
index 1911c429f..1911c429f 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_lxx.9.png
index cdef116d2..cdef116d2 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lxx.9.png
index dea5d076c..dea5d076c 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_background_lmp.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_background_lxx.9.png
index 896505518..896505518 100644
--- a/java/res/drawable-mdpi/keyboard_popup_panel_background_lmp.9.png
+++ b/java/res/drawable-mdpi/keyboard_popup_panel_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 5e58866a7..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
deleted file mode 100644
index d0090a305..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
new file mode 100644
index 000000000..eeb447cc3
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
deleted file mode 100644
index 20251a000..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
new file mode 100644
index 000000000..624ba8c27
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
deleted file mode 100644
index a932249a8..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index 84d173967..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
deleted file mode 100644
index ee4490eac..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
new file mode 100644
index 000000000..2bc16cfeb
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
deleted file mode 100644
index 3ca93fdb3..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
deleted file mode 100644
index e8124776c..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
new file mode 100644
index 000000000..80dedd228
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
deleted file mode 100644
index aa4f44fdd..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
deleted file mode 100644
index 4539255c2..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
deleted file mode 100644
index 568392444..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index f770962c3..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lmp.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lxx.9.png
index 891d00024..891d00024 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lmp.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png b/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
deleted file mode 100644
index 41e126a73..000000000
--- a/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx.9.png
index c211d89c8..c211d89c8 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lxx.9.png
index 543bc763e..543bc763e 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lxx.9.png
index ec42aadb6..ec42aadb6 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx.9.png
index 319e9d7cf..319e9d7cf 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lxx.9.png
index 052032be7..052032be7 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lxx.9.png
index c7e9d1c9e..c7e9d1c9e 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_popup_panel_background_lmp.9.png b/java/res/drawable-xhdpi/keyboard_popup_panel_background_lxx.9.png
index 36df715b6..36df715b6 100644
--- a/java/res/drawable-xhdpi/keyboard_popup_panel_background_lmp.9.png
+++ b/java/res/drawable-xhdpi/keyboard_popup_panel_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index 566ba1fcd..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
new file mode 100644
index 000000000..97b049eb0
--- /dev/null
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
deleted file mode 100644
index 97f96258e..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
new file mode 100644
index 000000000..2e8149709
--- /dev/null
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
deleted file mode 100644
index dfb16a76b..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
deleted file mode 100644
index bf1d34686..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
new file mode 100644
index 000000000..d844b1713
--- /dev/null
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
deleted file mode 100644
index 962277165..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
new file mode 100644
index 000000000..9661f4a6e
--- /dev/null
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png
deleted file mode 100644
index 17144b673..000000000
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_lmp.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lmp.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lxx.9.png
index 0cbb2ec84..0cbb2ec84 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lmp.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx.9.png
index fd2f9e514..fd2f9e514 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lxx.9.png
index 3ab79007e..3ab79007e 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lxx.9.png
index 99543a1e0..99543a1e0 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx.9.png
index 121411a06..121411a06 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lxx.9.png
index e9e379287..e9e379287 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lxx.9.png
index 6c1143aeb..6c1143aeb 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_lmp.9.png b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_lxx.9.png
index 91d5d7f90..91d5d7f90 100644
--- a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_lmp.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_lxx.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png b/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png
deleted file mode 100644
index f55af308c..000000000
--- a/java/res/drawable-xxhdpi/sym_keyboard_mic_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_key_functional_lmp.xml b/java/res/drawable/btn_keyboard_key_functional_lxx.xml
index 427b8d568..fc6f98d01 100644
--- a/java/res/drawable/btn_keyboard_key_functional_lmp.xml
+++ b/java/res/drawable/btn_keyboard_key_functional_lxx.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Functional keys. -->
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lxx" />
+ <item android:drawable="@color/key_background_lxx" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_key_ics.xml b/java/res/drawable/btn_keyboard_key_ics.xml
index 9db0eeef4..af14cd51c 100644
--- a/java/res/drawable/btn_keyboard_key_ics.xml
+++ b/java/res/drawable/btn_keyboard_key_ics.xml
@@ -15,12 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" />
- <item android:state_single="true"
- android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" />
diff --git a/java/res/drawable/btn_keyboard_key_klp.xml b/java/res/drawable/btn_keyboard_key_klp.xml
index 500e3ea75..56c295f14 100644
--- a/java/res/drawable/btn_keyboard_key_klp.xml
+++ b/java/res/drawable/btn_keyboard_key_klp.xml
@@ -15,12 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" />
- <item android:state_single="true"
- android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" />
diff --git a/java/res/drawable/btn_keyboard_key_lmp.xml b/java/res/drawable/btn_keyboard_key_lxx.xml
index fdd19df68..fc19a0bbd 100644
--- a/java/res/drawable/btn_keyboard_key_lmp.xml
+++ b/java/res/drawable/btn_keyboard_key_lxx.xml
@@ -15,34 +15,28 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Functional keys. -->
- <item android:state_single="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
- <item android:state_single="true"
- android:drawable="@android:color/transparent" />
-
<!-- Action keys. -->
<item android:state_active="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
+ android:drawable="@color/key_background_pressed_lxx" />
<item android:state_active="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_lxx" />
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_lmp" />
+ android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_lxx" />
<item android:state_checkable="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_dark_pressed_lmp" />
+ android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_lxx" />
<item android:state_checkable="true" android:state_checked="true"
- android:drawable="@drawable/btn_keyboard_key_dark_normal_on_lmp" />
+ android:drawable="@drawable/btn_keyboard_key_dark_normal_on_lxx" />
<item android:state_checkable="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@drawable/btn_keyboard_key_dark_normal_off_lxx" />
<!-- Empty background keys. -->
<item android:state_empty="true"
- android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_lxx" />
<!-- Normal keys. -->
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_light_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lxx" />
+ <item android:drawable="@color/key_background_lxx" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_key_popup_lmp.xml b/java/res/drawable/btn_keyboard_key_popup_lxx.xml
index ebedaea3a..7daebc8d3 100644
--- a/java/res/drawable/btn_keyboard_key_popup_lmp.xml
+++ b/java/res/drawable/btn_keyboard_key_popup_lxx.xml
@@ -16,6 +16,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_popup_selected_lmp" />
+ android:drawable="@drawable/btn_keyboard_key_popup_selected_lxx" />
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_spacebar_lmp.xml b/java/res/drawable/btn_keyboard_spacebar_lxx.xml
index 516cb0731..10d04a8cc 100644
--- a/java/res/drawable/btn_keyboard_spacebar_lmp.xml
+++ b/java/res/drawable/btn_keyboard_spacebar_lxx.xml
@@ -16,6 +16,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_light_pressed_lmp" />
- <item android:drawable="@android:color/transparent" />
+ android:drawable="@color/key_background_pressed_lxx" />
+ <item android:drawable="@color/key_background_lxx" />
</selector>
diff --git a/java/res/drawable/btn_suggestion_lmp.xml b/java/res/drawable/btn_suggestion_lxx.xml
index c778e236f..c73e1f772 100644
--- a/java/res/drawable/btn_suggestion_lmp.xml
+++ b/java/res/drawable/btn_suggestion_lxx.xml
@@ -23,5 +23,5 @@
>
<item
android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_popup_selected_lmp" />
+ android:drawable="@color/suggested_word_background_selected_lxx" />
</selector>
diff --git a/java/res/drawable/keyboard_key_feedback_lmp.xml b/java/res/drawable/keyboard_key_feedback_lxx.xml
index cdbe64c38..2abbc909d 100644
--- a/java/res/drawable/keyboard_key_feedback_lmp.xml
+++ b/java/res/drawable/keyboard_key_feedback_lxx.xml
@@ -20,17 +20,17 @@
>
<!-- Left edge -->
<item latin:state_left_edge="true" latin:state_has_morekeys="true"
- android:drawable="@drawable/keyboard_key_feedback_left_more_background_lmp" />
+ android:drawable="@drawable/keyboard_key_feedback_left_more_background_lxx" />
<item latin:state_left_edge="true"
- android:drawable="@drawable/keyboard_key_feedback_left_background_lmp" />
+ android:drawable="@drawable/keyboard_key_feedback_left_background_lxx" />
<!-- Right edge -->
<item latin:state_right_edge="true" latin:state_has_morekeys="true"
- android:drawable="@drawable/keyboard_key_feedback_right_more_background_lmp" />
+ android:drawable="@drawable/keyboard_key_feedback_right_more_background_lxx" />
<item latin:state_right_edge="true"
- android:drawable="@drawable/keyboard_key_feedback_right_background_lmp" />
+ android:drawable="@drawable/keyboard_key_feedback_right_background_lxx" />
<item latin:state_has_morekeys="true"
- android:drawable="@drawable/keyboard_key_feedback_more_background_lmp" />
- <item android:drawable="@drawable/keyboard_key_feedback_background_lmp" />
+ android:drawable="@drawable/keyboard_key_feedback_more_background_lxx" />
+ <item android:drawable="@drawable/keyboard_key_feedback_background_lxx" />
</selector>
diff --git a/java/res/layout/emoji_keyboard_page.xml b/java/res/layout/emoji_keyboard_page.xml
index 9afad366a..0d1086171 100644
--- a/java/res/layout/emoji_keyboard_page.xml
+++ b/java/res/layout/emoji_keyboard_page.xml
@@ -18,7 +18,7 @@
*/
-->
-<com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView
+<com.android.inputmethod.keyboard.emoji.EmojiPageKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emoji_keyboard_page"
android:layoutDirection="ltr"
diff --git a/java/res/layout/emoji_palettes_view.xml b/java/res/layout/emoji_palettes_view.xml
index 552a474b4..761887168 100644
--- a/java/res/layout/emoji_palettes_view.xml
+++ b/java/res/layout/emoji_palettes_view.xml
@@ -18,7 +18,7 @@
*/
-->
-<com.android.inputmethod.keyboard.EmojiPalettesView
+<com.android.inputmethod.keyboard.emoji.EmojiPalettesView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emoji_keyboard_view"
android:orientation="vertical"
@@ -78,7 +78,7 @@
android:id="@+id/emoji_keyboard_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- <com.android.inputmethod.keyboard.EmojiCategoryPageIndicatorView
+ <com.android.inputmethod.keyboard.emoji.EmojiCategoryPageIndicatorView
android:id="@+id/emoji_category_page_id_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -109,4 +109,4 @@
android:gravity="center"
android:layout_height="match_parent" />
</LinearLayout>
-</com.android.inputmethod.keyboard.EmojiPalettesView>
+</com.android.inputmethod.keyboard.emoji.EmojiPalettesView>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 519aa44d0..4d7de93c8 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -29,7 +29,7 @@
<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="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>
@@ -39,7 +39,7 @@
<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_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>
@@ -49,7 +49,7 @@
<string name="use_personalized_dicts" msgid="5167396352105467626">"ការ​ស្នើ​ផ្ទាល់​ខ្លួន"</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" 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>
@@ -60,7 +60,7 @@
<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="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>
@@ -123,7 +123,7 @@
<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_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="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
@@ -154,7 +154,7 @@
<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_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>
@@ -170,10 +170,10 @@
<string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
<string name="message_loading" msgid="5638680861387748936">"កំពុង​ផ្ទុក..."</string>
<string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
- <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
+ <string name="cancel" msgid="6830980399865683324">"បោះ​បង់​"</string>
<string name="go_to_settings" msgid="3876892339342569259">"ការ​កំណត់"</string>
<string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
- <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់​"</string>
<string name="delete_dict" msgid="756853268088330054">"លុប"</string>
<string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​ចល័ត​មាន​វចនានុក្រម​អាច​ប្រើ​បាន។&lt;br/&gt; យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ &lt;b&gt;ទាញ​យក&lt;/b&gt; វចនានុក្រម​ភាសា <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ដើម្បី​បង្កើន​បទពិសោធន៍​វាយ​បញ្ចូល​របស់​អ្នក។&lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​ប្រហែល​ពីរ​នាទី​នៅ​តាម 3G។ ការ​គិត​ថ្លៃ​អាច​អនុវត្ត​ប្រសិន​បើ​អ្នក​មិន​ប្រើ &lt;b&gt;ផែនការ​ទិន្នន័យ​គ្មាន​ដែន​កំណត់&lt;/b&gt;.&lt;br/&gt; បើ​អ្នក​មិន​ប្រាកដ​​ថា​ផែនការ​ណា​មួយ​ដែល​អ្នក​មាន យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ​​ភ្ជាប់​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យ​ប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​វចនានុក្រម​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា &amp; ការ​បញ្ចូល&lt;/b&gt; នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់&lt;/b&gt; សម្រាប់​ឧបករណ៍​ចល័ត។"</string>
<string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
@@ -191,7 +191,7 @@
<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_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>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 769a1d986..79cc139a2 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -41,13 +41,16 @@
</declare-styleable>
<declare-styleable name="KeyboardView">
- <!-- Image for the key. This image needs to be a {@link StateListDrawable}, with the
- following possible states: normal, pressed, checkable, checkable+pressed,
+ <!-- Background image for the key. This image needs to be a {@link StateListDrawable},
+ with the following possible states: normal, pressed, checkable, checkable+pressed,
checkable+checked, checkable+checked+pressed. -->
<attr name="keyBackground" format="reference" />
- <!-- Image for the functional key used in Emoji layout. -->
- <attr name="keyBackgroundEmojiFunctional" format="reference" />
-
+ <!-- Background image for the functional key. This image needs to be a
+ {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+ <attr name="functionalKeyBackground" format="reference" />
+ <!-- Background image for the spacebar. This image needs to be a
+ {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+ <attr name="spacebarBackground" format="reference" />
<!-- Horizontal padding of left/right aligned key label to the edge of the key. -->
<attr name="keyLabelHorizontalPadding" format="dimension" />
<!-- Right padding of hint letter to the edge of the key.-->
@@ -76,8 +79,6 @@
<attr name="languageOnSpacebarTextColor" format="color" />
<attr name="languageOnSpacebarTextShadowRadius" format="float" />
<attr name="languageOnSpacebarTextShadowColor" format="color" />
- <!-- Background image for the spacebar. -->
- <attr name="spacebarBackground" format="reference" />
<!-- Fadeout animator for spacebar language label. -->
<attr name="languageOnSpacebarFinalAlpha" format="integer" />
<attr name="languageOnSpacebarFadeoutAnimator" format="reference" />
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index baa0887bc..60b5cdfae 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -39,12 +39,18 @@
<color name="typed_word_color_klp">#D8F0F0F0</color>
<color name="suggested_word_color_klp">#B2F0F0F0</color>
<color name="highlight_translucent_color_klp">#99E0E0E0</color>
- <!-- Color resources for LMP theme. Base color = F0F0F0 -->
- <color name="key_hint_letter_color_lmp">@android:color/white</color>
- <color name="highlight_color_lmp">#FFF0F0F0</color>
- <color name="typed_word_color_lmp">#D8F0F0F0</color>
- <color name="suggested_word_color_lmp">#B2F0F0F0</color>
- <color name="highlight_translucent_color_lmp">#99E0E0E0</color>
+ <!-- Color resources for LXX theme. Base color = F0F0F0 -->
+ <color name="key_text_inactive_color_lxx">#808184</color>
+ <color name="key_hint_letter_color_lxx">#808184</color>
+ <color name="highlight_color_lxx">#7FCAC3</color>
+ <color name="typed_word_color_lxx">#D87FCAC3</color>
+ <color name="suggested_word_color_lxx">#B27FCAC3</color>
+ <color name="highlight_translucent_color_lxx">#997FCAC3</color>
+ <color name="keyboard_background_lxx">#384248</color>
+ <color name="key_background_lxx">#384248</color>
+ <color name="key_background_pressed_lxx">#546872</color>
+ <color name="suggestions_strip_background_lxx">#263238</color>
+ <color name="suggested_word_background_selected_lxx">#384248</color>
<!-- Color resources for setup wizard and tutorial -->
<color name="setup_background">#FFEBEBEB</color>
<color name="setup_text_dark">#FF707070</color>
diff --git a/java/res/values/config-common.xml b/java/res/values/config-common.xml
index 1962c0d45..ad27ab427 100644
--- a/java/res/values/config-common.xml
+++ b/java/res/values/config-common.xml
@@ -133,7 +133,7 @@
<integer name="config_gesture_trail_shadow_ratio">-1</integer>
<!-- Common configuration of Emoji keyboard -->
- <dimen name="config_emoji_category_page_id_height">3dp</dimen>
+ <dimen name="config_emoji_category_page_id_height">2dp</dimen>
<!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. -->
<dimen name="config_accessibility_edge_slop">8dp</dimen>
diff --git a/java/res/values/keyboard-icons-lmp.xml b/java/res/values/keyboard-icons-lxx.xml
index 39e0fe306..ea4b6e65c 100644
--- a/java/res/values/keyboard-icons-lmp.xml
+++ b/java/res/values/keyboard-icons-lxx.xml
@@ -19,7 +19,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="KeyboardIcons.LMP">
+ <style name="KeyboardIcons.LXX">
<!-- Keyboard icons -->
<item name="iconShiftKey">@drawable/sym_keyboard_shift_holo_dark</item>
<item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo_dark</item>
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 76abb10fb..df26fb3b4 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -109,12 +109,7 @@
<style name="KeyPreviewTextView" />
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
- <style
- name="EmojiPalettesView"
- parent="KeyboardView"
- >
- <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
- </style>
+ <style name="EmojiPalettesView" />
<style name="MoreKeysKeyboard" />
<style
name="MoreKeysKeyboardView"
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index d7943eeaf..560cfc505 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -48,6 +48,8 @@
>
<item name="android:background">@drawable/keyboard_background_holo</item>
<item name="keyBackground">@drawable/btn_keyboard_key_ics</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_ics</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_ics</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
<item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
@@ -73,7 +75,6 @@
<item name="languageOnSpacebarTextColor">@color/spacebar_text_color_holo</item>
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
- <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_ics</item>
</style>
<style
name="KeyPreviewTextView.ICS"
@@ -85,9 +86,8 @@
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiPalettesView.ICS"
- parent="KeyboardView.ICS"
+ parent="MainKeyboardView.ICS"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_ics</item>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
</style>
<style
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 13500fef2..453e5cbce 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -48,6 +48,8 @@
>
<item name="android:background">@drawable/keyboard_background_holo</item>
<item name="keyBackground">@drawable/btn_keyboard_key_klp</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_klp</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_klp</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
<item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
@@ -73,7 +75,6 @@
<item name="languageOnSpacebarTextColor">@color/spacebar_text_color_holo</item>
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
- <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_klp</item>
</style>
<style
name="KeyPreviewTextView.KLP"
@@ -85,9 +86,8 @@
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiPalettesView.KLP"
- parent="KeyboardView.KLP"
+ parent="MainKeyboardView.KLP"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_klp</item>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
</style>
<style
diff --git a/java/res/values/themes-lmp.xml b/java/res/values/themes-lxx.xml
index 41c4d09d5..4f3ee80c9 100644
--- a/java/res/values/themes-lmp.xml
+++ b/java/res/values/themes-lxx.xml
@@ -19,23 +19,23 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="KeyboardTheme.LMP" parent="KeyboardIcons.LMP">
- <item name="keyboardStyle">@style/Keyboard.LMP</item>
- <item name="keyboardViewStyle">@style/KeyboardView.LMP</item>
- <item name="mainKeyboardViewStyle">@style/MainKeyboardView.LMP</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.LMP</item>
- <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LMP</item>
- <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LMP</item>
- <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LMP</item>
- <item name="suggestionStripViewStyle">@style/SuggestionStripView.LMP</item>
- <item name="suggestionWordStyle">@style/SuggestionWord.LMP</item>
+ <style name="KeyboardTheme.LXX" parent="KeyboardIcons.LXX">
+ <item name="keyboardStyle">@style/Keyboard.LXX</item>
+ <item name="keyboardViewStyle">@style/KeyboardView.LXX</item>
+ <item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX</item>
+ <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.LXX</item>
+ <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LXX</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LXX</item>
+ <item name="suggestionStripViewStyle">@style/SuggestionStripView.LXX</item>
+ <item name="suggestionWordStyle">@style/SuggestionWord.LXX</item>
</style>
<style
- name="Keyboard.LMP"
+ name="Keyboard.LXX"
parent="Keyboard"
>
<!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
- <item name="themeId">0</item>
+ <item name="themeId">3</item>
<item name="keyboardTopPadding">@fraction/config_keyboard_top_padding_holo</item>
<item name="keyboardBottomPadding">@fraction/config_keyboard_bottom_padding_holo</item>
<item name="horizontalGap">@fraction/config_key_horizontal_gap_holo</item>
@@ -43,56 +43,56 @@
<item name="touchPositionCorrectionData">@array/touch_position_correction_data_holo</item>
</style>
<style
- name="KeyboardView.LMP"
+ name="KeyboardView.LXX"
parent="KeyboardView"
>
- <item name="android:background">@drawable/keyboard_background_holo</item>
- <item name="keyBackground">@drawable/btn_keyboard_key_lmp</item>
+ <item name="android:background">@color/keyboard_background_lxx</item>
+ <item name="keyBackground">@drawable/btn_keyboard_key_lxx</item>
+ <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_lxx</item>
+ <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_lxx</item>
<item name="keyTypeface">bold</item>
<item name="keyTextColor">@color/key_text_color_holo</item>
- <item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item>
- <item name="keyHintLetterColor">@color/key_hint_letter_color_lmp</item>
- <item name="keyHintLabelColor">@color/key_hint_label_color_holo</item>
- <item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item>
- <item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item>
+ <item name="keyTextInactivatedColor">@color/key_text_inactive_color_lxx</item>
+ <item name="keyHintLetterColor">@color/key_hint_letter_color_lxx</item>
+ <item name="keyHintLabelColor">@color/key_text_inactive_color_lxx</item>
+ <item name="keyShiftedLetterHintInactivatedColor">@color/key_text_inactive_color_lxx</item>
+ <item name="keyShiftedLetterHintActivatedColor">@color/key_text_color_holo</item>
<item name="keyPreviewTextColor">@color/key_text_color_holo</item>
<!-- A negative value to disable key text shadow layer. -->
<item name="keyTextShadowRadius">-1.0</item>
</style>
<style
- name="MainKeyboardView.LMP"
- parent="KeyboardView.LMP"
+ name="MainKeyboardView.LXX"
+ parent="KeyboardView.LXX"
>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
- <item name="gestureFloatingPreviewTextColor">@color/highlight_color_lmp</item>
+ <item name="gestureFloatingPreviewTextColor">@color/highlight_color_lxx</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
- <item name="gestureTrailColor">@color/highlight_color_lmp</item>
- <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_lmp</item>
+ <item name="gestureTrailColor">@color/highlight_color_lxx</item>
+ <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_lxx</item>
<item name="autoCorrectionSpacebarLedEnabled">false</item>
<item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item>
- <item name="languageOnSpacebarTextColor">@color/spacebar_text_color_holo</item>
- <item name="languageOnSpacebarTextShadowRadius">1.0</item>
- <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
- <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_lmp</item>
+ <item name="languageOnSpacebarTextColor">@color/key_text_inactive_color_lxx</item>
+ <!-- A negative value to disable text shadow layer. -->
+ <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
</style>
<style
- name="KeyPreviewTextView.LMP"
+ name="KeyPreviewTextView.LXX"
parent="KeyPreviewTextView"
>
- <item name="android:background">@drawable/keyboard_key_feedback_lmp</item>
+ <item name="android:background">@drawable/keyboard_key_feedback_lxx</item>
</style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
- name="EmojiPalettesView.LMP"
- parent="KeyboardView.LMP"
+ name="EmojiPalettesView.LXX"
+ parent="MainKeyboardView.LXX"
>
- <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_lmp</item>
- <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item>
+ <item name="emojiTabLabelColor">@color/emoji_tab_label_color_lxx</item>
</style>
<style
- name="MoreKeysKeyboard.LMP"
- parent="Keyboard.LMP"
+ name="MoreKeysKeyboard.LXX"
+ parent="Keyboard.LXX"
>
<item name="keyboardTopPadding">0%p</item>
<item name="keyboardBottomPadding">0%p</item>
@@ -100,17 +100,17 @@
<item name="touchPositionCorrectionData">@null</item>
</style>
<style
- name="MoreKeysKeyboardView.LMP"
- parent="KeyboardView.LMP"
+ name="MoreKeysKeyboardView.LXX"
+ parent="KeyboardView.LXX"
>
- <item name="android:background">@drawable/keyboard_popup_panel_background_lmp</item>
- <item name="keyBackground">@drawable/btn_keyboard_key_popup_lmp</item>
+ <item name="android:background">@drawable/keyboard_popup_panel_background_lxx</item>
+ <item name="keyBackground">@drawable/btn_keyboard_key_popup_lxx</item>
<item name="keyTypeface">normal</item>
<item name="verticalCorrection">@dimen/config_more_keys_keyboard_vertical_correction_holo</item>
</style>
<style
- name="SuggestionStripView.LMP"
- parent="KeyboardView.LMP"
+ name="SuggestionStripView.LXX"
+ parent="KeyboardView.LXX"
>
<item name="suggestionsCountInStrip">@integer/config_suggestions_count_in_strip</item>
<item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
@@ -118,17 +118,17 @@
<item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
<item name="android:background">@drawable/keyboard_suggest_strip_holo</item>
<item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item>
- <item name="colorValidTypedWord">@color/typed_word_color_lmp</item>
- <item name="colorTypedWord">@color/typed_word_color_lmp</item>
- <item name="colorAutoCorrect">@color/highlight_color_lmp</item>
- <item name="colorSuggested">@color/suggested_word_color_lmp</item>
+ <item name="colorValidTypedWord">@color/typed_word_color_lxx</item>
+ <item name="colorTypedWord">@color/typed_word_color_lxx</item>
+ <item name="colorAutoCorrect">@color/highlight_color_lxx</item>
+ <item name="colorSuggested">@color/suggested_word_color_lxx</item>
<item name="alphaObsoleted">70%</item>
</style>
<style
- name="SuggestionWord.LMP"
+ name="SuggestionWord.LXX"
parent="SuggestionWord"
>
- <item name="android:background">@drawable/btn_suggestion_lmp</item>
- <item name="android:textColor">@color/highlight_color_lmp</item>
+ <item name="android:background">@drawable/btn_suggestion_lxx</item>
+ <item name="android:textColor">@color/highlight_color_lxx</item>
</style>
</resources>
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 990f7deea..9e7f04d4f 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -56,18 +56,20 @@ public class CombinerChain {
*
* The combiner chain takes events as inputs and outputs code points and combining state.
* For example, if the input language is Japanese, the combining chain will typically perform
- * kana conversion.
+ * kana conversion. This takes a string for initial text, taken to be present before the
+ * cursor: we'll start after this.
*
+ * @param initialText The text that has already been combined so far.
* @param combinerList A list of combiners to be applied in order.
*/
- public CombinerChain(final Combiner... combinerList) {
+ public CombinerChain(final String initialText, final Combiner... combinerList) {
mCombiners = CollectionUtils.newArrayList();
// The dead key combiner is always active, and always first
mCombiners.add(new DeadKeyCombiner());
for (final Combiner combiner : combinerList) {
mCombiners.add(combiner);
}
- mCombinedText = new StringBuilder();
+ mCombinedText = new StringBuilder(initialText);
mStateFeedback = new SpannableStringBuilder();
}
diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java
index 27b8c14bb..da0228bd2 100644
--- a/java/src/com/android/inputmethod/event/MyanmarReordering.java
+++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java
@@ -207,9 +207,33 @@ public class MyanmarReordering implements Combiner {
return clearAndGetResultingEvent(newEvent);
}
} else if (Constants.CODE_DELETE == newEvent.mKeyCode) {
- if (mCurrentEvents.size() > 0) {
- mCurrentEvents.remove(mCurrentEvents.size() - 1);
- return null;
+ final Event lastEvent = getLastEvent();
+ final int eventSize = mCurrentEvents.size();
+ if (null != lastEvent) {
+ if (VOWEL_E == lastEvent.mCodePoint) {
+ // We have a VOWEL_E at the end. There are four cases.
+ // - The vowel is the only code point in the buffer. Remove it.
+ // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
+ // - The vowel is preceded by a consonant/medial, remove the consonant/medial.
+ // - In all other cases, it's strange, so just remove the last code point.
+ if (eventSize <= 1) {
+ mCurrentEvents.clear();
+ } else { // eventSize >= 2
+ final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
+ if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
+ mCurrentEvents.remove(eventSize - 1);
+ mCurrentEvents.remove(eventSize - 2);
+ } else if (isConsonantOrMedial(previousCodePoint)) {
+ mCurrentEvents.remove(eventSize - 2);
+ } else {
+ mCurrentEvents.remove(eventSize - 1);
+ }
+ }
+ return null;
+ } else if (eventSize > 0) {
+ mCurrentEvents.remove(eventSize - 1);
+ return null;
+ }
}
}
// This character is not part of the combining scheme, so we should reset everything.
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 816a94300..4c2250740 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -218,7 +218,7 @@ public class Key implements Comparable<Key> {
*
* @param keySpec the key specification.
* @param keyAttr the Key XML attributes array.
- * @param keyStyle the {@link KeyStyle} of this key.
+ * @param style the {@link KeyStyle} of this key.
* @param params the keyboard building parameters.
* @param row the row that this key belongs to. row's x-coordinate will be the right edge of
* this key.
@@ -857,17 +857,6 @@ public class Key implements Comparable<Key> {
android.R.attr.state_empty
};
- // functional normal state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
- android.R.attr.state_single
- };
-
- // functional pressed state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
- android.R.attr.state_single,
- android.R.attr.state_pressed
- };
-
// action normal state (with properties)
private static final int[] KEY_STATE_ACTIVE_NORMAL = {
android.R.attr.state_active
@@ -880,25 +869,43 @@ public class Key implements Comparable<Key> {
};
/**
- * Returns the drawable state for the key, based on the current state and type of the key.
- * @return the drawable state of the key.
+ * Returns the background drawable for the key, based on the current state and type of the key.
+ * @return the background drawable of the key.
* @see android.graphics.drawable.StateListDrawable#setState(int[])
*/
- public final int[] getCurrentDrawableState() {
+ public final Drawable selectBackgroundDrawable(final Drawable keyBackground,
+ final Drawable functionalKeyBackground, final Drawable spacebarBackground) {
+ final Drawable background;
+ if (mBackgroundType == BACKGROUND_TYPE_FUNCTIONAL) {
+ background = functionalKeyBackground;
+ } else if (getCode() == Constants.CODE_SPACE) {
+ background = spacebarBackground;
+ } else {
+ background = keyBackground;
+ }
+ final int[] stateSet;
switch (mBackgroundType) {
- case BACKGROUND_TYPE_FUNCTIONAL:
- return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
case BACKGROUND_TYPE_ACTION:
- return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+ stateSet = mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+ break;
case BACKGROUND_TYPE_STICKY_OFF:
- return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+ stateSet = mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+ break;
case BACKGROUND_TYPE_STICKY_ON:
- return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
+ stateSet = mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
+ break;
case BACKGROUND_TYPE_EMPTY:
- return mPressed ? KEY_STATE_PRESSED : KEY_STATE_EMPTY;
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_EMPTY;
+ break;
+ case BACKGROUND_TYPE_FUNCTIONAL:
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ break;
default: /* BACKGROUND_TYPE_NORMAL */
- return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ stateSet = mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+ break;
}
+ background.setState(stateSet);
+ return background;
}
public static class Spacer extends Key {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 4a46a4a46..fc9faa6e3 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -28,6 +28,7 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
+import com.android.inputmethod.keyboard.emoji.EmojiPalettesView;
import com.android.inputmethod.keyboard.internal.KeyboardState;
import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
import com.android.inputmethod.latin.InputView;
@@ -253,10 +254,11 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void setEmojiKeyboard() {
+ final Keyboard keyboard = mKeyboardView.getKeyboard();
mMainKeyboardFrame.setVisibility(View.GONE);
mEmojiPalettesView.startEmojiPalettes(
mKeyboardTextsSet.getText(KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL),
- mKeyboardView.getKeyVisualAttribute());
+ mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet);
mEmojiPalettesView.setVisibility(View.VISIBLE);
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
index 429c7ddd7..e0b74fa14 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
@@ -34,7 +34,7 @@ public final class KeyboardTheme {
static final int THEME_ID_ICS = 0;
static final int THEME_ID_KLP = 2;
- static final int THEME_ID_LMP = 3;
+ static final int THEME_ID_LXX = 3;
static final int DEFAULT_THEME_ID = THEME_ID_KLP;
private static final KeyboardTheme[] KEYBOARD_THEMES = {
@@ -42,7 +42,7 @@ public final class KeyboardTheme {
VERSION_CODES.ICE_CREAM_SANDWICH),
new KeyboardTheme(THEME_ID_KLP, R.style.KeyboardTheme_KLP,
VERSION_CODES.KITKAT),
- new KeyboardTheme(THEME_ID_LMP, R.style.KeyboardTheme_LMP,
+ new KeyboardTheme(THEME_ID_LXX, R.style.KeyboardTheme_LXX,
// TODO: Update this constant once the *next* version becomes available.
VERSION_CODES.CUR_DEVELOPMENT),
};
@@ -88,7 +88,7 @@ public final class KeyboardTheme {
return 5;
case THEME_ID_KLP:
return 9;
- case THEME_ID_LMP:
+ case THEME_ID_LXX:
return 10;
default: // Invalid theme
return -1;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 4450a4474..a6eac4cd7 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -47,6 +47,8 @@ import java.util.HashSet;
* A view that renders a virtual {@link Keyboard}.
*
* @attr ref R.styleable#KeyboardView_keyBackground
+ * @attr ref R.styleable#KeyboardView_functionalKeyBackground
+ * @attr ref R.styleable#KeyboardView_spacebarBackground
* @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding
* @attr ref R.styleable#KeyboardView_keyHintLetterPadding
* @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding
@@ -81,6 +83,8 @@ public class KeyboardView extends View {
private final float mKeyTextShadowRadius;
private final float mVerticalCorrection;
private final Drawable mKeyBackground;
+ private final Drawable mFunctionalKeyBackground;
+ private final Drawable mSpacebarBackground;
private final Rect mKeyBackgroundPadding = new Rect();
private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f;
@@ -125,6 +129,14 @@ public class KeyboardView extends View {
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
mKeyBackground = keyboardViewAttr.getDrawable(R.styleable.KeyboardView_keyBackground);
mKeyBackground.getPadding(mKeyBackgroundPadding);
+ final Drawable functionalKeyBackground = keyboardViewAttr.getDrawable(
+ R.styleable.KeyboardView_functionalKeyBackground);
+ mFunctionalKeyBackground = (functionalKeyBackground != null) ? functionalKeyBackground
+ : mKeyBackground;
+ final Drawable spacebarBackground = keyboardViewAttr.getDrawable(
+ R.styleable.KeyboardView_spacebarBackground);
+ mSpacebarBackground = (spacebarBackground != null) ? spacebarBackground
+ : mKeyBackground;
mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset(
R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
mKeyHintLetterPadding = keyboardViewAttr.getDimension(
@@ -324,7 +336,9 @@ public class KeyboardView extends View {
params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;
if (!key.isSpacer()) {
- onDrawKeyBackground(key, canvas, mKeyBackground);
+ final Drawable background = key.selectBackgroundDrawable(
+ mKeyBackground, mFunctionalKeyBackground, mSpacebarBackground);
+ onDrawKeyBackground(key, canvas, background);
}
onDrawKeyTopVisuals(key, canvas, paint, params);
@@ -339,8 +353,6 @@ public class KeyboardView extends View {
final int bgHeight = key.getHeight() + padding.top + padding.bottom;
final int bgX = -padding.left;
final int bgY = -padding.top;
- final int[] drawableState = key.getCurrentDrawableState();
- background.setState(drawableState);
final Rect bounds = background.getBounds();
if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
background.setBounds(0, 0, bgWidth, bgHeight);
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 1a8e4b7e9..4a0976845 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -76,7 +76,6 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowRadius
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowColor
- * @attr ref R.styleable#MainKeyboardView_spacebarBackground
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFinalAlpha
* @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFadeoutAnimator
* @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator
@@ -120,7 +119,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
/* Space key and its icon and background. */
private Key mSpaceKey;
private Drawable mSpacebarIcon;
- private final Drawable mSpacebarBackground;
// Stuff to draw language name on spacebar.
private final int mLanguageOnSpacebarFinalAlpha;
private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator;
@@ -154,7 +152,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private final SlidingKeyInputDrawingPreview mSlidingKeyInputDrawingPreview;
// Key preview
- private static final boolean FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED = false;
private final KeyPreviewDrawParams mKeyPreviewDrawParams;
private final KeyPreviewChoreographer mKeyPreviewChoreographer;
@@ -224,8 +221,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
R.styleable.MainKeyboardView_backgroundDimAlpha, 0);
mBackgroundDimAlphaPaint.setColor(Color.BLACK);
mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha);
- mSpacebarBackground = mainKeyboardViewAttr.getDrawable(
- R.styleable.MainKeyboardView_spacebarBackground);
mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean(
R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false);
mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable(
@@ -557,6 +552,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
// Note that this method is called from a non-UI thread.
+ @SuppressWarnings("static-method")
public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) {
PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable);
}
@@ -864,30 +860,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
}
- // Draw key background.
- @Override
- protected void onDrawKeyBackground(final Key key, final Canvas canvas,
- final Drawable background) {
- if (key.getCode() == Constants.CODE_SPACE) {
- super.onDrawKeyBackground(key, canvas, mSpacebarBackground);
- return;
- }
- super.onDrawKeyBackground(key, canvas, background);
- }
-
@Override
protected void onDrawKeyTopVisuals(final Key key, final Canvas canvas, final Paint paint,
final KeyDrawParams params) {
if (key.altCodeWhileTyping() && key.isEnabled()) {
params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha;
}
- // Don't draw key top letter when key preview is showing.
- if (FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED
- && mKeyPreviewChoreographer.isShowingKeyPreview(key)) {
- // TODO: Fade out animation for the key top letter, and fade in animation for the key
- // background color when the user presses the key.
- return;
- }
final int code = key.getCode();
if (code == Constants.CODE_SPACE) {
drawSpacebar(key, canvas, paint);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/emoji/DynamicGridKeyboard.java
index 67a222732..c7a9025c0 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/DynamicGridKeyboard.java
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-package com.android.inputmethod.keyboard.internal;
+package com.android.inputmethod.keyboard.emoji;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
-import com.android.inputmethod.keyboard.EmojiPalettesView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.settings.Settings;
@@ -36,7 +35,7 @@ import java.util.List;
/**
* This is a Keyboard class where you can add keys dynamically shown in a grid layout
*/
-public class DynamicGridKeyboard extends Keyboard {
+final class DynamicGridKeyboard extends Keyboard {
private static final String TAG = DynamicGridKeyboard.class.getSimpleName();
private static final int TEMPLATE_KEY_CODE_0 = 0x30;
private static final int TEMPLATE_KEY_CODE_1 = 0x31;
@@ -62,7 +61,7 @@ public class DynamicGridKeyboard extends Keyboard {
mVerticalStep = key0.getHeight() + mVerticalGap;
mColumnsNum = mBaseWidth / mHorizontalStep;
mMaxKeyCount = maxKeyCount;
- mIsRecents = categoryId == EmojiPalettesView.CATEGORY_ID_RECENTS;
+ mIsRecents = categoryId == EmojiCategory.ID_RECENTS;
mPrefs = prefs;
}
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
new file mode 100644
index 000000000..dd0e3e838
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.emoji;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+final class EmojiCategory {
+ private final String TAG = EmojiCategory.class.getSimpleName();
+
+ private static final int ID_UNSPECIFIED = -1;
+ public static final int ID_RECENTS = 0;
+ private static final int ID_PEOPLE = 1;
+ private static final int ID_OBJECTS = 2;
+ private static final int ID_NATURE = 3;
+ private static final int ID_PLACES = 4;
+ private static final int ID_SYMBOLS = 5;
+ private static final int ID_EMOTICONS = 6;
+
+ public final class CategoryProperties {
+ public final int mCategoryId;
+ public final int mPageCount;
+ public CategoryProperties(final int categoryId, final int pageCount) {
+ mCategoryId = categoryId;
+ mPageCount = pageCount;
+ }
+ }
+
+ private static final String[] sCategoryName = {
+ "recents",
+ "people",
+ "objects",
+ "nature",
+ "places",
+ "symbols",
+ "emoticons" };
+
+ private static final int[] sCategoryIcon = {
+ R.drawable.ic_emoji_recent_light,
+ R.drawable.ic_emoji_people_light,
+ R.drawable.ic_emoji_objects_light,
+ R.drawable.ic_emoji_nature_light,
+ R.drawable.ic_emoji_places_light,
+ R.drawable.ic_emoji_symbols_light,
+ 0 };
+
+ private static final String[] sCategoryLabel =
+ { null, null, null, null, null, null, ":-)" };
+
+ private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
+ R.string.spoken_descrption_emoji_category_recents,
+ R.string.spoken_descrption_emoji_category_people,
+ R.string.spoken_descrption_emoji_category_objects,
+ R.string.spoken_descrption_emoji_category_nature,
+ R.string.spoken_descrption_emoji_category_places,
+ R.string.spoken_descrption_emoji_category_symbols,
+ R.string.spoken_descrption_emoji_category_emoticons };
+
+ private static final int[] sCategoryElementId = {
+ KeyboardId.ELEMENT_EMOJI_RECENTS,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY1,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY2,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY3,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY4,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY5,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
+
+ private final SharedPreferences mPrefs;
+ private final Resources mRes;
+ private final int mMaxPageKeyCount;
+ private final KeyboardLayoutSet mLayoutSet;
+ private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
+ private final ArrayList<CategoryProperties> mShownCategories =
+ CollectionUtils.newArrayList();
+ private final ConcurrentHashMap<Long, DynamicGridKeyboard>
+ mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
+
+ private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED;
+ private int mCurrentCategoryPageId = 0;
+
+ public EmojiCategory(final SharedPreferences prefs, final Resources res,
+ final KeyboardLayoutSet layoutSet) {
+ mPrefs = prefs;
+ mRes = res;
+ mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
+ mLayoutSet = layoutSet;
+ for (int i = 0; i < sCategoryName.length; ++i) {
+ mCategoryNameToIdMap.put(sCategoryName[i], i);
+ }
+ addShownCategoryId(EmojiCategory.ID_RECENTS);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
+ addShownCategoryId(EmojiCategory.ID_PEOPLE);
+ addShownCategoryId(EmojiCategory.ID_OBJECTS);
+ addShownCategoryId(EmojiCategory.ID_NATURE);
+ addShownCategoryId(EmojiCategory.ID_PLACES);
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_PEOPLE);
+ } else {
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_SYMBOLS);
+ }
+ addShownCategoryId(EmojiCategory.ID_SYMBOLS);
+ addShownCategoryId(EmojiCategory.ID_EMOTICONS);
+ getKeyboard(EmojiCategory.ID_RECENTS, 0 /* cagetoryPageId */)
+ .loadRecentKeys(mCategoryKeyboardMap.values());
+ }
+
+ private void addShownCategoryId(final int categoryId) {
+ // Load a keyboard of categoryId
+ getKeyboard(categoryId, 0 /* cagetoryPageId */);
+ final CategoryProperties properties =
+ new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
+ mShownCategories.add(properties);
+ }
+
+ public String getCategoryName(final int categoryId, final int categoryPageId) {
+ return sCategoryName[categoryId] + "-" + categoryPageId;
+ }
+
+ public int getCategoryId(final String name) {
+ final String[] strings = name.split("-");
+ return mCategoryNameToIdMap.get(strings[0]);
+ }
+
+ public int getCategoryIcon(final int categoryId) {
+ return sCategoryIcon[categoryId];
+ }
+
+ public String getCategoryLabel(final int categoryId) {
+ return sCategoryLabel[categoryId];
+ }
+
+ public String getAccessibilityDescription(final int categoryId) {
+ return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
+ }
+
+ public ArrayList<CategoryProperties> getShownCategories() {
+ return mShownCategories;
+ }
+
+ public int getCurrentCategoryId() {
+ return mCurrentCategoryId;
+ }
+
+ public int getCurrentCategoryPageSize() {
+ return getCategoryPageSize(mCurrentCategoryId);
+ }
+
+ public int getCategoryPageSize(final int categoryId) {
+ for (final CategoryProperties prop : mShownCategories) {
+ if (prop.mCategoryId == categoryId) {
+ return prop.mPageCount;
+ }
+ }
+ Log.w(TAG, "Invalid category id: " + categoryId);
+ // Should not reach here.
+ return 0;
+ }
+
+ public void setCurrentCategoryId(final int categoryId) {
+ mCurrentCategoryId = categoryId;
+ Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
+ }
+
+ public void setCurrentCategoryPageId(final int id) {
+ mCurrentCategoryPageId = id;
+ }
+
+ public int getCurrentCategoryPageId() {
+ return mCurrentCategoryPageId;
+ }
+
+ public void saveLastTypedCategoryPage() {
+ Settings.writeLastTypedEmojiCategoryPageId(
+ mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
+ }
+
+ public boolean isInRecentTab() {
+ return mCurrentCategoryId == EmojiCategory.ID_RECENTS;
+ }
+
+ public int getTabIdFromCategoryId(final int categoryId) {
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ if (mShownCategories.get(i).mCategoryId == categoryId) {
+ return i;
+ }
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ // Returns the view pager's page position for the categoryId
+ public int getPageIdFromCategoryId(final int categoryId) {
+ final int lastSavedCategoryPageId =
+ Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
+ int sum = 0;
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ final CategoryProperties props = mShownCategories.get(i);
+ if (props.mCategoryId == categoryId) {
+ return sum + lastSavedCategoryPageId;
+ }
+ sum += props.mPageCount;
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ public int getRecentTabId() {
+ return getTabIdFromCategoryId(EmojiCategory.ID_RECENTS);
+ }
+
+ private int getCategoryPageCount(final int categoryId) {
+ final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
+ return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
+ }
+
+ // Returns a pair of the category id and the category page id from the view pager's page
+ // position. The category page id is numbered in each category. And the view page position
+ // is the position of the current shown page in the view pager which contains all pages of
+ // all categories.
+ public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(final int position) {
+ int sum = 0;
+ for (final CategoryProperties properties : mShownCategories) {
+ final int temp = sum;
+ sum += properties.mPageCount;
+ if (sum > position) {
+ return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
+ }
+ }
+ return null;
+ }
+
+ // Returns a keyboard from the view pager's page position.
+ public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
+ final Pair<Integer, Integer> categoryAndId =
+ getCategoryIdAndPageIdFromPagePosition(position);
+ if (categoryAndId != null) {
+ return getKeyboard(categoryAndId.first, categoryAndId.second);
+ }
+ return null;
+ }
+
+ private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) {
+ return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id;
+ }
+
+ public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) {
+ synchronized (mCategoryKeyboardMap) {
+ final Long categotyKeyboardMapKey = getCategoryKeyboardMapKey(categoryId, id);
+ if (mCategoryKeyboardMap.containsKey(categotyKeyboardMapKey)) {
+ return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
+ }
+
+ if (categoryId == EmojiCategory.ID_RECENTS) {
+ final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
+ mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
+ mMaxPageKeyCount, categoryId);
+ mCategoryKeyboardMap.put(categotyKeyboardMapKey, kbd);
+ return kbd;
+ }
+
+ final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
+ final Key[][] sortedKeys = sortKeysIntoPages(
+ keyboard.getSortedKeys(), mMaxPageKeyCount);
+ for (int pageId = 0; pageId < sortedKeys.length; ++pageId) {
+ final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
+ mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
+ mMaxPageKeyCount, categoryId);
+ for (final Key emojiKey : sortedKeys[pageId]) {
+ if (emojiKey == null) {
+ break;
+ }
+ tempKeyboard.addKeyLast(emojiKey);
+ }
+ mCategoryKeyboardMap.put(
+ getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
+ }
+ return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
+ }
+ }
+
+ public int getTotalPageCountOfAllCategories() {
+ int sum = 0;
+ for (CategoryProperties properties : mShownCategories) {
+ sum += properties.mPageCount;
+ }
+ return sum;
+ }
+
+ private static Comparator<Key> EMOJI_KEY_COMPARATOR = new Comparator<Key>() {
+ @Override
+ public int compare(final Key lhs, final Key rhs) {
+ final Rect lHitBox = lhs.getHitBox();
+ final Rect rHitBox = rhs.getHitBox();
+ if (lHitBox.top < rHitBox.top) {
+ return -1;
+ } else if (lHitBox.top > rHitBox.top) {
+ return 1;
+ }
+ if (lHitBox.left < rHitBox.left) {
+ return -1;
+ } else if (lHitBox.left > rHitBox.left) {
+ return 1;
+ }
+ if (lhs.getCode() == rhs.getCode()) {
+ return 0;
+ }
+ return lhs.getCode() < rhs.getCode() ? -1 : 1;
+ }
+ };
+
+ private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
+ final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
+ Collections.sort(keys, EMOJI_KEY_COMPARATOR);
+ final int pageCount = (keys.size() - 1) / maxPageCount + 1;
+ final Key[][] retval = new Key[pageCount][maxPageCount];
+ for (int i = 0; i < keys.size(); ++i) {
+ retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
+ }
+ return retval;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java
index d56a3cf25..74cfd9b4b 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategoryPageIndicatorView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.keyboard;
+package com.android.inputmethod.keyboard.emoji;
import com.android.inputmethod.latin.R;
@@ -24,8 +24,8 @@ import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.LinearLayout;
-public class EmojiCategoryPageIndicatorView extends LinearLayout {
- private static final float BOTTOM_MARGIN_RATIO = 0.66f;
+public final class EmojiCategoryPageIndicatorView extends LinearLayout {
+ private static final float BOTTOM_MARGIN_RATIO = 1.0f;
private final Paint mPaint = new Paint();
private int mCategoryPageSize = 0;
private int mCurrentCategoryPageId = 0;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java
index d57ea5a94..77c183a99 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.keyboard.internal;
+package com.android.inputmethod.keyboard.emoji;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.ResourceUtils;
@@ -24,7 +24,7 @@ import android.support.v4.view.ViewPager;
import android.widget.ImageView;
import android.widget.LinearLayout;
-public class EmojiLayoutParams {
+final class EmojiLayoutParams {
private static final int DEFAULT_KEYBOARD_ROWS = 4;
public final int mEmojiPagerHeight;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
index e175a051e..d14ffeef9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.keyboard.internal;
+package com.android.inputmethod.keyboard.emoji;
import android.content.Context;
import android.os.Handler;
@@ -26,15 +26,14 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.R;
/**
* This is an extended {@link KeyboardView} class that hosts an emoji page keyboard.
- * Multi-touch unsupported. No {@link PointerTracker}s. No gesture support.
+ * Multi-touch unsupported. No gesture support.
*/
// TODO: Implement key popup preview.
-public final class EmojiPageKeyboardView extends KeyboardView implements
+final class EmojiPageKeyboardView extends KeyboardView implements
GestureDetector.OnGestureListener {
private static final long KEY_PRESS_DELAY_TIME = 250; // msec
private static final long KEY_RELEASE_DELAY_TIME = 30; // msec
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java
new file mode 100644
index 000000000..52a4dde97
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.emoji;
+
+import android.support.v4.view.PagerAdapter;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+final class EmojiPalettesAdapter extends PagerAdapter {
+ private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
+ private static final boolean DEBUG_PAGER = false;
+
+ private final EmojiPageKeyboardView.OnKeyEventListener mListener;
+ private final DynamicGridKeyboard mRecentsKeyboard;
+ private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
+ CollectionUtils.newSparseArray();
+ private final EmojiCategory mEmojiCategory;
+ private int mActivePosition = 0;
+
+ public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
+ final EmojiPageKeyboardView.OnKeyEventListener listener) {
+ mEmojiCategory = emojiCategory;
+ mListener = listener;
+ mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
+ }
+
+ public void flushPendingRecentKeys() {
+ mRecentsKeyboard.flushPendingRecentKeys();
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void addRecentKey(final Key key) {
+ if (mEmojiCategory.isInRecentTab()) {
+ mRecentsKeyboard.addPendingKey(key);
+ return;
+ }
+ mRecentsKeyboard.addKeyFirst(key);
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void onPageScrolled() {
+ // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
+ // canceled.
+ final EmojiPageKeyboardView currentKeyboardView =
+ mActiveKeyboardViews.get(mActivePosition);
+ if (currentKeyboardView != null) {
+ currentKeyboardView.releaseCurrentKey();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mEmojiCategory.getTotalPageCountOfAllCategories();
+ }
+
+ @Override
+ public void setPrimaryItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (mActivePosition == position) {
+ return;
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.releaseCurrentKey();
+ oldKeyboardView.deallocateMemory();
+ }
+ mActivePosition = position;
+ }
+
+ @Override
+ public Object instantiateItem(final ViewGroup container, final int position) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "instantiate item: " + position);
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.deallocateMemory();
+ // This may be redundant but wanted to be safer..
+ mActiveKeyboardViews.remove(position);
+ }
+ final Keyboard keyboard =
+ mEmojiCategory.getKeyboardFromPagePosition(position);
+ final LayoutInflater inflater = LayoutInflater.from(container.getContext());
+ final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
+ R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
+ keyboardView.setKeyboard(keyboard);
+ keyboardView.setOnKeyEventListener(mListener);
+ container.addView(keyboardView);
+ mActiveKeyboardViews.put(position, keyboardView);
+ return keyboardView;
+ }
+
+ @Override
+ public boolean isViewFromObject(final View view, final Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void destroyItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
+ }
+ final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
+ if (keyboardView != null) {
+ keyboardView.deallocateMemory();
+ mActiveKeyboardViews.remove(position);
+ }
+ if (object instanceof View) {
+ container.removeView((View)object);
+ } else {
+ Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
index d8b5758a6..3813c578a 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
@@ -14,55 +14,44 @@
* limitations under the License.
*/
-package com.android.inputmethod.keyboard;
+package com.android.inputmethod.keyboard.emoji;
import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE;
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.Rect;
-import android.os.Build;
+import android.graphics.Typeface;
import android.os.CountDownTimer;
import android.preference.PreferenceManager;
-import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
-import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;
-import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard;
-import com.android.inputmethod.keyboard.internal.EmojiLayoutParams;
-import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView;
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.ResourceUtils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
@@ -79,17 +68,17 @@ import java.util.concurrent.TimeUnit;
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
EmojiPageKeyboardView.OnKeyEventListener {
- static final String TAG = EmojiPalettesView.class.getSimpleName();
- private static final boolean DEBUG_PAGER = false;
- private final int mKeyBackgroundId;
- private final int mEmojiFunctionalKeyBackgroundId;
+ private final int mFunctionalKeyBackgroundId;
+ private final int mSpacebarBackgroundId;
private final ColorStateList mTabLabelColor;
private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener;
private EmojiPalettesAdapter mEmojiPalettesAdapter;
private final EmojiLayoutParams mEmojiLayoutParams;
+ private ImageButton mDeleteKey;
private TextView mAlphabetKeyLeft;
private TextView mAlphabetKeyRight;
+ private ImageButton mSpacebar;
private TabHost mTabHost;
private ViewPager mEmojiPager;
private int mCurrentPagerPosition = 0;
@@ -97,317 +86,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
- private static final int CATEGORY_ID_UNSPECIFIED = -1;
- public static final int CATEGORY_ID_RECENTS = 0;
- public static final int CATEGORY_ID_PEOPLE = 1;
- public static final int CATEGORY_ID_OBJECTS = 2;
- public static final int CATEGORY_ID_NATURE = 3;
- public static final int CATEGORY_ID_PLACES = 4;
- public static final int CATEGORY_ID_SYMBOLS = 5;
- public static final int CATEGORY_ID_EMOTICONS = 6;
-
- private static class CategoryProperties {
- public int mCategoryId;
- public int mPageCount;
- public CategoryProperties(final int categoryId, final int pageCount) {
- mCategoryId = categoryId;
- mPageCount = pageCount;
- }
- }
-
- private static class EmojiCategory {
- private static final String[] sCategoryName = {
- "recents",
- "people",
- "objects",
- "nature",
- "places",
- "symbols",
- "emoticons" };
- private static final int[] sCategoryIcon = {
- R.drawable.ic_emoji_recent_light,
- R.drawable.ic_emoji_people_light,
- R.drawable.ic_emoji_objects_light,
- R.drawable.ic_emoji_nature_light,
- R.drawable.ic_emoji_places_light,
- R.drawable.ic_emoji_symbols_light,
- 0 };
- private static final String[] sCategoryLabel =
- { null, null, null, null, null, null, ":-)" };
- private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
- R.string.spoken_descrption_emoji_category_recents,
- R.string.spoken_descrption_emoji_category_people,
- R.string.spoken_descrption_emoji_category_objects,
- R.string.spoken_descrption_emoji_category_nature,
- R.string.spoken_descrption_emoji_category_places,
- R.string.spoken_descrption_emoji_category_symbols,
- R.string.spoken_descrption_emoji_category_emoticons };
- private static final int[] sCategoryElementId = {
- KeyboardId.ELEMENT_EMOJI_RECENTS,
- KeyboardId.ELEMENT_EMOJI_CATEGORY1,
- KeyboardId.ELEMENT_EMOJI_CATEGORY2,
- KeyboardId.ELEMENT_EMOJI_CATEGORY3,
- KeyboardId.ELEMENT_EMOJI_CATEGORY4,
- KeyboardId.ELEMENT_EMOJI_CATEGORY5,
- KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
- private final SharedPreferences mPrefs;
- private final Resources mRes;
- private final int mMaxPageKeyCount;
- private final KeyboardLayoutSet mLayoutSet;
- private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
- private final ArrayList<CategoryProperties> mShownCategories =
- CollectionUtils.newArrayList();
- private final ConcurrentHashMap<Long, DynamicGridKeyboard>
- mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
-
- private int mCurrentCategoryId = CATEGORY_ID_UNSPECIFIED;
- private int mCurrentCategoryPageId = 0;
-
- public EmojiCategory(final SharedPreferences prefs, final Resources res,
- final KeyboardLayoutSet layoutSet) {
- mPrefs = prefs;
- mRes = res;
- mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
- mLayoutSet = layoutSet;
- for (int i = 0; i < sCategoryName.length; ++i) {
- mCategoryNameToIdMap.put(sCategoryName[i], i);
- }
- addShownCategoryId(CATEGORY_ID_RECENTS);
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
- addShownCategoryId(CATEGORY_ID_PEOPLE);
- addShownCategoryId(CATEGORY_ID_OBJECTS);
- addShownCategoryId(CATEGORY_ID_NATURE);
- addShownCategoryId(CATEGORY_ID_PLACES);
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_PEOPLE);
- } else {
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_SYMBOLS);
- }
- addShownCategoryId(CATEGORY_ID_SYMBOLS);
- addShownCategoryId(CATEGORY_ID_EMOTICONS);
- getKeyboard(CATEGORY_ID_RECENTS, 0 /* cagetoryPageId */)
- .loadRecentKeys(mCategoryKeyboardMap.values());
- }
-
- private void addShownCategoryId(final int categoryId) {
- // Load a keyboard of categoryId
- getKeyboard(categoryId, 0 /* cagetoryPageId */);
- final CategoryProperties properties =
- new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
- mShownCategories.add(properties);
- }
-
- public String getCategoryName(final int categoryId, final int categoryPageId) {
- return sCategoryName[categoryId] + "-" + categoryPageId;
- }
-
- public int getCategoryId(final String name) {
- final String[] strings = name.split("-");
- return mCategoryNameToIdMap.get(strings[0]);
- }
-
- public int getCategoryIcon(final int categoryId) {
- return sCategoryIcon[categoryId];
- }
-
- public String getCategoryLabel(final int categoryId) {
- return sCategoryLabel[categoryId];
- }
-
- public String getAccessibilityDescription(final int categoryId) {
- return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
- }
-
- public ArrayList<CategoryProperties> getShownCategories() {
- return mShownCategories;
- }
-
- public int getCurrentCategoryId() {
- return mCurrentCategoryId;
- }
-
- public int getCurrentCategoryPageSize() {
- return getCategoryPageSize(mCurrentCategoryId);
- }
-
- public int getCategoryPageSize(final int categoryId) {
- for (final CategoryProperties prop : mShownCategories) {
- if (prop.mCategoryId == categoryId) {
- return prop.mPageCount;
- }
- }
- Log.w(TAG, "Invalid category id: " + categoryId);
- // Should not reach here.
- return 0;
- }
-
- public void setCurrentCategoryId(final int categoryId) {
- mCurrentCategoryId = categoryId;
- Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
- }
-
- public void setCurrentCategoryPageId(final int id) {
- mCurrentCategoryPageId = id;
- }
-
- public int getCurrentCategoryPageId() {
- return mCurrentCategoryPageId;
- }
-
- public void saveLastTypedCategoryPage() {
- Settings.writeLastTypedEmojiCategoryPageId(
- mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
- }
-
- public boolean isInRecentTab() {
- return mCurrentCategoryId == CATEGORY_ID_RECENTS;
- }
-
- public int getTabIdFromCategoryId(final int categoryId) {
- for (int i = 0; i < mShownCategories.size(); ++i) {
- if (mShownCategories.get(i).mCategoryId == categoryId) {
- return i;
- }
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- // Returns the view pager's page position for the categoryId
- public int getPageIdFromCategoryId(final int categoryId) {
- final int lastSavedCategoryPageId =
- Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
- int sum = 0;
- for (int i = 0; i < mShownCategories.size(); ++i) {
- final CategoryProperties props = mShownCategories.get(i);
- if (props.mCategoryId == categoryId) {
- return sum + lastSavedCategoryPageId;
- }
- sum += props.mPageCount;
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- public int getRecentTabId() {
- return getTabIdFromCategoryId(CATEGORY_ID_RECENTS);
- }
-
- private int getCategoryPageCount(final int categoryId) {
- final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
- return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
- }
-
- // Returns a pair of the category id and the category page id from the view pager's page
- // position. The category page id is numbered in each category. And the view page position
- // is the position of the current shown page in the view pager which contains all pages of
- // all categories.
- public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(final int position) {
- int sum = 0;
- for (final CategoryProperties properties : mShownCategories) {
- final int temp = sum;
- sum += properties.mPageCount;
- if (sum > position) {
- return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
- }
- }
- return null;
- }
-
- // Returns a keyboard from the view pager's page position.
- public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
- final Pair<Integer, Integer> categoryAndId =
- getCategoryIdAndPageIdFromPagePosition(position);
- if (categoryAndId != null) {
- return getKeyboard(categoryAndId.first, categoryAndId.second);
- }
- return null;
- }
-
- private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) {
- return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id;
- }
-
- public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) {
- synchronized (mCategoryKeyboardMap) {
- final Long categotyKeyboardMapKey = getCategoryKeyboardMapKey(categoryId, id);
- if (mCategoryKeyboardMap.containsKey(categotyKeyboardMapKey)) {
- return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
- }
-
- if (categoryId == CATEGORY_ID_RECENTS) {
- final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
- mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
- mMaxPageKeyCount, categoryId);
- mCategoryKeyboardMap.put(categotyKeyboardMapKey, kbd);
- return kbd;
- }
-
- final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
- final Key[][] sortedKeys = sortKeysIntoPages(
- keyboard.getSortedKeys(), mMaxPageKeyCount);
- for (int pageId = 0; pageId < sortedKeys.length; ++pageId) {
- final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
- mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
- mMaxPageKeyCount, categoryId);
- for (final Key emojiKey : sortedKeys[pageId]) {
- if (emojiKey == null) {
- break;
- }
- tempKeyboard.addKeyLast(emojiKey);
- }
- mCategoryKeyboardMap.put(
- getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
- }
- return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
- }
- }
-
- public int getTotalPageCountOfAllCategories() {
- int sum = 0;
- for (CategoryProperties properties : mShownCategories) {
- sum += properties.mPageCount;
- }
- return sum;
- }
-
- private static Comparator<Key> EMOJI_KEY_COMPARATOR = new Comparator<Key>() {
- @Override
- public int compare(final Key lhs, final Key rhs) {
- final Rect lHitBox = lhs.getHitBox();
- final Rect rHitBox = rhs.getHitBox();
- if (lHitBox.top < rHitBox.top) {
- return -1;
- } else if (lHitBox.top > rHitBox.top) {
- return 1;
- }
- if (lHitBox.left < rHitBox.left) {
- return -1;
- } else if (lHitBox.left > rHitBox.left) {
- return 1;
- }
- if (lhs.getCode() == rhs.getCode()) {
- return 0;
- }
- return lhs.getCode() < rhs.getCode() ? -1 : 1;
- }
- };
-
- private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
- final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
- Collections.sort(keys, EMOJI_KEY_COMPARATOR);
- final int pageCount = (keys.size() - 1) / maxPageCount + 1;
- final Key[][] retval = new Key[pageCount][maxPageCount];
- for (int i = 0; i < keys.size(); ++i) {
- retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
- }
- return retval;
- }
- }
-
private final EmojiCategory mEmojiCategory;
public EmojiPalettesView(final Context context, final AttributeSet attrs) {
@@ -418,10 +96,12 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
super(context, attrs, defStyle);
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
- mKeyBackgroundId = keyboardViewAttr.getResourceId(
+ final int keyBackgroundId = keyboardViewAttr.getResourceId(
R.styleable.KeyboardView_keyBackground, 0);
- mEmojiFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
- R.styleable.KeyboardView_keyBackgroundEmojiFunctional, 0);
+ mFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
+ R.styleable.KeyboardView_functionalKeyBackground, keyBackgroundId);
+ mSpacebarBackgroundId = keyboardViewAttr.getResourceId(
+ R.styleable.KeyboardView_spacebarBackground, keyBackgroundId);
keyboardViewAttr.recycle();
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
@@ -470,8 +150,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
final TextView textView = (TextView)LayoutInflater.from(getContext()).inflate(
R.layout.emoji_keyboard_tab_label, null);
textView.setText(mEmojiCategory.getCategoryLabel(categoryId));
+ textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setContentDescription(mEmojiCategory.getAccessibilityDescription(categoryId));
- textView.setTextColor(mTabLabelColor);
+ if (mTabLabelColor != null) {
+ textView.setTextColor(mTabLabelColor);
+ }
tspec.setIndicator(textView);
}
host.addTab(tspec);
@@ -481,7 +164,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
protected void onFinishInflate() {
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
mTabHost.setup();
- for (final CategoryProperties properties : mEmojiCategory.getShownCategories()) {
+ for (final EmojiCategory.CategoryProperties properties
+ : mEmojiCategory.getShownCategories()) {
addTab(mTabHost, properties.mCategoryId);
}
mTabHost.setOnTabChangedListener(this);
@@ -506,9 +190,10 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
mEmojiLayoutParams.setActionBarProperties(actionBar);
// deleteKey depends only on OnTouchListener.
- final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete);
- deleteKey.setTag(Constants.CODE_DELETE);
- deleteKey.setOnTouchListener(mDeleteKeyOnTouchListener);
+ mDeleteKey = (ImageButton)findViewById(R.id.emoji_keyboard_delete);
+ mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId);
+ mDeleteKey.setTag(Constants.CODE_DELETE);
+ mDeleteKey.setOnTouchListener(mDeleteKeyOnTouchListener);
// {@link #mAlphabetKeyLeft}, {@link #mAlphabetKeyRight, and spaceKey depend on
// {@link View.OnClickListener} as well as {@link View.OnTouchListener}.
@@ -518,21 +203,21 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
// The text on alphabet keys are set at
// {@link #startEmojiPalettes(String,int,float,Typeface)}.
mAlphabetKeyLeft = (TextView)findViewById(R.id.emoji_keyboard_alphabet_left);
- mAlphabetKeyLeft.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ mAlphabetKeyLeft.setBackgroundResource(mFunctionalKeyBackgroundId);
mAlphabetKeyLeft.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
mAlphabetKeyLeft.setOnTouchListener(this);
mAlphabetKeyLeft.setOnClickListener(this);
mAlphabetKeyRight = (TextView)findViewById(R.id.emoji_keyboard_alphabet_right);
- mAlphabetKeyRight.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ mAlphabetKeyRight.setBackgroundResource(mFunctionalKeyBackgroundId);
mAlphabetKeyRight.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
mAlphabetKeyRight.setOnTouchListener(this);
mAlphabetKeyRight.setOnClickListener(this);
- final ImageView spaceKey = (ImageView)findViewById(R.id.emoji_keyboard_space);
- spaceKey.setBackgroundResource(mKeyBackgroundId);
- spaceKey.setTag(Constants.CODE_SPACE);
- spaceKey.setOnTouchListener(this);
- spaceKey.setOnClickListener(this);
- mEmojiLayoutParams.setKeyProperties(spaceKey);
+ mSpacebar = (ImageButton)findViewById(R.id.emoji_keyboard_space);
+ mSpacebar.setBackgroundResource(mSpacebarBackgroundId);
+ mSpacebar.setTag(Constants.CODE_SPACE);
+ mSpacebar.setOnTouchListener(this);
+ mSpacebar.setOnClickListener(this);
+ mEmojiLayoutParams.setKeyProperties(mSpacebar);
}
@Override
@@ -631,7 +316,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
/**
* Called from {@link EmojiPageKeyboardView} through
- * {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
+ * {@link com.android.inputmethod.keyboard.emoji.EmojiPageKeyboardView.OnKeyEventListener}
* interface to handle touch events from non-View-based elements such as Emoji buttons.
*/
@Override
@@ -642,7 +327,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
/**
* Called from {@link EmojiPageKeyboardView} through
- * {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
+ * {@link com.android.inputmethod.keyboard.emoji.EmojiPageKeyboardView.OnKeyEventListener}
* interface to handle touch events from non-View-based elements such as Emoji buttons.
*/
@Override
@@ -674,10 +359,9 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
public void startEmojiPalettes(final String switchToAlphaLabel,
- final KeyVisualAttributes keyVisualAttr) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition);
- }
+ final KeyVisualAttributes keyVisualAttr, final KeyboardIconsSet iconSet) {
+ mDeleteKey.setImageDrawable(iconSet.getIconDrawable(KeyboardIconsSet.NAME_DELETE_KEY));
+ mSpacebar.setImageDrawable(iconSet.getIconDrawable(KeyboardIconsSet.NAME_SPACE_KEY));
final KeyDrawParams params = new KeyDrawParams();
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
@@ -687,9 +371,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
public void stopEmojiPalettes() {
- if (DEBUG_PAGER) {
- Log.d(TAG, "deallocate emoji palettes memory");
- }
mEmojiPalettesAdapter.flushPendingRecentKeys();
mEmojiPager.setAdapter(null);
}
@@ -714,7 +395,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
return;
}
- if (oldCategoryId == CATEGORY_ID_RECENTS) {
+ if (oldCategoryId == EmojiCategory.ID_RECENTS) {
// Needs to save pending updates for recent keys when we get out of the recents
// category because we don't want to move the recent emojis around while the user
// is in the recents category.
@@ -733,124 +414,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
}
- private static class EmojiPalettesAdapter extends PagerAdapter {
- private final EmojiPageKeyboardView.OnKeyEventListener mListener;
- private final DynamicGridKeyboard mRecentsKeyboard;
- private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
- CollectionUtils.newSparseArray();
- private final EmojiCategory mEmojiCategory;
- private int mActivePosition = 0;
-
- public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
- final EmojiPageKeyboardView.OnKeyEventListener listener) {
- mEmojiCategory = emojiCategory;
- mListener = listener;
- mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_ID_RECENTS, 0);
- }
-
- public void flushPendingRecentKeys() {
- mRecentsKeyboard.flushPendingRecentKeys();
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void addRecentKey(final Key key) {
- if (mEmojiCategory.isInRecentTab()) {
- mRecentsKeyboard.addPendingKey(key);
- return;
- }
- mRecentsKeyboard.addKeyFirst(key);
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void onPageScrolled() {
- // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
- // canceled.
- final EmojiPageKeyboardView currentKeyboardView =
- mActiveKeyboardViews.get(mActivePosition);
- if (currentKeyboardView != null) {
- currentKeyboardView.releaseCurrentKey();
- }
- }
-
- @Override
- public int getCount() {
- return mEmojiCategory.getTotalPageCountOfAllCategories();
- }
-
- @Override
- public void setPrimaryItem(final ViewGroup container, final int position,
- final Object object) {
- if (mActivePosition == position) {
- return;
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
- if (oldKeyboardView != null) {
- oldKeyboardView.releaseCurrentKey();
- oldKeyboardView.deallocateMemory();
- }
- mActivePosition = position;
- }
-
- @Override
- public Object instantiateItem(final ViewGroup container, final int position) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "instantiate item: " + position);
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
- if (oldKeyboardView != null) {
- oldKeyboardView.deallocateMemory();
- // This may be redundant but wanted to be safer..
- mActiveKeyboardViews.remove(position);
- }
- final Keyboard keyboard =
- mEmojiCategory.getKeyboardFromPagePosition(position);
- final LayoutInflater inflater = LayoutInflater.from(container.getContext());
- final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
- R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
- keyboardView.setKeyboard(keyboard);
- keyboardView.setOnKeyEventListener(mListener);
- container.addView(keyboardView);
- mActiveKeyboardViews.put(position, keyboardView);
- return keyboardView;
- }
-
- @Override
- public boolean isViewFromObject(final View view, final Object object) {
- return view == object;
- }
-
- @Override
- public void destroyItem(final ViewGroup container, final int position,
- final Object object) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
- }
- final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
- if (keyboardView != null) {
- keyboardView.deallocateMemory();
- mActiveKeyboardViews.remove(position);
- }
- if (object instanceof View) {
- container.removeView((View)object);
- } else {
- Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
- }
- }
- }
-
private static class DeleteKeyOnTouchListener implements OnTouchListener {
- private static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
- private final int mDeleteKeyPressedBackgroundColor;
- private final long mKeyRepeatStartTimeout;
- private final long mKeyRepeatInterval;
+ static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
+ final int mDeleteKeyPressedBackgroundColor;
+ final long mKeyRepeatStartTimeout;
+ final long mKeyRepeatInterval;
public DeleteKeyOnTouchListener(Context context) {
final Resources res = context.getResources();
@@ -953,7 +521,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
// Called by {@link #mTimer} in the UI thread as an auto key-repeat signal.
- private void onKeyRepeat() {
+ void onKeyRepeat() {
switch (mState) {
case KEY_REPEAT_STATE_INITIALIZED:
// Basically this should not happen.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 65d6a5633..b5a94807e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -138,6 +138,10 @@ public final class KeyboardIconsSet {
throw new RuntimeException("unknown icon name: " + name);
}
+ public Drawable getIconDrawable(final String name) {
+ return getIconDrawable(getIconId(name));
+ }
+
public Drawable getIconDrawable(final int iconId) {
if (isValidIconId(iconId)) {
return mIcons[iconId];
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 6818c156e..e323f0ab2 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -607,6 +607,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
Log.d(TAG, "Dump dictionary: " + mDictName);
try {
final DictionaryHeader header = mBinaryDictionary.getHeader();
+ Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
Log.d(TAG, CombinedFormatUtils.formatAttributeMap(
header.mDictionaryOptions.mAttributes));
} catch (final UnsupportedFormatException e) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7dc566a14..8a2ed1088 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -540,18 +540,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
refreshPersonalizationDictionarySession();
}
- private DistracterFilter createDistracterFilter() {
- final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
- // TODO: Create Keyboard when mainKeyboardView is null.
- // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
- // spellchecker's logic.
- final Keyboard keyboard = (mainKeyboardView != null) ?
- mainKeyboardView.getKeyboard() : null;
- final DistracterFilter distracterFilter = new DistracterFilter(mInputLogic.mSuggest,
- keyboard);
- return distracterFilter;
- }
-
private void refreshPersonalizationDictionarySession() {
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
mInputLogic.mSuggest.mDictionaryFacilitator;
@@ -1755,6 +1743,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.mSuggest.mDictionaryFacilitator.clearPersonalizationDictionary();
}
+ @UsedForTesting
+ /* package for test */ DistracterFilter createDistracterFilter() {
+ return DistracterFilter.createDistracterFilter(mInputLogic.mSuggest, mKeyboardSwitcher);
+ }
+
public void dumpDictionaryForDebug(final String dictName) {
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
mInputLogic.mSuggest.mDictionaryFacilitator;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index cdee496a8..ac6972928 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -80,7 +80,7 @@ public final class WordComposer {
private boolean mIsFirstCharCapitalized;
public WordComposer() {
- mCombinerChain = new CombinerChain();
+ mCombinerChain = new CombinerChain("");
mEvents = CollectionUtils.newArrayList();
mAutoCorrection = null;
mIsResumed = false;
@@ -92,18 +92,17 @@ public final class WordComposer {
}
/**
- * Restart input with a new combining spec.
+ * Restart the combiners, possibly with a new spec.
* @param combiningSpec The spec string for combining. This is found in the extra value.
*/
- public void restart(final String combiningSpec) {
+ public void restartCombining(final String combiningSpec) {
final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec;
- if (nonNullCombiningSpec.equals(mCombiningSpec)) {
- mCombinerChain.reset();
- } else {
- mCombinerChain = new CombinerChain(CombinerChain.createCombiners(nonNullCombiningSpec));
+ if (!nonNullCombiningSpec.equals(mCombiningSpec)) {
+ mCombinerChain = new CombinerChain(
+ mCombinerChain.getComposingWordWithCombiningFeedback().toString(),
+ CombinerChain.createCombiners(nonNullCombiningSpec));
mCombiningSpec = nonNullCombiningSpec;
}
- reset();
}
/**
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 8b795b82f..ea58abc14 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -127,7 +127,7 @@ public final class InputLogic {
public void startInput(final boolean restarting, final EditorInfo editorInfo,
final String combiningSpec) {
mEnteredText = null;
- mWordComposer.restart(combiningSpec);
+ mWordComposer.restartCombining(combiningSpec);
resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
mSpaceState = SpaceState.NONE;
@@ -150,7 +150,7 @@ public final class InputLogic {
* @param combiningSpec the spec string for the combining rules
*/
public void onSubtypeChanged(final String combiningSpec) {
- mWordComposer.restart(combiningSpec);
+ mWordComposer.restartCombining(combiningSpec);
}
/**
@@ -936,7 +936,11 @@ public final class InputLogic {
} else {
mWordComposer.processEvent(inputTransaction.mEvent);
}
- mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ if (mWordComposer.isComposingWord()) {
+ mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ } else {
+ mConnection.commitText("", 1);
+ }
inputTransaction.setRequiresUpdateSuggestions();
} else {
if (mLastComposedWord.canRevertCommit()) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index d4f7f36da..619804afa 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -124,9 +124,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mImportantNoticeStrip.setVisibility(INVISIBLE);
}
- public void showImportantNoticeStrip() {
+ public void showImportantNoticeStrip(final boolean enableVoiceKey) {
mSuggestionsStrip.setVisibility(INVISIBLE);
- mVoiceKey.setVisibility(INVISIBLE);
+ mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
mAddToDictionaryStrip.setVisibility(INVISIBLE);
mImportantNoticeStrip.setVisibility(VISIBLE);
}
@@ -274,7 +274,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
dismissMoreSuggestionsPanel();
}
mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle);
- mStripVisibilityGroup.showImportantNoticeStrip();
+ mStripVisibilityGroup.showImportantNoticeStrip(isVoiceKeyEnabled());
mImportantNoticeStrip.setOnClickListener(this);
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
index 48e43d6ef..55cbf79b3 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
@@ -17,21 +17,35 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Suggest;
+import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.WordComposer;
/**
- * This class is used to prevent distracters/misspellings being added to personalization
+ * This class is used to prevent distracters being added to personalization
* or user history dictionaries
*/
public class DistracterFilter {
private final Suggest mSuggest;
private final Keyboard mKeyboard;
+ // If the score of the top suggestion exceeds this value, the tested word (e.g.,
+ // an OOV, a misspelling, or an in-vocabulary word) would be considered as a distracter to
+ // words in dictionary. The greater the threshold is, the less likely the tested word would
+ // become a distracter, which means the tested word will be more likely to be added to
+ // the dictionary.
+ private static final float DISTRACTER_WORD_SCORE_THRESHOLD = 2.0f;
+
/**
* Create a DistracterFilter instance.
*
* @param suggest an instance of Suggest which will be used to obtain a list of suggestions
- * for a potential distracter/misspelling
+ * for a potential distracter
* @param keyboard the keyboard that is currently being used. This information is needed
* when calling mSuggest.getSuggestedWords(...) to obtain a list of suggestions.
*/
@@ -40,9 +54,79 @@ public class DistracterFilter {
mKeyboard = keyboard;
}
- public boolean isDistracterToWordsInDictionaries(final String prevWord,
- final String targetWord) {
- // TODO: to be implemented
+ public static DistracterFilter createDistracterFilter(final Suggest suggest,
+ final KeyboardSwitcher keyboardSwitcher) {
+ final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView();
+ // TODO: Create Keyboard when mainKeyboardView is null.
+ // TODO: Figure out the most reasonable keyboard for the filter. Refer to the
+ // spellchecker's logic.
+ final Keyboard keyboard = (mainKeyboardView != null) ?
+ mainKeyboardView.getKeyboard() : null;
+ final DistracterFilter distracterFilter = new DistracterFilter(suggest, keyboard);
+ return distracterFilter;
+ }
+
+ private static boolean suggestionExceedsDistracterThreshold(
+ final SuggestedWordInfo suggestion, final String consideredWord,
+ final float distracterThreshold) {
+ if (null != suggestion) {
+ final int suggestionScore = suggestion.mScore;
+ final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
+ consideredWord, suggestion.mWord, suggestionScore);
+ if (normalizedScore > distracterThreshold) {
+ return true;
+ }
+ }
return false;
}
+
+ /**
+ * Determine whether a word is a distracter to words in dictionaries.
+ *
+ * @param prevWord the previous word, or null if none.
+ * @param testedWord the word that will be tested to see whether it is a distracter to words
+ * in dictionaries.
+ * @return true if testedWord is a distracter, otherwise false.
+ */
+ public boolean isDistracterToWordsInDictionaries(final String prevWord,
+ final String testedWord) {
+ if (mSuggest == null) {
+ return false;
+ }
+
+ final WordComposer composer = new WordComposer();
+ final int[] codePoints = StringUtils.toCodePointArray(testedWord);
+ final int[] coordinates;
+ if (null == mKeyboard) {
+ coordinates = CoordinateUtils.newCoordinateArray(codePoints.length,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
+ } else {
+ coordinates = mKeyboard.getCoordinates(codePoints);
+ }
+ composer.setComposingWord(codePoints, coordinates, prevWord);
+
+ final int trailingSingleQuotesCount = composer.trailingSingleQuotesCount();
+ final String consideredWord = trailingSingleQuotesCount > 0 ? testedWord.substring(0,
+ testedWord.length() - trailingSingleQuotesCount) : testedWord;
+ final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>();
+ final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
+ @Override
+ public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
+ if (suggestedWords != null && suggestedWords.size() > 1) {
+ // The suggestedWordInfo at 0 is the typed word. The 1st suggestion from
+ // the decoder is at index 1.
+ final SuggestedWordInfo firstSuggestion = suggestedWords.getInfo(1);
+ final boolean hasStrongDistractor = suggestionExceedsDistracterThreshold(
+ firstSuggestion, consideredWord, DISTRACTER_WORD_SCORE_THRESHOLD);
+ holder.set(hasStrongDistractor);
+ }
+ }
+ };
+ mSuggest.getSuggestedWords(composer, prevWord, mKeyboard.getProximityInfo(),
+ true /* blockOffensiveWords */, true /* isCorrectionEnbaled */,
+ null /* additionalFeaturesOptions */, 0 /* sessionId */,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER, callback);
+
+ return holder.get(false /* defaultValue */, Constants.GET_SUGGESTED_WORDS_TIMEOUT);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
index 55061f45f..74e7db901 100644
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
@@ -129,6 +129,9 @@ public final class LanguageModelParam {
if (locale == null) {
return null;
}
+ // TODO: Though targetWord is an IV (in-vocabulary) word, we should still apply
+ // distracterFilter in the following code. If targetWord is a distracter,
+ // it should be filtered out.
if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) {
return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
true /* isValidWord */, locale);
diff --git a/native/jni/CleanupNativeFileList.mk b/native/jni/CleanupNativeFileList.mk
index 1738f8c58..eed6f1e63 100644
--- a/native/jni/CleanupNativeFileList.mk
+++ b/native/jni/CleanupNativeFileList.mk
@@ -13,6 +13,7 @@
# limitations under the License.
LATIN_IME_CORE_SRC_FILES :=
+LATIN_IME_CORE_SRC_FILES_BACKWARD_V401 :=
LATIN_IME_CORE_TEST_FILES :=
LATIN_IME_JNI_SRC_FILES :=
LATIN_IME_SRC_DIR :=
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index 6ccfec911..cb337e65c 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -95,9 +95,31 @@ LATIN_IME_CORE_SRC_FILES := \
$(addprefix utils/, \
autocorrection_threshold_utils.cpp \
char_utils.cpp \
+ jni_data_utils.cpp \
log_utils.cpp \
time_keeper.cpp)
+LATIN_IME_CORE_SRC_FILES_BACKWARD_V401 := \
+ $(addprefix suggest/policyimpl/dictionary/structure/backward/v401/, \
+ ver4_dict_buffers.cpp \
+ ver4_dict_constants.cpp \
+ ver4_patricia_trie_node_reader.cpp \
+ ver4_patricia_trie_node_writer.cpp \
+ ver4_patricia_trie_policy.cpp \
+ ver4_patricia_trie_reading_utils.cpp \
+ ver4_patricia_trie_writing_helper.cpp \
+ ver4_pt_node_array_reader.cpp) \
+ $(addprefix suggest/policyimpl/dictionary/structure/backward/v401/content/, \
+ bigram_dict_content.cpp \
+ probability_dict_content.cpp \
+ shortcut_dict_content.cpp \
+ sparse_table_dict_content.cpp \
+ terminal_position_lookup_table.cpp) \
+ $(addprefix suggest/policyimpl/dictionary/structure/backward/v401/bigram/, \
+ ver4_bigram_list_policy.cpp)
+
+LATIN_IME_CORE_SRC_FILES += $(LATIN_IME_CORE_SRC_FILES_BACKWARD_V401)
+
LATIN_IME_CORE_TEST_FILES := \
defines_test.cpp \
suggest/core/layout/normal_distribution_2d_test.cpp \
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index a55b2da96..18b78c4df 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -136,10 +136,9 @@ static void latinime_BinaryDictionary_getHeaderInfo(JNIEnv *env, jclass clazz, j
if (!dictionary) return;
const DictionaryHeaderStructurePolicy *const headerPolicy =
dictionary->getDictionaryStructurePolicy()->getHeaderStructurePolicy();
- const int headerSize = headerPolicy->getSize();
- env->SetIntArrayRegion(outHeaderSize, 0 /* start */, 1 /* len */, &headerSize);
- const int formatVersion = headerPolicy->getFormatVersionNumber();
- env->SetIntArrayRegion(outFormatVersion, 0 /* start */, 1 /* len */, &formatVersion);
+ JniDataUtils::putIntToArray(env, outHeaderSize, 0 /* index */, headerPolicy->getSize());
+ JniDataUtils::putIntToArray(env, outFormatVersion, 0 /* index */,
+ headerPolicy->getFormatVersionNumber());
// Output attribute map
jclass arrayListClass = env->FindClass("java/util/ArrayList");
jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
@@ -149,14 +148,16 @@ static void latinime_BinaryDictionary_getHeaderInfo(JNIEnv *env, jclass clazz, j
it != attributeMap->end(); ++it) {
// Output key
jintArray keyCodePointArray = env->NewIntArray(it->first.size());
- env->SetIntArrayRegion(
- keyCodePointArray, 0 /* start */, it->first.size(), &it->first.at(0));
+ JniDataUtils::outputCodePoints(env, keyCodePointArray, 0 /* start */,
+ it->first.size(), it->first.data(), it->first.size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outAttributeKeys, addMethodId, keyCodePointArray);
env->DeleteLocalRef(keyCodePointArray);
// Output value
jintArray valueCodePointArray = env->NewIntArray(it->second.size());
- env->SetIntArrayRegion(
- valueCodePointArray, 0 /* start */, it->second.size(), &it->second.at(0));
+ JniDataUtils::outputCodePoints(env, valueCodePointArray, 0 /* start */,
+ it->second.size(), it->second.data(), it->second.size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outAttributeValues, addMethodId, valueCodePointArray);
env->DeleteLocalRef(valueCodePointArray);
}
@@ -182,8 +183,7 @@ static void latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz,
jfloatArray inOutLanguageWeight) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
// Assign 0 to outSuggestionCount here in case of returning earlier in this method.
- int count = 0;
- env->SetIntArrayRegion(outSuggestionCount, 0, 1 /* len */, &count);
+ JniDataUtils::putIntToArray(env, outSuggestionCount, 0 /* index */, 0);
if (!dictionary) {
return;
}
@@ -300,7 +300,9 @@ static jint latinime_BinaryDictionary_getNextWord(JNIEnv *env, jclass clazz,
int wordCodePoints[outCodePointsLength];
memset(wordCodePoints, 0, sizeof(wordCodePoints));
const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints);
- env->SetIntArrayRegion(outCodePoints, 0, outCodePointsLength, wordCodePoints);
+ JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+ MAX_WORD_LENGTH /* maxLength */, wordCodePoints, outCodePointsLength,
+ false /* needsNullTermination */);
return nextToken;
}
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
index 95608dcf8..6f5f808f8 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
@@ -16,14 +16,17 @@
#include "suggest/core/dictionary/property/word_property.h"
+#include "utils/jni_data_utils.h"
+
namespace latinime {
void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
jobject outBigramProbabilities, jobject outShortcutTargets,
jobject outShortcutProbabilities) const {
- env->SetIntArrayRegion(outCodePoints, 0 /* start */, mCodePoints.size(), &mCodePoints[0]);
-
+ JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+ MAX_WORD_LENGTH /* maxLength */, mCodePoints.data(), mCodePoints.size(),
+ false /* needsNullTermination */);
jboolean flags[] = {mUnigramProperty.isNotAWord(), mUnigramProperty.isBlacklisted(),
!mBigrams.empty(), mUnigramProperty.hasShortcuts()};
env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
@@ -41,8 +44,9 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
for (const auto &bigramProperty : mBigrams) {
const std::vector<int> *const word1CodePoints = bigramProperty.getTargetCodePoints();
jintArray bigramWord1CodePointArray = env->NewIntArray(word1CodePoints->size());
- env->SetIntArrayRegion(bigramWord1CodePointArray, 0 /* start */,
- word1CodePoints->size(), word1CodePoints->data());
+ JniDataUtils::outputCodePoints(env, bigramWord1CodePointArray, 0 /* start */,
+ word1CodePoints->size(), word1CodePoints->data(), word1CodePoints->size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outBigramTargets, addMethodId, bigramWord1CodePointArray);
env->DeleteLocalRef(bigramWord1CodePointArray);
@@ -62,6 +66,9 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
targetCodePoints->size(), targetCodePoints->data());
+ JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
+ targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
+ false /* needsNullTermination */);
env->CallBooleanMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
env->DeleteLocalRef(shortcutTargetCodePointArray);
jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
diff --git a/native/jni/src/suggest/core/result/suggestion_results.cpp b/native/jni/src/suggest/core/result/suggestion_results.cpp
index 088a55f6f..4c10bd08a 100644
--- a/native/jni/src/suggest/core/result/suggestion_results.cpp
+++ b/native/jni/src/suggest/core/result/suggestion_results.cpp
@@ -16,6 +16,8 @@
#include "suggest/core/result/suggestion_results.h"
+#include "utils/jni_data_utils.h"
+
namespace latinime {
void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCount,
@@ -27,31 +29,22 @@ void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCo
const SuggestedWord &suggestedWord = mSuggestedWords.top();
suggestedWord.getCodePointCount();
const int start = outputIndex * MAX_WORD_LENGTH;
- env->SetIntArrayRegion(outputCodePointsArray, start, suggestedWord.getCodePointCount(),
- suggestedWord.getCodePoint());
- if (suggestedWord.getCodePointCount() < MAX_WORD_LENGTH) {
- const int terminal = 0;
- env->SetIntArrayRegion(outputCodePointsArray, start + suggestedWord.getCodePointCount(),
- 1 /* len */, &terminal);
- }
- const int score = suggestedWord.getScore();
- env->SetIntArrayRegion(outScoresArray, outputIndex, 1 /* len */, &score);
- const int indexToPartialCommit = suggestedWord.getIndexToPartialCommit();
- env->SetIntArrayRegion(outSpaceIndicesArray, outputIndex, 1 /* len */,
- &indexToPartialCommit);
- const int type = suggestedWord.getType();
- env->SetIntArrayRegion(outTypesArray, outputIndex, 1 /* len */, &type);
+ JniDataUtils::outputCodePoints(env, outputCodePointsArray, start,
+ MAX_WORD_LENGTH /* maxLength */, suggestedWord.getCodePoint(),
+ suggestedWord.getCodePointCount(), true /* needsNullTermination */);
+ JniDataUtils::putIntToArray(env, outScoresArray, outputIndex, suggestedWord.getScore());
+ JniDataUtils::putIntToArray(env, outSpaceIndicesArray, outputIndex,
+ suggestedWord.getIndexToPartialCommit());
+ JniDataUtils::putIntToArray(env, outTypesArray, outputIndex, suggestedWord.getType());
if (mSuggestedWords.size() == 1) {
- const int autoCommitFirstWordConfidence =
- suggestedWord.getAutoCommitFirstWordConfidence();
- env->SetIntArrayRegion(outAutoCommitFirstWordConfidenceArray, 0 /* start */,
- 1 /* len */, &autoCommitFirstWordConfidence);
+ JniDataUtils::putIntToArray(env, outAutoCommitFirstWordConfidenceArray, 0 /* index */,
+ suggestedWord.getAutoCommitFirstWordConfidence());
}
++outputIndex;
mSuggestedWords.pop();
}
- env->SetIntArrayRegion(outSuggestionCount, 0 /* start */, 1 /* len */, &outputIndex);
- env->SetFloatArrayRegion(outLanguageWeight, 0 /* start */, 1 /* len */, &mLanguageWeight);
+ JniDataUtils::putIntToArray(env, outSuggestionCount, 0 /* index */, outputIndex);
+ JniDataUtils::putFloatToArray(env, outLanguageWeight, 0 /* index */, mLanguageWeight);
}
void SuggestionResults::addPrediction(const int *const codePoints, const int codePointCount,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/Readme.txt b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/Readme.txt
new file mode 100644
index 000000000..9e29e836c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/Readme.txt
@@ -0,0 +1 @@
+Files under this directory have been auto generated.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.cpp
new file mode 100644
index 000000000..7ad072f09
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.cpp
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h"
+
+#include "suggest/core/dictionary/property/bigram_property.h"
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability,
+ bool *const outHasNext, int *const bigramEntryPos) const {
+ const BigramEntry bigramEntry =
+ mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos);
+ if (outBigramPos) {
+ // Lookup target PtNode position.
+ *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
+ bigramEntry.getTargetTerminalId());
+ }
+ if (outProbability) {
+ if (bigramEntry.hasHistoricalInfo()) {
+ *outProbability =
+ ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(),
+ mHeaderPolicy);
+ } else {
+ *outProbability = bigramEntry.getProbability();
+ }
+ }
+ if (outHasNext) {
+ *outHasNext = bigramEntry.hasNext();
+ }
+}
+
+bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
+ // 1. The word has no bigrams yet.
+ // 2. The word has bigrams, and there is the target in the list.
+ // 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
+ // 4. The word has bigrams. We have to append new bigram entry to the list.
+ // 5. Same as 4, but the list is the last entry of the content file.
+ if (outAddedNewEntry) {
+ *outAddedNewEntry = false;
+ }
+ const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ if (bigramListPos == NOT_A_DICT_POS) {
+ // Case 1. PtNode that doesn't have a bigram list.
+ // Create new bigram list.
+ if (!mBigramDictContent->createNewBigramList(terminalId)) {
+ return false;
+ }
+ const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+ newTargetTerminalId);
+ const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
+ bigramProperty);
+ // Write an entry.
+ const int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) {
+ return false;
+ }
+ if (outAddedNewEntry) {
+ *outAddedNewEntry = true;
+ }
+ return true;
+ }
+
+ int tailEntryPos = NOT_A_DICT_POS;
+ const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos,
+ &tailEntryPos);
+ if (tailEntryPos != NOT_A_DICT_POS || entryPosToUpdate == NOT_A_DICT_POS) {
+ // Case 4, 5.
+ // Add new entry to the bigram list.
+ if (tailEntryPos == NOT_A_DICT_POS) {
+ // Case 4. Create new bigram list.
+ if (!mBigramDictContent->createNewBigramList(terminalId)) {
+ return false;
+ }
+ const int destPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ // Copy existing bigram list.
+ if (!mBigramDictContent->copyBigramList(bigramListPos, destPos, &tailEntryPos)) {
+ return false;
+ }
+ }
+ // Write new entry at the tail position of the bigram content.
+ const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+ newTargetTerminalId);
+ const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
+ &newBigramEntry, bigramProperty);
+ if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) {
+ return false;
+ }
+ // Update has next flag of the tail entry.
+ if (!updateHasNextFlag(true /* hasNext */, tailEntryPos)) {
+ return false;
+ }
+ if (outAddedNewEntry) {
+ *outAddedNewEntry = true;
+ }
+ return true;
+ }
+
+ // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry.
+ const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
+ if (!originalBigramEntry.isValid()) {
+ // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing
+ // entry is updated.
+ if (outAddedNewEntry) {
+ *outAddedNewEntry = true;
+ }
+ }
+ const BigramEntry updatedBigramEntry =
+ originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
+ const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
+ &updatedBigramEntry, bigramProperty);
+ return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
+}
+
+bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) {
+ const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ if (bigramListPos == NOT_A_DICT_POS) {
+ // Bigram list doesn't exist.
+ return false;
+ }
+ const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos,
+ nullptr /* outTailEntryPos */);
+ if (entryPosToUpdate == NOT_A_DICT_POS) {
+ // Bigram entry doesn't exist.
+ return false;
+ }
+ const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
+ if (targetTerminalId != bigramEntry.getTargetTerminalId()) {
+ // Bigram entry doesn't exist.
+ return false;
+ }
+ // Remove bigram entry by marking it as invalid entry and overwriting the original entry.
+ const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+ return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate);
+}
+
+bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
+ int *const outBigramCount) {
+ const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ if (bigramListPos == NOT_A_DICT_POS) {
+ // Bigram list doesn't exist.
+ return true;
+ }
+ bool hasNext = true;
+ int readingPos = bigramListPos;
+ while (hasNext) {
+ const int entryPos = readingPos;
+ const BigramEntry bigramEntry =
+ mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ if (!bigramEntry.isValid()) {
+ continue;
+ }
+ const int targetPtNodePos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
+ bigramEntry.getTargetTerminalId());
+ if (targetPtNodePos == NOT_A_DICT_POS) {
+ // Invalidate bigram entry.
+ const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+ if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+ return false;
+ }
+ } else if (bigramEntry.hasHistoricalInfo()) {
+ const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
+ bigramEntry.getHistoricalInfo(), mHeaderPolicy);
+ if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) {
+ const BigramEntry updatedBigramEntry =
+ bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo);
+ if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+ return false;
+ }
+ *outBigramCount += 1;
+ } else {
+ // Remove entry.
+ const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+ if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+ return false;
+ }
+ }
+ } else {
+ *outBigramCount += 1;
+ }
+ }
+ return true;
+}
+
+int Ver4BigramListPolicy::getBigramEntryConut(const int terminalId) {
+ const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+ if (bigramListPos == NOT_A_DICT_POS) {
+ // Bigram list doesn't exist.
+ return 0;
+ }
+ int bigramCount = 0;
+ bool hasNext = true;
+ int readingPos = bigramListPos;
+ while (hasNext) {
+ const BigramEntry bigramEntry =
+ mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ if (bigramEntry.isValid()) {
+ bigramCount++;
+ }
+ }
+ return bigramCount;
+}
+
+int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
+ const int bigramListPos, int *const outTailEntryPos) const {
+ if (outTailEntryPos) {
+ *outTailEntryPos = NOT_A_DICT_POS;
+ }
+ bool hasNext = true;
+ int invalidEntryPos = NOT_A_DICT_POS;
+ int readingPos = bigramListPos;
+ while (hasNext) {
+ const int entryPos = readingPos;
+ const BigramEntry bigramEntry =
+ mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ if (bigramEntry.getTargetTerminalId() == targetTerminalIdToFind) {
+ // Entry with same target is found.
+ return entryPos;
+ } else if (!bigramEntry.isValid()) {
+ // Invalid entry that can be reused is found.
+ invalidEntryPos = entryPos;
+ }
+ if (!hasNext && mBigramDictContent->isContentTailPos(readingPos)) {
+ if (outTailEntryPos) {
+ *outTailEntryPos = entryPos;
+ }
+ }
+ }
+ return invalidEntryPos;
+}
+
+const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
+ const BigramEntry *const originalBigramEntry,
+ const BigramProperty *const bigramProperty) const {
+ // TODO: Consolidate historical info and probability.
+ if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+ const HistoricalInfo historicalInfoForUpdate(bigramProperty->getTimestamp(),
+ bigramProperty->getLevel(), bigramProperty->getCount());
+ const HistoricalInfo updatedHistoricalInfo =
+ ForgettingCurveUtils::createUpdatedHistoricalInfo(
+ originalBigramEntry->getHistoricalInfo(), bigramProperty->getProbability(),
+ &historicalInfoForUpdate, mHeaderPolicy);
+ return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
+ } else {
+ return originalBigramEntry->updateProbabilityAndGetEntry(bigramProperty->getProbability());
+ }
+}
+
+bool Ver4BigramListPolicy::updateHasNextFlag(const bool hasNext, const int bigramEntryPos) {
+ const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(bigramEntryPos);
+ const BigramEntry updatedBigramEntry = bigramEntry.updateHasNextAndGetEntry(hasNext);
+ return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, bigramEntryPos);
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h
new file mode 100644
index 000000000..adf687bac
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_BIGRAM_LIST_POLICY_H
+#define LATINIME_BACKWARD_V401_VER4_BIGRAM_LIST_POLICY_H
+
+#include "defines.h"
+#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class BigramDictContent;
+} // namespace v401
+} // namespace backward
+class BigramProperty;
+namespace backward {
+namespace v401 {
+} // namespace v401
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v401 {
+class TerminalPositionLookupTable;
+
+class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
+ public:
+ Ver4BigramListPolicy(BigramDictContent *const bigramDictContent,
+ const TerminalPositionLookupTable *const terminalPositionLookupTable,
+ const HeaderPolicy *const headerPolicy)
+ : mBigramDictContent(bigramDictContent),
+ mTerminalPositionLookupTable(terminalPositionLookupTable),
+ mHeaderPolicy(headerPolicy) {}
+
+ void getNextBigram(int *const outBigramPos, int *const outProbability,
+ bool *const outHasNext, int *const bigramEntryPos) const;
+
+ void skipAllBigrams(int *const pos) const {
+ // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
+ }
+
+ bool addNewEntry(const int terminalId, const int newTargetTerminalId,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
+
+ bool removeEntry(const int terminalId, const int targetTerminalId);
+
+ bool updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
+ int *const outBigramCount);
+
+ int getBigramEntryConut(const int terminalId);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy);
+
+ int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos,
+ int *const outTailEntryPos) const;
+
+ const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
+ const BigramProperty *const bigramProperty) const;
+
+ bool updateHasNextFlag(const bool hasNext, const int bigramEntryPos);
+
+ BigramDictContent *const mBigramDictContent;
+ const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
+ const HeaderPolicy *const mHeaderPolicy;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_BIGRAM_LIST_POLICY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.cpp
new file mode 100644
index 000000000..1e53ff94a
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h"
+
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition(
+ int *const bigramEntryPos) const {
+ const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer();
+ if (*bigramEntryPos < 0 || *bigramEntryPos >= bigramListBuffer->getTailPosition()) {
+ AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bufSize: %d",
+ *bigramEntryPos, bigramListBuffer->getTailPosition());
+ ASSERT(false);
+ return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+ Ver4DictConstants::NOT_A_TERMINAL_ID);
+ }
+ const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
+ const bool hasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0;
+ int probability = NOT_A_PROBABILITY;
+ int timestamp = NOT_A_TIMESTAMP;
+ int level = 0;
+ int count = 0;
+ if (mHasHistoricalInfo) {
+ probability = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::PROBABILITY_SIZE, bigramEntryPos);
+ timestamp = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::TIME_STAMP_FIELD_SIZE, bigramEntryPos);
+ level = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, bigramEntryPos);
+ count = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::WORD_COUNT_FIELD_SIZE, bigramEntryPos);
+ } else {
+ probability = bigramFlags & Ver4DictConstants::BIGRAM_PROBABILITY_MASK;
+ }
+ const int encodedTargetTerminalId = bigramListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos);
+ const int targetTerminalId =
+ (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
+ Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
+ if (mHasHistoricalInfo) {
+ const HistoricalInfo historicalInfo(timestamp, level, count);
+ return BigramEntry(hasNext, probability, &historicalInfo, targetTerminalId);
+ } else {
+ return BigramEntry(hasNext, probability, targetTerminalId);
+ }
+}
+
+bool BigramDictContent::writeBigramEntryAndAdvancePosition(
+ const BigramEntry *const bigramEntryToWrite, int *const entryWritingPos) {
+ BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer();
+ const int bigramFlags = createAndGetBigramFlags(
+ mHasHistoricalInfo ? 0 : bigramEntryToWrite->getProbability(),
+ bigramEntryToWrite->hasNext());
+ if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags,
+ Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram flags. pos: %d, flags: %x", *entryWritingPos, bigramFlags);
+ return false;
+ }
+ if (mHasHistoricalInfo) {
+ if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getProbability(),
+ Ver4DictConstants::PROBABILITY_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram probability. pos: %d, probability: %d", *entryWritingPos,
+ bigramEntryToWrite->getProbability());
+ return false;
+ }
+ const HistoricalInfo *const historicalInfo = bigramEntryToWrite->getHistoricalInfo();
+ if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
+ Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
+ historicalInfo->getTimeStamp());
+ return false;
+ }
+ if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getLevel(),
+ Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
+ historicalInfo->getLevel());
+ return false;
+ }
+ if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getCount(),
+ Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
+ historicalInfo->getCount());
+ return false;
+ }
+ }
+ const int targetTerminalIdToWrite =
+ (bigramEntryToWrite->getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) ?
+ Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID :
+ bigramEntryToWrite->getTargetTerminalId();
+ if (!bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite,
+ Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos)) {
+ AKLOGE("Cannot write bigram target terminal id. pos: %d, target terminal id: %d",
+ *entryWritingPos, bigramEntryToWrite->getTargetTerminalId());
+ return false;
+ }
+ return true;
+}
+
+bool BigramDictContent::copyBigramList(const int bigramListPos, const int toPos,
+ int *const outTailEntryPos) {
+ int readingPos = bigramListPos;
+ int writingPos = toPos;
+ bool hasNext = true;
+ while (hasNext) {
+ const BigramEntry bigramEntry = getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ if (!hasNext) {
+ *outTailEntryPos = writingPos;
+ }
+ if (!writeBigramEntryAndAdvancePosition(&bigramEntry, &writingPos)) {
+ AKLOGE("Cannot write bigram entry to copy. pos: %d", writingPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool BigramDictContent::runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const BigramDictContent *const originalBigramDictContent,
+ int *const outBigramEntryCount) {
+ for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+ it != terminalIdMap->end(); ++it) {
+ const int originalBigramListPos =
+ originalBigramDictContent->getBigramListHeadPos(it->first);
+ if (originalBigramListPos == NOT_A_DICT_POS) {
+ // This terminal does not have a bigram list.
+ continue;
+ }
+ const int bigramListPos = getContentBuffer()->getTailPosition();
+ int bigramEntryCount = 0;
+ // Copy bigram list with GC from original content.
+ if (!runGCBigramList(originalBigramListPos, originalBigramDictContent, bigramListPos,
+ terminalIdMap, &bigramEntryCount)) {
+ AKLOGE("Cannot complete GC for the bigram list. original pos: %d, pos: %d",
+ originalBigramListPos, bigramListPos);
+ return false;
+ }
+ if (bigramEntryCount == 0) {
+ // All bigram entries are useless. This terminal does not have a bigram list.
+ continue;
+ }
+ *outBigramEntryCount += bigramEntryCount;
+ // Set bigram list position to the lookup table.
+ if (!getUpdatableAddressLookupTable()->set(it->second, bigramListPos)) {
+ AKLOGE("Cannot set bigram list position. terminal id: %d, pos: %d",
+ it->second, bigramListPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Returns whether GC for the bigram list was succeeded or not.
+bool BigramDictContent::runGCBigramList(const int bigramListPos,
+ const BigramDictContent *const sourceBigramDictContent, const int toPos,
+ const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ int *const outEntrycount) {
+ bool hasNext = true;
+ int readingPos = bigramListPos;
+ int writingPos = toPos;
+ int lastEntryPos = NOT_A_DICT_POS;
+ while (hasNext) {
+ const BigramEntry originalBigramEntry =
+ sourceBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = originalBigramEntry.hasNext();
+ if (originalBigramEntry.getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) {
+ continue;
+ }
+ TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
+ terminalIdMap->find(originalBigramEntry.getTargetTerminalId());
+ if (it == terminalIdMap->end()) {
+ // Target word has been removed.
+ continue;
+ }
+ lastEntryPos = hasNext ? writingPos : NOT_A_DICT_POS;
+ const BigramEntry updatedBigramEntry =
+ originalBigramEntry.updateTargetTerminalIdAndGetEntry(it->second);
+ if (!writeBigramEntryAndAdvancePosition(&updatedBigramEntry, &writingPos)) {
+ AKLOGE("Cannot write bigram entry to run GC. pos: %d", writingPos);
+ return false;
+ }
+ *outEntrycount += 1;
+ }
+ if (lastEntryPos != NOT_A_DICT_POS) {
+ // Update has next flag in the last written entry.
+ const BigramEntry bigramEntry = getBigramEntry(lastEntryPos).updateHasNextAndGetEntry(
+ false /* hasNext */);
+ if (!writeBigramEntry(&bigramEntry, lastEntryPos)) {
+ AKLOGE("Cannot write bigram entry to set hasNext flag after GC. pos: %d", writingPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h
new file mode 100644
index 000000000..f9c474b4a
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_BIGRAM_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_BIGRAM_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class BigramDictContent : public SparseTableDictContent {
+ public:
+ BigramDictContent(const char *const dictPath, const bool hasHistoricalInfo,
+ const bool isUpdatable)
+ : SparseTableDictContent(dictPath,
+ Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_FILE_EXTENSION, isUpdatable,
+ Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
+ Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
+ mHasHistoricalInfo(hasHistoricalInfo) {}
+
+ BigramDictContent(const bool hasHistoricalInfo)
+ : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
+ Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
+ mHasHistoricalInfo(hasHistoricalInfo) {}
+
+ const BigramEntry getBigramEntry(const int bigramEntryPos) const {
+ int readingPos = bigramEntryPos;
+ return getBigramEntryAndAdvancePosition(&readingPos);
+ }
+
+ const BigramEntry getBigramEntryAndAdvancePosition(int *const bigramEntryPos) const;
+
+ // Returns head position of bigram list for a PtNode specified by terminalId.
+ int getBigramListHeadPos(const int terminalId) const {
+ const SparseTable *const addressLookupTable = getAddressLookupTable();
+ if (!addressLookupTable->contains(terminalId)) {
+ return NOT_A_DICT_POS;
+ }
+ return addressLookupTable->get(terminalId);
+ }
+
+ bool writeBigramEntryAtTail(const BigramEntry *const bigramEntryToWrite) {
+ int writingPos = getContentBuffer()->getTailPosition();
+ return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
+ }
+
+ bool writeBigramEntry(const BigramEntry *const bigramEntryToWrite, const int entryWritingPos) {
+ int writingPos = entryWritingPos;
+ return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
+ }
+
+ bool writeBigramEntryAndAdvancePosition(const BigramEntry *const bigramEntryToWrite,
+ int *const entryWritingPos);
+
+ bool createNewBigramList(const int terminalId) {
+ const int bigramListPos = getContentBuffer()->getTailPosition();
+ return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos);
+ }
+
+ bool copyBigramList(const int bigramListPos, const int toPos, int *const outTailEntryPos);
+
+ bool flushToFile(const char *const dictPath) const {
+ return flush(dictPath, Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_FILE_EXTENSION);
+ }
+
+ bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const BigramDictContent *const originalBigramDictContent,
+ int *const outBigramEntryCount);
+
+ bool isContentTailPos(const int pos) const {
+ return pos == getContentBuffer()->getTailPosition();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BigramDictContent);
+
+ int createAndGetBigramFlags(const int probability, const bool hasNext) const {
+ return (probability & Ver4DictConstants::BIGRAM_PROBABILITY_MASK)
+ | (hasNext ? Ver4DictConstants::BIGRAM_HAS_NEXT_MASK : 0);
+ }
+
+ bool runGCBigramList(const int bigramListPos,
+ const BigramDictContent *const sourceBigramDictContent, const int toPos,
+ const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ int *const outEntryCount);
+
+ bool mHasHistoricalInfo;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_BIGRAM_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h
new file mode 100644
index 000000000..82c4b53a8
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_entry.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_BIGRAM_ENTRY_H
+#define LATINIME_BACKWARD_V401_BIGRAM_ENTRY_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/historical_info.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class BigramEntry {
+ public:
+ BigramEntry(const BigramEntry& bigramEntry)
+ : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
+ mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
+
+ // Entry with historical information.
+ BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
+ : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
+ mTargetTerminalId(targetTerminalId) {}
+
+ // Entry with historical information.
+ BigramEntry(const bool hasNext, const int probability,
+ const HistoricalInfo *const historicalInfo, const int targetTerminalId)
+ : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
+ mTargetTerminalId(targetTerminalId) {}
+
+ const BigramEntry getInvalidatedEntry() const {
+ return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
+ }
+
+ const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
+ return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
+ }
+
+ const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
+ return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
+ }
+
+ const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
+ return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
+ }
+
+ const BigramEntry updateHistoricalInfoAndGetEntry(
+ const HistoricalInfo *const historicalInfo) const {
+ return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
+ }
+
+ bool isValid() const {
+ return mTargetTerminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
+ }
+
+ bool hasNext() const {
+ return mHasNext;
+ }
+
+ int getProbability() const {
+ return mProbability;
+ }
+
+ bool hasHistoricalInfo() const {
+ return mHistoricalInfo.isValid();
+ }
+
+ const HistoricalInfo *getHistoricalInfo() const {
+ return &mHistoricalInfo;
+ }
+
+ int getTargetTerminalId() const {
+ return mTargetTerminalId;
+ }
+
+ private:
+ // Copy constructor is public to use this class as a type of return value.
+ DISALLOW_DEFAULT_CONSTRUCTOR(BigramEntry);
+ DISALLOW_ASSIGNMENT_OPERATOR(BigramEntry);
+
+ const bool mHasNext;
+ const int mProbability;
+ const HistoricalInfo mHistoricalInfo;
+ const int mTargetTerminalId;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_BIGRAM_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h
new file mode 100644
index 000000000..39e29001c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_DICT_CONTENT_H
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class DictContent {
+ public:
+ virtual ~DictContent() {}
+ virtual bool isValid() const = 0;
+
+ protected:
+ DictContent() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DictContent);
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.cpp
new file mode 100644
index 000000000..337b97c05
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h"
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+const ProbabilityEntry ProbabilityDictContent::getProbabilityEntry(const int terminalId) const {
+ if (terminalId < 0 || terminalId >= mSize) {
+ // This method can be called with invalid terminal id during GC.
+ return ProbabilityEntry(0 /* flags */, NOT_A_PROBABILITY);
+ }
+ const BufferWithExtendableBuffer *const buffer = getBuffer();
+ int entryPos = getEntryPos(terminalId);
+ const int flags = buffer->readUintAndAdvancePosition(
+ Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &entryPos);
+ const int probability = buffer->readUintAndAdvancePosition(
+ Ver4DictConstants::PROBABILITY_SIZE, &entryPos);
+ if (mHasHistoricalInfo) {
+ const int timestamp = buffer->readUintAndAdvancePosition(
+ Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &entryPos);
+ const int level = buffer->readUintAndAdvancePosition(
+ Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &entryPos);
+ const int count = buffer->readUintAndAdvancePosition(
+ Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &entryPos);
+ const HistoricalInfo historicalInfo(timestamp, level, count);
+ return ProbabilityEntry(flags, probability, &historicalInfo);
+ } else {
+ return ProbabilityEntry(flags, probability);
+ }
+}
+
+bool ProbabilityDictContent::setProbabilityEntry(const int terminalId,
+ const ProbabilityEntry *const probabilityEntry) {
+ if (terminalId < 0) {
+ return false;
+ }
+ const int entryPos = getEntryPos(terminalId);
+ if (terminalId >= mSize) {
+ ProbabilityEntry dummyEntry;
+ // Write new entry.
+ int writingPos = getBuffer()->getTailPosition();
+ while (writingPos <= entryPos) {
+ // Fulfilling with dummy entries until writingPos.
+ if (!writeEntry(&dummyEntry, writingPos)) {
+ AKLOGE("Cannot write dummy entry. pos: %d, mSize: %d", writingPos, mSize);
+ return false;
+ }
+ writingPos += getEntrySize();
+ mSize++;
+ }
+ }
+ return writeEntry(probabilityEntry, entryPos);
+}
+
+bool ProbabilityDictContent::flushToFile(const char *const dictPath) const {
+ if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
+ ProbabilityDictContent probabilityDictContentToWrite(mHasHistoricalInfo);
+ for (int i = 0; i < mSize; ++i) {
+ const ProbabilityEntry probabilityEntry = getProbabilityEntry(i);
+ if (!probabilityDictContentToWrite.setProbabilityEntry(i, &probabilityEntry)) {
+ AKLOGE("Cannot set probability entry in flushToFile. terminalId: %d", i);
+ return false;
+ }
+ }
+ return probabilityDictContentToWrite.flush(dictPath,
+ Ver4DictConstants::FREQ_FILE_EXTENSION);
+ } else {
+ return flush(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION);
+ }
+}
+
+bool ProbabilityDictContent::runGC(
+ const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const ProbabilityDictContent *const originalProbabilityDictContent) {
+ mSize = 0;
+ for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+ it != terminalIdMap->end(); ++it) {
+ const ProbabilityEntry probabilityEntry =
+ originalProbabilityDictContent->getProbabilityEntry(it->first);
+ if (!setProbabilityEntry(it->second, &probabilityEntry)) {
+ AKLOGE("Cannot set probability entry in runGC. terminalId: %d", it->second);
+ return false;
+ }
+ mSize++;
+ }
+ return true;
+}
+
+int ProbabilityDictContent::getEntrySize() const {
+ if (mHasHistoricalInfo) {
+ return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
+ + Ver4DictConstants::PROBABILITY_SIZE
+ + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
+ + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+ + Ver4DictConstants::WORD_COUNT_FIELD_SIZE;
+ } else {
+ return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
+ + Ver4DictConstants::PROBABILITY_SIZE;
+ }
+}
+
+int ProbabilityDictContent::getEntryPos(const int terminalId) const {
+ return terminalId * getEntrySize();
+}
+
+bool ProbabilityDictContent::writeEntry(const ProbabilityEntry *const probabilityEntry,
+ const int entryPos) {
+ BufferWithExtendableBuffer *const bufferToWrite = getWritableBuffer();
+ int writingPos = entryPos;
+ if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getFlags(),
+ Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &writingPos)) {
+ AKLOGE("Cannot write flags in probability dict content. pos: %d", writingPos);
+ return false;
+ }
+ if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getProbability(),
+ Ver4DictConstants::PROBABILITY_SIZE, &writingPos)) {
+ AKLOGE("Cannot write probability in probability dict content. pos: %d", writingPos);
+ return false;
+ }
+ if (mHasHistoricalInfo) {
+ const HistoricalInfo *const historicalInfo = probabilityEntry->getHistoricalInfo();
+ if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
+ Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &writingPos)) {
+ AKLOGE("Cannot write timestamp in probability dict content. pos: %d", writingPos);
+ return false;
+ }
+ if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getLevel(),
+ Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &writingPos)) {
+ AKLOGE("Cannot write level in probability dict content. pos: %d", writingPos);
+ return false;
+ }
+ if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getCount(),
+ Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &writingPos)) {
+ AKLOGE("Cannot write count in probability dict content. pos: %d", writingPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h
new file mode 100644
index 000000000..db3070994
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_PROBABILITY_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_PROBABILITY_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class ProbabilityEntry;
+
+class ProbabilityDictContent : public SingleDictContent {
+ public:
+ ProbabilityDictContent(const char *const dictPath, const bool hasHistoricalInfo,
+ const bool isUpdatable)
+ : SingleDictContent(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION, isUpdatable),
+ mHasHistoricalInfo(hasHistoricalInfo),
+ mSize(getBuffer()->getTailPosition() / getEntrySize()) {}
+
+ ProbabilityDictContent(const bool hasHistoricalInfo)
+ : mHasHistoricalInfo(hasHistoricalInfo), mSize(0) {}
+
+ const ProbabilityEntry getProbabilityEntry(const int terminalId) const;
+
+ bool setProbabilityEntry(const int terminalId, const ProbabilityEntry *const probabilityEntry);
+
+ bool flushToFile(const char *const dictPath) const;
+
+ bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const ProbabilityDictContent *const originalProbabilityDictContent);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProbabilityDictContent);
+
+ int getEntrySize() const;
+
+ int getEntryPos(const int terminalId) const;
+
+ bool writeEntry(const ProbabilityEntry *const probabilityEntry, const int entryPos);
+
+ bool mHasHistoricalInfo;
+ int mSize;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_PROBABILITY_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h
new file mode 100644
index 000000000..d341e7b07
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_PROBABILITY_ENTRY_H
+#define LATINIME_BACKWARD_V401_PROBABILITY_ENTRY_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/historical_info.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class ProbabilityEntry {
+ public:
+ ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
+ : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
+ mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
+
+ // Dummy entry
+ ProbabilityEntry()
+ : mFlags(0), mProbability(NOT_A_PROBABILITY), mHistoricalInfo() {}
+
+ // Entry without historical information
+ ProbabilityEntry(const int flags, const int probability)
+ : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
+
+ // Entry with historical information.
+ ProbabilityEntry(const int flags, const int probability,
+ const HistoricalInfo *const historicalInfo)
+ : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
+
+ const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
+ return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
+ }
+
+ const ProbabilityEntry createEntryWithUpdatedHistoricalInfo(
+ const HistoricalInfo *const historicalInfo) const {
+ return ProbabilityEntry(mFlags, mProbability, historicalInfo);
+ }
+
+ bool hasHistoricalInfo() const {
+ return mHistoricalInfo.isValid();
+ }
+
+ int getFlags() const {
+ return mFlags;
+ }
+
+ int getProbability() const {
+ return mProbability;
+ }
+
+ const HistoricalInfo *getHistoricalInfo() const {
+ return &mHistoricalInfo;
+ }
+
+ private:
+ // Copy constructor is public to use this class as a type of return value.
+ DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry);
+
+ const int mFlags;
+ const int mProbability;
+ const HistoricalInfo mHistoricalInfo;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.cpp
new file mode 100644
index 000000000..3214807ad
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h"
+
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+ int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+ bool *const outhasNext, int *const shortcutEntryPos) const {
+ const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
+ if (*shortcutEntryPos < 0 || *shortcutEntryPos >= shortcutListBuffer->getTailPosition()) {
+ AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
+ *shortcutEntryPos, shortcutListBuffer->getTailPosition());
+ ASSERT(false);
+ if (outhasNext) {
+ *outhasNext = false;
+ }
+ if (outCodePointCount) {
+ *outCodePointCount = 0;
+ }
+ return;
+ }
+
+ const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
+ Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+ if (outProbability) {
+ *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
+ }
+ if (outhasNext) {
+ *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+ }
+ if (outCodePoint && outCodePointCount) {
+ shortcutListBuffer->readCodePointsAndAdvancePosition(
+ maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
+ }
+}
+
+int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
+ const SparseTable *const addressLookupTable = getAddressLookupTable();
+ if (!addressLookupTable->contains(terminalId)) {
+ return NOT_A_DICT_POS;
+ }
+ return addressLookupTable->get(terminalId);
+}
+
+bool ShortcutDictContent::flushToFile(const char *const dictPath) const {
+ return flush(dictPath, Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_FILE_EXTENSION);
+}
+
+bool ShortcutDictContent::runGC(
+ const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const ShortcutDictContent *const originalShortcutDictContent) {
+ for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+ it != terminalIdMap->end(); ++it) {
+ const int originalShortcutListPos =
+ originalShortcutDictContent->getShortcutListHeadPos(it->first);
+ if (originalShortcutListPos == NOT_A_DICT_POS) {
+ continue;
+ }
+ const int shortcutListPos = getContentBuffer()->getTailPosition();
+ // Copy shortcut list from original content.
+ if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
+ shortcutListPos)) {
+ AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
+ originalShortcutListPos, shortcutListPos);
+ return false;
+ }
+ // Set shortcut list position to the lookup table.
+ if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
+ AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
+ it->second, shortcutListPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
+ const int shortcutListListPos = getContentBuffer()->getTailPosition();
+ return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
+}
+
+bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
+ return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
+}
+
+bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
+ const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
+ bool hasNext = true;
+ int readingPos = shortcutListPos;
+ int writingPos = toPos;
+ int codePoints[MAX_WORD_LENGTH];
+ while (hasNext) {
+ int probability = 0;
+ int codePointCount = 0;
+ sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
+ codePoints, &codePointCount, &probability, &hasNext, &readingPos);
+ if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
+ hasNext, &writingPos)) {
+ AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
+ BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+ const int shortcutFlags = shortcutListBuffer->readUint(
+ Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+ const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+ const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
+ return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
+ Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+}
+
+bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+ const int codePointCount, const int probability, const bool hasNext,
+ int *const shortcutEntryPos) {
+ BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+ const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
+ if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
+ Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
+ AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
+ return false;
+ }
+ if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
+ true /* writesTerminator */, shortcutEntryPos)) {
+ AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
+ return false;
+ }
+ return true;
+}
+
+// Find a shortcut entry that has specified target and return its position.
+int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
+ const int *const targetCodePointsToFind, const int codePointCount) const {
+ bool hasNext = true;
+ int readingPos = shortcutListPos;
+ int targetCodePoints[MAX_WORD_LENGTH];
+ while (hasNext) {
+ const int entryPos = readingPos;
+ int probability = 0;
+ int targetCodePointCount = 0;
+ getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
+ &probability, &hasNext, &readingPos);
+ if (targetCodePointCount != codePointCount) {
+ continue;
+ }
+ bool matched = true;
+ for (int i = 0; i < codePointCount; ++i) {
+ if (targetCodePointsToFind[i] != targetCodePoints[i]) {
+ matched = false;
+ break;
+ }
+ }
+ if (matched) {
+ return entryPos;
+ }
+ }
+ return NOT_A_DICT_POS;
+}
+
+int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
+ const bool hasNext) const {
+ return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
+ | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h
new file mode 100644
index 000000000..75fd4f3b2
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_SHORTCUT_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_SHORTCUT_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class ShortcutDictContent : public SparseTableDictContent {
+ public:
+ ShortcutDictContent(const char *const dictPath, const bool isUpdatable)
+ : SparseTableDictContent(dictPath,
+ Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_FILE_EXTENSION, isUpdatable,
+ Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+ Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+ ShortcutDictContent()
+ : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+ Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+ void getShortcutEntry(const int maxCodePointCount, int *const outCodePoint,
+ int *const outCodePointCount, int *const outProbability, bool *const outhasNext,
+ const int shortcutEntryPos) {
+ int readingPos = shortcutEntryPos;
+ return getShortcutEntryAndAdvancePosition(maxCodePointCount, outCodePoint,
+ outCodePointCount, outProbability, outhasNext, &readingPos);
+ }
+
+ void getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+ int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+ bool *const outhasNext, int *const shortcutEntryPos) const;
+
+ // Returns head position of shortcut list for a PtNode specified by terminalId.
+ int getShortcutListHeadPos(const int terminalId) const;
+
+ bool flushToFile(const char *const dictPath) const;
+
+ bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+ const ShortcutDictContent *const originalShortcutDictContent);
+
+ bool createNewShortcutList(const int terminalId);
+
+ bool copyShortcutList(const int shortcutListPos, const int toPos);
+
+ bool setProbability(const int probability, const int shortcutEntryPos);
+
+ bool writeShortcutEntry(const int *const codePoint, const int codePointCount,
+ const int probability, const bool hasNext, const int shortcutEntryPos) {
+ int writingPos = shortcutEntryPos;
+ return writeShortcutEntryAndAdvancePosition(codePoint, codePointCount, probability,
+ hasNext, &writingPos);
+ }
+
+ bool writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+ const int codePointCount, const int probability, const bool hasNext,
+ int *const shortcutEntryPos);
+
+ int findShortcutEntryAndGetPos(const int shortcutListPos,
+ const int *const targetCodePointsToFind, const int codePointCount) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent);
+
+ bool copyShortcutListFromDictContent(const int shortcutListPos,
+ const ShortcutDictContent *const sourceShortcutDictContent, const int toPos);
+
+ int createAndGetShortcutFlags(const int probability, const bool hasNext) const;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_SHORTCUT_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h
new file mode 100644
index 000000000..a519cd835
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_SINGLE_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_SINGLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class SingleDictContent : public DictContent {
+ public:
+ SingleDictContent(const char *const dictPath, const char *const contentFileName,
+ const bool isUpdatable)
+ : mMmappedBuffer(MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
+ mExpandableContentBuffer(mMmappedBuffer ? mMmappedBuffer->getBuffer() : nullptr,
+ mMmappedBuffer ? mMmappedBuffer->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mIsValid(mMmappedBuffer) {}
+
+ SingleDictContent()
+ : mMmappedBuffer(nullptr),
+ mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), mIsValid(true) {}
+
+ virtual ~SingleDictContent() {}
+
+ virtual bool isValid() const {
+ return mIsValid;
+ }
+
+ bool isNearSizeLimit() const {
+ return mExpandableContentBuffer.isNearSizeLimit();
+ }
+
+ protected:
+ BufferWithExtendableBuffer *getWritableBuffer() {
+ return &mExpandableContentBuffer;
+ }
+
+ const BufferWithExtendableBuffer *getBuffer() const {
+ return &mExpandableContentBuffer;
+ }
+
+ bool flush(const char *const dictPath, const char *const contentFileNameSuffix) const {
+ return DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+ contentFileNameSuffix, &mExpandableContentBuffer);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SingleDictContent);
+
+ const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
+ BufferWithExtendableBuffer mExpandableContentBuffer;
+ const bool mIsValid;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_SINGLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.cpp
new file mode 100644
index 000000000..638132c3d
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+bool SparseTableDictContent::flush(const char *const dictPath,
+ const char *const lookupTableFileNameSuffix, const char *const addressTableFileNameSuffix,
+ const char *const contentFileNameSuffix) const {
+ if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, lookupTableFileNameSuffix,
+ &mExpandableLookupTableBuffer)){
+ return false;
+ }
+ if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, addressTableFileNameSuffix,
+ &mExpandableAddressTableBuffer)) {
+ return false;
+ }
+ if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, contentFileNameSuffix,
+ &mExpandableContentBuffer)) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h
new file mode 100644
index 000000000..b95de2eda
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/sparse_table_dict_content.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_SPARSE_TABLE_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V401_SPARSE_TABLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/sparse_table.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+// TODO: Support multiple contents.
+class SparseTableDictContent : public DictContent {
+ public:
+ AK_FORCE_INLINE SparseTableDictContent(const char *const dictPath,
+ const char *const lookupTableFileName, const char *const addressTableFileName,
+ const char *const contentFileName, const bool isUpdatable,
+ const int sparseTableBlockSize, const int sparseTableDataSize)
+ : mLookupTableBuffer(
+ MmappedBuffer::openBuffer(dictPath, lookupTableFileName, isUpdatable)),
+ mAddressTableBuffer(
+ MmappedBuffer::openBuffer(dictPath, addressTableFileName, isUpdatable)),
+ mContentBuffer(
+ MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
+ mExpandableLookupTableBuffer(
+ mLookupTableBuffer ? mLookupTableBuffer->getBuffer() : nullptr,
+ mLookupTableBuffer ? mLookupTableBuffer->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mExpandableAddressTableBuffer(
+ mAddressTableBuffer ? mAddressTableBuffer->getBuffer() : nullptr,
+ mAddressTableBuffer ? mAddressTableBuffer->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mExpandableContentBuffer(mContentBuffer ? mContentBuffer->getBuffer() : nullptr,
+ mContentBuffer ? mContentBuffer->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+ sparseTableBlockSize, sparseTableDataSize),
+ mIsValid(mLookupTableBuffer && mAddressTableBuffer && mContentBuffer) {}
+
+ SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize)
+ : mLookupTableBuffer(), mAddressTableBuffer(), mContentBuffer(),
+ mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+ mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+ mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+ mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+ sparseTableBlockSize, sparseTableDataSize), mIsValid(true) {}
+
+ virtual ~SparseTableDictContent() {}
+
+ virtual bool isValid() const {
+ return mIsValid;
+ }
+
+ bool isNearSizeLimit() const {
+ return mExpandableLookupTableBuffer.isNearSizeLimit()
+ || mExpandableAddressTableBuffer.isNearSizeLimit()
+ || mExpandableContentBuffer.isNearSizeLimit();
+ }
+
+ protected:
+ SparseTable *getUpdatableAddressLookupTable() {
+ return &mAddressLookupTable;
+ }
+
+ const SparseTable *getAddressLookupTable() const {
+ return &mAddressLookupTable;
+ }
+
+ BufferWithExtendableBuffer *getWritableContentBuffer() {
+ return &mExpandableContentBuffer;
+ }
+
+ const BufferWithExtendableBuffer *getContentBuffer() const {
+ return &mExpandableContentBuffer;
+ }
+
+ bool flush(const char *const dictDirPath, const char *const lookupTableFileName,
+ const char *const addressTableFileName, const char *const contentFileName) const;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
+
+ const MmappedBuffer::MmappedBufferPtr mLookupTableBuffer;
+ const MmappedBuffer::MmappedBufferPtr mAddressTableBuffer;
+ const MmappedBuffer::MmappedBufferPtr mContentBuffer;
+ BufferWithExtendableBuffer mExpandableLookupTableBuffer;
+ BufferWithExtendableBuffer mExpandableAddressTableBuffer;
+ BufferWithExtendableBuffer mExpandableContentBuffer;
+ SparseTable mAddressLookupTable;
+ const bool mIsValid;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_SPARSE_TABLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.cpp
new file mode 100644
index 000000000..ab8a3ae43
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
+ if (terminalId < 0 || terminalId >= mSize) {
+ return NOT_A_DICT_POS;
+ }
+ const int terminalPos = getBuffer()->readUint(
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
+ return (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) ?
+ NOT_A_DICT_POS : terminalPos;
+}
+
+bool TerminalPositionLookupTable::setTerminalPtNodePosition(
+ const int terminalId, const int terminalPtNodePos) {
+ if (terminalId < 0) {
+ return NOT_A_DICT_POS;
+ }
+ while (terminalId >= mSize) {
+ // Write new entry.
+ if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
+ return false;
+ }
+ mSize++;
+ }
+ const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
+ terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
+ return getWritableBuffer()->writeUint(terminalPos,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
+}
+
+bool TerminalPositionLookupTable::flushToFile(const char *const dictPath) const {
+ // If the used buffer size is smaller than the actual buffer size, regenerate the lookup
+ // table and write the new table to the file.
+ if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
+ TerminalPositionLookupTable lookupTableToWrite;
+ for (int i = 0; i < mSize; ++i) {
+ const int terminalPtNodePosition = getTerminalPtNodePosition(i);
+ if (!lookupTableToWrite.setTerminalPtNodePosition(i, terminalPtNodePosition)) {
+ AKLOGE("Cannot set terminal position to lookupTableToWrite."
+ " terminalId: %d, position: %d", i, terminalPtNodePosition);
+ return false;
+ }
+ }
+ return lookupTableToWrite.flush(dictPath,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
+ } else {
+ // We can simply use this lookup table because the buffer size has not been
+ // changed.
+ return flush(dictPath, Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
+ }
+}
+
+bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
+ int removedEntryCount = 0;
+ int nextNewTerminalId = 0;
+ for (int i = 0; i < mSize; ++i) {
+ const int terminalPos = getBuffer()->readUint(
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
+ if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
+ // This entry is a garbage.
+ removedEntryCount++;
+ } else {
+ // Give a new terminal id to the entry.
+ if (!getWritableBuffer()->writeUint(terminalPos,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
+ getEntryPos(nextNewTerminalId))) {
+ return false;
+ }
+ // Memorize the mapping to the old terminal id to the new terminal id.
+ terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
+ nextNewTerminalId++;
+ }
+ }
+ mSize = nextNewTerminalId;
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h
new file mode 100644
index 000000000..dbf0e6088
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_TERMINAL_POSITION_LOOKUP_TABLE_H
+#define LATINIME_BACKWARD_V401_TERMINAL_POSITION_LOOKUP_TABLE_H
+
+#include <unordered_map>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/single_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class TerminalPositionLookupTable : public SingleDictContent {
+ public:
+ typedef std::unordered_map<int, int> TerminalIdMap;
+
+ TerminalPositionLookupTable(const char *const dictPath, const bool isUpdatable)
+ : SingleDictContent(dictPath,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable),
+ mSize(getBuffer()->getTailPosition()
+ / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
+
+ TerminalPositionLookupTable() : mSize(0) {}
+
+ int getTerminalPtNodePosition(const int terminalId) const;
+
+ bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos);
+
+ int getNextTerminalId() const {
+ return mSize;
+ }
+
+ bool flushToFile(const char *const dictPath) const;
+
+ bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable);
+
+ int getEntryPos(const int terminalId) const {
+ return terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+ }
+
+ int mSize;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V401_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h
new file mode 100644
index 000000000..6a4e83c0d
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_SHORTCUT_LIST_POLICY_H
+#define LATINIME_BACKWARD_V401_VER4_SHORTCUT_LIST_POLICY_H
+
+#include "defines.h"
+#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
+ public:
+ Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
+ const TerminalPositionLookupTable *const terminalPositionLookupTable)
+ : mShortcutDictContent(shortcutDictContent) {}
+
+ ~Ver4ShortcutListPolicy() {}
+
+ int getStartPos(const int pos) const {
+ // The first shortcut entry is located at the head position of the shortcut list.
+ return pos;
+ }
+
+ void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
+ int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
+ int *const pos) const {
+ int probability = 0;
+ mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount,
+ outCodePoint, outCodePointCount, &probability, outHasNext, pos);
+ if (outIsWhitelist) {
+ *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(probability);
+ }
+ }
+
+ void skipAllShortcuts(int *const pos) const {
+ // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries.
+ }
+
+ bool addNewShortcut(const int terminalId, const int *const codePoints, const int codePointCount,
+ const int probability) {
+ const int shortcutListPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
+ if (shortcutListPos == NOT_A_DICT_POS) {
+ // Create shortcut list.
+ if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+ AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+ return false;
+ }
+ const int writingPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
+ return mShortcutDictContent->writeShortcutEntry(codePoints, codePointCount, probability,
+ false /* hasNext */, writingPos);
+ }
+ const int entryPos = mShortcutDictContent->findShortcutEntryAndGetPos(shortcutListPos,
+ codePoints, codePointCount);
+ if (entryPos == NOT_A_DICT_POS) {
+ // Add new entry to the shortcut list.
+ // Create new shortcut list.
+ if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+ AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+ return false;
+ }
+ int writingPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
+ if (!mShortcutDictContent->writeShortcutEntryAndAdvancePosition(codePoints,
+ codePointCount, probability, true /* hasNext */, &writingPos)) {
+ AKLOGE("Cannot write shortcut entry. terminal id: %d, pos: %d", terminalId,
+ writingPos);
+ return false;
+ }
+ return mShortcutDictContent->copyShortcutList(shortcutListPos, writingPos);
+ }
+ // Overwrite existing entry.
+ bool hasNext = false;
+ mShortcutDictContent->getShortcutEntry(MAX_WORD_LENGTH, 0 /* outCodePoint */,
+ 0 /* outCodePointCount */ , 0 /* probability */, &hasNext, entryPos);
+ if (!mShortcutDictContent->writeShortcutEntry(codePoints,
+ codePointCount, probability, hasNext, entryPos)) {
+ AKLOGE("Cannot overwrite shortcut entry. terminal id: %d, pos: %d", terminalId,
+ entryPos);
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
+
+ ShortcutDictContent *const mShortcutDictContent;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V401_VER4_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.cpp
new file mode 100644
index 000000000..55ead01a9
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
+
+#include <cerrno>
+#include <cstring>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
+#include "suggest/policyimpl/dictionary/utils/file_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+/* static */ Ver4DictBuffers::Ver4DictBuffersPtr Ver4DictBuffers::openVer4DictBuffers(
+ const char *const dictPath, MmappedBuffer::MmappedBufferPtr headerBuffer,
+ const FormatUtils::FORMAT_VERSION formatVersion) {
+ if (!headerBuffer) {
+ ASSERT(false);
+ AKLOGE("The header buffer must be valid to open ver4 dict buffers.");
+ return Ver4DictBuffersPtr(nullptr);
+ }
+ // TODO: take only dictDirPath, and open both header and trie files in the constructor below
+ const bool isUpdatable = headerBuffer->isUpdatable();
+ return Ver4DictBuffersPtr(new Ver4DictBuffers(dictPath, std::move(headerBuffer), isUpdatable,
+ formatVersion));
+}
+
+bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
+ const BufferWithExtendableBuffer *const headerBuffer) const {
+ // Create temporary directory.
+ const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath,
+ DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
+ char tmpDirPath[tmpDirPathBufSize];
+ FileUtils::getFilePathWithSuffix(dictDirPath,
+ DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize,
+ tmpDirPath);
+ if (FileUtils::existsDir(tmpDirPath)) {
+ if (!FileUtils::removeDirAndFiles(tmpDirPath)) {
+ AKLOGE("Existing directory %s cannot be removed.", tmpDirPath);
+ ASSERT(false);
+ return false;
+ }
+ }
+ if (mkdir(tmpDirPath, S_IRWXU) == -1) {
+ AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
+ return false;
+ }
+ // Get dictionary base path.
+ const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
+ char dictName[dictNameBufSize];
+ FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
+ const int dictPathBufSize = FileUtils::getFilePathBufSize(tmpDirPath, dictName);
+ char dictPath[dictPathBufSize];
+ FileUtils::getFilePath(tmpDirPath, dictName, dictPathBufSize, dictPath);
+
+ // Write header file.
+ if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+ Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
+ AKLOGE("Dictionary header file %s%s cannot be written.", tmpDirPath,
+ Ver4DictConstants::HEADER_FILE_EXTENSION);
+ return false;
+ }
+ // Write trie file.
+ if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+ Ver4DictConstants::TRIE_FILE_EXTENSION, &mExpandableTrieBuffer)) {
+ AKLOGE("Dictionary trie file %s%s cannot be written.", tmpDirPath,
+ Ver4DictConstants::TRIE_FILE_EXTENSION);
+ return false;
+ }
+ // Write dictionary contents.
+ if (!mTerminalPositionLookupTable.flushToFile(dictPath)) {
+ AKLOGE("Terminal position lookup table cannot be written. %s", tmpDirPath);
+ return false;
+ }
+ if (!mProbabilityDictContent.flushToFile(dictPath)) {
+ AKLOGE("Probability dict content cannot be written. %s", tmpDirPath);
+ return false;
+ }
+ if (!mBigramDictContent.flushToFile(dictPath)) {
+ AKLOGE("Bigram dict content cannot be written. %s", tmpDirPath);
+ return false;
+ }
+ if (!mShortcutDictContent.flushToFile(dictPath)) {
+ AKLOGE("Shortcut dict content cannot be written. %s", tmpDirPath);
+ return false;
+ }
+ // Remove existing dictionary.
+ if (!FileUtils::removeDirAndFiles(dictDirPath)) {
+ AKLOGE("Existing directory %s cannot be removed.", dictDirPath);
+ ASSERT(false);
+ return false;
+ }
+ // Rename temporary directory.
+ if (rename(tmpDirPath, dictDirPath) != 0) {
+ AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath);
+ ASSERT(false);
+ return false;
+ }
+ return true;
+}
+
+Ver4DictBuffers::Ver4DictBuffers(const char *const dictPath,
+ MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
+ const FormatUtils::FORMAT_VERSION formatVersion)
+ : mHeaderBuffer(std::move(headerBuffer)),
+ mDictBuffer(MmappedBuffer::openBuffer(dictPath,
+ Ver4DictConstants::TRIE_FILE_EXTENSION, isUpdatable)),
+ mHeaderPolicy(mHeaderBuffer->getBuffer(), formatVersion),
+ mExpandableHeaderBuffer(mHeaderBuffer ? mHeaderBuffer->getBuffer() : nullptr,
+ mHeaderPolicy.getSize(),
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mExpandableTrieBuffer(mDictBuffer ? mDictBuffer->getBuffer() : nullptr,
+ mDictBuffer ? mDictBuffer->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mTerminalPositionLookupTable(dictPath, isUpdatable),
+ mProbabilityDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
+ mBigramDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
+ mShortcutDictContent(dictPath, isUpdatable),
+ mIsUpdatable(isUpdatable) {}
+
+Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize)
+ : mHeaderBuffer(nullptr), mDictBuffer(nullptr), mHeaderPolicy(headerPolicy),
+ mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+ mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
+ mProbabilityDictContent(headerPolicy->hasHistoricalInfoOfWords()),
+ mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
+ mIsUpdatable(true) {}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h
new file mode 100644
index 000000000..716ed931b
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_DICT_BUFFER_H
+#define LATINIME_BACKWARD_V401_VER4_DICT_BUFFER_H
+
+#include <memory>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/bigram_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/shortcut_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+class Ver4DictBuffers {
+ public:
+ typedef std::unique_ptr<Ver4DictBuffers> Ver4DictBuffersPtr;
+
+ static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
+ MmappedBuffer::MmappedBufferPtr headerBuffer,
+ const FormatUtils::FORMAT_VERSION formatVersion);
+
+ static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
+ const HeaderPolicy *const headerPolicy, const int maxTrieSize) {
+ return Ver4DictBuffersPtr(new Ver4DictBuffers(headerPolicy, maxTrieSize));
+ }
+
+ AK_FORCE_INLINE bool isValid() const {
+ return mHeaderBuffer && mDictBuffer && mHeaderPolicy.isValid()
+ && mProbabilityDictContent.isValid() && mTerminalPositionLookupTable.isValid()
+ && mBigramDictContent.isValid() && mShortcutDictContent.isValid();
+ }
+
+ AK_FORCE_INLINE bool isNearSizeLimit() const {
+ return mExpandableTrieBuffer.isNearSizeLimit()
+ || mTerminalPositionLookupTable.isNearSizeLimit()
+ || mProbabilityDictContent.isNearSizeLimit()
+ || mBigramDictContent.isNearSizeLimit()
+ || mShortcutDictContent.isNearSizeLimit();
+ }
+
+ AK_FORCE_INLINE const HeaderPolicy *getHeaderPolicy() const {
+ return &mHeaderPolicy;
+ }
+
+ AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() {
+ return &mExpandableHeaderBuffer;
+ }
+
+ AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() {
+ return &mExpandableTrieBuffer;
+ }
+
+ AK_FORCE_INLINE const BufferWithExtendableBuffer *getTrieBuffer() const {
+ return &mExpandableTrieBuffer;
+ }
+
+ AK_FORCE_INLINE TerminalPositionLookupTable *getMutableTerminalPositionLookupTable() {
+ return &mTerminalPositionLookupTable;
+ }
+
+ AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const {
+ return &mTerminalPositionLookupTable;
+ }
+
+ AK_FORCE_INLINE ProbabilityDictContent *getMutableProbabilityDictContent() {
+ return &mProbabilityDictContent;
+ }
+
+ AK_FORCE_INLINE const ProbabilityDictContent *getProbabilityDictContent() const {
+ return &mProbabilityDictContent;
+ }
+
+ AK_FORCE_INLINE BigramDictContent *getMutableBigramDictContent() {
+ return &mBigramDictContent;
+ }
+
+ AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const {
+ return &mBigramDictContent;
+ }
+
+ AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
+ return &mShortcutDictContent;
+ }
+
+ AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const {
+ return &mShortcutDictContent;
+ }
+
+ AK_FORCE_INLINE bool isUpdatable() const {
+ return mIsUpdatable;
+ }
+
+ bool flush(const char *const dictDirPath) const {
+ return flushHeaderAndDictBuffers(dictDirPath, &mExpandableHeaderBuffer);
+ }
+
+ bool flushHeaderAndDictBuffers(const char *const dictDirPath,
+ const BufferWithExtendableBuffer *const headerBuffer) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
+
+ Ver4DictBuffers(const char *const dictDirPath,
+ const MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
+ const FormatUtils::FORMAT_VERSION formatVersion);
+
+ Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize);
+
+ const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
+ const MmappedBuffer::MmappedBufferPtr mDictBuffer;
+ const HeaderPolicy mHeaderPolicy;
+ BufferWithExtendableBuffer mExpandableHeaderBuffer;
+ BufferWithExtendableBuffer mExpandableTrieBuffer;
+ TerminalPositionLookupTable mTerminalPositionLookupTable;
+ ProbabilityDictContent mProbabilityDictContent;
+ BigramDictContent mBigramDictContent;
+ ShortcutDictContent mShortcutDictContent;
+ const int mIsUpdatable;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_DICT_BUFFER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.cpp
new file mode 100644
index 000000000..793b44ed4
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+// These values MUST match the definitions in FormatSpec.java.
+const char *const Ver4DictConstants::TRIE_FILE_EXTENSION = ".trie";
+const char *const Ver4DictConstants::HEADER_FILE_EXTENSION = ".header";
+const char *const Ver4DictConstants::FREQ_FILE_EXTENSION = ".freq";
+// tat = Terminal Address Table
+const char *const Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
+const char *const Ver4DictConstants::BIGRAM_FILE_EXTENSION = ".bigram_freq";
+const char *const Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION = ".bigram_lookup";
+const char *const Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION = ".bigram_index_freq";
+const char *const Ver4DictConstants::SHORTCUT_FILE_EXTENSION = ".shortcut_shortcut";
+const char *const Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION = ".shortcut_lookup";
+const char *const Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION =
+ ".shortcut_index_shortcut";
+
+// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets.
+const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 8 * 1024 * 1024;
+// Extended region size, which is not GCed region size in dict file + additional buffer size, is
+// limited to 1MB to prevent from inefficient traversing.
+const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
+
+const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
+const int Ver4DictConstants::PROBABILITY_SIZE = 1;
+const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
+const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
+const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
+const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
+const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4;
+const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 1;
+const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 1;
+
+const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
+const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4;
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
+
+const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3;
+// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing
+// invalid terminal ID in bigram lists.
+const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID =
+ (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1;
+const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1;
+const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F;
+const int Ver4DictConstants::BIGRAM_HAS_NEXT_MASK = 0x80;
+const int Ver4DictConstants::BIGRAM_LARGE_PROBABILITY_FIELD_SIZE = 1;
+
+const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
+const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
+const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h
new file mode 100644
index 000000000..17afeb156
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_DICT_CONSTANTS_H
+#define LATINIME_BACKWARD_V401_VER4_DICT_CONSTANTS_H
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+// TODO: Create PtConstants under the pt_common and move some constant values there.
+// Note that there are corresponding definitions in FormatSpec.java.
+class Ver4DictConstants {
+ public:
+ static const char *const TRIE_FILE_EXTENSION;
+ static const char *const HEADER_FILE_EXTENSION;
+ static const char *const FREQ_FILE_EXTENSION;
+ static const char *const TERMINAL_ADDRESS_TABLE_FILE_EXTENSION;
+ static const char *const BIGRAM_FILE_EXTENSION;
+ static const char *const BIGRAM_LOOKUP_TABLE_FILE_EXTENSION;
+ static const char *const BIGRAM_CONTENT_TABLE_FILE_EXTENSION;
+ static const char *const SHORTCUT_FILE_EXTENSION;
+ static const char *const SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION;
+ static const char *const SHORTCUT_CONTENT_TABLE_FILE_EXTENSION;
+
+ static const int MAX_DICTIONARY_SIZE;
+ static const int MAX_DICT_EXTENDED_REGION_SIZE;
+
+ static const int NOT_A_TERMINAL_ID;
+ static const int PROBABILITY_SIZE;
+ static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
+ static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+ static const int NOT_A_TERMINAL_ADDRESS;
+ static const int TERMINAL_ID_FIELD_SIZE;
+ static const int TIME_STAMP_FIELD_SIZE;
+ static const int WORD_LEVEL_FIELD_SIZE;
+ static const int WORD_COUNT_FIELD_SIZE;
+
+ static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE;
+ static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE;
+ static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
+ static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
+
+ static const int BIGRAM_FLAGS_FIELD_SIZE;
+ static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
+ static const int INVALID_BIGRAM_TARGET_TERMINAL_ID;
+ static const int BIGRAM_PROBABILITY_MASK;
+ static const int BIGRAM_HAS_NEXT_MASK;
+ // Used when bigram list has time stamp.
+ static const int BIGRAM_LARGE_PROBABILITY_FIELD_SIZE;
+
+ static const int SHORTCUT_FLAGS_FIELD_SIZE;
+ static const int SHORTCUT_PROBABILITY_MASK;
+ static const int SHORTCUT_HAS_NEXT_MASK;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_DICT_CONSTANTS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.cpp
new file mode 100644
index 000000000..80b51b292
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h"
+
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
+ const int ptNodePos, const int siblingNodePos) const {
+ if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
+ // Reading invalid position because of bug or broken dictionary.
+ AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
+ ptNodePos, mBuffer->getTailPosition());
+ ASSERT(false);
+ return PtNodeParams();
+ }
+ const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
+ const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+ int pos = ptNodePos;
+ const int headPos = ptNodePos;
+ if (usesAdditionalBuffer) {
+ pos -= mBuffer->getOriginalBufferSize();
+ }
+ const PatriciaTrieReadingUtils::NodeFlags flags =
+ PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+ const int parentPosOffset =
+ DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
+ dictBuf, &pos);
+ const int parentPos =
+ DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
+ int codePoints[MAX_WORD_LENGTH];
+ const int codePonitCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
+ dictBuf, flags, MAX_WORD_LENGTH, codePoints, &pos);
+ int terminalIdFieldPos = NOT_A_DICT_POS;
+ int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+ int probability = NOT_A_PROBABILITY;
+ if (PatriciaTrieReadingUtils::isTerminal(flags)) {
+ terminalIdFieldPos = pos;
+ if (usesAdditionalBuffer) {
+ terminalIdFieldPos += mBuffer->getOriginalBufferSize();
+ }
+ terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
+ const ProbabilityEntry probabilityEntry =
+ mProbabilityDictContent->getProbabilityEntry(terminalId);
+ if (probabilityEntry.hasHistoricalInfo()) {
+ probability = ForgettingCurveUtils::decodeProbability(
+ probabilityEntry.getHistoricalInfo(), mHeaderPolicy);
+ } else {
+ probability = probabilityEntry.getProbability();
+ }
+ }
+ int childrenPosFieldPos = pos;
+ if (usesAdditionalBuffer) {
+ childrenPosFieldPos += mBuffer->getOriginalBufferSize();
+ }
+ int childrenPos = DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
+ dictBuf, &pos);
+ if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
+ childrenPos += mBuffer->getOriginalBufferSize();
+ }
+ if (usesAdditionalBuffer) {
+ pos += mBuffer->getOriginalBufferSize();
+ }
+ // Sibling position is the tail position of original PtNode.
+ int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos;
+ // Read destination node if the read node is a moved node.
+ if (DynamicPtReadingUtils::isMoved(flags)) {
+ // The destination position is stored at the same place as the parent position.
+ return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
+ } else {
+ return PtNodeParams(headPos, flags, parentPos, codePonitCount, codePoints,
+ terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos,
+ newSiblingNodePos);
+ }
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h
new file mode 100644
index 000000000..0531b0a29
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_READER_H
+#define LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_READER_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v401 {
+} // namespace v401
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v401 {
+class ProbabilityDictContent;
+
+/*
+ * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
+ * node and reads node attributes including probability form probabilityBuffer.
+ */
+class Ver4PatriciaTrieNodeReader : public PtNodeReader {
+ public:
+ Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
+ const ProbabilityDictContent *const probabilityDictContent,
+ const HeaderPolicy *const headerPolicy)
+ : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent),
+ mHeaderPolicy(headerPolicy) {}
+
+ ~Ver4PatriciaTrieNodeReader() {}
+
+ virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const {
+ return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
+ NOT_A_DICT_POS /* siblingNodePos */);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
+
+ const BufferWithExtendableBuffer *const mBuffer;
+ const ProbabilityDictContent *const mProbabilityDictContent;
+ const HeaderPolicy *const mHeaderPolicy;
+
+ const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
+ const int siblingNodePos) const;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.cpp
new file mode 100644
index 000000000..8de6bacfc
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.cpp
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h"
+
+#include "suggest/core/dictionary/property/unigram_property.h"
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3;
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted(
+ const PtNodeParams *const toBeUpdatedPtNodeParams) {
+ int pos = toBeUpdatedPtNodeParams->getHeadPos();
+ const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+ const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+ if (usesAdditionalBuffer) {
+ pos -= mTrieBuffer->getOriginalBufferSize();
+ }
+ // Read original flags
+ const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+ PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+ const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+ DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+ true /* isDeleted */, false /* willBecomeNonTerminal */);
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+ // Update flags.
+ if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+ &writingPos)) {
+ return false;
+ }
+ if (toBeUpdatedPtNodeParams->isTerminal()) {
+ // The PtNode is a terminal. Delete entry from the terminal position lookup table.
+ return mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+ toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */);
+ } else {
+ return true;
+ }
+}
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
+ const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const int movedPos, const int bigramLinkedNodePos) {
+ int pos = toBeUpdatedPtNodeParams->getHeadPos();
+ const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+ const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+ if (usesAdditionalBuffer) {
+ pos -= mTrieBuffer->getOriginalBufferSize();
+ }
+ // Read original flags
+ const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+ PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+ const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+ DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
+ false /* isDeleted */, false /* willBecomeNonTerminal */);
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+ // Update flags.
+ if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+ &writingPos)) {
+ return false;
+ }
+ // Update moved position, which is stored in the parent offset field.
+ if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+ mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+ return false;
+ }
+ if (toBeUpdatedPtNodeParams->hasChildren()) {
+ // Update children's parent position.
+ mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
+ while (!mReadingHelper.isEnd()) {
+ const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams());
+ int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
+ + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+ if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+ mTrieBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
+ &parentOffsetFieldPos)) {
+ // Parent offset cannot be written because of a bug or a broken dictionary; thus,
+ // we give up to update dictionary.
+ return false;
+ }
+ mReadingHelper.readNextSiblingNode(childPtNodeParams);
+ }
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsWillBecomeNonTerminal(
+ const PtNodeParams *const toBeUpdatedPtNodeParams) {
+ int pos = toBeUpdatedPtNodeParams->getHeadPos();
+ const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+ const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+ if (usesAdditionalBuffer) {
+ pos -= mTrieBuffer->getOriginalBufferSize();
+ }
+ // Read original flags
+ const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+ PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+ const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+ DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+ false /* isDeleted */, true /* willBecomeNonTerminal */);
+ if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+ toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */)) {
+ AKLOGE("Cannot update terminal position lookup table. terminal id: %d",
+ toBeUpdatedPtNodeParams->getTerminalId());
+ return false;
+ }
+ // Update flags.
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+ return DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+ &writingPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
+ const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const UnigramProperty *const unigramProperty) {
+ // Update probability and historical information.
+ // TODO: Update other information in the unigram property.
+ if (!toBeUpdatedPtNodeParams->isTerminal()) {
+ return false;
+ }
+ const ProbabilityEntry originalProbabilityEntry =
+ mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+ toBeUpdatedPtNodeParams->getTerminalId());
+ const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
+ unigramProperty);
+ return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+ toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+ const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
+ if (!toBeUpdatedPtNodeParams->isTerminal()) {
+ AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
+ return false;
+ }
+ const ProbabilityEntry originalProbabilityEntry =
+ mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+ toBeUpdatedPtNodeParams->getTerminalId());
+ if (originalProbabilityEntry.hasHistoricalInfo()) {
+ const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
+ originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy);
+ const ProbabilityEntry probabilityEntry =
+ originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo);
+ if (!mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+ toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) {
+ AKLOGE("Cannot write updated probability entry. terminalId: %d",
+ toBeUpdatedPtNodeParams->getTerminalId());
+ return false;
+ }
+ const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy);
+ if (!isValid) {
+ if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
+ AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
+ return false;
+ }
+ }
+ *outNeedsToKeepPtNode = isValid;
+ } else {
+ // No need to update probability.
+ *outNeedsToKeepPtNode = true;
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
+ const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
+ int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
+ return DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+ newChildrenPosition, &childrenPosFieldPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const int newTerminalId) {
+ return mTrieBuffer->writeUint(newTerminalId, Ver4DictConstants::TERMINAL_ID_FIELD_SIZE,
+ toBeUpdatedPtNodeParams->getTerminalIdFieldPos());
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition(
+ const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) {
+ return writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, 0 /* outTerminalId */,
+ ptNodeWritingPos);
+}
+
+
+bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
+ const PtNodeParams *const ptNodeParams, const UnigramProperty *const unigramProperty,
+ int *const ptNodeWritingPos) {
+ int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+ if (!writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, &terminalId,
+ ptNodeWritingPos)) {
+ return false;
+ }
+ // Write probability.
+ ProbabilityEntry newProbabilityEntry;
+ const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
+ &newProbabilityEntry, unigramProperty);
+ return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(terminalId,
+ &probabilityEntryToWrite);
+}
+
+bool Ver4PatriciaTrieNodeWriter::addNewBigramEntry(
+ const PtNodeParams *const sourcePtNodeParams, const PtNodeParams *const targetPtNodeParam,
+ const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
+ if (!mBigramPolicy->addNewEntry(sourcePtNodeParams->getTerminalId(),
+ targetPtNodeParam->getTerminalId(), bigramProperty, outAddedNewBigram)) {
+ AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
+ sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
+ return false;
+ }
+ if (!sourcePtNodeParams->hasBigrams()) {
+ // Update has bigrams flag.
+ return updatePtNodeFlags(sourcePtNodeParams->getHeadPos(),
+ sourcePtNodeParams->isBlacklisted(), sourcePtNodeParams->isNotAWord(),
+ sourcePtNodeParams->isTerminal(), sourcePtNodeParams->hasShortcutTargets(),
+ true /* hasBigrams */,
+ sourcePtNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::removeBigramEntry(
+ const PtNodeParams *const sourcePtNodeParams, const PtNodeParams *const targetPtNodeParam) {
+ return mBigramPolicy->removeEntry(sourcePtNodeParams->getTerminalId(),
+ targetPtNodeParam->getTerminalId());
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
+ const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
+ return mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(
+ sourcePtNodeParams->getTerminalId(), outBigramEntryCount);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
+ const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const DictPositionRelocationMap *const dictPositionRelocationMap,
+ int *const outBigramEntryCount) {
+ int parentPos = toBeUpdatedPtNodeParams->getParentPos();
+ if (parentPos != NOT_A_DICT_POS) {
+ PtNodeWriter::PtNodePositionRelocationMap::const_iterator it =
+ dictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
+ if (it != dictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
+ parentPos = it->second;
+ }
+ }
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos()
+ + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+ // Write updated parent offset.
+ if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+ parentPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+ return false;
+ }
+
+ // Updates children position.
+ int childrenPos = toBeUpdatedPtNodeParams->getChildrenPos();
+ if (childrenPos != NOT_A_DICT_POS) {
+ PtNodeWriter::PtNodeArrayPositionRelocationMap::const_iterator it =
+ dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
+ if (it != dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
+ childrenPos = it->second;
+ }
+ }
+ if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
+ return false;
+ }
+
+ // Counts bigram entries.
+ if (outBigramEntryCount) {
+ *outBigramEntryCount = mBigramPolicy->getBigramEntryConut(
+ toBeUpdatedPtNodeParams->getTerminalId());
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptNodeParams,
+ const int *const targetCodePoints, const int targetCodePointCount,
+ const int shortcutProbability) {
+ if (!mShortcutPolicy->addNewShortcut(ptNodeParams->getTerminalId(),
+ targetCodePoints, targetCodePointCount, shortcutProbability)) {
+ AKLOGE("Cannot add new shortuct entry. terminalId: %d", ptNodeParams->getTerminalId());
+ return false;
+ }
+ if (!ptNodeParams->hasShortcutTargets()) {
+ // Update has shortcut targets flag.
+ return updatePtNodeFlags(ptNodeParams->getHeadPos(),
+ ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
+ ptNodeParams->isTerminal(), true /* hasShortcutTargets */,
+ ptNodeParams->hasBigrams(),
+ ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeHasBigramsAndShortcutTargetsFlags(
+ const PtNodeParams *const ptNodeParams) {
+ const bool hasBigrams = mBuffers->getBigramDictContent()->getBigramListHeadPos(
+ ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
+ const bool hasShortcutTargets = mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
+ ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
+ return updatePtNodeFlags(ptNodeParams->getHeadPos(), ptNodeParams->isBlacklisted(),
+ ptNodeParams->isNotAWord(), ptNodeParams->isTerminal(), hasShortcutTargets,
+ hasBigrams, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
+ const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+ int *const ptNodeWritingPos) {
+ const int nodePos = *ptNodeWritingPos;
+ // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the
+ // PtNode writing.
+ if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer,
+ 0 /* nodeFlags */, ptNodeWritingPos)) {
+ return false;
+ }
+ // Calculate a parent offset and write the offset.
+ if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+ ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) {
+ return false;
+ }
+ // Write code points
+ if (!DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer,
+ ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) {
+ return false;
+ }
+ int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+ if (!ptNodeParams->willBecomeNonTerminal()) {
+ if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) {
+ terminalId = ptNodeParams->getTerminalId();
+ } else if (ptNodeParams->isTerminal()) {
+ // Write terminal information using a new terminal id.
+ // Get a new unused terminal id.
+ terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId();
+ }
+ }
+ const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
+ if (isTerminal) {
+ // Update the lookup table.
+ if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+ terminalId, nodePos)) {
+ return false;
+ }
+ // Write terminal Id.
+ if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId,
+ Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) {
+ return false;
+ }
+ if (outTerminalId) {
+ *outTerminalId = terminalId;
+ }
+ }
+ // Write children position
+ if (!DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+ ptNodeParams->getChildrenPos(), ptNodeWritingPos)) {
+ return false;
+ }
+ return updatePtNodeFlags(nodePos, ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
+ isTerminal, ptNodeParams->hasShortcutTargets(), ptNodeParams->hasBigrams(),
+ ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+}
+
+const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
+ const ProbabilityEntry *const originalProbabilityEntry,
+ const UnigramProperty *const unigramProperty) const {
+ // TODO: Consolidate historical info and probability.
+ if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+ const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
+ unigramProperty->getLevel(), unigramProperty->getCount());
+ const HistoricalInfo updatedHistoricalInfo =
+ ForgettingCurveUtils::createUpdatedHistoricalInfo(
+ originalProbabilityEntry->getHistoricalInfo(),
+ unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
+ return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
+ &updatedHistoricalInfo);
+ } else {
+ return originalProbabilityEntry->createEntryWithUpdatedProbability(
+ unigramProperty->getProbability());
+ }
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
+ const bool isBlacklisted, const bool isNotAWord, const bool isTerminal,
+ const bool hasShortcutTargets, const bool hasBigrams, const bool hasMultipleChars) {
+ // Create node flags and write them.
+ PatriciaTrieReadingUtils::NodeFlags nodeFlags =
+ PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, isTerminal,
+ hasShortcutTargets, hasBigrams, hasMultipleChars,
+ CHILDREN_POSITION_FIELD_SIZE);
+ if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
+ AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
+ return false;
+ }
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h
new file mode 100644
index 000000000..7f1851d63
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_WRITER_H
+#define LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_WRITER_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/probability_entry.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v401 {
+} // namespace v401
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v401 {
+class Ver4BigramListPolicy;
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PtNodeArrayReader;
+class Ver4ShortcutListPolicy;
+
+/*
+ * This class is used for helping to writes nodes of ver4 patricia trie.
+ */
+class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
+ public:
+ Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer,
+ Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy,
+ const PtNodeReader *const ptNodeReader,
+ const PtNodeArrayReader *const ptNodeArrayReader,
+ Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy)
+ : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy),
+ mReadingHelper(ptNodeReader, ptNodeArrayReader), mBigramPolicy(bigramPolicy),
+ mShortcutPolicy(shortcutPolicy) {}
+
+ virtual ~Ver4PatriciaTrieNodeWriter() {}
+
+ virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+ virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const int movedPos, const int bigramLinkedNodePos);
+
+ virtual bool markPtNodeAsWillBecomeNonTerminal(
+ const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+ virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const UnigramProperty *const unigramProperty);
+
+ virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+ const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
+
+ virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const int newChildrenPosition);
+
+ bool updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const int newTerminalId);
+
+ virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+ int *const ptNodeWritingPos);
+
+ virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+ const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
+
+ virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams,
+ const PtNodeParams *const targetPtNodeParam, const BigramProperty *const bigramProperty,
+ bool *const outAddedNewBigram);
+
+ virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams,
+ const PtNodeParams *const targetPtNodeParam);
+
+ virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
+ const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount);
+
+ virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
+ const DictPositionRelocationMap *const dictPositionRelocationMap,
+ int *const outBigramEntryCount);
+
+ virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
+ const int *const targetCodePoints, const int targetCodePointCount,
+ const int shortcutProbability);
+
+ bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
+
+ bool writePtNodeAndGetTerminalIdAndAdvancePosition(
+ const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+ int *const ptNodeWritingPos);
+
+ // Create updated probability entry using given unigram property. In addition to the
+ // probability, this method updates historical information if needed.
+ // TODO: Update flags belonging to the unigram property.
+ const ProbabilityEntry createUpdatedEntryFrom(
+ const ProbabilityEntry *const originalProbabilityEntry,
+ const UnigramProperty *const unigramProperty) const;
+
+ bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
+ const bool isTerminal, const bool hasShortcutTargets, const bool hasBigrams,
+ const bool hasMultipleChars);
+
+ static const int CHILDREN_POSITION_FIELD_SIZE;
+
+ BufferWithExtendableBuffer *const mTrieBuffer;
+ Ver4DictBuffers *const mBuffers;
+ const HeaderPolicy *const mHeaderPolicy;
+ DynamicPtReadingHelper mReadingHelper;
+ Ver4BigramListPolicy *const mBigramPolicy;
+ Ver4ShortcutListPolicy *const mShortcutPolicy;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_NODE_WRITER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp
new file mode 100644
index 000000000..dde1af299
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h"
+
+#include <vector>
+
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/dictionary/property/bigram_property.h"
+#include "suggest/core/dictionary/property/unigram_property.h"
+#include "suggest/core/dictionary/property/word_property.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
+#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+// Note that there are corresponding definitions in Java side in BinaryDictionaryTests and
+// BinaryDictionaryDecayingTests.
+const char *const Ver4PatriciaTriePolicy::UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
+const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024;
+const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
+ Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+
+void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
+ DicNodeVector *const childDicNodes) const {
+ if (!dicNode->hasChildren()) {
+ return;
+ }
+ DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+ readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
+ while (!readingHelper.isEnd()) {
+ const PtNodeParams ptNodeParams = readingHelper.getPtNodeParams();
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
+ bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
+ if (isTerminal && mHeaderPolicy->isDecayingDict()) {
+ // A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
+ // probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
+ // valid terminal DicNode.
+ isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
+ }
+ childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
+ ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
+ ptNodeParams.hasChildren(),
+ ptNodeParams.isBlacklisted()
+ || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
+ ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
+ readingHelper.readNextSiblingNode(ptNodeParams);
+ }
+ if (readingHelper.isError()) {
+ mIsCorrupted = true;
+ AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
+ }
+}
+
+int Ver4PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
+ const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
+ int *const outUnigramProbability) const {
+ DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+ readingHelper.initWithPtNodePos(ptNodePos);
+ const int codePointCount = readingHelper.getCodePointsAndProbabilityAndReturnCodePointCount(
+ maxCodePointCount, outCodePoints, outUnigramProbability);
+ if (readingHelper.isError()) {
+ mIsCorrupted = true;
+ AKLOGE("Dictionary reading error in getCodePointsAndProbabilityAndReturnCodePointCount().");
+ }
+ return codePointCount;
+}
+
+int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
+ const int length, const bool forceLowerCaseSearch) const {
+ DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+ readingHelper.initWithPtNodeArrayPos(getRootPosition());
+ const int ptNodePos =
+ readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
+ if (readingHelper.isError()) {
+ mIsCorrupted = true;
+ AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
+ }
+ return ptNodePos;
+}
+
+int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
+ const int bigramProbability) const {
+ if (mHeaderPolicy->isDecayingDict()) {
+ // Both probabilities are encoded. Decode them and get probability.
+ return ForgettingCurveUtils::getProbability(unigramProbability, bigramProbability);
+ } else {
+ if (unigramProbability == NOT_A_PROBABILITY) {
+ return NOT_A_PROBABILITY;
+ } else if (bigramProbability == NOT_A_PROBABILITY) {
+ return ProbabilityUtils::backoff(unigramProbability);
+ } else {
+ // bigramProbability is a bigram probability delta.
+ return ProbabilityUtils::computeProbabilityForBigram(unigramProbability,
+ bigramProbability);
+ }
+ }
+}
+
+int Ver4PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) const {
+ if (ptNodePos == NOT_A_DICT_POS) {
+ return NOT_A_PROBABILITY;
+ }
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
+ return NOT_A_PROBABILITY;
+ }
+ return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
+}
+
+int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
+ if (ptNodePos == NOT_A_DICT_POS) {
+ return NOT_A_DICT_POS;
+ }
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted()) {
+ return NOT_A_DICT_POS;
+ }
+ return mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
+ ptNodeParams.getTerminalId());
+}
+
+int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
+ if (ptNodePos == NOT_A_DICT_POS) {
+ return NOT_A_DICT_POS;
+ }
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted()) {
+ return NOT_A_DICT_POS;
+ }
+ return mBuffers->getBigramDictContent()->getBigramListHeadPos(
+ ptNodeParams.getTerminalId());
+}
+
+bool Ver4PatriciaTriePolicy::addUnigramWord(const int *const word, const int length,
+ const UnigramProperty *const unigramProperty) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: addUnigramWord() is called for non-updatable dictionary.");
+ return false;
+ }
+ if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+ AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+ mDictBuffer->getTailPosition());
+ return false;
+ }
+ if (length > MAX_WORD_LENGTH) {
+ AKLOGE("The word is too long to insert to the dictionary, length: %d", length);
+ return false;
+ }
+ for (const auto &shortcut : unigramProperty->getShortcuts()) {
+ if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+ AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
+ shortcut.getTargetCodePoints()->size());
+ return false;
+ }
+ }
+ DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+ readingHelper.initWithPtNodeArrayPos(getRootPosition());
+ bool addedNewUnigram = false;
+ if (mUpdatingHelper.addUnigramWord(&readingHelper, word, length,
+ unigramProperty, &addedNewUnigram)) {
+ if (addedNewUnigram) {
+ mUnigramCount++;
+ }
+ if (unigramProperty->getShortcuts().size() > 0) {
+ // Add shortcut target.
+ const int wordPos = getTerminalPtNodePositionOfWord(word, length,
+ false /* forceLowerCaseSearch */);
+ if (wordPos == NOT_A_DICT_POS) {
+ AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
+ return false;
+ }
+ for (const auto &shortcut : unigramProperty->getShortcuts()) {
+ if (!mUpdatingHelper.addShortcutTarget(wordPos,
+ shortcut.getTargetCodePoints()->data(),
+ shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
+ AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
+ "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
+ shortcut.getProbability());
+ return false;
+ }
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
+ return false;
+ }
+ if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+ AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+ mDictBuffer->getTailPosition());
+ return false;
+ }
+ if (length0 > MAX_WORD_LENGTH
+ || bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+ AKLOGE("Either src word or target word is too long to insert the bigram to the dictionary. "
+ "length0: %d, length1: %d", length0, bigramProperty->getTargetCodePoints()->size());
+ return false;
+ }
+ const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0,
+ false /* forceLowerCaseSearch */);
+ if (word0Pos == NOT_A_DICT_POS) {
+ return false;
+ }
+ const int word1Pos = getTerminalPtNodePositionOfWord(
+ bigramProperty->getTargetCodePoints()->data(),
+ bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
+ if (word1Pos == NOT_A_DICT_POS) {
+ return false;
+ }
+ bool addedNewBigram = false;
+ if (mUpdatingHelper.addBigramWords(word0Pos, word1Pos, bigramProperty, &addedNewBigram)) {
+ if (addedNewBigram) {
+ mBigramCount++;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Ver4PatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0,
+ const int *const word1, const int length1) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
+ return false;
+ }
+ if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+ AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+ mDictBuffer->getTailPosition());
+ return false;
+ }
+ if (length0 > MAX_WORD_LENGTH || length1 > MAX_WORD_LENGTH) {
+ AKLOGE("Either src word or target word is too long to remove the bigram to from the "
+ "dictionary. length0: %d, length1: %d", length0, length1);
+ return false;
+ }
+ const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0,
+ false /* forceLowerCaseSearch */);
+ if (word0Pos == NOT_A_DICT_POS) {
+ return false;
+ }
+ const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1,
+ false /* forceLowerCaseSearch */);
+ if (word1Pos == NOT_A_DICT_POS) {
+ return false;
+ }
+ if (mUpdatingHelper.removeBigramWords(word0Pos, word1Pos)) {
+ mBigramCount--;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Ver4PatriciaTriePolicy::flush(const char *const filePath) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath);
+ return;
+ }
+ if (!mWritingHelper.writeToDictFile(filePath, mUnigramCount, mBigramCount)) {
+ AKLOGE("Cannot flush the dictionary to file.");
+ mIsCorrupted = true;
+ }
+}
+
+void Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
+ return;
+ }
+ if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) {
+ AKLOGE("Cannot flush the dictionary to file with GC.");
+ mIsCorrupted = true;
+ }
+}
+
+bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
+ return false;
+ }
+ if (mBuffers->isNearSizeLimit()) {
+ // Additional buffer size is near the limit.
+ return true;
+ } else if (mHeaderPolicy->getExtendedRegionSize() + mDictBuffer->getUsedAdditionalBufferSize()
+ > Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE) {
+ // Total extended region size of the trie exceeds the limit.
+ return true;
+ } else if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS
+ && mDictBuffer->getUsedAdditionalBufferSize() > 0) {
+ // Needs to reduce dictionary size.
+ return true;
+ } else if (mHeaderPolicy->isDecayingDict()) {
+ return ForgettingCurveUtils::needsToDecay(mindsBlockByGC, mUnigramCount, mBigramCount,
+ mHeaderPolicy);
+ }
+ return false;
+}
+
+void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength,
+ char *const outResult, const int maxResultLength) {
+ const int compareLength = queryLength + 1 /* terminator */;
+ if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+ snprintf(outResult, maxResultLength, "%d", mUnigramCount);
+ } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) {
+ snprintf(outResult, maxResultLength, "%d", mBigramCount);
+ } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+ snprintf(outResult, maxResultLength, "%d",
+ mHeaderPolicy->isDecayingDict() ?
+ ForgettingCurveUtils::getUnigramCountHardLimit(
+ mHeaderPolicy->getMaxUnigramCount()) :
+ static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+ } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) {
+ snprintf(outResult, maxResultLength, "%d",
+ mHeaderPolicy->isDecayingDict() ?
+ ForgettingCurveUtils::getBigramCountHardLimit(
+ mHeaderPolicy->getMaxBigramCount()) :
+ static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+ }
+}
+
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
+ const int codePointCount) const {
+ const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
+ false /* forceLowerCaseSearch */);
+ if (ptNodePos == NOT_A_DICT_POS) {
+ AKLOGE("getWordProperty is called for invalid word.");
+ return WordProperty();
+ }
+ const PtNodeParams ptNodeParams = mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
+ ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
+ const ProbabilityEntry probabilityEntry =
+ mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+ ptNodeParams.getTerminalId());
+ const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+ // Fetch bigram information.
+ std::vector<BigramProperty> bigrams;
+ const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
+ if (bigramListPos != NOT_A_DICT_POS) {
+ int bigramWord1CodePoints[MAX_WORD_LENGTH];
+ const BigramDictContent *const bigramDictContent = mBuffers->getBigramDictContent();
+ const TerminalPositionLookupTable *const terminalPositionLookupTable =
+ mBuffers->getTerminalPositionLookupTable();
+ bool hasNext = true;
+ int readingPos = bigramListPos;
+ while (hasNext) {
+ const BigramEntry bigramEntry =
+ bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ const int word1TerminalId = bigramEntry.getTargetTerminalId();
+ const int word1TerminalPtNodePos =
+ terminalPositionLookupTable->getTerminalPtNodePosition(word1TerminalId);
+ if (word1TerminalPtNodePos == NOT_A_DICT_POS) {
+ continue;
+ }
+ // Word (unigram) probability
+ int word1Probability = NOT_A_PROBABILITY;
+ const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+ word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
+ &word1Probability);
+ const std::vector<int> word1(bigramWord1CodePoints,
+ bigramWord1CodePoints + codePointCount);
+ const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
+ const int probability = bigramEntry.hasHistoricalInfo() ?
+ ForgettingCurveUtils::decodeProbability(
+ bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
+ getProbability(word1Probability, bigramEntry.getProbability());
+ bigrams.emplace_back(&word1, probability,
+ historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+ historicalInfo->getCount());
+ }
+ }
+ // Fetch shortcut information.
+ std::vector<UnigramProperty::ShortcutProperty> shortcuts;
+ int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
+ if (shortcutPos != NOT_A_DICT_POS) {
+ int shortcutTarget[MAX_WORD_LENGTH];
+ const ShortcutDictContent *const shortcutDictContent =
+ mBuffers->getShortcutDictContent();
+ bool hasNext = true;
+ while (hasNext) {
+ int shortcutTargetLength = 0;
+ int shortcutProbability = NOT_A_PROBABILITY;
+ shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
+ &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
+ const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
+ shortcuts.emplace_back(&target, shortcutProbability);
+ }
+ }
+ const UnigramProperty unigramProperty(ptNodeParams.isNotAWord(),
+ ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
+ historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+ historicalInfo->getCount(), &shortcuts);
+ return WordProperty(&codePointVector, &unigramProperty, &bigrams);
+}
+
+int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints) {
+ // TODO: Return code point count like other methods.
+ // Null termination.
+ outCodePoints[0] = 0;
+ if (token == 0) {
+ mTerminalPtNodePositionsForIteratingWords.clear();
+ DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
+ &mTerminalPtNodePositionsForIteratingWords);
+ DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+ readingHelper.initWithPtNodeArrayPos(getRootPosition());
+ readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
+ }
+ const int terminalPtNodePositionsVectorSize =
+ static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
+ if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
+ AKLOGE("Given token %d is invalid.", token);
+ return 0;
+ }
+ const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
+ int unigramProbability = NOT_A_PROBABILITY;
+ const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+ terminalPtNodePos, MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
+ if (codePointCount < MAX_WORD_LENGTH) {
+ // Null termination. outCodePoints have to be null terminated or contain MAX_WORD_LENGTH
+ // code points.
+ outCodePoints[codePointCount] = 0;
+ }
+ const int nextToken = token + 1;
+ if (nextToken >= terminalPtNodePositionsVectorSize) {
+ // All words have been iterated.
+ mTerminalPtNodePositionsForIteratingWords.clear();
+ return 0;
+ }
+ return nextToken;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h
new file mode 100644
index 000000000..2f8ad539c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_POLICY_H
+#define LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_POLICY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class DicNode;
+namespace backward {
+namespace v401 {
+} // namespace v401
+} // namespace backward
+class DicNodeVector;
+namespace backward {
+namespace v401 {
+
+class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
+ public:
+ Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
+ : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
+ mDictBuffer(mBuffers->getWritableTrieBuffer()),
+ mBigramPolicy(mBuffers->getMutableBigramDictContent(),
+ mBuffers->getTerminalPositionLookupTable(), mHeaderPolicy),
+ mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+ mBuffers->getTerminalPositionLookupTable()),
+ mNodeReader(mDictBuffer, mBuffers->getProbabilityDictContent(), mHeaderPolicy),
+ mPtNodeArrayReader(mDictBuffer),
+ mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
+ &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy),
+ mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
+ mWritingHelper(mBuffers.get()),
+ mUnigramCount(mHeaderPolicy->getUnigramCount()),
+ mBigramCount(mHeaderPolicy->getBigramCount()),
+ mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
+
+ AK_FORCE_INLINE int getRootPosition() const {
+ return 0;
+ }
+
+ void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+ DicNodeVector *const childDicNodes) const;
+
+ int getCodePointsAndProbabilityAndReturnCodePointCount(
+ const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
+ int *const outUnigramProbability) const;
+
+ int getTerminalPtNodePositionOfWord(const int *const inWord,
+ const int length, const bool forceLowerCaseSearch) const;
+
+ int getProbability(const int unigramProbability, const int bigramProbability) const;
+
+ int getUnigramProbabilityOfPtNode(const int ptNodePos) const;
+
+ int getShortcutPositionOfPtNode(const int ptNodePos) const;
+
+ int getBigramsPositionOfPtNode(const int ptNodePos) const;
+
+ const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+ return mHeaderPolicy;
+ }
+
+ const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const {
+ return &mBigramPolicy;
+ }
+
+ const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const {
+ return &mShortcutPolicy;
+ }
+
+ bool addUnigramWord(const int *const word, const int length,
+ const UnigramProperty *const unigramProperty);
+
+ bool addBigramWords(const int *const word0, const int length0,
+ const BigramProperty *const bigramProperty);
+
+ bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
+ const int length1);
+
+ void flush(const char *const filePath);
+
+ void flushWithGC(const char *const filePath);
+
+ bool needsToRunGC(const bool mindsBlockByGC) const;
+
+ void getProperty(const char *const query, const int queryLength, char *const outResult,
+ const int maxResultLength);
+
+ const WordProperty getWordProperty(const int *const codePoints,
+ const int codePointCount) const;
+
+ int getNextWordAndNextToken(const int token, int *const outCodePoints);
+
+ bool isCorrupted() const {
+ return mIsCorrupted;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
+
+ static const char *const UNIGRAM_COUNT_QUERY;
+ static const char *const BIGRAM_COUNT_QUERY;
+ static const char *const MAX_UNIGRAM_COUNT_QUERY;
+ static const char *const MAX_BIGRAM_COUNT_QUERY;
+ // When the dictionary size is near the maximum size, we have to refuse dynamic operations to
+ // prevent the dictionary from overflowing.
+ static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+ static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
+
+ const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
+ const HeaderPolicy *const mHeaderPolicy;
+ BufferWithExtendableBuffer *const mDictBuffer;
+ Ver4BigramListPolicy mBigramPolicy;
+ Ver4ShortcutListPolicy mShortcutPolicy;
+ Ver4PatriciaTrieNodeReader mNodeReader;
+ Ver4PtNodeArrayReader mPtNodeArrayReader;
+ Ver4PatriciaTrieNodeWriter mNodeWriter;
+ DynamicPtUpdatingHelper mUpdatingHelper;
+ Ver4PatriciaTrieWritingHelper mWritingHelper;
+ int mUnigramCount;
+ int mBigramCount;
+ std::vector<int> mTerminalPtNodePositionsForIteratingWords;
+ mutable bool mIsCorrupted;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.cpp
new file mode 100644
index 000000000..6cc36fbef
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h"
+
+#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(
+ const uint8_t *const buffer, int *pos) {
+ return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos);
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h
new file mode 100644
index 000000000..7417c261e
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_reading_utils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_READING_UTILS_H
+#define LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_READING_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v401 {
+
+class Ver4PatriciaTrieReadingUtils {
+ public:
+ static int getTerminalIdAndAdvancePosition(const uint8_t *const buffer,
+ int *const pos);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieReadingUtils);
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_READING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.cpp
new file mode 100644
index 000000000..10f27beb7
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h"
+
+#include <cstring>
+#include <queue>
+
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/bigram/ver4_bigram_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/shortcut/ver4_shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_node_writer.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/file_utils.h"
+#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFile(const char *const dictDirPath,
+ const int unigramCount, const int bigramCount) const {
+ const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+ BufferWithExtendableBuffer headerBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+ const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
+ + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
+ if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
+ unigramCount, bigramCount, extendedRegionSize, &headerBuffer)) {
+ AKLOGE("Cannot write header structure to buffer. "
+ "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, "
+ "extendedRegionSize: %d", false, unigramCount, bigramCount,
+ extendedRegionSize);
+ return false;
+ }
+ return mBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
+ const char *const dictDirPath) {
+ const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+ Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
+ Ver4DictBuffers::createVer4DictBuffers(headerPolicy,
+ Ver4DictConstants::MAX_DICTIONARY_SIZE));
+ int unigramCount = 0;
+ int bigramCount = 0;
+ if (!runGC(rootPtNodeArrayPos, headerPolicy, dictBuffers.get(), &unigramCount, &bigramCount)) {
+ return false;
+ }
+ BufferWithExtendableBuffer headerBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+ if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+ unigramCount, bigramCount, 0 /* extendedRegionSize */, &headerBuffer)) {
+ return false;
+ }
+ return dictBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
+ const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
+ int *const outUnigramCount, int *const outBigramCount) {
+ Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
+ mBuffers->getProbabilityDictContent(), headerPolicy);
+ Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
+ Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(),
+ mBuffers->getTerminalPositionLookupTable(), headerPolicy);
+ Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+ mBuffers->getTerminalPositionLookupTable());
+ Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
+ mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
+ &shortcutPolicy);
+
+ DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader);
+ readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+ DynamicPtGcEventListeners
+ ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+ traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
+ &ptNodeWriter);
+ if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+ &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
+ return false;
+ }
+ const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+ .getValidUnigramCount();
+ const int maxUnigramCount = headerPolicy->getMaxUnigramCount();
+ if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) {
+ if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) {
+ AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount,
+ maxUnigramCount);
+ return false;
+ }
+ }
+
+ readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+ DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
+ traversePolicyToUpdateBigramProbability(&ptNodeWriter);
+ if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+ &traversePolicyToUpdateBigramProbability)) {
+ return false;
+ }
+ const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount();
+ const int maxBigramCount = headerPolicy->getMaxBigramCount();
+ if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) {
+ if (!truncateBigrams(maxBigramCount)) {
+ AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount);
+ return false;
+ }
+ }
+
+ // Mapping from positions in mBuffer to positions in bufferToWrite.
+ PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
+ readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+ Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
+ buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
+ &shortcutPolicy);
+ DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+ traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
+ buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
+ if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+ &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
+ return false;
+ }
+
+ // Create policy instances for the GCed dictionary.
+ Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
+ buffersToWrite->getProbabilityDictContent(), headerPolicy);
+ Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
+ Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(),
+ buffersToWrite->getTerminalPositionLookupTable(), headerPolicy);
+ Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
+ buffersToWrite->getTerminalPositionLookupTable());
+ Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
+ buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy,
+ &newShortcutPolicy);
+ // Re-assign terminal IDs for valid terminal PtNodes.
+ TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
+ if(!buffersToWrite->getMutableTerminalPositionLookupTable()->runGCTerminalIds(
+ &terminalIdMap)) {
+ return false;
+ }
+ // Run GC for probability dict content.
+ if (!buffersToWrite->getMutableProbabilityDictContent()->runGC(&terminalIdMap,
+ mBuffers->getProbabilityDictContent())) {
+ return false;
+ }
+ // Run GC for bigram dict content.
+ if(!buffersToWrite->getMutableBigramDictContent()->runGC(&terminalIdMap,
+ mBuffers->getBigramDictContent(), outBigramCount)) {
+ return false;
+ }
+ // Run GC for shortcut dict content.
+ if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
+ mBuffers->getShortcutDictContent())) {
+ return false;
+ }
+ DynamicPtReadingHelper newDictReadingHelper(&newPtNodeReader, &newPtNodeArrayreader);
+ newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+ DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
+ traversePolicyToUpdateAllPositionFields(&newPtNodeWriter, &dictPositionRelocationMap);
+ if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+ &traversePolicyToUpdateAllPositionFields)) {
+ return false;
+ }
+ newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+ TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+ traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(&newPtNodeWriter, &terminalIdMap);
+ if (!newDictReadingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+ &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
+ return false;
+ }
+ *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount();
+ return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
+ const Ver4PatriciaTrieNodeReader *const ptNodeReader,
+ Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount) {
+ const TerminalPositionLookupTable *const terminalPosLookupTable =
+ mBuffers->getTerminalPositionLookupTable();
+ const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
+ std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
+ priorityQueue;
+ for (int i = 0; i < nextTerminalId; ++i) {
+ const int terminalPos = terminalPosLookupTable->getTerminalPtNodePosition(i);
+ if (terminalPos == NOT_A_DICT_POS) {
+ continue;
+ }
+ const ProbabilityEntry probabilityEntry =
+ mBuffers->getProbabilityDictContent()->getProbabilityEntry(i);
+ const int probability = probabilityEntry.hasHistoricalInfo() ?
+ ForgettingCurveUtils::decodeProbability(
+ probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
+ probabilityEntry.getProbability();
+ priorityQueue.push(DictProbability(terminalPos, probability,
+ probabilityEntry.getHistoricalInfo()->getTimeStamp()));
+ }
+
+ // Delete unigrams.
+ while (static_cast<int>(priorityQueue.size()) > maxUnigramCount) {
+ const int ptNodePos = priorityQueue.top().getDictPos();
+ const PtNodeParams ptNodeParams =
+ ptNodeReader->fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ if (!ptNodeWriter->markPtNodeAsWillBecomeNonTerminal(&ptNodeParams)) {
+ AKLOGE("Cannot mark PtNode as willBecomeNonterminal. PtNode pos: %d", ptNodePos);
+ return false;
+ }
+ priorityQueue.pop();
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) {
+ const TerminalPositionLookupTable *const terminalPosLookupTable =
+ mBuffers->getTerminalPositionLookupTable();
+ const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
+ std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
+ priorityQueue;
+ BigramDictContent *const bigramDictContent = mBuffers->getMutableBigramDictContent();
+ for (int i = 0; i < nextTerminalId; ++i) {
+ const int bigramListPos = bigramDictContent->getBigramListHeadPos(i);
+ if (bigramListPos == NOT_A_DICT_POS) {
+ continue;
+ }
+ bool hasNext = true;
+ int readingPos = bigramListPos;
+ while (hasNext) {
+ const int entryPos = readingPos;
+ const BigramEntry bigramEntry =
+ bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+ hasNext = bigramEntry.hasNext();
+ if (!bigramEntry.isValid()) {
+ continue;
+ }
+ const int probability = bigramEntry.hasHistoricalInfo() ?
+ ForgettingCurveUtils::decodeProbability(
+ bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
+ bigramEntry.getProbability();
+ priorityQueue.push(DictProbability(entryPos, probability,
+ bigramEntry.getHistoricalInfo()->getTimeStamp()));
+ }
+ }
+
+ // Delete bigrams.
+ while (static_cast<int>(priorityQueue.size()) > maxBigramCount) {
+ const int entryPos = priorityQueue.top().getDictPos();
+ const BigramEntry bigramEntry = bigramDictContent->getBigramEntry(entryPos);
+ const BigramEntry invalidatedBigramEntry = bigramEntry.getInvalidatedEntry();
+ if (!bigramDictContent->writeBigramEntry(&invalidatedBigramEntry, entryPos)) {
+ AKLOGE("Cannot write bigram entry to remove. pos: %d", entryPos);
+ return false;
+ }
+ priorityQueue.pop();
+ }
+ return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+ ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+ if (!ptNodeParams->isTerminal()) {
+ return true;
+ }
+ TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
+ mTerminalIdMap->find(ptNodeParams->getTerminalId());
+ if (it == mTerminalIdMap->end()) {
+ AKLOGE("terminal Id %d is not in the terminal position map. map size: %zd",
+ ptNodeParams->getTerminalId(), mTerminalIdMap->size());
+ return false;
+ }
+ if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
+ AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
+ }
+ return mPtNodeWriter->updatePtNodeHasBigramsAndShortcutTargetsFlags(ptNodeParams);
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h
new file mode 100644
index 000000000..be44aaa33
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_writing_helper.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+#define LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
+#include "suggest/policyimpl/dictionary/structure/backward/v401/content/terminal_position_lookup_table.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v401 {
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PatriciaTrieNodeWriter;
+
+class Ver4PatriciaTrieWritingHelper {
+ public:
+ Ver4PatriciaTrieWritingHelper(Ver4DictBuffers *const buffers)
+ : mBuffers(buffers) {}
+
+ bool writeToDictFile(const char *const dictDirPath, const int unigramCount,
+ const int bigramCount) const;
+
+ // This method cannot be const because the original dictionary buffer will be updated to detect
+ // useless PtNodes during GC.
+ bool writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const dictDirPath);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieWritingHelper);
+
+ class TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+ : public DynamicPtReadingHelper::TraversingEventListener {
+ public:
+ TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(
+ Ver4PatriciaTrieNodeWriter *const ptNodeWriter,
+ const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap)
+ : mPtNodeWriter(ptNodeWriter), mTerminalIdMap(terminalIdMap) {}
+
+ bool onAscend() { return true; }
+
+ bool onDescend(const int ptNodeArrayPos) { return true; }
+
+ bool onReadingPtNodeArrayTail() { return true; }
+
+ bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds);
+
+ Ver4PatriciaTrieNodeWriter *const mPtNodeWriter;
+ const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
+ };
+
+ // For truncateUnigrams() and truncateBigrams().
+ class DictProbability {
+ public:
+ DictProbability(const int dictPos, const int probability, const int timestamp)
+ : mDictPos(dictPos), mProbability(probability), mTimestamp(timestamp) {}
+
+ int getDictPos() const {
+ return mDictPos;
+ }
+
+ int getProbability() const {
+ return mProbability;
+ }
+
+ int getTimestamp() const {
+ return mTimestamp;
+ }
+
+ private:
+ DISALLOW_DEFAULT_CONSTRUCTOR(DictProbability);
+
+ int mDictPos;
+ int mProbability;
+ int mTimestamp;
+ };
+
+ // For truncateUnigrams() and truncateBigrams().
+ class DictProbabilityComparator {
+ public:
+ bool operator()(const DictProbability &left, const DictProbability &right) {
+ if (left.getProbability() != right.getProbability()) {
+ return left.getProbability() > right.getProbability();
+ }
+ if (left.getTimestamp() != right.getTimestamp()) {
+ return left.getTimestamp() < right.getTimestamp();
+ }
+ return left.getDictPos() > right.getDictPos();
+ }
+
+ private:
+ DISALLOW_ASSIGNMENT_OPERATOR(DictProbabilityComparator);
+ };
+
+ bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
+ Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount,
+ int *const outBigramCount);
+
+ bool truncateUnigrams(const Ver4PatriciaTrieNodeReader *const ptNodeReader,
+ Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount);
+
+ bool truncateBigrams(const int maxBigramCount);
+
+ Ver4DictBuffers *const mBuffers;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+
+#endif /* LATINIME_BACKWARD_V401_VER4_PATRICIA_TRIE_WRITING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.cpp
new file mode 100644
index 000000000..33e4e55e2
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
+ */
+
+#include "suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h"
+
+#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+ int *const outPtNodeCount, int *const outFirstPtNodePos) const {
+ if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
+ // Reading invalid position because of a bug or a broken dictionary.
+ AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
+ ptNodeArrayPos, mBuffer->getTailPosition());
+ ASSERT(false);
+ return false;
+ }
+ const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
+ const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+ int readingPos = ptNodeArrayPos;
+ if (usesAdditionalBuffer) {
+ readingPos -= mBuffer->getOriginalBufferSize();
+ }
+ const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+ dictBuf, &readingPos);
+ if (usesAdditionalBuffer) {
+ readingPos += mBuffer->getOriginalBufferSize();
+ }
+ if (ptNodeCountInArray < 0) {
+ AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
+ return false;
+ }
+ *outPtNodeCount = ptNodeCountInArray;
+ *outFirstPtNodePos = readingPos;
+ return true;
+}
+
+bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+ int *const outNextPtNodeArrayPos) const {
+ if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
+ // Reading invalid position because of bug or broken dictionary.
+ AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
+ forwordLinkPos, mBuffer->getTailPosition());
+ ASSERT(false);
+ return false;
+ }
+ const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
+ const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+ int readingPos = forwordLinkPos;
+ if (usesAdditionalBuffer) {
+ readingPos -= mBuffer->getOriginalBufferSize();
+ }
+ const int nextPtNodeArrayOffset =
+ DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
+ if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
+ *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
+ } else {
+ *outNextPtNodeArrayPos = NOT_A_DICT_POS;
+ }
+ return true;
+}
+
+} // namespace v401
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h
new file mode 100644
index 000000000..3a7eefa44
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_pt_node_array_reader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ * suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h
+ */
+
+#ifndef LATINIME_BACKWARD_V401_VER4_PT_NODE_ARRAY_READER_H
+#define LATINIME_BACKWARD_V401_VER4_PT_NODE_ARRAY_READER_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h"
+
+namespace latinime {
+namespace backward {
+namespace v401 {
+
+} // namespace v401
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v401 {
+
+class Ver4PtNodeArrayReader : public PtNodeArrayReader {
+ public:
+ Ver4PtNodeArrayReader(const BufferWithExtendableBuffer *const buffer) : mBuffer(buffer) {};
+
+ virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+ int *const outPtNodeCount, int *const outFirstPtNodePos) const;
+ virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+ int *const outNextPtNodeArrayPos) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Ver4PtNodeArrayReader);
+
+ const BufferWithExtendableBuffer *const mBuffer;
+};
+} // namespace v401
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V401_VER4_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
index 91192fc57..bef401f87 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
@@ -23,6 +23,7 @@
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+#include "utils/char_utils.h"
namespace latinime {
@@ -158,6 +159,10 @@ class PtNodeParams {
return PatriciaTrieReadingUtils::hasShortcutTargets(mFlags);
}
+ AK_FORCE_INLINE bool representsNonWordInfo() const {
+ return getCodePointCount() > 0 && CharUtils::isInUnicodeSpace(getCodePoints()[0]);
+ }
+
// Parent node position
AK_FORCE_INLINE int getParentPos() const {
return mParentPos;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index b3af1f47a..30dcfba37 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -24,6 +24,7 @@
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
+#include "utils/char_utils.h"
namespace latinime {
@@ -318,12 +319,15 @@ int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNod
PatriciaTrieReadingUtils::readPtNodeInfo(mDictRoot, ptNodePos, getShortcutsStructurePolicy(),
getBigramsStructurePolicy(), &flags, &mergedNodeCodePointCount, mergedNodeCodePoints,
&probability, &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
- childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
- PatriciaTrieReadingUtils::isTerminal(flags),
- PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
- PatriciaTrieReadingUtils::isBlacklisted(flags)
- || PatriciaTrieReadingUtils::isNotAWord(flags),
- mergedNodeCodePointCount, mergedNodeCodePoints);
+ // Skip PtNodes don't start with Unicode code point because they represent non-word information.
+ if (CharUtils::isInUnicodeSpace(mergedNodeCodePoints[0])) {
+ childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
+ PatriciaTrieReadingUtils::isTerminal(flags),
+ PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
+ PatriciaTrieReadingUtils::isBlacklisted(flags)
+ || PatriciaTrieReadingUtils::isNotAWord(flags),
+ mergedNodeCodePointCount, mergedNodeCodePoints);
+ }
return siblingPos;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
index 77ed38b89..5aa6b9a92 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
@@ -56,6 +56,7 @@ bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
return false;
}
}
+ umask(S_IWGRP | S_IWOTH);
if (mkdir(tmpDirPath, S_IRWXU) == -1) {
AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
return false;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 2fb3decee..8373dc549 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -59,13 +59,17 @@ void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const d
// valid terminal DicNode.
isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
}
+ readingHelper.readNextSiblingNode(ptNodeParams);
+ if (!ptNodeParams.representsNonWordInfo()) {
+ // Skip PtNodes that represent non-word information.
+ continue;
+ }
childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
ptNodeParams.hasChildren(),
ptNodeParams.isBlacklisted()
|| ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
- readingHelper.readNextSiblingNode(ptNodeParams);
}
if (readingHelper.isError()) {
mIsCorrupted = true;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 7bc7b0a48..80970c7f8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -17,6 +17,10 @@
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
#include <cstdio>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "suggest/policyimpl/dictionary/header/header_policy.h"
#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
@@ -100,9 +104,15 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
/* static */ bool DictFileWritingUtils::flushBufferToFile(const char *const filePath,
const BufferWithExtendableBuffer *const buffer) {
- FILE *const file = fopen(filePath, "wb");
+ const int fd = open(filePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ AKLOGE("File %s cannot be opened. errno: %d", filePath, errno);
+ ASSERT(false);
+ return false;
+ }
+ FILE *const file = fdopen(fd, "wb");
if (!file) {
- AKLOGE("File %s cannot be opened.", filePath);
+ AKLOGE("fdopen failed for the file %s. errno: %d", filePath, errno);
ASSERT(false);
return false;
}
diff --git a/native/jni/src/utils/char_utils.cpp b/native/jni/src/utils/char_utils.cpp
index adc474b4c..b17e0847d 100644
--- a/native/jni/src/utils/char_utils.cpp
+++ b/native/jni/src/utils/char_utils.cpp
@@ -22,6 +22,9 @@
namespace latinime {
+const int CharUtils::MIN_UNICODE_CODE_POINT = 0;
+const int CharUtils::MAX_UNICODE_CODE_POINT = 0x10FFFF;
+
struct LatinCapitalSmallPair {
unsigned short capital;
unsigned short small;
diff --git a/native/jni/src/utils/char_utils.h b/native/jni/src/utils/char_utils.h
index 239419d5b..634c45b04 100644
--- a/native/jni/src/utils/char_utils.h
+++ b/native/jni/src/utils/char_utils.h
@@ -86,12 +86,19 @@ class CharUtils {
return spaceCount;
}
+ static AK_FORCE_INLINE int isInUnicodeSpace(const int codePoint) {
+ return codePoint >= MIN_UNICODE_CODE_POINT && codePoint <= MAX_UNICODE_CODE_POINT;
+ }
+
static unsigned short latin_tolower(const unsigned short c);
static const std::vector<int> EMPTY_STRING;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CharUtils);
+ static const int MIN_UNICODE_CODE_POINT;
+ static const int MAX_UNICODE_CODE_POINT;
+
/**
* Table mapping most combined Latin, Greek, and Cyrillic characters
* to their base characters. If c is in range, BASE_CHARS[c] == c
diff --git a/native/jni/src/utils/jni_data_utils.cpp b/native/jni/src/utils/jni_data_utils.cpp
new file mode 100644
index 000000000..5555293d5
--- /dev/null
+++ b/native/jni/src/utils/jni_data_utils.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/jni_data_utils.h"
+
+namespace latinime {
+
+const int JniDataUtils::CODE_POINT_REPLACEMENT_CHARACTER = 0xFFFD;
+const int JniDataUtils::CODE_POINT_NULL = 0;
+
+} // namespace latinime
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index 2ce02dc05..67a66fdfe 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -23,6 +23,7 @@
#include "jni.h"
#include "suggest/core/policy/dictionary_header_structure_policy.h"
#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
+#include "utils/char_utils.h"
namespace latinime {
@@ -65,8 +66,44 @@ class JniDataUtils {
return attributeMap;
}
+ static void outputCodePoints(JNIEnv *env, jintArray intArrayToOutputCodePoints, const int start,
+ const int maxLength, const int *const codePoints, const int codePointCount,
+ const bool needsNullTermination) {
+ const int outputCodePointCount = std::min(maxLength, codePointCount);
+ int outputCodePonts[outputCodePointCount];
+ for (int i = 0; i < outputCodePointCount; ++i) {
+ const int codePoint = codePoints[i];
+ if (!CharUtils::isInUnicodeSpace(codePoint)) {
+ outputCodePonts[i] = CODE_POINT_REPLACEMENT_CHARACTER;
+ } else if (codePoint >= 0x01 && codePoint <= 0x1F) {
+ // Control code.
+ outputCodePonts[i] = CODE_POINT_REPLACEMENT_CHARACTER;
+ } else {
+ outputCodePonts[i] = codePoint;
+ }
+ }
+ env->SetIntArrayRegion(intArrayToOutputCodePoints, start, outputCodePointCount,
+ outputCodePonts);
+ if (needsNullTermination && outputCodePointCount < maxLength) {
+ env->SetIntArrayRegion(intArrayToOutputCodePoints, start + outputCodePointCount,
+ 1 /* len */, &CODE_POINT_NULL);
+ }
+ }
+
+ static void putIntToArray(JNIEnv *env, jintArray array, const int index, const int value) {
+ env->SetIntArrayRegion(array, index, 1 /* len */, &value);
+ }
+
+ static void putFloatToArray(JNIEnv *env, jfloatArray array, const int index,
+ const float value) {
+ env->SetFloatArrayRegion(array, index, 1 /* len */, &value);
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JniDataUtils);
+
+ static const int CODE_POINT_REPLACEMENT_CHARACTER;
+ static const int CODE_POINT_NULL;
};
} // namespace latinime
#endif // LATINIME_JNI_DATA_UTILS_H
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
index 9b532fe6f..555b1a47a 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
@@ -29,7 +29,7 @@ public class KeyboardThemeTests extends AndroidTestCase {
private static final int THEME_ID_NULL = -1;
private static final int THEME_ID_ICS = KeyboardTheme.THEME_ID_ICS;
private static final int THEME_ID_KLP = KeyboardTheme.THEME_ID_KLP;
- private static final int THEME_ID_LMP = KeyboardTheme.THEME_ID_LMP;
+ private static final int THEME_ID_LXX = KeyboardTheme.THEME_ID_LXX;
@Override
protected void setUp() throws Exception {
@@ -64,11 +64,11 @@ public class KeyboardThemeTests extends AndroidTestCase {
assertDefaultKeyboardTheme(sdkVersion, THEME_ID_KLP, THEME_ID_KLP);
}
- private void assertDefaultKeyboardThemeLMP(final int sdkVersion) {
- // Forced to switch to LMP theme.
- assertDefaultKeyboardTheme(sdkVersion, THEME_ID_NULL, THEME_ID_LMP);
- assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ICS, THEME_ID_LMP);
- assertDefaultKeyboardTheme(sdkVersion, THEME_ID_KLP, THEME_ID_LMP);
+ private void assertDefaultKeyboardThemeLXX(final int sdkVersion) {
+ // Forced to switch to LXX theme.
+ assertDefaultKeyboardTheme(sdkVersion, THEME_ID_NULL, THEME_ID_LXX);
+ assertDefaultKeyboardTheme(sdkVersion, THEME_ID_ICS, THEME_ID_LXX);
+ assertDefaultKeyboardTheme(sdkVersion, THEME_ID_KLP, THEME_ID_LXX);
}
public void testDefaultKeyboardThemeICS() {
@@ -86,8 +86,8 @@ public class KeyboardThemeTests extends AndroidTestCase {
assertDefaultKeyboardThemeKLP(VERSION_CODES.KITKAT);
}
- public void testDefaultKeyboardThemeLMP() {
+ public void testDefaultKeyboardThemeLXX() {
// TODO: Update this constant once the *next* version becomes available.
- assertDefaultKeyboardThemeLMP(VERSION_CODES.CUR_DEVELOPMENT);
+ assertDefaultKeyboardThemeLXX(VERSION_CODES.CUR_DEVELOPMENT);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
new file mode 100644
index 000000000..186542ae5
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.inputmethod.latin.utils.DistracterFilter;
+
+/**
+ * Unit test for DistracterFilter
+ */
+@LargeTest
+public class DistracterFilterTest extends InputTestsBase {
+ private DistracterFilter mDistracterFilter;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDistracterFilter = mLatinIME.createDistracterFilter();
+ }
+
+ public void testIsDistractorToWordsInDictionaries() {
+ final String EMPTY_PREV_WORD = null;
+ String typedWord = "alot";
+ // For this test case, we consider "alot" is a distracter to "a lot".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "mot";
+ // For this test case, we consider "mot" is a distracter to "not".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "wierd";
+ // For this test case, we consider "wierd" is a distracter to "weird".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "hoe";
+ // For this test case, we consider "hoe" is a distracter to "how".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "nit";
+ // For this test case, we consider "nit" is a distracter to "not".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "ill";
+ // For this test case, we consider "ill" is a distracter to "I'll".
+ assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "asdfd";
+ // For this test case, we consider "asdfd" is not a distracter to any word in dictionaries.
+ assertFalse(
+ mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+
+ typedWord = "thank";
+ // For this test case, we consider "thank" is not a distracter to any other word
+ // in dictionaries.
+ assertFalse(
+ mDistracterFilter.isDistracterToWordsInDictionaries(EMPTY_PREV_WORD, typedWord));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 29423e8e3..a9444160f 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -600,4 +600,16 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("type words letter by letter", EXPECTED_RESULT,
mEditText.getText().toString());
}
+
+ public void testSwitchLanguages() {
+ final String WORD_TO_TYPE_FIRST_PART = "com";
+ final String WORD_TO_TYPE_SECOND_PART = "md ";
+ final String EXPECTED_RESULT = "comme ";
+ changeLanguage("en");
+ type(WORD_TO_TYPE_FIRST_PART);
+ changeLanguage("fr");
+ type(WORD_TO_TYPE_SECOND_PART);
+ assertEquals("Composing continues after switching languages", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
index b3f2819cf..bb36a2a16 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
@@ -220,7 +220,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
public void testMyanmarReordering() {
int testNumber = 0;
- changeLanguage("mm_MY");
+ changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
for (final Pair[] test : TESTS) {
// Small trick to reset LatinIME : setText("") and send updateSelection with values
// LatinIME has never seen, and cursor pos 0,0.
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 260e534ee..09c53204b 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -299,11 +299,15 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
}
protected void changeLanguage(final String locale) {
- changeLanguageWithoutWait(locale);
+ changeLanguage(locale, null);
+ }
+
+ protected void changeLanguage(final String locale, final String combiningSpec) {
+ changeLanguageWithoutWait(locale, combiningSpec);
waitForDictionariesToBeLoaded();
}
- protected void changeLanguageWithoutWait(final String locale) {
+ protected void changeLanguageWithoutWait(final String locale, final String combiningSpec) {
mEditText.mCurrentLocale = LocaleUtils.constructLocaleFromString(locale);
// TODO: this is forcing a QWERTY keyboard for all locales, which is wrong.
// It's still better than using whatever keyboard is the current one, but we
@@ -314,7 +318,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
- + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+ + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE
+ + null == combiningSpec ? "" : ("," + combiningSpec);
final InputMethodSubtype subtype = InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_no_language_qwerty,
R.drawable.ic_ime_switcher_dark,
@@ -325,7 +330,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
false /* overridesImplicitlyEnabledSubtype */,
0 /* id */);
SubtypeSwitcher.getInstance().forceSubtype(subtype);
- mLatinIME.loadKeyboard();
+ mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
runMessages();
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
mLatinIME.clearPersonalizedDictionariesForTest();
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
index db14b8329..0a29d8326 100644
--- a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
@@ -33,7 +33,8 @@ public class LatinImeStressTests extends InputTestsBase {
final int codePointSetSize = 30;
final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
for (int i = 0; i < switchCount; ++i) {
- changeLanguageWithoutWait(locales[random.nextInt(locales.length)]);
+ changeLanguageWithoutWait(locales[random.nextInt(locales.length)],
+ null /* combiningSpec */);
final int wordCount = random.nextInt(maxWordCountToTypeInEachIteration);
for (int j = 0; j < wordCount; ++j) {
final String word = CodePointUtils.generateWord(random, codePointSet);
@@ -50,7 +51,8 @@ public class LatinImeStressTests extends InputTestsBase {
final int codePointSetSize = 30;
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
for (int i = 0; i < switchCount; ++i) {
- changeLanguageWithoutWait(locales[random.nextInt(locales.length)]);
+ changeLanguageWithoutWait(locales[random.nextInt(locales.length)],
+ null /* combiningSpec */);
final int wordCount = random.nextInt(maxWordCountToTypeInEachIteration);
for (int j = 0; j < wordCount; ++j) {
final String word = CodePointUtils.generateWord(random, codePointSet);
diff --git a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java b/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
index 47f781e62..538d759c8 100644
--- a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
+++ b/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
@@ -28,8 +28,10 @@ import java.util.ArrayList;
// TODO: there should not be a dependency to this in dicttool, so there
// should be a sensible way to separate them cleanly.
public class CombinerChain {
- private StringBuilder mComposingWord = new StringBuilder();
- public CombinerChain(final Combiner... combinerList) {}
+ private StringBuilder mComposingWord;
+ public CombinerChain(final String initialText, final Combiner... combinerList) {
+ mComposingWord = new StringBuilder(initialText);
+ }
public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
mComposingWord.append(newEvent.getTextToCommit());