diff --git a/Kconfig b/Kconfig index 4023a3814b..76e86c597b 100644 --- a/Kconfig +++ b/Kconfig @@ -1030,14 +1030,22 @@ menu "LVGL configuration" config LV_USE_IME_PINYIN bool "Enable Pinyin input method" default n + config LV_IME_PINYIN_USE_K9_MODE + bool "Enable Pinyin input method 9 key input mode" + depends on LV_USE_IME_PINYIN + default n + config LV_IME_PINYIN_K9_CAND_TEXT_NUM + int "Maximum number of candidate panels for 9-key input mode" + depends on LV_IME_PINYIN_USE_K9_MODE + default 3 config LV_IME_PINYIN_USE_DEFAULT_DICT bool "Use built-in Thesaurus" depends on LV_USE_IME_PINYIN default y help - If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss + If you do not use the default thesaurus, be sure to use lv_ime_pinyin after setting the thesauruss config LV_IME_PINYIN_CAND_TEXT_NUM - int "maximum number of candidate panels" + int "Maximum number of candidate panels" depends on LV_USE_IME_PINYIN default 6 help diff --git a/docs/others/ime_pinyin.md b/docs/others/ime_pinyin.md index c660d02c4a..82747fff89 100644 --- a/docs/others/ime_pinyin.md +++ b/docs/others/ime_pinyin.md @@ -1,6 +1,6 @@ # Pinyin IME -Pinyin IME provides API to provide Chinese Pinyin input method (Chinese input) for keyboard object. You can think of `lv_ime_pinyin` as a Pinyin input method plug-in for keyboard objects. +Pinyin IME provides API to provide Chinese Pinyin input method (Chinese input) for keyboard object, which supports 26 key and 9 key input modes. You can think of `lv_ime_pinyin` as a Pinyin input method plug-in for keyboard objects. Normally, an environment where [lv_keyboard](/widgets/extra/keyboard) can run can also run `lv_ime_pinyin`. There are two main influencing factors: the size of the font file and the size of the dictionary. @@ -8,7 +8,7 @@ Normally, an environment where [lv_keyboard](/widgets/extra/keyboard) can run ca 中文

