feat(ime_pinyin): add API to support 9-key input mode (#3447)

* feat(ime_pinyin): add API to support 9-key input mode

* some optimizations for lv_ime_pinyin

* Update lv_example_ime_pinyin_2.c

* Update src/extra/others/ime/lv_ime_pinyin.h

Co-authored-by: YobeZhou <smilezyb@163.com>
Co-authored-by: Yobe Zhou <33565334+YobeZhou@users.noreply.github.com>
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
100ask
2022-07-06 15:04:53 +08:00
committed by GitHub
parent 73114028d3
commit 10e0b7a1ad
10 changed files with 572 additions and 46 deletions

12
Kconfig
View File

@@ -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

View File

@@ -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
<summary>中文</summary>
<p>
`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 '.
<details>
<summary>中文</summary>
<p>
`lv_ime_pinyin` 支持26键和9键输入模式。模式的切换非常简单只需调用函数 `lv_ime_pinyin_set_mode` 即可。如果函数 `lv_ime_pinyin_set_mode` 的第2个参数为 `1` 则切换到 26 键输入模式,如果为 `0` 则切换到 9 键输入法模式,默认为 `1`
</p>
</details>
## Example
```eval_rst

View File

@@ -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

View File

@@ -26,6 +26,7 @@ extern "C" {
* GLOBAL PROTOTYPES
**********************/
void lv_example_ime_pinyin_1(void);
void lv_example_ime_pinyin_2(void);
/**********************
* MACROS

View File

@@ -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());

View File

@@ -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

View File

@@ -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
/*==================

View File

@@ -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*/

View File

@@ -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*/

View File

@@ -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
/*==================