1 /**
2  * @file lv_ime_pinyin.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_ime_pinyin.h"
10 #if LV_USE_IME_PINYIN != 0
11 
12 #include <stdio.h>
13 
14 /*********************
15  *      DEFINES
16  *********************/
17 #define MY_CLASS    &lv_ime_pinyin_class
18 
19 /**********************
20  *      TYPEDEFS
21  **********************/
22 
23 /**********************
24  *  STATIC PROTOTYPES
25  **********************/
26 static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
27 static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
28 static void lv_ime_pinyin_style_change_event(lv_event_t * e);
29 static void lv_ime_pinyin_kb_event(lv_event_t * e);
30 static void lv_ime_pinyin_cand_panel_event(lv_event_t * e);
31 
32 static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict);
33 static void pinyin_input_proc(lv_obj_t * obj);
34 static void pinyin_page_proc(lv_obj_t * obj, uint16_t btn);
35 static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num);
36 static void pinyin_ime_clear_data(lv_obj_t * obj);
37 
38 #if LV_IME_PINYIN_USE_K9_MODE
39     static void pinyin_k9_init_data(lv_obj_t * obj);
40     static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]);
41     static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str);
42     static void pinyin_k9_fill_cand(lv_obj_t * obj);
43     static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir);
44 #endif
45 
46 /**********************
47  *  STATIC VARIABLES
48  **********************/
49 const lv_obj_class_t lv_ime_pinyin_class = {
50     .constructor_cb = lv_ime_pinyin_constructor,
51     .destructor_cb  = lv_ime_pinyin_destructor,
52     .width_def      = LV_SIZE_CONTENT,
53     .height_def     = LV_SIZE_CONTENT,
54     .group_def      = LV_OBJ_CLASS_GROUP_DEF_TRUE,
55     .instance_size  = sizeof(lv_ime_pinyin_t),
56     .base_class     = &lv_obj_class
57 };
58 
59 #if LV_IME_PINYIN_USE_K9_MODE
60 static char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 20] = {\
61                                                                                 ",\0", "1#\0",  "abc \0", "def\0",  LV_SYMBOL_BACKSPACE"\0", "\n\0",
62                                                                                 ".\0", "ghi\0", "jkl\0", "mno\0",  LV_SYMBOL_KEYBOARD"\0", "\n\0",
63                                                                                 "?\0", "pqrs\0", "tuv\0", "wxyz\0",  LV_SYMBOL_NEW_LINE"\0", "\n\0",
64                                                                                 LV_SYMBOL_LEFT"\0", "\0"
65                                                                                };
66 
67 static lv_btnmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = { 1 };
68 static char   lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 2][LV_IME_PINYIN_K9_MAX_INPUT] = {0};
69 #endif
70 
71 static char   lv_pinyin_cand_str[LV_IME_PINYIN_CAND_TEXT_NUM][4];
72 static char * lv_btnm_def_pinyin_sel_map[LV_IME_PINYIN_CAND_TEXT_NUM + 3];
73 
74 #if LV_IME_PINYIN_USE_DEFAULT_DICT
75 lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = {
76     { "a", "啊" },
77     { "ai", "愛" },
78     { "an", "安暗案" },
79     { "ba", "吧把爸八" },
80     { "bai", "百白敗" },
81     { "ban", "半般辦" },
82     { "bang", "旁" },
83     { "bao", "保薄包報" },
84     { "bei", "被背悲北杯備" },
85     { "ben", "本" },
86     { "bi", "必比避鼻彼筆秘閉" },
87     { "bian", "便邊變変辺" },
88     { "biao", "表標" },
89     { "bie", "別" },
90     { "bing", "病並氷" },
91     { "bo", "波薄泊" },
92     { "bu", "不布步部捕補歩" },
93     { "ca", "察" },
94     { "cai", "才材菜財採" },
95     { "can", "参残參" },
96     { "ce", "策側" },
97     { "ceng", "曾" },
98     { "cha", "差查茶" },
99     { "chai", "差" },
100     { "chan", "產産單" },
101     { "chang", "場廠" },
102     { "chao", "超朝" },
103     { "che", "車" },
104     { "cheng", "成程乗" },
105     { "chi", "尺吃持赤池遅歯" },
106     { "chong", "充种重種" },
107     { "chu", "出初楚触處処" },
108     { "chuan", "川船傳" },
109     { "chuang", "創窓" },
110     { "chun", "春" },
111     { "ci", "此次辞差" },
112     { "cong", "從従" },
113     { "cu", "卒" },
114     { "cun", "存村" },
115     { "cuo", "錯" },
116     { "da", "大打答達" },
117     { "dai", "代待帯帶貸" },
118     { "dan", "但担擔誕單単" },
119     { "dang", "当党當黨" },
120     { "dao", "到道盗導島辺" },
121     { "de", "的得" },
122     { "dei", "" },
123     { "deng", "等" },
124     { "di", "地得低底弟第締" },
125     { "dian", "点电店點電" },
126     { "diao", "調" },
127     { "ding", "定町" },
128     { "dong", "冬東動働凍" },
129     { "du", "独度都渡読" },
130     { "duan", "段断短斷" },
131     { "dui", "對対" },
132     { "duo", "多駄" },
133     { "e", "嗯悪" },
134     { "en", "嗯" },
135     { "er", "而耳二兒" },
136     { "fa", "乏法發発髪" },
137     { "fan", "反返犯番仮販飯範払" },
138     { "fang", "方放房坊訪" },
139     { "fei", "非飛費" },
140     { "fen", "分份" },
141     { "feng", "風豐" },
142     { "fou", "否不" },
143     { "fu", "父夫富服符付附府幅婦復複負払" },
144     { "gai", "改概該" },
145     { "gan", "甘感敢" },
146     { "gang", "港剛" },
147     { "gao", "告高" },
148     { "ge", "各格歌革割個" },
149     { "gei", "給" },
150     { "gen", "跟根" },
151     { "geng", "更" },
152     { "gong", "工共供功公" },
153     { "gou", "夠構溝" },
154     { "gu", "古故鼓" },
155     { "guai", "掛" },
156     { "guan", "官管慣館觀関關" },
157     { "guang", "光広" },
158     { "gui", "規帰" },
159     { "guo", "果国裏菓國過" },
160     { "hai", "孩海害還" },
161     { "han", "寒漢" },
162     { "hang", "航行" },
163     { "hao", "好号" },
164     { "he", "合和喝何荷" },
165     { "hei", "黒" },
166     { "hen", "很" },
167     { "heng", "行横" },
168     { "hou", "厚喉候後" },
169     { "hu", "乎呼湖護" },
170     { "hua", "化画花話畫劃" },
171     { "huai", "壊劃" },
172     { "huan", "緩環歡還換" },
173     { "huang", "黄" },
174     { "hui", "回会慧絵揮會" },
175     { "hun", "混婚" },
176     { "huo", "活或火獲" },
177     { "i", "" },
178     { "ji", "己计及机既急季寄技即集基祭系奇紀積計記済幾際極繼績機濟" },
179     { "jia", "家加價" },
180     { "jian", "件建健肩見減間検簡漸" },
181     { "jiang", "降強講將港" },
182     { "jiao", "叫教交角覚覺較學" },
183     { "jie", "介借接姐皆届界解結階節價" },
184     { "jin", "今近禁金僅進" },
185     { "jing", "京境景静精經経" },
186     { "jiu", "就久九酒究" },
187     { "ju", "句具局居決挙據舉" },
188     { "jue", "角覚覺" },
189     { "jun", "均" },
190     { "kai", "開" },
191     { "kan", "看刊" },
192     { "kang", "康" },
193     { "kao", "考" },
194     { "ke", "可刻科克客渇課" },
195     { "ken", "肯" },
196     { "kong", "空控" },
197     { "kou", "口" },
198     { "ku", "苦庫" },
199     { "kuai", "快塊会會" },
200     { "kuang", "況" },
201     { "kun", "困" },
202     { "kuo", "括拡適" },
203     { "la", "拉啦落" },
204     { "lai", "来來頼" },
205     { "lao", "老絡落" },
206     { "le", "了楽樂" },
207     { "lei", "類" },
208     { "leng", "冷" },
209     { "li", "力立利理例礼離麗裡勵歷" },
210     { "lian", "連練臉聯" },
211     { "liang", "良量涼兩両" },
212     { "liao", "料" },
213     { "lie", "列" },
214     { "lin", "林隣賃" },
215     { "ling", "另令領" },
216     { "liu", "六留流" },
217     { "lu", "律路録緑陸履慮" },
218     { "lv", "旅" },
219     { "lun", "輪論" },
220     { "luo", "落絡" },
221     { "ma", "媽嗎嘛" },
222     { "mai", "買売" },
223     { "man", "滿" },
224     { "mang", "忙" },
225     { "mao", "毛猫貿" },
226     { "me", "麼" },
227     { "mei", "美妹每沒毎媒" },
228     { "men", "們" },
229     { "mi", "米密秘" },
230     { "mian", "免面勉眠" },
231     { "miao", "描" },
232     { "min", "民皿" },
233     { "ming", "命明名" },
234     { "mo", "末模麼" },
235     { "mou", "某" },
236     { "mu", "母木目模" },
237     { "na", "那哪拿內南" },
238     { "nan", "男南難" },
239     { "nao", "腦" },
240     { "ne", "那哪呢" },
241     { "nei", "内那哪內" },
242     { "neng", "能" },
243     { "ni", "你妳呢" },
244     { "nian", "年念" },
245     { "niang", "娘" },
246     { "nin", "您" },
247     { "ning", "凝" },
248     { "niu", "牛" },
249     { "nong", "農濃" },
250     { "nu", "女努" },
251     { "nuan", "暖" },
252     { "o", "" },
253     { "ou", "歐" },
254     { "pa", "怕" },
255     { "pian", "片便" },
256     { "pai", "迫派排" },
257     { "pan", "判番" },
258     { "pang", "旁" },
259     { "pei", "配" },
260     { "peng", "朋" },
261     { "pi", "疲否" },
262     { "pin", "品貧" },
263     { "ping", "平評" },
264     { "po", "迫破泊頗" },
265     { "pu", "普僕" },
266     { "qi", "起其奇七气期泣企妻契気" },
267     { "qian", "嵌浅千前鉛錢針" },
268     { "qiang", "強將" },
269     { "qiao", "橋繰" },
270     { "qie", "且切契" },
271     { "qin", "寝勤親" },
272     { "qing", "青清情晴輕頃請軽" },
273     { "qiu", "求秋球" },
274     { "qu", "去取趣曲區" },
275     { "quan", "全犬券" },
276     { "que", "缺確卻" },
277     { "ran", "然" },
278     { "rang", "讓" },
279     { "re", "熱" },
280     { "ren", "人任認" },
281     { "reng", "仍" },
282     { "ri", "日" },
283     { "rong", "容" },
284     { "rou", "弱若肉" },
285     { "ru", "如入" },
286     { "ruan", "軟" },
287     { "sai", "賽" },
288     { "san", "三" },
289     { "sao", "騒繰" },
290     { "se", "色" },
291     { "sen", "森" },
292     { "sha", "砂" },
293     { "shan", "善山單" },
294     { "shang", "上尚商" },
295     { "shao", "少紹" },
296     { "shaung", "雙" },
297     { "she", "社射設捨渉" },
298     { "shei", "誰" },
299     { "shen", "什申深甚身伸沈神" },
300     { "sheng", "生声昇勝乗聲" },
301     { "shi", "是失示食时事式十石施使世实史室市始柿氏士仕拭時視師試適実實識" },
302     { "shou", "手首守受授" },
303     { "shu", "束数暑殊樹書屬輸術" },
304     { "shui", "水説說誰" },
305     { "shuo", "数説說" },
306     { "si", "思寺司四私似死価" },
307     { "song", "送" },
308     { "su", "速宿素蘇訴" },
309     { "suan", "算酸" },
310     { "sui", "隨雖歲歳" },
311     { "sun", "孫" },
312     { "suo", "所" },
313     { "ta", "她他它牠" },
314     { "tai", "太台態臺" },
315     { "tan", "探談曇" },
316     { "tang", "糖" },
317     { "tao", "桃逃套討" },
318     { "te", "特" },
319     { "ti", "体提替題體戻" },
320     { "tian", "天田" },
321     { "tiao", "条條調" },
322     { "tie", "鉄" },
323     { "ting", "停庭聽町" },
324     { "tong", "同童通痛统統" },
325     { "tou", "投透頭" },
326     { "tu", "土徒茶図" },
327     { "tuan", "團" },
328     { "tui", "推退" },
329     { "tuo", "脱駄" },
330     { "u", "" },
331     { "v", "" },
332     { "wai", "外" },
333     { "wan", "完万玩晩腕灣" },
334     { "wang", "忘望亡往網" },
335     { "wei", "危位未味委為謂維違圍" },
336     { "wen", "文温問聞" },
337     { "wo", "我" },
338     { "wu", "午物五無屋亡鳥務汚" },
339     { "xi", "夕息西洗喜系昔席希析嬉膝細習係" },
340     { "xia", "下夏狭暇" },
341     { "xian", "先限嫌洗現見線顯" },
342     { "xiang", "向相香像想象降項詳響" },
343     { "xiao", "小笑消效校削咲" },
344     { "xie", "写携些解邪械協謝寫契" },
345     { "xin", "心信新辛" },
346     { "xing", "行形性幸型星興" },
347     { "xiong", "兄胸" },
348     { "xiu", "休秀修" },
349     { "xu", "須需許續緒続" },
350     { "xuan", "選懸" },
351     { "xue", "学雪削靴學" },
352     { "xun", "訓訊" },
353     { "ya", "呀押壓" },
354     { "yan", "言顔研煙嚴厳験驗塩" },
355     { "yang", "央洋陽樣様" },
356     { "yao", "要揺腰薬曜" },
357     { "ye", "也野夜邪業葉" },
358     { "yi", "一已亦依以移意医易伊役異億義議藝醫訳" },
359     { "yin", "因引音飲銀" },
360     { "ying", "英迎影映應營営" },
361     { "yong", "永用泳擁" },
362     { "you", "又有右友由尤油遊郵誘優" },
363     { "yu", "予育余雨浴欲愈御宇域語於魚與込" },
364     { "yuan", "元原源院員円園遠猿願" },
365     { "yue", "月越約楽" },
366     { "yun", "雲伝運" },
367     { "za", "雑" },
368     { "zai", "在再載災" },
369     { "zang", "蔵" },
370     { "zao", "早造" },
371     { "ze", "則擇責" },
372     { "zen", "怎" },
373     { "zeng", "曾增増" },
374     { "zha", "札" },
375     { "zhai", "宅擇" },
376     { "zhan", "站展戰戦" },
377     { "zhang", "丈長障帳張" },
378     { "zhao", "找着朝招" },
379     { "zhe", "者這" },
380     { "zhen", "真震針" },
381     { "zheng", "正整争政爭" },
382     { "zhi", "之只知支止制至治直指值置智値紙製質誌織隻識職執" },
383     { "zhong", "中种終重種眾" },
384     { "zhou", "周州昼宙洲週" },
385     { "zhu", "助主住柱株祝逐注著諸屬術" },
386     { "zhuan", "专專転" },
387     { "zhuang", "状狀" },
388     { "zhui", "追" },
389     { "zhun", "準" },
390     { "zhuo", "着" },
391     { "zi", "子自字姉資" },
392     { "zong", "總" },
393     { "zuo", "左做昨坐座作" },
394     { "zu", "足祖族卒組" },
395     { "zui", "最酔" },
396     { "zou", "走" },
397     {NULL, NULL}
398 };
399 #endif
400 
401 /**********************
402  *      MACROS
403  **********************/
404 
405 /**********************
406  *   GLOBAL FUNCTIONS
407  **********************/
lv_ime_pinyin_create(lv_obj_t * parent)408 lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent)
409 {
410     LV_LOG_INFO("begin");
411     lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
412     lv_obj_class_init_obj(obj);
413     return obj;
414 }
415 
416 /*=====================
417  * Setter functions
418  *====================*/
419 
420 /**
421  * Set the keyboard of Pinyin input method.
422  * @param obj  pointer to a Pinyin input method object
423  * @param dict pointer to a Pinyin input method keyboard
424  */
lv_ime_pinyin_set_keyboard(lv_obj_t * obj,lv_obj_t * kb)425 void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb)
426 {
427     if(kb) {
428         LV_ASSERT_OBJ(kb, &lv_keyboard_class);
429     }
430 
431     LV_ASSERT_OBJ(obj, MY_CLASS);
432     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
433 
434     pinyin_ime->kb = kb;
435     lv_obj_add_event_cb(pinyin_ime->kb, lv_ime_pinyin_kb_event, LV_EVENT_VALUE_CHANGED, obj);
436     lv_obj_align_to(pinyin_ime->cand_panel, pinyin_ime->kb, LV_ALIGN_OUT_TOP_MID, 0, 0);
437 }
438 
439 /**
440  * Set the dictionary of Pinyin input method.
441  * @param obj  pointer to a Pinyin input method object
442  * @param dict pointer to a Pinyin input method dictionary
443  */
lv_ime_pinyin_set_dict(lv_obj_t * obj,lv_pinyin_dict_t * dict)444 void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict)
445 {
446     LV_ASSERT_OBJ(obj, MY_CLASS);
447 
448     init_pinyin_dict(obj, dict);
449 }
450 
451 /**
452  * Set mode, 26-key input(k26) or 9-key input(k9).
453  * @param obj  pointer to a Pinyin input method object
454  * @param mode   the mode from 'lv_keyboard_mode_t'
455  */
lv_ime_pinyin_set_mode(lv_obj_t * obj,lv_ime_pinyin_mode_t mode)456 void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode)
457 {
458     LV_ASSERT_OBJ(obj, MY_CLASS);
459     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
460 
461     LV_ASSERT_OBJ(pinyin_ime->kb, &lv_keyboard_class);
462 
463     pinyin_ime->mode = mode;
464 
465 #if LV_IME_PINYIN_USE_K9_MODE
466     if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) {
467         pinyin_k9_init_data(obj);
468         lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1, (const char *)lv_btnm_def_pinyin_k9_map,
469                             (const)default_kb_ctrl_k9_map);
470         lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1);
471     }
472 #endif
473 }
474 
475 /*=====================
476  * Getter functions
477  *====================*/
478 
479 /**
480  * Set the dictionary of Pinyin input method.
481  * @param obj  pointer to a Pinyin IME object
482  * @return     pointer to the Pinyin IME keyboard
483  */
lv_ime_pinyin_get_kb(lv_obj_t * obj)484 lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj)
485 {
486     LV_ASSERT_OBJ(obj, MY_CLASS);
487 
488     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
489 
490     return pinyin_ime->kb;
491 }
492 
493 /**
494  * Set the dictionary of Pinyin input method.
495  * @param obj  pointer to a Pinyin input method object
496  * @return     pointer to the Pinyin input method candidate panel
497  */
lv_ime_pinyin_get_cand_panel(lv_obj_t * obj)498 lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj)
499 {
500     LV_ASSERT_OBJ(obj, MY_CLASS);
501 
502     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
503 
504     return pinyin_ime->cand_panel;
505 }
506 
507 /**
508  * Set the dictionary of Pinyin input method.
509  * @param obj  pointer to a Pinyin input method object
510  * @return     pointer to the Pinyin input method dictionary
511  */
lv_ime_pinyin_get_dict(lv_obj_t * obj)512 lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj)
513 {
514     LV_ASSERT_OBJ(obj, MY_CLASS);
515 
516     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
517 
518     return pinyin_ime->dict;
519 }
520 
521 /*=====================
522  * Other functions
523  *====================*/
524 
525 /**********************
526  *   STATIC FUNCTIONS
527  **********************/
528 
lv_ime_pinyin_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)529 static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
530 {
531     LV_UNUSED(class_p);
532     LV_TRACE_OBJ_CREATE("begin");
533 
534     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
535 
536     uint16_t py_str_i = 0;
537     uint16_t btnm_i = 0;
538     for(btnm_i = 0; btnm_i < (LV_IME_PINYIN_CAND_TEXT_NUM + 3); btnm_i++) {
539         if(btnm_i == 0) {
540             lv_btnm_def_pinyin_sel_map[btnm_i] = "<";
541         }
542         else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) {
543             lv_btnm_def_pinyin_sel_map[btnm_i] = ">";
544         }
545         else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 2)) {
546             lv_btnm_def_pinyin_sel_map[btnm_i] = "";
547         }
548         else {
549             lv_pinyin_cand_str[py_str_i][0] = ' ';
550             lv_btnm_def_pinyin_sel_map[btnm_i] = lv_pinyin_cand_str[py_str_i];
551             py_str_i++;
552         }
553     }
554 
555     pinyin_ime->mode = LV_IME_PINYIN_MODE_K26;
556     pinyin_ime->py_page = 0;
557     pinyin_ime->ta_count = 0;
558     pinyin_ime->cand_num = 0;
559     lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
560     lv_memset_00(pinyin_ime->py_num, sizeof(pinyin_ime->py_num));
561     lv_memset_00(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos));
562 
563     lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
564 
565     lv_obj_set_size(obj, LV_PCT(100), LV_PCT(55));
566     lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0);
567 
568 #if LV_IME_PINYIN_USE_DEFAULT_DICT
569     init_pinyin_dict(obj, lv_ime_pinyin_def_dict);
570 #endif
571 
572     /* Init pinyin_ime->cand_panel */
573     pinyin_ime->cand_panel = lv_btnmatrix_create(lv_scr_act());
574     lv_btnmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map);
575     lv_obj_set_size(pinyin_ime->cand_panel, LV_PCT(100), LV_PCT(5));
576     lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
577 
578     lv_btnmatrix_set_one_checked(pinyin_ime->cand_panel, true);
579     lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_CLICK_FOCUSABLE);
580 
581     /* Set cand_panel style*/
582     // Default style
583     lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, 0);
584     lv_obj_set_style_border_width(pinyin_ime->cand_panel, 0, 0);
585     lv_obj_set_style_pad_all(pinyin_ime->cand_panel, 8, 0);
586     lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0);
587     lv_obj_set_style_radius(pinyin_ime->cand_panel, 0, 0);
588     lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0);
589     lv_obj_set_style_base_dir(pinyin_ime->cand_panel, LV_BASE_DIR_LTR, 0);
590 
591     // LV_PART_ITEMS style
592     lv_obj_set_style_radius(pinyin_ime->cand_panel, 12, LV_PART_ITEMS);
593     lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS);
594     lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS);
595     lv_obj_set_style_shadow_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS);
596 
597     // LV_PART_ITEMS | LV_STATE_PRESSED style
598     lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_COVER, LV_PART_ITEMS | LV_STATE_PRESSED);
599     lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS | LV_STATE_PRESSED);
600 
601     /* event handler */
602     lv_obj_add_event_cb(pinyin_ime->cand_panel, lv_ime_pinyin_cand_panel_event, LV_EVENT_VALUE_CHANGED, obj);
603     lv_obj_add_event_cb(obj, lv_ime_pinyin_style_change_event, LV_EVENT_STYLE_CHANGED, NULL);
604 
605 #if LV_IME_PINYIN_USE_K9_MODE
606     pinyin_ime->k9_input_str_len = 0;
607     pinyin_ime->k9_py_ll_pos = 0;
608     pinyin_ime->k9_legal_py_count = 0;
609     lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT);
610 
611     pinyin_k9_init_data(obj);
612 
613     _lv_ll_init(&(pinyin_ime->k9_legal_py_ll), sizeof(ime_pinyin_k9_py_str_t));
614 #endif
615 }
616 
lv_ime_pinyin_destructor(const lv_obj_class_t * class_p,lv_obj_t * obj)617 static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
618 {
619     LV_UNUSED(class_p);
620 
621     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
622 
623     if(lv_obj_is_valid(pinyin_ime->kb))
624         lv_obj_del(pinyin_ime->kb);
625 
626     if(lv_obj_is_valid(pinyin_ime->cand_panel))
627         lv_obj_del(pinyin_ime->cand_panel);
628 }
629 
lv_ime_pinyin_kb_event(lv_event_t * e)630 static void lv_ime_pinyin_kb_event(lv_event_t * e)
631 {
632     lv_event_code_t code = lv_event_get_code(e);
633     lv_obj_t * kb = lv_event_get_target(e);
634     lv_obj_t * obj = lv_event_get_user_data(e);
635 
636     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
637 
638 #if LV_IME_PINYIN_USE_K9_MODE
639     static const char * k9_py_map[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
640 #endif
641 
642     if(code == LV_EVENT_VALUE_CHANGED) {
643         uint16_t btn_id  = lv_btnmatrix_get_selected_btn(kb);
644         if(btn_id == LV_BTNMATRIX_BTN_NONE) return;
645 
646         const char * txt = lv_btnmatrix_get_btn_text(kb, lv_btnmatrix_get_selected_btn(kb));
647         if(txt == NULL) return;
648 
649 #if LV_IME_PINYIN_USE_K9_MODE
650         if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) {
651             lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
652             uint16_t tmp_btn_str_len = strlen(pinyin_ime->input_char);
653             if((btn_id >= 16) && (tmp_btn_str_len > 0) && (btn_id < (16 + LV_IME_PINYIN_K9_CAND_TEXT_NUM))) {
654                 tmp_btn_str_len = strlen(pinyin_ime->input_char);
655                 lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
656                 strcat(pinyin_ime->input_char, txt);
657                 pinyin_input_proc(obj);
658 
659                 for(int index = 0; index < (pinyin_ime->ta_count + tmp_btn_str_len); index++) {
660                     lv_textarea_del_char(ta);
661                 }
662 
663                 pinyin_ime->ta_count = tmp_btn_str_len;
664                 pinyin_ime->k9_input_str_len = tmp_btn_str_len;
665                 lv_textarea_add_text(ta, pinyin_ime->input_char);
666 
667                 return;
668             }
669         }
670 #endif
671 
672         if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) {
673             pinyin_ime_clear_data(obj);
674             lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
675         }
676         else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) {
677             // del input char
678             if(pinyin_ime->ta_count > 0) {
679                 if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26)
680                     pinyin_ime->input_char[pinyin_ime->ta_count - 1] = '\0';
681 #if LV_IME_PINYIN_USE_K9_MODE
682                 else
683                     pinyin_ime->k9_input_str[pinyin_ime->ta_count - 1] = '\0';
684 #endif
685 
686                 pinyin_ime->ta_count = pinyin_ime->ta_count - 1;
687                 if(pinyin_ime->ta_count <= 0) {
688                     lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
689 #if LV_IME_PINYIN_USE_K9_MODE
690                     lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
691                     strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
692                     strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
693 #endif
694                 }
695                 else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) {
696                     pinyin_input_proc(obj);
697                 }
698 #if LV_IME_PINYIN_USE_K9_MODE
699                 else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) {
700                     pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char) - 1;
701                     pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map);
702                     pinyin_k9_fill_cand(obj);
703                     pinyin_input_proc(obj);
704                 }
705 #endif
706             }
707         }
708         else if((strcmp(txt, "ABC") == 0) || (strcmp(txt, "abc") == 0) || (strcmp(txt, "1#") == 0)) {
709             pinyin_ime->ta_count = 0;
710             lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
711             return;
712         }
713         else if(strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) {
714             if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) {
715                 lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K9);
716             }
717             else {
718                 lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K26);
719                 lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER);
720             }
721             pinyin_ime_clear_data(obj);
722         }
723         else if(strcmp(txt, LV_SYMBOL_OK) == 0) {
724             pinyin_ime_clear_data(obj);
725         }
726         else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) && ((txt[0] >= 'a' && txt[0] <= 'z') || (txt[0] >= 'A' &&
727                                                                                                       txt[0] <= 'Z'))) {
728             strcat(pinyin_ime->input_char, txt);
729             pinyin_input_proc(obj);
730             pinyin_ime->ta_count++;
731         }
732 #if LV_IME_PINYIN_USE_K9_MODE
733         else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) && (txt[0] >= 'a' && txt[0] <= 'z')) {
734             for(uint16_t i = 0; i < 8; i++) {
735                 if((strcmp(txt, k9_py_map[i]) == 0) || (strcmp(txt, "abc ") == 0)) {
736                     if(strcmp(txt, "abc ") == 0)    pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]) + 1;
737                     else                            pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]);
738                     pinyin_ime->k9_input_str[pinyin_ime->ta_count] = 50 + i;
739 
740                     break;
741                 }
742             }
743             pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map);
744             pinyin_k9_fill_cand(obj);
745             pinyin_input_proc(obj);
746         }
747         else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) {
748             pinyin_k9_cand_page_proc(obj, 0);
749         }
750         else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
751             pinyin_k9_cand_page_proc(obj, 1);
752         }
753 #endif
754     }
755 }
756 
lv_ime_pinyin_cand_panel_event(lv_event_t * e)757 static void lv_ime_pinyin_cand_panel_event(lv_event_t * e)
758 {
759     lv_event_code_t code = lv_event_get_code(e);
760     lv_obj_t * cand_panel = lv_event_get_target(e);
761     lv_obj_t * obj = (lv_obj_t *)lv_event_get_user_data(e);
762 
763     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
764 
765     if(code == LV_EVENT_VALUE_CHANGED) {
766         uint32_t id = lv_btnmatrix_get_selected_btn(cand_panel);
767         if(id == 0) {
768             pinyin_page_proc(obj, 0);
769             return;
770         }
771         if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) {
772             pinyin_page_proc(obj, 1);
773             return;
774         }
775 
776         const char * txt = lv_btnmatrix_get_btn_text(cand_panel, id);
777         lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
778         uint16_t index = 0;
779         for(index = 0; index < pinyin_ime->ta_count; index++)
780             lv_textarea_del_char(ta);
781 
782         lv_textarea_add_text(ta, txt);
783 
784         pinyin_ime_clear_data(obj);
785     }
786 }
787 
pinyin_input_proc(lv_obj_t * obj)788 static void pinyin_input_proc(lv_obj_t * obj)
789 {
790     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
791 
792     pinyin_ime->cand_str = pinyin_search_matching(obj, pinyin_ime->input_char, &pinyin_ime->cand_num);
793     if(pinyin_ime->cand_str == NULL) {
794         return;
795     }
796 
797     pinyin_ime->py_page = 0;
798 
799     for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) {
800         memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i]));
801         lv_pinyin_cand_str[i][0] = ' ';
802     }
803 
804     // fill buf
805     for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) {
806         for(uint8_t j = 0; j < 3; j++) {
807             lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[i * 3 + j];
808         }
809     }
810 
811     lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
812 }
813 
pinyin_page_proc(lv_obj_t * obj,uint16_t dir)814 static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir)
815 {
816     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
817     uint16_t page_num = pinyin_ime->cand_num / LV_IME_PINYIN_CAND_TEXT_NUM;
818     uint16_t sur = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM;
819 
820     if(dir == 0) {
821         if(pinyin_ime->py_page) {
822             pinyin_ime->py_page--;
823         }
824     }
825     else {
826         if(sur == 0) {
827             page_num -= 1;
828         }
829         if(pinyin_ime->py_page < page_num) {
830             pinyin_ime->py_page++;
831         }
832         else return;
833     }
834 
835     for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) {
836         memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i]));
837         lv_pinyin_cand_str[i][0] = ' ';
838     }
839 
840     // fill buf
841     uint16_t offset = pinyin_ime->py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM);
842     for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) {
843         if((sur > 0) && (pinyin_ime->py_page == page_num)) {
844             if(i > sur)
845                 break;
846         }
847         for(uint8_t j = 0; j < 3; j++) {
848             lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[offset + (i * 3) + j];
849         }
850     }
851 }
852 
lv_ime_pinyin_style_change_event(lv_event_t * e)853 static void lv_ime_pinyin_style_change_event(lv_event_t * e)
854 {
855     lv_event_code_t code = lv_event_get_code(e);
856     lv_obj_t * obj = lv_event_get_target(e);
857 
858     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
859 
860     if(code == LV_EVENT_STYLE_CHANGED) {
861         const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
862         lv_obj_set_style_text_font(pinyin_ime->cand_panel, font, 0);
863     }
864 }
865 
init_pinyin_dict(lv_obj_t * obj,lv_pinyin_dict_t * dict)866 static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict)
867 {
868     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
869 
870     char headletter = 'a';
871     uint16_t offset_sum = 0;
872     uint16_t offset_count = 0;
873     uint16_t letter_calc = 0;
874 
875     pinyin_ime->dict = dict;
876 
877     for(uint16_t i = 0; ; i++) {
878         if((NULL == (dict[i].py)) || (NULL == (dict[i].py_mb))) {
879             headletter = dict[i - 1].py[0];
880             letter_calc = headletter - 'a';
881             pinyin_ime->py_num[letter_calc] = offset_count;
882             break;
883         }
884 
885         if(headletter == (dict[i].py[0])) {
886             offset_count++;
887         }
888         else {
889             headletter = dict[i].py[0];
890             letter_calc = headletter - 'a';
891             pinyin_ime->py_num[letter_calc - 1] = offset_count;
892             offset_sum += offset_count;
893             pinyin_ime->py_pos[letter_calc] = offset_sum;
894 
895             offset_count = 1;
896         }
897     }
898 }
899 
pinyin_search_matching(lv_obj_t * obj,char * py_str,uint16_t * cand_num)900 static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num)
901 {
902     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
903 
904     lv_pinyin_dict_t * cpHZ;
905     uint8_t index, len = 0, offset;
906     volatile uint8_t count = 0;
907 
908     if(*py_str == '\0')    return NULL;
909     if(*py_str == 'i')     return NULL;
910     if(*py_str == 'u')     return NULL;
911     if(*py_str == 'v')     return NULL;
912 
913     offset = py_str[0] - 'a';
914     len = strlen(py_str);
915 
916     cpHZ  = &pinyin_ime->dict[pinyin_ime->py_pos[offset]];
917     count = pinyin_ime->py_num[offset];
918 
919     while(count--) {
920         for(index = 0; index < len; index++) {
921             if(*(py_str + index) != *((cpHZ->py) + index)) {
922                 break;
923             }
924         }
925 
926         // perfect match
927         if(len == 1 || index == len) {
928             // The Chinese character in UTF-8 encoding format is 3 bytes
929             * cand_num = strlen((const char *)(cpHZ->py_mb)) / 3;
930             return (char *)(cpHZ->py_mb);
931         }
932         cpHZ++;
933     }
934     return NULL;
935 }
936 
pinyin_ime_clear_data(lv_obj_t * obj)937 static void pinyin_ime_clear_data(lv_obj_t * obj)
938 {
939     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
940 
941 #if LV_IME_PINYIN_USE_K9_MODE
942     if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) {
943         pinyin_ime->k9_input_str_len = 0;
944         pinyin_ime->k9_py_ll_pos = 0;
945         pinyin_ime->k9_legal_py_count = 0;
946         lv_memset_00(pinyin_ime->k9_input_str,  LV_IME_PINYIN_K9_MAX_INPUT);
947         lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
948         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
949         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
950     }
951 #endif
952 
953     pinyin_ime->ta_count = 0;
954     lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str)));
955     lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char));
956 
957     lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN);
958 }
959 
960 #if LV_IME_PINYIN_USE_K9_MODE
pinyin_k9_init_data(lv_obj_t * obj)961 static void pinyin_k9_init_data(lv_obj_t * obj)
962 {
963     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
964 
965     uint16_t py_str_i = 0;
966     uint16_t btnm_i = 0;
967     for(btnm_i = 19; btnm_i < (LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21); btnm_i++) {
968         if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM) {
969             strcpy(lv_pinyin_k9_cand_str[py_str_i], LV_SYMBOL_RIGHT"\0");
970         }
971         else if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1) {
972             strcpy(lv_pinyin_k9_cand_str[py_str_i], "\0");
973         }
974         else {
975             strcpy(lv_pinyin_k9_cand_str[py_str_i], " \0");
976         }
977 
978         lv_btnm_def_pinyin_k9_map[btnm_i] = lv_pinyin_k9_cand_str[py_str_i];
979         py_str_i++;
980     }
981 
982     default_kb_ctrl_k9_map[0]  = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
983     default_kb_ctrl_k9_map[4]  = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
984     default_kb_ctrl_k9_map[5]  = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
985     default_kb_ctrl_k9_map[9]  = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
986     default_kb_ctrl_k9_map[10] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
987     default_kb_ctrl_k9_map[14] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
988     default_kb_ctrl_k9_map[15] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
989     default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1;
990 }
991 
pinyin_k9_get_legal_py(lv_obj_t * obj,char * k9_input,const char * py9_map[])992 static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[])
993 {
994     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
995 
996     uint16_t len = strlen(k9_input);
997 
998     if((len == 0) || (len >= LV_IME_PINYIN_K9_MAX_INPUT)) {
999         return;
1000     }
1001 
1002     char py_comp[LV_IME_PINYIN_K9_MAX_INPUT] = {0};
1003     int mark[LV_IME_PINYIN_K9_MAX_INPUT] = {0};
1004     int index = 0;
1005     int flag = 0;
1006     int count = 0;
1007 
1008     uint32_t ll_len = 0;
1009     ime_pinyin_k9_py_str_t * ll_index = NULL;
1010 
1011     ll_len = _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll);
1012     ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll);
1013 
1014     while(index != -1) {
1015         if(index == len) {
1016             if(pinyin_k9_is_valid_py(obj, py_comp)) {
1017                 if((count >= ll_len) || (ll_len == 0)) {
1018                     ll_index = _lv_ll_ins_tail(&pinyin_ime->k9_legal_py_ll);
1019                     strcpy(ll_index->py_str, py_comp);
1020                 }
1021                 else if((count < ll_len)) {
1022                     strcpy(ll_index->py_str, py_comp);
1023                     ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index);
1024                 }
1025                 count++;
1026             }
1027             index--;
1028         }
1029         else {
1030             flag = mark[index];
1031             if(flag < strlen(py9_map[k9_input[index] - '2'])) {
1032                 py_comp[index] = py9_map[k9_input[index] - '2'][flag];
1033                 mark[index] = mark[index] + 1;
1034                 index++;
1035             }
1036             else {
1037                 mark[index] = 0;
1038                 index--;
1039             }
1040         }
1041     }
1042 
1043     if(count > 0) {
1044         pinyin_ime->ta_count++;
1045         pinyin_ime->k9_legal_py_count = count;
1046     }
1047 }
1048 
1049 /*true: visible; false: not visible*/
pinyin_k9_is_valid_py(lv_obj_t * obj,char * py_str)1050 static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str)
1051 {
1052     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
1053 
1054     lv_pinyin_dict_t * cpHZ = NULL;
1055     uint8_t index = 0, len = 0, offset = 0;
1056     uint16_t ret = 1;
1057     volatile uint8_t count = 0;
1058 
1059     if(*py_str == '\0')    return false;
1060     if(*py_str == 'i')     return false;
1061     if(*py_str == 'u')     return false;
1062     if(*py_str == 'v')     return false;
1063 
1064     offset = py_str[0] - 'a';
1065     len = strlen(py_str);
1066 
1067     cpHZ  = &pinyin_ime->dict[pinyin_ime->py_pos[offset]];
1068     count = pinyin_ime->py_num[offset];
1069 
1070     while(count--) {
1071         for(index = 0; index < len; index++) {
1072             if(*(py_str + index) != *((cpHZ->py) + index)) {
1073                 break;
1074             }
1075         }
1076 
1077         // perfect match
1078         if(len == 1 || index == len) {
1079             return true;
1080         }
1081         cpHZ++;
1082     }
1083     return false;
1084 }
1085 
pinyin_k9_fill_cand(lv_obj_t * obj)1086 static void pinyin_k9_fill_cand(lv_obj_t * obj)
1087 {
1088     static uint16_t len = 0;
1089     uint16_t index = 0, tmp_len = 0;
1090     ime_pinyin_k9_py_str_t * ll_index = NULL;
1091 
1092     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
1093 
1094     tmp_len = pinyin_ime->k9_legal_py_count;
1095 
1096     if(tmp_len != len) {
1097         lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
1098         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
1099         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
1100         len = tmp_len;
1101     }
1102 
1103     ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll);
1104     strcpy(pinyin_ime->input_char, ll_index->py_str);
1105     while(ll_index) {
1106         if((index >= LV_IME_PINYIN_K9_CAND_TEXT_NUM) || \
1107            (index >= pinyin_ime->k9_legal_py_count))
1108             break;
1109 
1110         strcpy(lv_pinyin_k9_cand_str[index], ll_index->py_str);
1111         ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/
1112         index++;
1113     }
1114     pinyin_ime->k9_py_ll_pos = index;
1115 
1116     lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
1117     for(index = 0; index < pinyin_ime->k9_input_str_len; index++) {
1118         lv_textarea_del_char(ta);
1119     }
1120     pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char);
1121     lv_textarea_add_text(ta, pinyin_ime->input_char);
1122 }
1123 
pinyin_k9_cand_page_proc(lv_obj_t * obj,uint16_t dir)1124 static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir)
1125 {
1126     lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj;
1127 
1128     lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb);
1129     uint16_t ll_len =  _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll);
1130 
1131     if((ll_len > LV_IME_PINYIN_K9_CAND_TEXT_NUM) && (pinyin_ime->k9_legal_py_count > LV_IME_PINYIN_K9_CAND_TEXT_NUM)) {
1132         ime_pinyin_k9_py_str_t * ll_index = NULL;
1133         uint16_t tmp_btn_str_len = 0;
1134         int count = 0;
1135 
1136         ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll);
1137         while(ll_index) {
1138             if(count >= pinyin_ime->k9_py_ll_pos)   break;
1139 
1140             ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/
1141             count++;
1142         }
1143 
1144         if((NULL == ll_index) && (dir == 1))   return;
1145 
1146         lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str));
1147         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0");
1148         strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0");
1149 
1150         // next page
1151         if(dir == 1) {
1152             count = 0;
1153             while(ll_index) {
1154                 if(count >= (LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1))
1155                     break;
1156 
1157                 strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str);
1158                 ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/
1159                 count++;
1160             }
1161             pinyin_ime->k9_py_ll_pos += count - 1;
1162 
1163         }
1164         // previous page
1165         else {
1166             count = LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1;
1167             ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index);
1168             while(ll_index) {
1169                 if(count < 0)  break;
1170 
1171                 strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str);
1172                 ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the previous list*/
1173                 count--;
1174             }
1175 
1176             if(pinyin_ime->k9_py_ll_pos > LV_IME_PINYIN_K9_CAND_TEXT_NUM)
1177                 pinyin_ime->k9_py_ll_pos -= 1;
1178         }
1179 
1180         lv_textarea_set_cursor_pos(ta, LV_TEXTAREA_CURSOR_LAST);
1181     }
1182 }
1183 
1184 #endif  /*LV_IME_PINYIN_USE_K9_MODE*/
1185 
1186 #endif  /*LV_USE_IME_PINYIN*/
1187