-`lv_ime_pinyin`为[键盘](/widgets/extra/keyboard)组件提供汉语拼音输入法(中文输入)的功能(后文简称为拼音输入法)。您可以将 `lv_ime_pinyin` 看成是键盘组件的汉语拼音输入法插件。 +`lv_ime_pinyin`为[键盘](/widgets/extra/keyboard)组件提供汉语拼音输入法(中文输入)的功能(后文简称为拼音输入法),支持26键和9键输入模式。您可以将 `lv_ime_pinyin` 看成是键盘组件的汉语拼音输入法插件。 一般情况下,只要是[键盘](/widgets/extra/keyboard)组件能运行的环境 `lv_ime_pinyin` 也能运行。有两个影响因素:字库的大小和词库的大小。 @@ -118,6 +118,20 @@ After writing a dictionary according to the above dictionary format, you only ne lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict); ``` +## Input modes + +`lv_ime_pinyin` supports 26 key and 9 key input modes. The mode switching is very simple, just call the function `lv_ime_pinyin_set_mode`. If the second parameter of function `lv_ime_pinyin_set_mode` is' 1 ', switch to 26 key input mode; if it is' 0', switch to 9 key input mode, and the default is' 1 '. + +

+中文 +

+ +`lv_ime_pinyin` 支持26键和9键输入模式。模式的切换非常简单,只需调用函数 `lv_ime_pinyin_set_mode` 即可。如果函数 `lv_ime_pinyin_set_mode` 的第2个参数为 `1` 则切换到 26 键输入模式,如果为 `0` 则切换到 9 键输入法模式,默认为 `1` 。 + +

+
+ + ## Example ```eval_rst diff --git a/examples/others/ime/index.rst b/examples/others/ime/index.rst index 2633da5ef0..e7cc1fb9a3 100644 --- a/examples/others/ime/index.rst +++ b/examples/others/ime/index.rst @@ -1,8 +1,12 @@ -Simple Pinyin IME example -""""""""""""""""""" +Pinyin IME 26 key input +""""""""""""""""""""""""" .. lv_example:: others/ime/lv_example_ime_pinyin_1 :language: c +Pinyin IME 9 key input +""""""""""""""""""""""""" +.. lv_example:: others/ime/lv_example_ime_pinyin_2 + :language: c diff --git a/examples/others/ime/lv_example_ime_pinyin.h b/examples/others/ime/lv_example_ime_pinyin.h index b43bfeaee1..96991e3a32 100644 --- a/examples/others/ime/lv_example_ime_pinyin.h +++ b/examples/others/ime/lv_example_ime_pinyin.h @@ -26,6 +26,7 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ void lv_example_ime_pinyin_1(void); +void lv_example_ime_pinyin_2(void); /********************** * MACROS diff --git a/examples/others/ime/lv_example_ime_pinyin_1.c b/examples/others/ime/lv_example_ime_pinyin_1.c index eb6101ac69..b609ee6141 100644 --- a/examples/others/ime/lv_example_ime_pinyin_1.c +++ b/examples/others/ime/lv_example_ime_pinyin_1.c @@ -1,5 +1,5 @@ #include "../../lv_examples.h" -#if LV_USE_LABEL && LV_USE_TEXTAREA && LV_FONT_SIMSUN_16_CJK && LV_USE_IME_PINYIN && LV_BUILD_EXAMPLES +#if LV_USE_LABEL && LV_USE_TEXTAREA && LV_FONT_SIMSUN_16_CJK && LV_USE_IME_PINYIN && LV_BUILD_EXAMPLES static void ta_event_cb(lv_event_t * e) { @@ -13,7 +13,7 @@ static void ta_event_cb(lv_event_t * e) lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN); } } - else if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL) { + else if(code == LV_EVENT_CANCEL) { lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_state(ta, LV_STATE_FOCUSED); lv_indev_reset(NULL, ta); /*To forget the last clicked object to make it focusable again*/ @@ -24,7 +24,7 @@ void lv_example_ime_pinyin_1(void) { lv_obj_t * pinyin_ime = lv_ime_pinyin_create(lv_scr_act()); lv_obj_set_style_text_font(pinyin_ime, &lv_font_simsun_16_cjk, 0); - //lv_ime_pinyin_set_dict(pinyin_ime, your_dict); // Use a custom dictionary. If it is not set, the built-in thesaurus will be used. + //lv_ime_pinyin_set_dict(pinyin_ime, your_dict); // Use a custom dictionary. If it is not set, the built-in dictionary will be used. /* ta1 */ lv_obj_t * ta1 = lv_textarea_create(lv_scr_act()); diff --git a/examples/others/ime/lv_example_ime_pinyin_2.c b/examples/others/ime/lv_example_ime_pinyin_2.c new file mode 100644 index 0000000000..af5a0589d0 --- /dev/null +++ b/examples/others/ime/lv_example_ime_pinyin_2.c @@ -0,0 +1,58 @@ +#include "../../lv_examples.h" +#if LV_USE_LABEL && LV_USE_TEXTAREA && LV_FONT_SIMSUN_16_CJK && LV_USE_IME_PINYIN && LV_IME_PINYIN_USE_K9_MODE && LV_BUILD_EXAMPLES + +static void ta_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * ta = lv_event_get_target(e); + lv_obj_t * kb = lv_event_get_user_data(e); + + if(code == LV_EVENT_FOCUSED) { + if(lv_indev_get_type(lv_indev_get_act()) != LV_INDEV_TYPE_KEYPAD) { + lv_keyboard_set_textarea(kb, ta); + lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN); + } + } + else if(code == LV_EVENT_READY) { + lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN); + lv_obj_clear_state(ta, LV_STATE_FOCUSED); + lv_indev_reset(NULL, ta); /*To forget the last clicked object to make it focusable again*/ + } +} + +void lv_example_ime_pinyin_2(void) +{ + lv_obj_t * pinyin_ime = lv_ime_pinyin_create(lv_scr_act()); + lv_obj_set_style_text_font(pinyin_ime, &lv_font_simsun_16_cjk, 0); + //lv_ime_pinyin_set_dict(pinyin_ime, your_dict); // Use a custom dictionary. If it is not set, the built-in dictionary will be used. + + /* ta1 */ + lv_obj_t * ta1 = lv_textarea_create(lv_scr_act()); + lv_textarea_set_one_line(ta1, true); + lv_obj_set_style_text_font(ta1, &lv_font_simsun_16_cjk, 0); + lv_obj_align(ta1, LV_ALIGN_TOP_LEFT, 0, 0); + + /*Create a keyboard and add it to ime_pinyin*/ + lv_obj_t * kb = lv_keyboard_create(lv_scr_act()); + lv_keyboard_set_textarea(kb, ta1); + + lv_ime_pinyin_set_keyboard(pinyin_ime, kb); + lv_ime_pinyin_set_mode(pinyin_ime, + LV_IME_PINYIN_MODE_K9); // Set to 9-key input mode. Default: 26-key input(k26) mode. + lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_ALL, kb); + + /*Get the cand_panel, and adjust its size and position*/ + lv_obj_t * cand_panel = lv_ime_pinyin_get_cand_panel(pinyin_ime); + lv_obj_set_size(cand_panel, LV_PCT(100), LV_PCT(10)); + lv_obj_align_to(cand_panel, kb, LV_ALIGN_OUT_TOP_MID, 0, 0); + + /*Try using ime_pinyin to output the Chinese below in the ta1 above*/ + lv_obj_t * cz_label = lv_label_create(lv_scr_act()); + lv_label_set_text(cz_label, + "嵌入式系统(Embedded System),\n是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。"); + lv_obj_set_style_text_font(cz_label, &lv_font_simsun_16_cjk, 0); + lv_obj_set_width(cz_label, 310); + lv_obj_align_to(cz_label, ta1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); +} + +#endif diff --git a/lv_conf_template.h b/lv_conf_template.h index b4a1600ced..fcbaf73f72 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -704,6 +704,12 @@ /*Set the maximum number of candidate panels that can be displayed*/ /*This needs to be adjusted according to the size of the screen*/ #define LV_IME_PINYIN_CAND_TEXT_NUM 6 + + /*Use 9 key input(k9)*/ + #define LV_IME_PINYIN_USE_K9_MODE 1 + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif // LV_IME_PINYIN_USE_K9_MODE #endif /*================== diff --git a/src/extra/others/ime/lv_ime_pinyin.c b/src/extra/others/ime/lv_ime_pinyin.c index ab0bfc6e05..b1661e4f71 100644 --- a/src/extra/others/ime/lv_ime_pinyin.c +++ b/src/extra/others/ime/lv_ime_pinyin.c @@ -32,7 +32,16 @@ static void lv_ime_pinyin_cand_panel_event(lv_event_t * e); static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); static void pinyin_input_proc(lv_obj_t * obj); static void pinyin_page_proc(lv_obj_t * obj, uint16_t btn); -static char * pinyin_search_matching(lv_obj_t * obj, char * strInput_py_str, uint16_t * cand_num); +static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num); +static void pinyin_ime_clear_data(lv_obj_t * obj); + +#if LV_IME_PINYIN_USE_K9_MODE + static void pinyin_k9_init_data(lv_obj_t * obj); + static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]); + static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str); + static void pinyin_k9_fill_cand(lv_obj_t * obj); + static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir); +#endif /********************** * STATIC VARIABLES @@ -47,6 +56,18 @@ const lv_obj_class_t lv_ime_pinyin_class = { .base_class = &lv_obj_class }; +#if LV_IME_PINYIN_USE_K9_MODE +static char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 20] = {\ + ",\0", "1#\0", "abc \0", "def\0", LV_SYMBOL_BACKSPACE"\0", "\n\0", + ".\0", "ghi\0", "jkl\0", "mno\0", LV_SYMBOL_KEYBOARD"\0", "\n\0", + "?\0", "pqrs\0", "tuv\0", "wxyz\0", LV_SYMBOL_NEW_LINE"\0", "\n\0", + LV_SYMBOL_LEFT"\0", "\0" + }; + +static lv_btnmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = { 1 }; +static char lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 2][LV_IME_PINYIN_K9_MAX_INPUT] = {0}; +#endif + static char lv_pinyin_cand_str[LV_IME_PINYIN_CAND_TEXT_NUM][4]; static char * lv_btnm_def_pinyin_sel_map[LV_IME_PINYIN_CAND_TEXT_NUM + 3]; @@ -429,6 +450,30 @@ void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) init_pinyin_dict(obj, dict); } +/** + * Set mode, 26-key input(k26) or 9-key input(k9). + * @param obj pointer to a Pinyin input method object + * @param mode the mode from 'lv_keyboard_mode_t' + */ +void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + LV_ASSERT_OBJ(pinyin_ime->kb, &lv_keyboard_class); + + pinyin_ime->mode = mode; + +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_k9_init_data(obj); + lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1, (const char *)lv_btnm_def_pinyin_k9_map, + (const)default_kb_ctrl_k9_map); + lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1); + } +#endif +} + /*===================== * Getter functions *====================*/ @@ -491,7 +536,8 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; uint16_t py_str_i = 0; - for(uint16_t btnm_i = 0; btnm_i < (LV_IME_PINYIN_CAND_TEXT_NUM + 3); btnm_i++) { + uint16_t btnm_i = 0; + for(btnm_i = 0; btnm_i < (LV_IME_PINYIN_CAND_TEXT_NUM + 3); btnm_i++) { if(btnm_i == 0) { lv_btnm_def_pinyin_sel_map[btnm_i] = "<"; } @@ -508,6 +554,7 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * } } + pinyin_ime->mode = LV_IME_PINYIN_MODE_K26; pinyin_ime->py_page = 0; pinyin_ime->ta_count = 0; pinyin_ime->cand_num = 0; @@ -553,6 +600,17 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * /* event handler */ lv_obj_add_event_cb(pinyin_ime->cand_panel, lv_ime_pinyin_cand_panel_event, LV_EVENT_VALUE_CHANGED, obj); lv_obj_add_event_cb(obj, lv_ime_pinyin_style_change_event, LV_EVENT_STYLE_CHANGED, NULL); + +#if LV_IME_PINYIN_USE_K9_MODE + pinyin_ime->k9_input_str_len = 0; + pinyin_ime->k9_py_ll_pos = 0; + pinyin_ime->k9_legal_py_count = 0; + lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + + pinyin_k9_init_data(obj); + + _lv_ll_init(&(pinyin_ime->k9_legal_py_ll), sizeof(ime_pinyin_k9_py_str_t)); +#endif } @@ -578,6 +636,10 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; +#if LV_IME_PINYIN_USE_K9_MODE + static const char * k9_py_map[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; +#endif + if(code == LV_EVENT_VALUE_CHANGED) { uint16_t btn_id = lv_btnmatrix_get_selected_btn(kb); if(btn_id == LV_BTNMATRIX_BTN_NONE) return; @@ -585,38 +647,111 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) const char * txt = lv_btnmatrix_get_btn_text(kb, lv_btnmatrix_get_selected_btn(kb)); if(txt == NULL) return; +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + uint16_t tmp_btn_str_len = strlen(pinyin_ime->input_char); + if((btn_id >= 16) && (tmp_btn_str_len > 0) && (btn_id < (16 + LV_IME_PINYIN_K9_CAND_TEXT_NUM))) { + tmp_btn_str_len = strlen(pinyin_ime->input_char); + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + strcat(pinyin_ime->input_char, txt); + pinyin_input_proc(obj); + + for(int index = 0; index < (pinyin_ime->ta_count + tmp_btn_str_len); index++) { + lv_textarea_del_char(ta); + } + + pinyin_ime->ta_count = tmp_btn_str_len; + pinyin_ime->k9_input_str_len = tmp_btn_str_len; + lv_textarea_add_text(ta, pinyin_ime->input_char); + + return; + } + } +#endif + if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { - lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str))); - pinyin_ime->ta_count = 0; - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + pinyin_ime_clear_data(obj); + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); } else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { // del input char - for(int i = strlen(pinyin_ime->input_char) - 1; i >= 0; i--) { - if(pinyin_ime->input_char[i] != '\0') { - pinyin_ime->input_char[i] = '\0'; + if(pinyin_ime->ta_count > 0) { + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) + pinyin_ime->input_char[pinyin_ime->ta_count - 1] = '\0'; +#if LV_IME_PINYIN_USE_K9_MODE + else + pinyin_ime->k9_input_str[pinyin_ime->ta_count - 1] = '\0'; +#endif + + pinyin_ime->ta_count = pinyin_ime->ta_count - 1; + if(pinyin_ime->ta_count <= 0) { lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); - break; +#if LV_IME_PINYIN_USE_K9_MODE + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); +#endif } + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { + pinyin_input_proc(obj); + } +#if LV_IME_PINYIN_USE_K9_MODE + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char) - 1; + pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map); + pinyin_k9_fill_cand(obj); + pinyin_input_proc(obj); + } +#endif } - pinyin_input_proc(obj); - pinyin_ime->ta_count--; } else if((strcmp(txt, "ABC") == 0) || (strcmp(txt, "abc") == 0) || (strcmp(txt, "1#") == 0)) { pinyin_ime->ta_count = 0; lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); return; } - else if((strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) || (strcmp(txt, LV_SYMBOL_OK) == 0)) { - pinyin_ime->ta_count = 0; - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); - lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + else if(strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { + lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K9); + } + else { + lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K26); + lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER); + } + pinyin_ime_clear_data(obj); } - else if((txt[0] >= 'a' && txt[0] <= 'z') || (txt[0] >= 'A' && txt[0] <= 'Z')) { + else if(strcmp(txt, LV_SYMBOL_OK) == 0) { + pinyin_ime_clear_data(obj); + } + else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) && ((txt[0] >= 'a' && txt[0] <= 'z') || (txt[0] >= 'A' && + txt[0] <= 'Z'))) { strcat(pinyin_ime->input_char, txt); pinyin_input_proc(obj); pinyin_ime->ta_count++; } +#if LV_IME_PINYIN_USE_K9_MODE + else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) && (txt[0] >= 'a' && txt[0] <= 'z')) { + for(uint16_t i = 0; i < 8; i++) { + if((strcmp(txt, k9_py_map[i]) == 0) || (strcmp(txt, "abc ") == 0)) { + if(strcmp(txt, "abc ") == 0) pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]) + 1; + else pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]); + pinyin_ime->k9_input_str[pinyin_ime->ta_count] = 50 + i; + + break; + } + } + pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map); + pinyin_k9_fill_cand(obj); + pinyin_input_proc(obj); + } + else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { + pinyin_k9_cand_page_proc(obj, 0); + } + else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { + pinyin_k9_cand_page_proc(obj, 1); + } +#endif } } @@ -642,17 +777,13 @@ static void lv_ime_pinyin_cand_panel_event(lv_event_t * e) const char * txt = lv_btnmatrix_get_btn_text(cand_panel, id); lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); - - for(int i = 0; i < pinyin_ime->ta_count; i++) { + uint16_t index = 0; + for(index = 0; index < pinyin_ime->ta_count; index++) lv_textarea_del_char(ta); - } lv_textarea_add_text(ta, txt); - pinyin_ime->ta_count = 0; - lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str))); - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); - lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + pinyin_ime_clear_data(obj); } } @@ -772,34 +903,34 @@ static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) } -static char * pinyin_search_matching(lv_obj_t * obj, char * strInput_py_str, uint16_t * cand_num) +static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; lv_pinyin_dict_t * cpHZ; - uint8_t i, cInputStrLength = 0, offset; + uint8_t index, len = 0, offset; volatile uint8_t count = 0; - if(*strInput_py_str == '\0') return NULL; - if(*strInput_py_str == 'i') return NULL; - if(*strInput_py_str == 'u') return NULL; - if(*strInput_py_str == 'v') return NULL; + if(*py_str == '\0') return NULL; + if(*py_str == 'i') return NULL; + if(*py_str == 'u') return NULL; + if(*py_str == 'v') return NULL; - offset = strInput_py_str[0] - 'a'; - cInputStrLength = strlen(strInput_py_str); + offset = py_str[0] - 'a'; + len = strlen(py_str); cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; count = pinyin_ime->py_num[offset]; while(count--) { - for(i = 0; i < cInputStrLength; i++) { - if(*(strInput_py_str + i) != *((cpHZ->py) + i)) { + for(index = 0; index < len; index++) { + if(*(py_str + index) != *((cpHZ->py) + index)) { break; } } // perfect match - if(cInputStrLength == 1 || i == cInputStrLength) { + if(len == 1 || index == len) { // The Chinese character in UTF-8 encoding format is 3 bytes * cand_num = strlen((const char *)(cpHZ->py_mb)) / 3; return (char *)(cpHZ->py_mb); @@ -809,5 +940,259 @@ static char * pinyin_search_matching(lv_obj_t * obj, char * strInput_py_str, uin return NULL; } +static void pinyin_ime_clear_data(lv_obj_t * obj) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_ime->k9_input_str_len = 0; + pinyin_ime->k9_py_ll_pos = 0; + pinyin_ime->k9_legal_py_count = 0; + lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + } +#endif + + pinyin_ime->ta_count = 0; + lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str))); + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); +} + + +#if LV_IME_PINYIN_USE_K9_MODE +static void pinyin_k9_init_data(lv_obj_t * obj) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + uint16_t py_str_i = 0; + uint16_t btnm_i = 0; + for(btnm_i = 19; btnm_i < (LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21); btnm_i++) { + if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM) { + strcpy(lv_pinyin_k9_cand_str[py_str_i], LV_SYMBOL_RIGHT"\0"); + } + else if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1) { + strcpy(lv_pinyin_k9_cand_str[py_str_i], "\0"); + } + else { + strcpy(lv_pinyin_k9_cand_str[py_str_i], " \0"); + } + + lv_btnm_def_pinyin_k9_map[btnm_i] = lv_pinyin_k9_cand_str[py_str_i]; + py_str_i++; + } + + default_kb_ctrl_k9_map[0] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[4] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[5] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[9] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[10] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[14] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[15] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; +} + +static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + uint16_t len = strlen(k9_input); + + if((len == 0) || (len >= LV_IME_PINYIN_K9_MAX_INPUT)) { + return; + } + + char py_comp[LV_IME_PINYIN_K9_MAX_INPUT] = {0}; + int mark[LV_IME_PINYIN_K9_MAX_INPUT] = {0}; + int index = 0; + int flag = 0; + int count = 0; + + uint32_t ll_len = 0; + ime_pinyin_k9_py_str_t * ll_index = NULL; + + ll_len = _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll); + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + + while(index != -1) { + if(index == len) { + if(pinyin_k9_is_valid_py(obj, py_comp)) { + if((count >= ll_len) || (ll_len == 0)) { + ll_index = _lv_ll_ins_tail(&pinyin_ime->k9_legal_py_ll); + strcpy(ll_index->py_str, py_comp); + } + else if((count < ll_len)) { + strcpy(ll_index->py_str, py_comp); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); + } + count++; + } + index--; + } + else { + flag = mark[index]; + if(flag < strlen(py9_map[k9_input[index] - '2'])) { + py_comp[index] = py9_map[k9_input[index] - '2'][flag]; + mark[index] = mark[index] + 1; + index++; + } + else { + mark[index] = 0; + index--; + } + } + } + + if(count > 0) { + pinyin_ime->ta_count++; + pinyin_ime->k9_legal_py_count = count; + } +} + + +/*true: visible; false: not visible*/ +static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + lv_pinyin_dict_t * cpHZ = NULL; + uint8_t index = 0, len = 0, offset = 0; + uint16_t ret = 1; + volatile uint8_t count = 0; + + if(*py_str == '\0') return false; + if(*py_str == 'i') return false; + if(*py_str == 'u') return false; + if(*py_str == 'v') return false; + + offset = py_str[0] - 'a'; + len = strlen(py_str); + + cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; + count = pinyin_ime->py_num[offset]; + + while(count--) { + for(index = 0; index < len; index++) { + if(*(py_str + index) != *((cpHZ->py) + index)) { + break; + } + } + + // perfect match + if(len == 1 || index == len) { + return true; + } + cpHZ++; + } + return false; +} + + +static void pinyin_k9_fill_cand(lv_obj_t * obj) +{ + static uint16_t len = 0; + uint16_t index = 0, tmp_len = 0; + ime_pinyin_k9_py_str_t * ll_index = NULL; + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + tmp_len = pinyin_ime->k9_legal_py_count; + + if(tmp_len != len) { + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + len = tmp_len; + } + + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + strcpy(pinyin_ime->input_char, ll_index->py_str); + while(ll_index) { + if((index >= LV_IME_PINYIN_K9_CAND_TEXT_NUM) || \ + (index >= pinyin_ime->k9_legal_py_count)) + break; + + strcpy(lv_pinyin_k9_cand_str[index], ll_index->py_str); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + index++; + } + pinyin_ime->k9_py_ll_pos = index; + + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + for(index = 0; index < pinyin_ime->k9_input_str_len; index++) { + lv_textarea_del_char(ta); + } + pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char); + lv_textarea_add_text(ta, pinyin_ime->input_char); +} + + +static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + uint16_t ll_len = _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll); + + if((ll_len > LV_IME_PINYIN_K9_CAND_TEXT_NUM) && (pinyin_ime->k9_legal_py_count > LV_IME_PINYIN_K9_CAND_TEXT_NUM)) { + ime_pinyin_k9_py_str_t * ll_index = NULL; + uint16_t tmp_btn_str_len = 0; + int count = 0; + + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + while(ll_index) { + if(count >= pinyin_ime->k9_py_ll_pos) break; + + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + count++; + } + + if((NULL == ll_index) && (dir == 1)) return; + + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + + // next page + if(dir == 1) { + count = 0; + while(ll_index) { + if(count >= (LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1)) + break; + + strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + count++; + } + pinyin_ime->k9_py_ll_pos += count - 1; + + } + // previous page + else { + count = LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1; + ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); + while(ll_index) { + if(count < 0) break; + + strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the previous list*/ + count--; + } + + if(pinyin_ime->k9_py_ll_pos > LV_IME_PINYIN_K9_CAND_TEXT_NUM) + pinyin_ime->k9_py_ll_pos -= 1; + } + + lv_textarea_set_cursor_pos(ta, LV_TEXTAREA_CURSOR_LAST); + } +} + +#endif /*LV_IME_PINYIN_USE_K9_MODE*/ #endif /*LV_USE_IME_PINYIN*/ + diff --git a/src/extra/others/ime/lv_ime_pinyin.h b/src/extra/others/ime/lv_ime_pinyin.h index 9d5c2bc66e..3ff7bb9800 100644 --- a/src/extra/others/ime/lv_ime_pinyin.h +++ b/src/extra/others/ime/lv_ime_pinyin.h @@ -19,29 +19,49 @@ extern "C" { /********************* * DEFINES *********************/ +#define LV_IME_PINYIN_K9_MAX_INPUT 7 /********************** * TYPEDEFS **********************/ + +typedef enum { + LV_IME_PINYIN_MODE_K26, + LV_IME_PINYIN_MODE_K9, +} lv_ime_pinyin_mode_t; + +/*Data of pinyin_dict*/ typedef struct { const char * const py; const char * const py_mb; } lv_pinyin_dict_t; +/*Data of 9-key input(k9) mode*/ +typedef struct { + char py_str[7]; +} ime_pinyin_k9_py_str_t; + /*Data of lv_ime_pinyin*/ typedef struct { lv_obj_t obj; lv_obj_t * kb; lv_obj_t * cand_panel; lv_pinyin_dict_t * dict; + lv_ll_t k9_legal_py_ll; char * cand_str; /* Candidate string */ - char * btnm_pinyin_sel[LV_IME_PINYIN_CAND_TEXT_NUM + 3]; - char input_char[16]; /* Input box character */ + char input_char[16]; /* Input box character */ +#if LV_IME_PINYIN_USE_K9_MODE + char k9_input_str[LV_IME_PINYIN_K9_MAX_INPUT]; /* 9-key input(k9) mode input string */ + uint16_t k9_py_ll_pos; /* Current pinyin map pages(k9) */ + uint16_t k9_legal_py_count; /* Count of legal Pinyin numbers(k9) */ + uint16_t k9_input_str_len; /* 9-key input(k9) mode input string max len */ +#endif uint16_t ta_count; /* The number of characters entered in the text box this time */ uint16_t cand_num; /* Number of candidates */ - uint16_t py_page; /* Current pinyin map pages */ + uint16_t py_page; /* Current pinyin map pages(k26) */ uint16_t py_num[26]; /* Number and length of Pinyin */ uint16_t py_pos[26]; /* Pinyin position */ + uint8_t mode : 1; /* Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1. */ } lv_ime_pinyin_t; /*********************** @@ -71,6 +91,13 @@ void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb); */ void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); +/** + * Set mode, 26-key input(k26) or 9-key input(k9). + * @param obj pointer to a Pinyin input method object + * @param mode the mode from 'lv_ime_pinyin_mode_t' + */ +void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode); + /*===================== * Getter functions @@ -115,3 +142,4 @@ lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj); #endif /*LV_USE_IME_PINYIN*/ + diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index c2b4ccc561..97807fe378 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -2288,6 +2288,28 @@ #define LV_IME_PINYIN_CAND_TEXT_NUM 6 #endif #endif + + /*Use 9 key input(k9)*/ + #ifndef LV_IME_PINYIN_USE_K9_MODE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_IME_PINYIN_USE_K9_MODE + #define LV_IME_PINYIN_USE_K9_MODE CONFIG_LV_IME_PINYIN_USE_K9_MODE + #else + #define LV_IME_PINYIN_USE_K9_MODE 0 + #endif + #else + #define LV_IME_PINYIN_USE_K9_MODE 1 + #endif + #endif + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #ifndef LV_IME_PINYIN_K9_CAND_TEXT_NUM + #ifdef CONFIG_LV_IME_PINYIN_K9_CAND_TEXT_NUM + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM CONFIG_LV_IME_PINYIN_K9_CAND_TEXT_NUM + #else + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif + #endif + #endif // LV_IME_PINYIN_USE_K9_MODE #endif /*==================