diff --git a/.gitignore b/.gitignore
index 6a8878be6d..f05715425e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,6 @@ test_screenshot_error.h
build/
tests/build_*/
tests/report/
+.DS_Store
+.vscode
+*.bak
diff --git a/Kconfig b/Kconfig
index e3902b3410..ae86eb989a 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1018,6 +1018,27 @@ menu "LVGL configuration"
config LV_USE_IMGFONT
bool "draw img in label or span obj"
default n
+
+ config LV_USE_MSG
+ bool "Enable a published subscriber based messaging system"
+ default n
+
+ config LV_USE_IME_PINYIN
+ bool "Enable Pinyin input method"
+ default n
+ 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
+ config LV_IME_PINYIN_CAND_TEXT_NUM
+ int "maximum number of candidate panels"
+ depends on LV_USE_IME_PINYIN
+ default 6
+ help
+ Set the maximum number of candidate panels that can be displayed.
+ This needs to be adjusted according to the size of the screen.
endmenu
menu "Examples"
diff --git a/docs/others/ime_pinyin.md b/docs/others/ime_pinyin.md
new file mode 100644
index 0000000000..c660d02c4a
--- /dev/null
+++ b/docs/others/ime_pinyin.md
@@ -0,0 +1,136 @@
+# 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.
+
+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.
+
+
+中文
+
+
+`lv_ime_pinyin`为[键盘](/widgets/extra/keyboard)组件提供汉语拼音输入法(中文输入)的功能(后文简称为拼音输入法)。您可以将 `lv_ime_pinyin` 看成是键盘组件的汉语拼音输入法插件。
+
+一般情况下,只要是[键盘](/widgets/extra/keyboard)组件能运行的环境 `lv_ime_pinyin` 也能运行。有两个影响因素:字库的大小和词库的大小。
+
+
+
+
+## Usage
+
+Enable `LV_USE_IME_PINYIN` in `lv_conf.h`.
+
+First use `lv_ime_pinyin_create(lv_scr_act())` to create a Pinyin input method plug-in, then use `lv_ime_pinyin_set_keyboard(pinyin_ime, kb)` to add the `keyboard` you created to the Pinyin input method plug-in.
+You can use `lv_ime_pinyin_set_dict(pinyin_ime, your_dict)` to use a custom dictionary (if you don't want to use the built-in dictionary at first, you can disable `LV_IME_PINYIN_USE_DEFAULT_DICT` in `lv_conf.h`, which can save a lot of memory space).
+
+The built-in thesaurus is customized based on the **LV_FONT_SIMSUN_16_CJK** font library, which currently only has more than `1,000` most common CJK radicals, so it is recommended to use custom fonts and thesaurus.
+
+In the process of using the Pinyin input method plug-in, you can change the keyboard and dictionary at any time.
+
+
+中文
+
+
+在 `lv_conf.h` 中打开 `LV_USE_IME_PINYIN`。
+
+首先,使用 `lv_ime_pinyin_create(lv_scr_act())` 函数创建一个拼音输入法插件,
+然后使用 `lv_ime_pinyin_set_keyboard(pinyin_ime, kb)` 函数将您创建的键盘组件添加到插件中。
+
+内置的词库是基于 LVGL 的 **LV_FONT_SIMSUN_16_CJK** 字库定制,这个字库目前只有 `1000` 多个最常见的 CJK 部首,所以建议使用自定义字库和词库。
+
+您可以使用 `lv_ime_pinyin_set_dict(pinyin_ime, your_dict)` 函数来设置使用自定义的词库,如果您一开始就不打算使用内置的词库,建议您在 `lv_conf.h` 中将 `LV_IME_PINYIN_USE_DEFAULT_DICT` 关闭,这可以节省一些内存空间。
+
+
+
+
+## Custom dictionary
+
+If you don't want to use the built-in Pinyin dictionary, you can use the custom dictionary.
+Or if you think that the built-in phonetic dictionary consumes a lot of memory, you can also use a custom dictionary.
+
+Customizing the dictionary is very simple.
+
+First, set `LV_IME_PINYIN_USE_DEFAULT_DICT` to `0` in `lv_conf.h`
+
+Then, write a dictionary in the following format.
+
+
+中文
+
+
+如果您不想使用内置的词库,可以通过下面的方法自定义词库。
+
+自定义词典非常简单。
+首先,在 `lv_conf.h` 将 `LV_IME_PINYIN_USE_DEFAULT_DICT` 设置为 0。
+然后按照下面的格式编写词库。
+
+
+
+
+### Dictionary format
+
+The arrangement order of each pinyin syllable is very important. You need to customize your own thesaurus according to the Hanyu Pinyin syllable table. You can read [here](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981) to learn about the Hanyu Pinyin syllables and the syllable table.
+
+Then, write your own dictionary according to the following format:
+
+
+中文
+
+
+**注意**,各个拼音音节的排列顺序非常重要,您需要按照汉语拼音音节表定制自己的词库,可以阅读[这里](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981)了解[汉语拼音音节](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981)以及[音节表](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981#1)。
+
+然后,根据下面的格式编写自己的词库:
+
+
+
+
+```c
+lv_100ask_pinyin_dict_t your_pinyin_dict[] = {
+ { "a", "啊阿呵吖" },
+ { "ai", "埃挨哎唉哀皑蔼矮碍爱隘癌艾" },
+ { "an", "按安暗岸俺案鞍氨胺厂广庵揞犴铵桉谙鹌埯黯" },
+ { "ang", "昂肮盎仰" },
+ { "ao", "凹敖熬翱袄傲奥懊澳" },
+ { "ba", "芭捌叭吧笆八疤巴拔跋靶把坝霸罢爸扒耙" },
+ { "bai", "白摆佰败拜柏百稗伯" },
+ /* ...... */
+ { "zuo", "昨左佐做作坐座撮琢柞"},
+ {NULL, NULL}
+
+```
+
+**The last item** must end with `{null, null}` , or it will not work properly.
+
+### Apply new dictionary
+
+After writing a dictionary according to the above dictionary format, you only need to call this function to set up and use your dictionary:
+
+
+中文
+
+
+按照上面的词库格式编写好自己的词库之后,参考下面的用法,调用 `lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict)` 函数即可设置和使用新词库:
+
+
+
+
+```c
+ lv_obj_t * pinyin_ime = lv_100ask_pinyin_ime_create(lv_scr_act());
+ lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict);
+```
+
+## Example
+
+```eval_rst
+
+.. include:: ../../examples/others/ime/index.rst
+
+```
+
+## API
+
+```eval_rst
+
+.. doxygenfile:: lv_ime_pinyin.h
+ :project: lvgl
+
+```
diff --git a/docs/others/index.md b/docs/others/index.md
index 8d0160ac79..e45d1caf45 100644
--- a/docs/others/index.md
+++ b/docs/others/index.md
@@ -12,5 +12,6 @@
fragment
msg
imgfont
+ ime_pinyin
```
diff --git a/examples/others/ime/index.rst b/examples/others/ime/index.rst
new file mode 100644
index 0000000000..2633da5ef0
--- /dev/null
+++ b/examples/others/ime/index.rst
@@ -0,0 +1,8 @@
+
+Simple Pinyin IME example
+"""""""""""""""""""
+
+.. lv_example:: others/ime/lv_example_ime_pinyin_1
+ :language: c
+
+
diff --git a/examples/others/ime/lv_example_ime_pinyin.h b/examples/others/ime/lv_example_ime_pinyin.h
new file mode 100644
index 0000000000..b43bfeaee1
--- /dev/null
+++ b/examples/others/ime/lv_example_ime_pinyin.h
@@ -0,0 +1,38 @@
+/**
+ * @file lv_example_ime_pinyin.h
+ *
+ */
+
+#ifndef LV_EX_IME_PINYIN_H
+#define LV_EX_IME_PINYIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+void lv_example_ime_pinyin_1(void);
+
+/**********************
+ * MACROS
+ **********************/
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*LV_EX_IME_PINYIN_H*/
diff --git a/examples/others/ime/lv_example_ime_pinyin_1.c b/examples/others/ime/lv_example_ime_pinyin_1.c
new file mode 100644
index 0000000000..caac8f2e75
--- /dev/null
+++ b/examples/others/ime/lv_example_ime_pinyin_1.c
@@ -0,0 +1,56 @@
+#include "../../lv_examples.h"
+#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)
+{
+ 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 || 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*/
+ }
+}
+
+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_obj_t * kb = lv_keyboard_create(lv_scr_act());
+ lv_ime_pinyin_set_keyboard(pinyin_ime, kb);
+
+ /* ta1 */
+ lv_obj_t * ta1 = lv_textarea_create(lv_scr_act());
+ lv_obj_set_style_text_font(ta1, &lv_font_simsun_16_cjk, 0);
+ lv_obj_align(ta1, LV_ALIGN_TOP_LEFT, 10, 10);
+
+ lv_keyboard_set_textarea(kb, ta1);
+
+ lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_ALL, kb);
+
+ /* ta2 */
+ lv_obj_t * ta2 = lv_textarea_create(lv_scr_act());
+ lv_obj_set_style_text_font(ta2, &lv_font_simsun_16_cjk, 0);
+ lv_obj_align_to(ta2, ta1, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
+
+ lv_obj_add_event_cb(ta2, ta_event_cb, LV_EVENT_ALL, kb);
+
+ 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, 5, 5);
+}
+
+#endif
diff --git a/examples/others/lv_example_others.h b/examples/others/lv_example_others.h
index eeb97391bb..4b27194905 100644
--- a/examples/others/lv_example_others.h
+++ b/examples/others/lv_example_others.h
@@ -19,6 +19,7 @@ extern "C" {
#include "fragment/lv_example_fragment.h"
#include "imgfont/lv_example_imgfont.h"
#include "msg/lv_example_msg.h"
+#include "ime/lv_example_ime_pinyin.h"
/*********************
* DEFINES
diff --git a/lv_conf_template.h b/lv_conf_template.h
index 3dae8418dd..eae3249534 100644
--- a/lv_conf_template.h
+++ b/lv_conf_template.h
@@ -691,6 +691,18 @@
/*1: Enable a published subscriber based messaging system */
#define LV_USE_MSG 0
+/*1: Enable Pinyin input method*/
+/*Requires: lv_keyboard*/
+#define LV_USE_IME_PINYIN 0
+#if LV_USE_IME_PINYIN
+ /*1: Use default thesaurus*/
+ /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
+ #define LV_IME_PINYIN_USE_DEFAULT_DICT 1
+ /*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
+#endif
+
/*==================
* EXAMPLES
*==================*/
diff --git a/src/extra/others/ime/lv_ime_pinyin.c b/src/extra/others/ime/lv_ime_pinyin.c
new file mode 100644
index 0000000000..ab0bfc6e05
--- /dev/null
+++ b/src/extra/others/ime/lv_ime_pinyin.c
@@ -0,0 +1,813 @@
+/**
+ * @file lv_ime_pinyin.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_ime_pinyin.h"
+#if LV_USE_IME_PINYIN != 0
+
+#include
+
+/*********************
+ * DEFINES
+ *********************/
+#define MY_CLASS &lv_ime_pinyin_class
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
+static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
+static void lv_ime_pinyin_style_change_event(lv_event_t * e);
+static void lv_ime_pinyin_kb_event(lv_event_t * e);
+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 VARIABLES
+ **********************/
+const lv_obj_class_t lv_ime_pinyin_class = {
+ .constructor_cb = lv_ime_pinyin_constructor,
+ .destructor_cb = lv_ime_pinyin_destructor,
+ .width_def = LV_SIZE_CONTENT,
+ .height_def = LV_SIZE_CONTENT,
+ .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
+ .instance_size = sizeof(lv_ime_pinyin_t),
+ .base_class = &lv_obj_class
+};
+
+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];
+
+#if LV_IME_PINYIN_USE_DEFAULT_DICT
+lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = {
+ { "a", "啊" },
+ { "ai", "愛" },
+ { "an", "安暗案" },
+ { "ba", "吧把爸八" },
+ { "bai", "百白敗" },
+ { "ban", "半般辦" },
+ { "bang", "旁" },
+ { "bao", "保薄包報" },
+ { "bei", "被背悲北杯備" },
+ { "ben", "本" },
+ { "bi", "必比避鼻彼筆秘閉" },
+ { "bian", "便邊變変辺" },
+ { "biao", "表標" },
+ { "bie", "別" },
+ { "bing", "病並氷" },
+ { "bo", "波薄泊" },
+ { "bu", "不布步部捕補歩" },
+ { "ca", "察" },
+ { "cai", "才材菜財採" },
+ { "can", "参残參" },
+ { "ce", "策側" },
+ { "ceng", "曾" },
+ { "cha", "差查茶" },
+ { "chai", "差" },
+ { "chan", "產産單" },
+ { "chang", "場廠" },
+ { "chao", "超朝" },
+ { "che", "車" },
+ { "cheng", "成程乗" },
+ { "chi", "尺吃持赤池遅歯" },
+ { "chong", "充种重種" },
+ { "chu", "出初楚触處処" },
+ { "chuan", "川船傳" },
+ { "chuang", "創窓" },
+ { "chun", "春" },
+ { "ci", "此次辞差" },
+ { "cong", "從従" },
+ { "cu", "卒" },
+ { "cun", "存村" },
+ { "cuo", "錯" },
+ { "da", "大打答達" },
+ { "dai", "代待帯帶貸" },
+ { "dan", "但担擔誕單単" },
+ { "dang", "当党當黨" },
+ { "dao", "到道盗導島辺" },
+ { "de", "的得" },
+ { "dei", "" },
+ { "deng", "等" },
+ { "di", "地得低底弟第締" },
+ { "dian", "点电店點電" },
+ { "diao", "調" },
+ { "ding", "定町" },
+ { "dong", "冬東動働凍" },
+ { "du", "独度都渡読" },
+ { "duan", "段断短斷" },
+ { "dui", "對対" },
+ { "duo", "多駄" },
+ { "e", "嗯悪" },
+ { "en", "嗯" },
+ { "er", "而耳二兒" },
+ { "fa", "乏法發発髪" },
+ { "fan", "反返犯番仮販飯範払" },
+ { "fang", "方放房坊訪" },
+ { "fei", "非飛費" },
+ { "fen", "分份" },
+ { "feng", "風豐" },
+ { "fou", "否不" },
+ { "fu", "父夫富服符付附府幅婦復複負払" },
+ { "gai", "改概該" },
+ { "gan", "甘感敢" },
+ { "gang", "港剛" },
+ { "gao", "告高" },
+ { "ge", "各格歌革割個" },
+ { "gei", "給" },
+ { "gen", "跟根" },
+ { "geng", "更" },
+ { "gong", "工共供功公" },
+ { "gou", "夠構溝" },
+ { "gu", "古故鼓" },
+ { "guai", "掛" },
+ { "guan", "官管慣館觀関關" },
+ { "guang", "光広" },
+ { "gui", "規帰" },
+ { "guo", "果国裏菓國過" },
+ { "hai", "孩海害還" },
+ { "han", "寒漢" },
+ { "hang", "航行" },
+ { "hao", "好号" },
+ { "he", "合和喝何荷" },
+ { "hei", "黒" },
+ { "hen", "很" },
+ { "heng", "行横" },
+ { "hou", "厚喉候後" },
+ { "hu", "乎呼湖護" },
+ { "hua", "化画花話畫劃" },
+ { "huai", "壊劃" },
+ { "huan", "緩環歡還換" },
+ { "huang", "黄" },
+ { "hui", "回会慧絵揮會" },
+ { "hun", "混婚" },
+ { "huo", "活或火獲" },
+ { "i", "" },
+ { "ji", "己计及机既急季寄技即集基祭系奇紀積計記済幾際極繼績機濟" },
+ { "jia", "家加價" },
+ { "jian", "件建健肩見減間検簡漸" },
+ { "jiang", "降強講將港" },
+ { "jiao", "叫教交角覚覺較學" },
+ { "jie", "介借接姐皆届界解結階節價" },
+ { "jin", "今近禁金僅進" },
+ { "jing", "京境景静精經経" },
+ { "jiu", "就久九酒究" },
+ { "ju", "句具局居決挙據舉" },
+ { "jue", "角覚覺" },
+ { "jun", "均" },
+ { "kai", "開" },
+ { "kan", "看刊" },
+ { "kang", "康" },
+ { "kao", "考" },
+ { "ke", "可刻科克客渇課" },
+ { "ken", "肯" },
+ { "kong", "空控" },
+ { "kou", "口" },
+ { "ku", "苦庫" },
+ { "kuai", "快塊会會" },
+ { "kuang", "況" },
+ { "kun", "困" },
+ { "kuo", "括拡適" },
+ { "la", "拉啦落" },
+ { "lai", "来來頼" },
+ { "lao", "老絡落" },
+ { "le", "了楽樂" },
+ { "lei", "類" },
+ { "leng", "冷" },
+ { "li", "力立利理例礼離麗裡勵歷" },
+ { "lian", "連練臉聯" },
+ { "liang", "良量涼兩両" },
+ { "liao", "料" },
+ { "lie", "列" },
+ { "lin", "林隣賃" },
+ { "ling", "另令領" },
+ { "liu", "六留流" },
+ { "lu", "律路録緑陸履慮" },
+ { "lv", "旅" },
+ { "lun", "輪論" },
+ { "luo", "落絡" },
+ { "ma", "媽嗎嘛" },
+ { "mai", "買売" },
+ { "man", "滿" },
+ { "mang", "忙" },
+ { "mao", "毛猫貿" },
+ { "me", "麼" },
+ { "mei", "美妹每沒毎媒" },
+ { "men", "們" },
+ { "mi", "米密秘" },
+ { "mian", "免面勉眠" },
+ { "miao", "描" },
+ { "min", "民皿" },
+ { "ming", "命明名" },
+ { "mo", "末模麼" },
+ { "mou", "某" },
+ { "mu", "母木目模" },
+ { "na", "那哪拿內南" },
+ { "nan", "男南難" },
+ { "nao", "腦" },
+ { "ne", "那哪呢" },
+ { "nei", "内那哪內" },
+ { "neng", "能" },
+ { "ni", "你妳呢" },
+ { "nian", "年念" },
+ { "niang", "娘" },
+ { "nin", "您" },
+ { "ning", "凝" },
+ { "niu", "牛" },
+ { "nong", "農濃" },
+ { "nu", "女努" },
+ { "nuan", "暖" },
+ { "o", "" },
+ { "ou", "歐" },
+ { "pa", "怕" },
+ { "pian", "片便" },
+ { "pai", "迫派排" },
+ { "pan", "判番" },
+ { "pang", "旁" },
+ { "pei", "配" },
+ { "peng", "朋" },
+ { "pi", "疲否" },
+ { "pin", "品貧" },
+ { "ping", "平評" },
+ { "po", "迫破泊頗" },
+ { "pu", "普僕" },
+ { "qi", "起其奇七气期泣企妻契気" },
+ { "qian", "嵌浅千前鉛錢針" },
+ { "qiang", "強將" },
+ { "qiao", "橋繰" },
+ { "qie", "且切契" },
+ { "qin", "寝勤親" },
+ { "qing", "青清情晴輕頃請軽" },
+ { "qiu", "求秋球" },
+ { "qu", "去取趣曲區" },
+ { "quan", "全犬券" },
+ { "que", "缺確卻" },
+ { "ran", "然" },
+ { "rang", "讓" },
+ { "re", "熱" },
+ { "ren", "人任認" },
+ { "reng", "仍" },
+ { "ri", "日" },
+ { "rong", "容" },
+ { "rou", "弱若肉" },
+ { "ru", "如入" },
+ { "ruan", "軟" },
+ { "sai", "賽" },
+ { "san", "三" },
+ { "sao", "騒繰" },
+ { "se", "色" },
+ { "sen", "森" },
+ { "sha", "砂" },
+ { "shan", "善山單" },
+ { "shang", "上尚商" },
+ { "shao", "少紹" },
+ { "shaung", "雙" },
+ { "she", "社射設捨渉" },
+ { "shei", "誰" },
+ { "shen", "什申深甚身伸沈神" },
+ { "sheng", "生声昇勝乗聲" },
+ { "shi", "是失示食时事式十石施使世实史室市始柿氏士仕拭時視師試適実實識" },
+ { "shou", "手首守受授" },
+ { "shu", "束数暑殊樹書屬輸術" },
+ { "shui", "水説說誰" },
+ { "shuo", "数説說" },
+ { "si", "思寺司四私似死価" },
+ { "song", "送" },
+ { "su", "速宿素蘇訴" },
+ { "suan", "算酸" },
+ { "sui", "隨雖歲歳" },
+ { "sun", "孫" },
+ { "suo", "所" },
+ { "ta", "她他它牠" },
+ { "tai", "太台態臺" },
+ { "tan", "探談曇" },
+ { "tang", "糖" },
+ { "tao", "桃逃套討" },
+ { "te", "特" },
+ { "ti", "体提替題體戻" },
+ { "tian", "天田" },
+ { "tiao", "条條調" },
+ { "tie", "鉄" },
+ { "ting", "停庭聽町" },
+ { "tong", "同童通痛统統" },
+ { "tou", "投透頭" },
+ { "tu", "土徒茶図" },
+ { "tuan", "團" },
+ { "tui", "推退" },
+ { "tuo", "脱駄" },
+ { "u", "" },
+ { "v", "" },
+ { "wai", "外" },
+ { "wan", "完万玩晩腕灣" },
+ { "wang", "忘望亡往網" },
+ { "wei", "危位未味委為謂維違圍" },
+ { "wen", "文温問聞" },
+ { "wo", "我" },
+ { "wu", "午物五無屋亡鳥務汚" },
+ { "xi", "夕息西洗喜系昔席希析嬉膝細習係" },
+ { "xia", "下夏狭暇" },
+ { "xian", "先限嫌洗現見線顯" },
+ { "xiang", "向相香像想象降項詳響" },
+ { "xiao", "小笑消效校削咲" },
+ { "xie", "写携些解邪械協謝寫契" },
+ { "xin", "心信新辛" },
+ { "xing", "行形性幸型星興" },
+ { "xiong", "兄胸" },
+ { "xiu", "休秀修" },
+ { "xu", "須需許續緒続" },
+ { "xuan", "選懸" },
+ { "xue", "学雪削靴學" },
+ { "xun", "訓訊" },
+ { "ya", "呀押壓" },
+ { "yan", "言顔研煙嚴厳験驗塩" },
+ { "yang", "央洋陽樣様" },
+ { "yao", "要揺腰薬曜" },
+ { "ye", "也野夜邪業葉" },
+ { "yi", "一已亦依以移意医易伊役異億義議藝醫訳" },
+ { "yin", "因引音飲銀" },
+ { "ying", "英迎影映應營営" },
+ { "yong", "永用泳擁" },
+ { "you", "又有右友由尤油遊郵誘優" },
+ { "yu", "予育余雨浴欲愈御宇域語於魚與込" },
+ { "yuan", "元原源院員円園遠猿願" },
+ { "yue", "月越約楽" },
+ { "yun", "雲伝運" },
+ { "za", "雑" },
+ { "zai", "在再載災" },
+ { "zang", "蔵" },
+ { "zao", "早造" },
+ { "ze", "則擇責" },
+ { "zen", "怎" },
+ { "zeng", "曾增増" },
+ { "zha", "札" },
+ { "zhai", "宅擇" },
+ { "zhan", "站展戰戦" },
+ { "zhang", "丈長障帳張" },
+ { "zhao", "找着朝招" },
+ { "zhe", "者這" },
+ { "zhen", "真震針" },
+ { "zheng", "正整争政爭" },
+ { "zhi", "之只知支止制至治直指值置智値紙製質誌織隻識職執" },
+ { "zhong", "中种終重種眾" },
+ { "zhou", "周州昼宙洲週" },
+ { "zhu", "助主住柱株祝逐注著諸屬術" },
+ { "zhuan", "专專転" },
+ { "zhuang", "状狀" },
+ { "zhui", "追" },
+ { "zhun", "準" },
+ { "zhuo", "着" },
+ { "zi", "子自字姉資" },
+ { "zong", "總" },
+ { "zuo", "左做昨坐座作" },
+ { "zu", "足祖族卒組" },
+ { "zui", "最酔" },
+ { "zou", "走" },
+ {NULL, NULL}
+};
+#endif
+
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent)
+{
+ LV_LOG_INFO("begin");
+ lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
+ lv_obj_class_init_obj(obj);
+ return obj;
+}
+
+
+/*=====================
+ * Setter functions
+ *====================*/
+
+/**
+ * Set the keyboard of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @param dict pointer to a Pinyin input method keyboard
+ */
+void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb)
+{
+ if(kb) {
+ LV_ASSERT_OBJ(kb, &lv_keyboard_class);
+ }
+
+ LV_ASSERT_OBJ(obj, MY_CLASS);
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ pinyin_ime->kb = kb;
+ lv_obj_add_event_cb(pinyin_ime->kb, lv_ime_pinyin_kb_event, LV_EVENT_VALUE_CHANGED, obj);
+ lv_obj_align_to(pinyin_ime->cand_panel, pinyin_ime->kb, LV_ALIGN_OUT_TOP_MID, 0, 0);
+}
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @param dict pointer to a Pinyin input method dictionary
+ */
+void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict)
+{
+ LV_ASSERT_OBJ(obj, MY_CLASS);
+
+ init_pinyin_dict(obj, dict);
+}
+
+/*=====================
+ * Getter functions
+ *====================*/
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin IME object
+ * @return pointer to the Pinyin IME keyboard
+ */
+lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj)
+{
+ LV_ASSERT_OBJ(obj, MY_CLASS);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ return pinyin_ime->kb;
+}
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @return pointer to the Pinyin input method candidate panel
+ */
+lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj)
+{
+ LV_ASSERT_OBJ(obj, MY_CLASS);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ return pinyin_ime->cand_panel;
+}
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @return pointer to the Pinyin input method dictionary
+ */
+lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj)
+{
+ LV_ASSERT_OBJ(obj, MY_CLASS);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ return pinyin_ime->dict;
+}
+
+/*=====================
+ * Other functions
+ *====================*/
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
+{
+ LV_UNUSED(class_p);
+ LV_TRACE_OBJ_CREATE("begin");
+
+ 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++) {
+ if(btnm_i == 0) {
+ lv_btnm_def_pinyin_sel_map[btnm_i] = "<";
+ }
+ else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) {
+ lv_btnm_def_pinyin_sel_map[btnm_i] = ">";
+ }
+ else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 2)) {
+ lv_btnm_def_pinyin_sel_map[btnm_i] = "";
+ }
+ else {
+ lv_pinyin_cand_str[py_str_i][0] = ' ';
+ lv_btnm_def_pinyin_sel_map[btnm_i] = lv_pinyin_cand_str[py_str_i];
+ py_str_i++;
+ }
+ }
+
+ pinyin_ime->py_page = 0;
+ pinyin_ime->ta_count = 0;
+ pinyin_ime->cand_num = 0;
+ lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
+ lv_memset_00(pinyin_ime->py_num, sizeof(pinyin_ime->py_num));
+ lv_memset_00(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos));
+
+ lv_obj_set_size(obj, LV_PCT(100), LV_PCT(55));
+ lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0);
+
+#if LV_IME_PINYIN_USE_DEFAULT_DICT
+ init_pinyin_dict(obj, lv_ime_pinyin_def_dict);
+#endif
+
+ /* Init pinyin_ime->cand_panel */
+ pinyin_ime->cand_panel = lv_btnmatrix_create(lv_scr_act());
+ lv_btnmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map);
+ lv_obj_set_size(pinyin_ime->cand_panel, LV_PCT(100), LV_PCT(5));
+ lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
+
+ lv_btnmatrix_set_one_checked(pinyin_ime->cand_panel, true);
+
+ /* Set cand_panel style*/
+ // Default style
+ lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, 0);
+ lv_obj_set_style_border_width(pinyin_ime->cand_panel, 0, 0);
+ lv_obj_set_style_pad_all(pinyin_ime->cand_panel, 8, 0);
+ lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0);
+ lv_obj_set_style_radius(pinyin_ime->cand_panel, 0, 0);
+ lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0);
+ lv_obj_set_style_base_dir(pinyin_ime->cand_panel, LV_BASE_DIR_LTR, 0);
+
+ // LV_PART_ITEMS style
+ lv_obj_set_style_radius(pinyin_ime->cand_panel, 12, LV_PART_ITEMS);
+ lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS);
+ lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS);
+ lv_obj_set_style_shadow_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS);
+
+ // LV_PART_ITEMS | LV_STATE_PRESSED style
+ lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_COVER, LV_PART_ITEMS | LV_STATE_PRESSED);
+ lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS | LV_STATE_PRESSED);
+
+ /* 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);
+}
+
+
+static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
+{
+ LV_UNUSED(class_p);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ if(lv_obj_is_valid(pinyin_ime->kb))
+ lv_obj_del(pinyin_ime->kb);
+
+ if(lv_obj_is_valid(pinyin_ime->cand_panel))
+ lv_obj_del(pinyin_ime->cand_panel);
+}
+
+
+static void lv_ime_pinyin_kb_event(lv_event_t * e)
+{
+ lv_event_code_t code = lv_event_get_code(e);
+ lv_obj_t * kb = lv_event_get_target(e);
+ lv_obj_t * obj = lv_event_get_user_data(e);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ if(code == LV_EVENT_VALUE_CHANGED) {
+ uint16_t btn_id = lv_btnmatrix_get_selected_btn(kb);
+ if(btn_id == LV_BTNMATRIX_BTN_NONE) return;
+
+ const char * txt = lv_btnmatrix_get_btn_text(kb, lv_btnmatrix_get_selected_btn(kb));
+ if(txt == NULL) return;
+
+ 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));
+ }
+ 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';
+ lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
+ break;
+ }
+ }
+ 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((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++;
+ }
+ }
+}
+
+
+static void lv_ime_pinyin_cand_panel_event(lv_event_t * e)
+{
+ lv_event_code_t code = lv_event_get_code(e);
+ lv_obj_t * cand_panel = lv_event_get_target(e);
+ lv_obj_t * obj = (lv_obj_t *)lv_event_get_user_data(e);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ if(code == LV_EVENT_VALUE_CHANGED) {
+ uint32_t id = lv_btnmatrix_get_selected_btn(cand_panel);
+ if(id == 0) {
+ pinyin_page_proc(obj, 0);
+ return;
+ }
+ if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) {
+ pinyin_page_proc(obj, 1);
+ return;
+ }
+
+ 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++) {
+ 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);
+ }
+}
+
+
+static void pinyin_input_proc(lv_obj_t * obj)
+{
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ pinyin_ime->cand_str = pinyin_search_matching(obj, pinyin_ime->input_char, &pinyin_ime->cand_num);
+ if(pinyin_ime->cand_str == NULL) {
+ return;
+ }
+
+ pinyin_ime->py_page = 0;
+
+ for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) {
+ memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i]));
+ lv_pinyin_cand_str[i][0] = ' ';
+ }
+
+ // fill buf
+ for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) {
+ for(uint8_t j = 0; j < 3; j++) {
+ lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[i * 3 + j];
+ }
+ }
+
+ lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
+}
+
+static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir)
+{
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+ uint16_t page_num = pinyin_ime->cand_num / LV_IME_PINYIN_CAND_TEXT_NUM;
+ uint16_t sur = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM;
+
+ if(dir == 0) {
+ if(pinyin_ime->py_page) {
+ pinyin_ime->py_page--;
+ }
+ }
+ else {
+ if(sur == 0) {
+ page_num -= 1;
+ }
+ if(pinyin_ime->py_page < page_num) {
+ pinyin_ime->py_page++;
+ }
+ else return;
+ }
+
+ for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) {
+ memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i]));
+ lv_pinyin_cand_str[i][0] = ' ';
+ }
+
+ // fill buf
+ uint16_t offset = pinyin_ime->py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM);
+ for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) {
+ if((sur > 0) && (pinyin_ime->py_page == page_num)) {
+ if(i > sur)
+ break;
+ }
+ for(uint8_t j = 0; j < 3; j++) {
+ lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[offset + (i * 3) + j];
+ }
+ }
+}
+
+
+static void lv_ime_pinyin_style_change_event(lv_event_t * e)
+{
+ lv_event_code_t code = lv_event_get_code(e);
+ lv_obj_t * obj = lv_event_get_target(e);
+
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ if(code == LV_EVENT_STYLE_CHANGED) {
+ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
+ lv_obj_set_style_text_font(pinyin_ime->cand_panel, font, 0);
+ }
+}
+
+
+static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict)
+{
+ lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
+
+ char headletter = 'a';
+ uint16_t offset_sum = 0;
+ uint16_t offset_count = 0;
+ uint16_t letter_calc = 0;
+
+ pinyin_ime->dict = dict;
+
+ for(uint16_t i = 0; ; i++) {
+ if((NULL == (dict[i].py)) || (NULL == (dict[i].py_mb))) {
+ headletter = dict[i - 1].py[0];
+ letter_calc = headletter - 'a';
+ pinyin_ime->py_num[letter_calc] = offset_count;
+ break;
+ }
+
+ if(headletter == (dict[i].py[0])) {
+ offset_count++;
+ }
+ else {
+ headletter = dict[i].py[0];
+ letter_calc = headletter - 'a';
+ pinyin_ime->py_num[letter_calc - 1] = offset_count;
+ offset_sum += offset_count;
+ pinyin_ime->py_pos[letter_calc] = offset_sum;
+
+ offset_count = 1;
+ }
+ }
+}
+
+
+static char * pinyin_search_matching(lv_obj_t * obj, char * strInput_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;
+ 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;
+
+ offset = strInput_py_str[0] - 'a';
+ cInputStrLength = strlen(strInput_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)) {
+ break;
+ }
+ }
+
+ // perfect match
+ if(cInputStrLength == 1 || i == cInputStrLength) {
+ // 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);
+ }
+ cpHZ++;
+ }
+ return NULL;
+}
+
+
+#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
new file mode 100644
index 0000000000..9d5c2bc66e
--- /dev/null
+++ b/src/extra/others/ime/lv_ime_pinyin.h
@@ -0,0 +1,117 @@
+/**
+ * @file lv_ime_pinyin.h
+ *
+ */
+#ifndef LV_IME_PINYIN_H
+#define LV_IME_PINYIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "../../../lvgl.h"
+
+#if LV_USE_IME_PINYIN != 0
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+typedef struct {
+ const char * const py;
+ const char * const py_mb;
+} lv_pinyin_dict_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;
+ char * cand_str; /* Candidate string */
+ char * btnm_pinyin_sel[LV_IME_PINYIN_CAND_TEXT_NUM + 3];
+ char input_char[16]; /* Input box character */
+ 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_num[26]; /* Number and length of Pinyin */
+ uint16_t py_pos[26]; /* Pinyin position */
+} lv_ime_pinyin_t;
+
+/***********************
+ * GLOBAL VARIABLES
+ ***********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent);
+
+/*=====================
+ * Setter functions
+ *====================*/
+
+/**
+ * Set the keyboard of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @param dict pointer to a Pinyin input method keyboard
+ */
+void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb);
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @param dict pointer to a Pinyin input method dictionary
+ */
+void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict);
+
+
+/*=====================
+ * Getter functions
+ *====================*/
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin IME object
+ * @return pointer to the Pinyin IME keyboard
+ */
+lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj);
+
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @return pointer to the Pinyin input method candidate panel
+ */
+lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj);
+
+
+/**
+ * Set the dictionary of Pinyin input method.
+ * @param obj pointer to a Pinyin input method object
+ * @return pointer to the Pinyin input method dictionary
+ */
+lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj);
+
+/*=====================
+ * Other functions
+ *====================*/
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /*LV_IME_PINYIN*/
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*LV_USE_IME_PINYIN*/
+
diff --git a/src/extra/others/lv_others.h b/src/extra/others/lv_others.h
index 19afdde3de..106d85e4ef 100644
--- a/src/extra/others/lv_others.h
+++ b/src/extra/others/lv_others.h
@@ -19,6 +19,7 @@ extern "C" {
#include "fragment/lv_fragment.h"
#include "imgfont/lv_imgfont.h"
#include "msg/lv_msg.h"
+#include "ime/lv_ime_pinyin.h"
/*********************
* DEFINES
diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h
index a01176d53e..03e6df984e 100644
--- a/src/lv_conf_internal.h
+++ b/src/lv_conf_internal.h
@@ -2243,6 +2243,40 @@
#endif
#endif
+/*1: Enable Pinyin input method*/
+/*Requires: lv_keyboard*/
+#ifndef LV_USE_IME_PINYIN
+ #ifdef CONFIG_LV_USE_IME_PINYIN
+ #define LV_USE_IME_PINYIN CONFIG_LV_USE_IME_PINYIN
+ #else
+ #define LV_USE_IME_PINYIN 0
+ #endif
+#endif
+#if LV_USE_IME_PINYIN
+ /*1: Use default thesaurus*/
+ /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
+ #ifndef LV_IME_PINYIN_USE_DEFAULT_DICT
+ #ifdef _LV_KCONFIG_PRESENT
+ #ifdef CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT
+ #define LV_IME_PINYIN_USE_DEFAULT_DICT CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT
+ #else
+ #define LV_IME_PINYIN_USE_DEFAULT_DICT 0
+ #endif
+ #else
+ #define LV_IME_PINYIN_USE_DEFAULT_DICT 1
+ #endif
+ #endif
+ /*Set the maximum number of candidate panels that can be displayed*/
+ /*This needs to be adjusted according to the size of the screen*/
+ #ifndef LV_IME_PINYIN_CAND_TEXT_NUM
+ #ifdef CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM
+ #define LV_IME_PINYIN_CAND_TEXT_NUM CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM
+ #else
+ #define LV_IME_PINYIN_CAND_TEXT_NUM 6
+ #endif
+ #endif
+#endif
+
/*==================
* EXAMPLES
*==================*/