一、LVGL8.3的拼音输入法优化
lv_ime_pinyin.c
/**
* @file lv_ime_pinyin.c
* @author Jaychen (719095404@qq.com)
* @brief
* @version 0.1
* @date 2025-08-17
*
* @copyright Copyright (c) 2025
*
*/
/*********************
* 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 pinyin_ime_clear_data(lv_obj_t * obj);
static void init_pinyin_dict(lv_obj_t * obj, const lv_pinyin_dict_t * dict);
static int 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 * py_str, uint16_t * cand_num);
#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
**********************/
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
};
#if LV_IME_PINYIN_USE_K9_MODE
static char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 20 + 1] = {
",", "123", "abc", "def", LV_SYMBOL_BACKSPACE, "\n",
".", "ghi", "jkl", "mno", LV_SYMBOL_KEYBOARD, "\n",
"?", "pqrs", "tuv", "wxyz", LV_SYMBOL_NEW_LINE, "\n",
LV_SYMBOL_LEFT, ""
};
static lv_btnmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16 + 1] = { 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];
static const char * kb_26_ch_lower_map[] = {
"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
"abc", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "Ch", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const char * kb_26_en_lower_map[] = {
"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
"abc", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "En", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const char * kb_26_en_upper_map[] = {
"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
"ABC", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "En", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const lv_btnmatrix_ctrl_t kb_26_ctrl[] = {
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 1,
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 6, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
};
#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_set_parent(obj, lv_obj_get_parent(kb));
lv_obj_set_parent(pinyin_ime->cand_panel, lv_obj_get_parent(kb));
/*************add by Jaychen****************** */
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_CH);
/******************************* */
lv_obj_remove_event_cb(pinyin_ime->kb, lv_keyboard_def_event_cb);
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);
}
/**
* 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)
{
static uint8_t K26_mode = LV_KEYBOARD_MODE_TEXT_LOWER;
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;
switch(mode) {
case LV_IME_PINYIN_MODE_K26_CH:
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER, kb_26_ch_lower_map, kb_26_ctrl);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER);
K26_mode = LV_KEYBOARD_MODE_TEXT_LOWER;
break;
case LV_IME_PINYIN_MODE_K26_EN:
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER, kb_26_en_lower_map, kb_26_ctrl);
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_UPPER, kb_26_en_upper_map, kb_26_ctrl);
if (K26_mode == LV_KEYBOARD_MODE_TEXT_LOWER) {
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER);
}
else {
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_UPPER);
}
break;
case LV_IME_PINYIN_NODE_K26_SPECIAL:
K26_mode = lv_keyboard_get_mode(pinyin_ime->kb);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_SPECIAL);
break;
#if LV_IME_PINYIN_USE_K9_MODE
case LV_IME_PINYIN_MODE_K9_CH:
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,
default_kb_ctrl_k9_map);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1);
break;
case LV_IME_PINYIN_MODE_K9_NUMBER:
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_NUMBER);
break;
#endif
}
}
/*=====================
* 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
*/
const 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;
}
/**
* @brief Hide pinyin input method.
*
* @param pinyin_ime
*/
void lv_ime_pinyin_hide(lv_obj_t *pinyin_ime)
{
lv_obj_t *kb = lv_ime_pinyin_get_kb(pinyin_ime);
pinyin_ime_clear_data(pinyin_ime);
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
}
/**
* @brief Show pinyin input method.
*
* @param pinyin_ime
*/
void lv_ime_pinyin_show(lv_obj_t *pinyin_ime)
{
lv_obj_t *kb = lv_ime_pinyin_get_kb(pinyin_ime);
pinyin_ime_clear_data(pinyin_ime);
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
}
/*=====================
* 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;
uint16_t btnm_i = 0;
for(btnm_i = 0; 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->mode = LV_IME_PINYIN_MODE_K26_CH;
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_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
#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);
lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_CLICK_FOCUSABLE);
/* Set cand_panel style*/
// Default style
lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_50, 0);
lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_make(230, 230, 230), 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);
#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
}
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);
#if LV_IME_PINYIN_USE_K9_MODE
_lv_ll_clear(&pinyin_ime->k9_legal_py_ll);
pinyin_ime->k9_input_str_len = 0;
pinyin_ime->k9_py_ll_pos = 0;
pinyin_ime->k9_legal_py_count = 0;
#endif
}
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_current_target(e);
lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)lv_event_get_user_data(e);
lv_keyboard_t * keyboard = (lv_keyboard_t *)kb;
static uint8_t prv_mode = LV_IME_PINYIN_MODE_K26_CH;
#if LV_IME_PINYIN_USE_K9_MODE
const char * k9_py_map[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
#endif
if (code != LV_EVENT_VALUE_CHANGED) return;
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, btn_id);
if(txt == NULL) return ;
if (strcmp(txt, LV_SYMBOL_KEYBOARD) == 0)
{
if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH || pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_EN) {
prv_mode = pinyin_ime->mode;
#if LV_IME_PINYIN_USE_K9_MODE
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_CH);
#endif
}
else if(pinyin_ime->mode == LV_IME_PINYIN_NODE_K26_SPECIAL) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, prv_mode);
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_CH) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, prv_mode);
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_NUMBER) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_CH);
}
#endif
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return;
}
else if (strcmp(txt, "En") == 0 || strcmp(txt, "Ch") == 0) {
if (strcmp(txt, "Ch") == 0) {
prv_mode = LV_IME_PINYIN_MODE_K26_CH;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_EN);
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER);
}
else {
prv_mode = LV_IME_PINYIN_MODE_K26_EN;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_CH);
}
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
else if(strcmp(txt, "abc") == 0 || strcmp(txt, "ABC") == 0) {
if (pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_EN) {
lv_keyboard_set_mode(kb,
lv_keyboard_get_mode(kb) == LV_KEYBOARD_MODE_TEXT_LOWER ?
LV_KEYBOARD_MODE_TEXT_UPPER : LV_KEYBOARD_MODE_TEXT_LOWER);
return ;
}
else if (pinyin_ime->mode == LV_IME_PINYIN_NODE_K26_SPECIAL) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_EN);
prv_mode = LV_IME_PINYIN_MODE_K26_EN;
return ;
}
else if (pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
return ;
}
}
else if(strcmp(txt, "1#") == 0) {
prv_mode = pinyin_ime->mode;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_NODE_K26_SPECIAL);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(strcmp(txt, "123") == 0) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_NUMBER);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
#endif
else if (strcmp(txt, LV_SYMBOL_OK) == 0) {
lv_event_send(keyboard->ta, LV_EVENT_READY, NULL);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return;
}
else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) {
if(pinyin_ime->ta_count > 0) {
pinyin_ime->ta_count--;
lv_textarea_del_char(keyboard->ta);
if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
pinyin_ime->input_char[pinyin_ime->ta_count] = '\0';
}
#if LV_IME_PINYIN_USE_K9_MODE
else
pinyin_ime->k9_input_str[pinyin_ime->ta_count] = '\0';
#endif
if(pinyin_ime->ta_count cand_panel, LV_OBJ_FLAG_HIDDEN);
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
pinyin_input_proc((lv_obj_t *)pinyin_ime);
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_CH) {
pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char) - 1;
pinyin_k9_get_legal_py((lv_obj_t *)pinyin_ime, pinyin_ime->k9_input_str, k9_py_map);
pinyin_k9_fill_cand((lv_obj_t *)pinyin_ime);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
pinyin_ime->ta_count--;
}
#endif
}
else
{
lv_textarea_del_char(keyboard->ta);
}
return ;
}
else if (strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) {
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(keyboard->ta, "\n");
return ;
}
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) {
if (pinyin_ime->ta_count ta);
return ;
}
#if LV_IME_PINYIN_USE_K9_MODE
else if (pinyin_ime->mode != LV_IME_PINYIN_MODE_K9_CH) {
return ;
}
#else
return ;
#endif
}
else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0 ) {
if (pinyin_ime->ta_count ta);
return ;
}
#if LV_IME_PINYIN_USE_K9_MODE
else if (pinyin_ime->mode != LV_IME_PINYIN_MODE_K9_CH) {
return ;
}
#else
return ;
#endif
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(strcmp(txt, "+/-") == 0) {
uint16_t cur = lv_textarea_get_cursor_pos(keyboard->ta);
const char * ta_txt = lv_textarea_get_text(keyboard->ta);
if(ta_txt[0] == '-') {
lv_textarea_set_cursor_pos(keyboard->ta, 1);
lv_textarea_del_char(keyboard->ta);
lv_textarea_add_char(keyboard->ta, '+');
lv_textarea_set_cursor_pos(keyboard->ta, cur);
}
else if(ta_txt[0] == '+') {
lv_textarea_set_cursor_pos(keyboard->ta, 1);
lv_textarea_del_char(keyboard->ta);
lv_textarea_add_char(keyboard->ta, '-');
lv_textarea_set_cursor_pos(keyboard->ta, cur);
}
else {
lv_textarea_set_cursor_pos(keyboard->ta, 0);
lv_textarea_add_char(keyboard->ta, '-');
lv_textarea_set_cursor_pos(keyboard->ta, cur + 1);
}
return ;
}
#endif
switch(pinyin_ime->mode) {
case LV_IME_PINYIN_MODE_K26_CH:
if((txt[0] >= 'a' && txt[0] = 'A' && txt[0] input_char);
if(len input_char) - 1) {
pinyin_ime->input_char[len] = txt[0];
pinyin_ime->input_char[len+1] = '\0';
if (pinyin_input_proc((lv_obj_t *)pinyin_ime) == 0) {
lv_textarea_add_text(keyboard->ta, txt);
pinyin_ime->ta_count++;
}
else {
pinyin_ime->input_char[len] = '\0';
}
}
}
else {
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(keyboard->ta, txt);
}
break;
#if LV_IME_PINYIN_USE_K9_MODE
case LV_IME_PINYIN_MODE_K9_CH:
if((btn_id >= 16) && (strlen(pinyin_ime->input_char) > 0) && (btn_id input_char);
lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
strcat(pinyin_ime->input_char, txt);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
uint16_t len = tmp_btn_str_len > pinyin_ime->ta_count ? tmp_btn_str_len : pinyin_ime->ta_count;
for(int index = 0; index ta);
}
pinyin_ime->ta_count = tmp_btn_str_len;
pinyin_ime->k9_input_str_len = tmp_btn_str_len;
lv_textarea_add_text(keyboard->ta, pinyin_ime->input_char);
return;
}
else if (txt[0] >= 'a' && txt[0] 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] = '2' + i;
pinyin_ime->k9_input_str[pinyin_ime->ta_count + 1] = '\0';
break;
}
}
pinyin_k9_get_legal_py((lv_obj_t *)pinyin_ime, pinyin_ime->k9_input_str, k9_py_map);
pinyin_k9_fill_cand((lv_obj_t *)pinyin_ime);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
}
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) {
pinyin_k9_cand_page_proc((lv_obj_t *)pinyin_ime, 0);
}
else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
pinyin_k9_cand_page_proc((lv_obj_t *)pinyin_ime, 1);
}
else
{
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(keyboard->ta, txt);
}
break;
#endif
default:
lv_textarea_add_text(keyboard->ta, txt);
break;
}
}
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_current_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) {
lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
if(ta == NULL) return;
uint32_t id = lv_btnmatrix_get_selected_btn(cand_panel);
if(id == LV_BTNMATRIX_BTN_NONE) {
return;
}
else if(id == 0) {
pinyin_page_proc(obj, 0);
return;
}
else 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);
uint16_t index = 0;
for(index = 0; index ta_count; index++)
lv_textarea_del_char(ta);
lv_textarea_add_text(ta, txt);
pinyin_ime_clear_data(obj);
}
}
static int 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 -1;
}
pinyin_ime->py_page = 0;
for(uint8_t i = 0; i cand_num && i cand_str[i * 3 + j];
}
}
lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
lv_obj_invalidate(pinyin_ime->cand_panel);
return 0;
}
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 remainder = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM;
if(!pinyin_ime->cand_str) return;
if(dir == 0) {
if(pinyin_ime->py_page) {
pinyin_ime->py_page--;
}
}
else {
if(remainder == 0) {
page_num -= 1;
}
if(pinyin_ime->py_page py_page++;
}
else return;
}
for(uint8_t i = 0; i py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM);
for(uint8_t i = 0; (i cand_num && i 0) && (pinyin_ime->py_page == page_num)) {
if(i >= remainder)
break;
}
for(uint8_t j = 0; j 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_current_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,const 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];
pinyin_ime->py_num[letter_calc] = offset_count;
letter_calc = headletter - 'a';
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 * py_str, uint16_t * cand_num)
{
lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
const lv_pinyin_dict_t * cpHZ;
uint8_t index, len = 0, offset;
volatile uint8_t count = 0;
if(*py_str == '\0') return NULL;
if(*py_str == 'i') return NULL;
if(*py_str == 'u') return NULL;
if(*py_str == 'v') return NULL;
if(*py_str == ' ') return NULL;
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 py) + index)) {
break;
}
}
// perfect match
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);
}
cpHZ++;
}
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_CH) {
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));
for(uint8_t i = 0; i kb, (const char **)lv_btnm_def_pinyin_k9_map);
}
#endif
pinyin_ime->ta_count = 0;
for(uint8_t i = 0; i input_char, sizeof(pinyin_ime->input_char));
lv_btnmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map);
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_UNUSED(obj);
uint16_t py_str_i = 0;
uint16_t btnm_i = 0;
for(btnm_i = 19; btnm_i = 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;
uint16_t 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 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((size_t)flag ta_count; index++) {
lv_textarea_del_char(keyboard->ta);
}
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;
const lv_pinyin_dict_t * cpHZ = NULL;
uint8_t index = 0, len = 0, offset = 0;
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 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);
for(uint8_t i = 0; i = LV_IME_PINYIN_K9_CAND_TEXT_NUM)
break;
if(index k9_legal_py_count) {
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);
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;
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) {
for(uint8_t i = 0; i = (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 {
for(uint8_t i = 0; i k9_legal_py_ll, ll_index);
while(ll_index) {
if(count 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*/
lv_ime_pinyin.h
/**
* @file lv_ime_pinyin.h
* @author Jaychen (719095404@qq.com)
* @brief
* @version 0.1
* @date 2025-08-17
*
* @copyright Copyright (c) 2025
*
*/
#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
*********************/
#if LV_IME_PINYIN_USE_K9_MODE
#define LV_IME_PINYIN_K9_MAX_INPUT 7
#endif
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_IME_PINYIN_MODE_K26_CH,
LV_IME_PINYIN_MODE_K26_EN,
LV_IME_PINYIN_NODE_K26_SPECIAL,
#if LV_IME_PINYIN_USE_K9_MODE
LV_IME_PINYIN_MODE_K9_NUMBER,
LV_IME_PINYIN_MODE_K9_CH,
#endif
} 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;
const lv_pinyin_dict_t * dict;
lv_ll_t k9_legal_py_ll;
char * cand_str; /* Candidate string */
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(k26) */
uint16_t py_num[26]; /* Number and length of Pinyin */
uint16_t py_pos[26]; /* Pinyin position */
uint8_t mode : 3; /* Set mode */
} lv_ime_pinyin_t;
/***********************
* GLOBAL VARIABLES
***********************/
extern const lv_obj_class_t lv_ime_pinyin_class;
/**********************
* 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 kb 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);
/**
* 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
*====================*/
/**
* 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
*/
const lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj);
/**
* @brief Hide pinyin input method.
*
* @param pinyin_ime
*/
void lv_ime_pinyin_hide(lv_obj_t *pinyin_ime);
/**
* @brief Show pinyin input method.
*
* @param pinyin_ime
*/
void lv_ime_pinyin_show(lv_obj_t *pinyin_ime);
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_IME_PINYIN*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IME_PINYIN_H*/
二、LVGL9.4的拼音输入法优化
lv_ime_pinyin.c
/**
* @file lv_ime_pinyin.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_ime_pinyin_private.h"
#include "../../core/lv_obj_class_private.h"
#if LV_USE_IME_PINYIN != 0
#include "../../lvgl.h"
#include "../../core/lv_global.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS (&lv_ime_pinyin_class)
#define cand_len LV_GLOBAL_DEFAULT()->ime_cand_len
/**********************
* 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, const lv_pinyin_dict_t * dict);
static int 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 * 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
**********************/
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,
.name = "lv_ime_pinyin",
};
#if LV_IME_PINYIN_USE_K9_MODE
static const char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21] = {
",", "123", "abc", "def", LV_SYMBOL_BACKSPACE, "\n",
".", "ghi", "jkl", "mno", LV_SYMBOL_KEYBOARD, "\n",
"?", "pqrs", "tuv", "wxyz", LV_SYMBOL_NEW_LINE, "\n",
LV_SYMBOL_LEFT, ""
};
static lv_buttonmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 17] = { 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];
static const char * kb_26_ch_lower_map[] = {
"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
"abc", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "Ch", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const char * kb_26_en_lower_map[] = {
"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
"abc", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "En", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const char * kb_26_en_upper_map[] = {
"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
"ABC", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", "En", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
};
static const lv_btnmatrix_ctrl_t kb_26_ctrl[] = {
LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_BUTTONMATRIX_CTRL_CHECKED | 1,
LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 6, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2
};
#if LV_IME_PINYIN_USE_DEFAULT_DICT
static const 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", "怕" },
{ "pai", "迫派排" },
{ "pan", "判番" },
{ "pang", "旁" },
{ "pei", "配" },
{ "peng", "朋" },
{ "pi", "疲否" },
{ "pian", "片便" },
{ "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
*====================*/
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_set_parent(obj, lv_obj_get_parent(kb));
lv_obj_set_parent(pinyin_ime->cand_panel, lv_obj_get_parent(kb));
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_CH);
lv_obj_remove_event_cb(pinyin_ime->kb, lv_keyboard_def_event_cb);
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);
}
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);
}
void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode)
{
static uint8_t K26_mode = LV_KEYBOARD_MODE_TEXT_LOWER;
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;
switch(mode) {
case LV_IME_PINYIN_MODE_K26_CH:
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER, kb_26_ch_lower_map, kb_26_ctrl);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER);
K26_mode = LV_KEYBOARD_MODE_TEXT_LOWER;
break;
case LV_IME_PINYIN_MODE_K26_EN:
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER, kb_26_en_lower_map, kb_26_ctrl);
lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_UPPER, kb_26_en_upper_map, kb_26_ctrl);
if(K26_mode == LV_KEYBOARD_MODE_TEXT_LOWER) {
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER);
}
else {
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_UPPER);
}
break;
case LV_IME_PINYIN_MODE_K26_SPECIAL:
K26_mode = lv_keyboard_get_mode(pinyin_ime->kb);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_SPECIAL);
break;
#if LV_IME_PINYIN_USE_K9_MODE
case LV_IME_PINYIN_MODE_K9_CH:
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,
default_kb_ctrl_k9_map);
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1);
break;
case LV_IME_PINYIN_MODE_K9_NUMBER:
lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_NUMBER);
break;
#endif
}
}
/*=====================
* Getter functions
*====================*/
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;
}
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;
}
const 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;
uint16_t btnm_i = 0;
for(btnm_i = 0; 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->mode = LV_IME_PINYIN_MODE_K26_CH;
pinyin_ime->py_page = 0;
pinyin_ime->ta_count = 0;
pinyin_ime->cand_num = 0;
lv_memzero(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
lv_memzero(pinyin_ime->py_num, sizeof(pinyin_ime->py_num));
lv_memzero(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos));
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
#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_buttonmatrix_create(lv_obj_get_parent(obj));
lv_buttonmatrix_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_buttonmatrix_set_one_checked(pinyin_ime->cand_panel, true);
lv_obj_remove_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_CLICK_FOCUSABLE);
/* Set cand_panel style*/
// Default style
lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_50, 0);
lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_make(230, 230, 230), 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);
#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_memzero(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
}
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_delete(pinyin_ime->kb);
if(lv_obj_is_valid(pinyin_ime->cand_panel))
lv_obj_delete(pinyin_ime->cand_panel);
#if LV_IME_PINYIN_USE_K9_MODE
_lv_ll_clear(&pinyin_ime->k9_legal_py_ll);
pinyin_ime->k9_input_str_len = 0;
pinyin_ime->k9_py_ll_pos = 0;
pinyin_ime->k9_legal_py_count = 0;
#endif
}
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_current_target(e);
lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)lv_event_get_user_data(e);
lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
static uint8_t prv_mode = LV_IME_PINYIN_MODE_K26_CH;
#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) return;
uint16_t btn_id = lv_buttonmatrix_get_selected_button(kb);
if(btn_id == LV_BUTTONMATRIX_BUTTON_NONE) return;
const char * txt = lv_buttonmatrix_get_button_text(kb, btn_id);
if(txt == NULL) return ;
if(lv_strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) {
if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH || pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_EN) {
prv_mode = pinyin_ime->mode;
#if LV_IME_PINYIN_USE_K9_MODE
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_CH);
#endif
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_SPECIAL) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, prv_mode);
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_CH) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, prv_mode);
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_NUMBER) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_CH);
}
#endif
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return;
}
else if(lv_strcmp(txt, "En") == 0 || lv_strcmp(txt, "Ch") == 0) {
if(lv_strcmp(txt, "Ch") == 0) {
prv_mode = LV_IME_PINYIN_MODE_K26_CH;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_EN);
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER);
}
else {
prv_mode = LV_IME_PINYIN_MODE_K26_EN;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_CH);
}
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
else if(lv_strcmp(txt, "abc") == 0 || lv_strcmp(txt, "ABC") == 0) {
if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_EN) {
lv_keyboard_set_mode(kb,
lv_keyboard_get_mode(kb) == LV_KEYBOARD_MODE_TEXT_LOWER ?
LV_KEYBOARD_MODE_TEXT_UPPER : LV_KEYBOARD_MODE_TEXT_LOWER);
return ;
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_SPECIAL) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_EN);
prv_mode = LV_IME_PINYIN_MODE_K26_EN;
return ;
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
return ;
}
}
else if(lv_strcmp(txt, "1#") == 0) {
prv_mode = pinyin_ime->mode;
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K26_SPECIAL);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(lv_strcmp(txt, "123") == 0) {
lv_ime_pinyin_set_mode((lv_obj_t *)pinyin_ime, LV_IME_PINYIN_MODE_K9_NUMBER);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return ;
}
#endif
else if(lv_strcmp(txt, LV_SYMBOL_OK) == 0) {
lv_obj_send_event(ta, LV_EVENT_READY, NULL);
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
return;
}
else if(lv_strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) {
if(pinyin_ime->ta_count > 0) {
pinyin_ime->ta_count--;
lv_textarea_delete_char(ta);
if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
pinyin_ime->input_char[pinyin_ime->ta_count] = '\0';
}
#if LV_IME_PINYIN_USE_K9_MODE
else
pinyin_ime->k9_input_str[pinyin_ime->ta_count] = '\0';
#endif
if(pinyin_ime->ta_count cand_panel, LV_OBJ_FLAG_HIDDEN);
}
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26_CH) {
pinyin_input_proc((lv_obj_t *)pinyin_ime);
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_CH) {
pinyin_ime->k9_input_str_len = lv_strlen(pinyin_ime->input_char) - 1;
pinyin_k9_get_legal_py((lv_obj_t *)pinyin_ime, pinyin_ime->k9_input_str, k9_py_map);
pinyin_k9_fill_cand((lv_obj_t *)pinyin_ime);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
pinyin_ime->ta_count--;
}
#endif
}
else {
lv_textarea_delete_char(ta);
}
return ;
}
else if(lv_strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) {
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(ta, "\n");
return ;
}
else if(lv_strcmp(txt, LV_SYMBOL_LEFT) == 0) {
if(pinyin_ime->ta_count mode != LV_IME_PINYIN_MODE_K9_CH) {
return ;
}
#else
return ;
#endif
}
else if(lv_strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
if(pinyin_ime->ta_count mode != LV_IME_PINYIN_MODE_K9_CH) {
return ;
}
#else
return ;
#endif
}
#if LV_IME_PINYIN_USE_K9_MODE
else if(lv_strcmp(txt, "+/-") == 0) {
uint16_t cur = lv_textarea_get_cursor_pos(ta);
const char * ta_txt = lv_textarea_get_text(ta);
if(ta_txt[0] == '-') {
lv_textarea_set_cursor_pos(ta, 1);
lv_textarea_delete_char(ta);
lv_textarea_add_char(ta, '+');
lv_textarea_set_cursor_pos(ta, cur);
}
else if(ta_txt[0] == '+') {
lv_textarea_set_cursor_pos(ta, 1);
lv_textarea_delete_char(ta);
lv_textarea_add_char(ta, '-');
lv_textarea_set_cursor_pos(ta, cur);
}
else {
lv_textarea_set_cursor_pos(ta, 0);
lv_textarea_add_char(ta, '-');
lv_textarea_set_cursor_pos(ta, cur + 1);
}
return ;
}
#endif
switch(pinyin_ime->mode) {
case LV_IME_PINYIN_MODE_K26_CH:
if((txt[0] >= 'a' && txt[0] = 'A' && txt[0] input_char);
if(len input_char) - 1) {
pinyin_ime->input_char[len] = txt[0];
pinyin_ime->input_char[len + 1] = '\0';
if(pinyin_input_proc((lv_obj_t *)pinyin_ime) == 0) {
lv_textarea_add_text(ta, txt);
pinyin_ime->ta_count++;
}
else {
pinyin_ime->input_char[len] = '\0';
}
}
}
else {
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(ta, txt);
}
break;
#if LV_IME_PINYIN_USE_K9_MODE
case LV_IME_PINYIN_MODE_K9_CH:
if((btn_id >= 16) && (lv_strlen(pinyin_ime->input_char) > 0) && (btn_id input_char);
lv_memzero(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
lv_strcat(pinyin_ime->input_char, txt);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
uint16_t len = tmp_btn_str_len > pinyin_ime->ta_count ? tmp_btn_str_len : pinyin_ime->ta_count;
for(int index = 0; index 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;
}
else if(txt[0] >= 'a' && txt[0] k9_input_str_len += lv_strlen(k9_py_map[i]) + 1;
else pinyin_ime->k9_input_str_len += lv_strlen(k9_py_map[i]);
pinyin_ime->k9_input_str[pinyin_ime->ta_count] = '2' + i;
pinyin_ime->k9_input_str[pinyin_ime->ta_count + 1] = '\0';
break;
}
}
pinyin_k9_get_legal_py((lv_obj_t *)pinyin_ime, pinyin_ime->k9_input_str, k9_py_map);
pinyin_k9_fill_cand((lv_obj_t *)pinyin_ime);
pinyin_input_proc((lv_obj_t *)pinyin_ime);
}
else if(lv_strcmp(txt, LV_SYMBOL_LEFT) == 0) {
pinyin_k9_cand_page_proc((lv_obj_t *)pinyin_ime, 0);
}
else if(lv_strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
pinyin_k9_cand_page_proc((lv_obj_t *)pinyin_ime, 1);
}
else {
pinyin_ime_clear_data((lv_obj_t *)pinyin_ime);
lv_textarea_add_text(ta, txt);
}
break;
#endif
default:
lv_textarea_add_text(ta, txt);
break;
}
}
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_current_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) {
lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
if(ta == NULL) return;
uint32_t id = lv_buttonmatrix_get_selected_button(cand_panel);
if(id == LV_BUTTONMATRIX_BUTTON_NONE) {
return;
}
else if(id == 0) {
pinyin_page_proc(obj, 0);
return;
}
else if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) {
pinyin_page_proc(obj, 1);
return;
}
const char * txt = lv_buttonmatrix_get_button_text(cand_panel, id);
uint16_t index = 0;
for(index = 0; index ta_count; index++)
lv_textarea_delete_char(ta);
lv_textarea_add_text(ta, txt);
pinyin_ime_clear_data(obj);
}
}
static int 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 -1;
}
pinyin_ime->py_page = 0;
for(uint8_t i = 0; i cand_num && i cand_str[i * 3 + j];
}
}
lv_obj_remove_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
lv_obj_invalidate(pinyin_ime->cand_panel);
return 0;
}
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 remainder = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM;
if(!pinyin_ime->cand_str) return;
if(dir == 0) {
if(pinyin_ime->py_page) {
pinyin_ime->py_page--;
}
}
else {
if(remainder == 0) {
page_num -= 1;
}
if(pinyin_ime->py_page py_page++;
}
else return;
}
for(uint8_t i = 0; i py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM);
for(uint8_t i = 0; (i cand_num && i 0) && (pinyin_ime->py_page == page_num)) {
if(i >= remainder)
break;
}
for(uint8_t j = 0; j 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_current_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, const 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];
pinyin_ime->py_num[letter_calc] = offset_count;
letter_calc = headletter - 'a';
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 * py_str, uint16_t * cand_num)
{
lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
const lv_pinyin_dict_t * cpHZ;
uint8_t index, len = 0, offset;
volatile uint8_t count = 0;
if(*py_str == '\0') return NULL;
if(*py_str == 'i') return NULL;
if(*py_str == 'u') return NULL;
if(*py_str == 'v') return NULL;
if(*py_str == ' ') return NULL;
offset = py_str[0] - 'a';
len = lv_strlen(py_str);
cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]];
count = pinyin_ime->py_num[offset];
while(count--) {
for(index = 0; index py) + index)) {
break;
}
}
// perfect match
if(len == 1 || index == len) {
// The Chinese character in UTF-8 encoding format is 3 bytes
* cand_num = lv_strlen((const char *)(cpHZ->py_mb)) / 3;
return (char *)(cpHZ->py_mb);
}
cpHZ++;
}
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_CH) {
pinyin_ime->k9_input_str_len = 0;
pinyin_ime->k9_py_ll_pos = 0;
pinyin_ime->k9_legal_py_count = 0;
lv_memzero(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT);
lv_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
for(uint8_t i = 0; i kb, (const char **)lv_btnm_def_pinyin_k9_map);
}
#endif
pinyin_ime->ta_count = 0;
for(uint8_t i = 0; i input_char, sizeof(pinyin_ime->input_char));
lv_buttonmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map);
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_UNUSED(obj);
uint16_t py_str_i = 0;
uint16_t btnm_i = 0;
for(btnm_i = 19; btnm_i = 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;
uint16_t 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);
lv_strcpy(ll_index->py_str, py_comp);
}
else if((count 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((size_t)flag kb);
for(index = 0; index ta_count; index++) {
lv_textarea_delete_char(ta);
}
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;
const lv_pinyin_dict_t * cpHZ = NULL;
uint8_t index = 0, len = 0, offset = 0;
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 = lv_strlen(py_str);
cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]];
count = pinyin_ime->py_num[offset];
while(count--) {
for(index = 0; index 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)
{
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 != cand_len) {
lv_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
cand_len = tmp_len;
}
ll_index = lv_ll_get_head(&pinyin_ime->k9_legal_py_ll);
lv_strcpy(pinyin_ime->input_char, ll_index->py_str);
for(uint8_t i = 0; i = LV_IME_PINYIN_K9_CAND_TEXT_NUM)
break;
if(index k9_legal_py_count) {
lv_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);
pinyin_ime->k9_input_str_len = lv_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;
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_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
// next page
if(dir == 1) {
for(uint8_t i = 0; i = (LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1))
break;
lv_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 {
for(uint8_t i = 0; i k9_legal_py_ll, ll_index);
while(ll_index) {
if(count 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*/
lv_ime_pinyin.h
/**
* @file lv_ime_pinyin.h
*
*/
#ifndef LV_IME_PINYIN_H
#define LV_IME_PINYIN_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#include "../../core/lv_obj.h"
#if LV_USE_IME_PINYIN != 0
/*********************
* DEFINES
*********************/
#if LV_IME_PINYIN_USE_K9_MODE
#define LV_IME_PINYIN_K9_MAX_INPUT 7
#endif
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_IME_PINYIN_MODE_K26_CH,
LV_IME_PINYIN_MODE_K26_EN,
LV_IME_PINYIN_MODE_K26_SPECIAL,
#if LV_IME_PINYIN_USE_K9_MODE
LV_IME_PINYIN_MODE_K9_NUMBER,
LV_IME_PINYIN_MODE_K9_CH,
#endif
} 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;
/***********************
* GLOBAL VARIABLES
***********************/
extern const lv_obj_class_t lv_ime_pinyin_class;
/**********************
* 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 kb 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);
/**
* 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
*====================*/
/**
* 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
*/
const 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_IME_PINYIN_H*/
lv_example_ime_pinyin_1.c
#include "../../lv_examples.h"
#if LV_USE_LABEL && LV_USE_TEXTAREA && LV_FONT_SOURCE_HAN_SANS_SC_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_obj(e);
lv_obj_t * kb = (lv_obj_t *) lv_event_get_user_data(e);
if(code == LV_EVENT_FOCUSED) {
if(lv_indev_get_type(lv_indev_active()) != LV_INDEV_TYPE_KEYPAD) {
lv_keyboard_set_textarea(kb, ta);
lv_obj_remove_flag(kb, LV_OBJ_FLAG_HIDDEN);
}
}
else if(code == LV_EVENT_CANCEL || code == LV_EVENT_DEFOCUSED || code == LV_EVENT_READY) {
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_remove_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_screen_active());
lv_obj_set_style_text_font(pinyin_ime, &lv_font_source_han_sans_sc_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_screen_active());
lv_textarea_set_one_line(ta1, true);
lv_obj_set_style_text_font(ta1, &lv_font_source_han_sans_sc_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_screen_active());
lv_ime_pinyin_set_keyboard(pinyin_ime, kb);
lv_keyboard_set_textarea(kb, ta1);
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);
}
#endif