/src/im/gpinyin/ftk/ftk_input_method_gpinyin.cpp

http://ftk.googlecode.com/ · C++ · 279 lines · 200 code · 50 blank · 29 comment · 32 complexity · 8b67df6b007567f894a61d37d0b2b493 MD5 · raw file

  1. /*
  2. * File: ftk_input_method_py.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: google pinyin input method.
  5. *
  6. * Copyright (c) 2009 - 2011 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2011-04-10 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_log.h"
  31. #include "ftk_util.h"
  32. #include "ftk_event.h"
  33. #include "ftk_globals.h"
  34. #include "pinyinime.h"
  35. #include "ftk_file_system.h"
  36. #include "ftk_input_method_gpinyin.h"
  37. using namespace ime_pinyin;
  38. typedef struct _PrivInfo
  39. {
  40. int raw_text_size;
  41. FtkWidget* editor;
  42. FtkInputType input_type;
  43. FtkCommitInfo commit_info;
  44. char16 utf16[FTK_IM_WORD_LENGTH];
  45. char utf8[FTK_IM_WORD_LENGTH << 2];
  46. }PrivInfo;
  47. static Ret ftk_input_method_gpinyin_handle_event(FtkInputMethod* thiz, FtkEvent* event);
  48. static Ret ftk_input_method_gpinyin_init(FtkInputMethod* thiz)
  49. {
  50. Ret ret = RET_FAIL;
  51. char dict_filename[FTK_MAX_PATH+1];
  52. char user_dict_filename[FTK_MAX_PATH+1];
  53. ftk_snprintf(dict_filename, FTK_MAX_PATH, "%s/data/gpinyin.dat", DATA_DIR);
  54. if(!ftk_file_exist(dict_filename))
  55. {
  56. ftk_snprintf(dict_filename, FTK_MAX_PATH, "%s/data/gpinyin.dat", LOCAL_DATA_DIR);
  57. ftk_snprintf(user_dict_filename, FTK_MAX_PATH, "%s/data/gpinyin_user.dat", LOCAL_DATA_DIR);
  58. }
  59. else
  60. {
  61. ftk_snprintf(user_dict_filename, FTK_MAX_PATH, "%s/data/gpinyin_user.dat", DATA_DIR);
  62. }
  63. ret = im_open_decoder(dict_filename, user_dict_filename) ? RET_OK : RET_FAIL;
  64. im_set_max_lens(FTK_IM_RAW_TEXT_LENGTH, FTK_IM_WORD_LENGTH);
  65. return ret;
  66. }
  67. static Ret ftk_input_method_gpinyin_reset(FtkInputMethod* thiz)
  68. {
  69. im_reset_search();
  70. return RET_OK;
  71. }
  72. static Ret ftk_input_method_gpinyin_activate(FtkInputMethod* thiz)
  73. {
  74. ftk_wnd_manager_add_global_listener(ftk_default_wnd_manager(),
  75. (FtkListener)ftk_input_method_gpinyin_handle_event, thiz);
  76. ftk_logd("%s\n", __func__);
  77. return RET_OK;
  78. }
  79. static Ret ftk_input_method_gpinyin_deactivate(FtkInputMethod* thiz)
  80. {
  81. ftk_wnd_manager_remove_global_listener(ftk_default_wnd_manager(),
  82. (FtkListener)ftk_input_method_gpinyin_handle_event, thiz);
  83. ftk_input_method_gpinyin_reset(thiz);
  84. ftk_logd("%s\n", __func__);
  85. return RET_OK;
  86. }
  87. static Ret ftk_input_method_gpinyin_focus_in(FtkInputMethod* thiz, FtkWidget* editor)
  88. {
  89. DECL_PRIV(thiz, priv);
  90. return_val_if_fail(priv != NULL && editor != NULL, RET_FAIL);
  91. priv->editor = editor;
  92. return ftk_input_method_gpinyin_activate(thiz);
  93. }
  94. static Ret ftk_input_method_gpinyin_focus_out(FtkInputMethod* thiz)
  95. {
  96. DECL_PRIV(thiz, priv);
  97. return_val_if_fail(priv != NULL, RET_FAIL);
  98. priv->editor = NULL;
  99. return ftk_input_method_gpinyin_deactivate(thiz);
  100. }
  101. static Ret ftk_input_method_gpinyin_set_type(FtkInputMethod* thiz, FtkInputType input_type)
  102. {
  103. DECL_PRIV(thiz, priv);
  104. return_val_if_fail(priv != NULL, RET_FAIL);
  105. priv->input_type = input_type;
  106. return RET_OK;
  107. }
  108. #define IS_IME_CHAR(c) ((c < 0xff) && (((c) >= 'a' && (c) <= 'z') || (c) == '\''))
  109. static Ret ftk_input_method_gpinyin_handle_event(FtkInputMethod* thiz, FtkEvent* event)
  110. {
  111. Ret ret = RET_OK;
  112. DECL_PRIV(thiz, priv);
  113. return_val_if_fail(priv != NULL && event != NULL, RET_FAIL);
  114. switch(event->type)
  115. {
  116. case FTK_EVT_KEY_DOWN:
  117. {
  118. FtkEvent evt;
  119. int matched_nr = 0;
  120. int code = event->u.key.code;
  121. if((code != FTK_KEY_BACKSPACE) && !IS_IME_CHAR(code))
  122. {
  123. break;
  124. }
  125. if(code == FTK_KEY_BACKSPACE)
  126. {
  127. if(priv->raw_text_size == 0)
  128. {
  129. break;
  130. }
  131. else
  132. {
  133. priv->raw_text_size--;
  134. priv->commit_info.raw_text[priv->raw_text_size] = '\0';
  135. }
  136. }
  137. if(priv->raw_text_size >= FTK_IM_RAW_TEXT_LENGTH)
  138. {
  139. ret = RET_REMOVE;
  140. break;
  141. }
  142. if(IS_IME_CHAR(code))
  143. {
  144. priv->commit_info.raw_text[priv->raw_text_size++] = 0xff & (event->u.key.code);
  145. priv->commit_info.raw_text[priv->raw_text_size] = '\0';
  146. }
  147. priv->commit_info.candidate_nr = 0;
  148. if(priv->raw_text_size > 0)
  149. {
  150. matched_nr = im_search(priv->commit_info.raw_text, strlen(priv->commit_info.raw_text));
  151. }
  152. else
  153. {
  154. im_reset_search();
  155. }
  156. if(matched_nr > 0)
  157. {
  158. int i = 0;
  159. int n = 0;
  160. int offset = 0;
  161. FtkCommitInfo* info = &(priv->commit_info);
  162. info->candidate_nr = 0;
  163. info->candidates[0] = '\0';
  164. for(i = 0; i < matched_nr; i++)
  165. {
  166. im_get_candidate(i, priv->utf16, FTK_IM_WORD_LENGTH);
  167. utf16_to_utf8(priv->utf16, FTK_IM_WORD_LENGTH, priv->utf8, FTK_IM_WORD_LENGTH << 2);
  168. n = strlen(priv->utf8);
  169. if((offset + n + 1) < FTK_IM_CANDIDATE_BUFF_LENGTH
  170. && info->candidate_nr < FTK_IM_MAX_CANDIDATES)
  171. {
  172. info->candidate_nr++;
  173. strcpy(info->candidates+offset, priv->utf8);
  174. offset += n + 1;
  175. ftk_logd("%d/%d %s\n", i, matched_nr, priv->utf8);
  176. }
  177. else
  178. {
  179. break;
  180. }
  181. }
  182. }
  183. else
  184. {
  185. priv->commit_info.candidate_nr = (priv->raw_text_size) > 0 ? 1 : 0;
  186. strcpy(priv->commit_info.candidates, priv->commit_info.raw_text);
  187. }
  188. evt.type = FTK_EVT_IM_PREEDIT;
  189. evt.u.extra = &(priv->commit_info);
  190. evt.widget = priv->editor;
  191. ftk_widget_event(priv->editor, &evt);
  192. ret = RET_REMOVE;
  193. break;
  194. }
  195. case FTK_EVT_IM_ACT_COMMIT:
  196. {
  197. priv->raw_text_size = 0;
  198. priv->commit_info.raw_text[priv->raw_text_size] = '\0';
  199. break;
  200. }
  201. default:break;
  202. }
  203. return ret;
  204. }
  205. static void ftk_input_method_gpinyin_destroy(FtkInputMethod* thiz)
  206. {
  207. if(thiz != NULL)
  208. {
  209. FTK_ZFREE(thiz, sizeof(FtkInputMethod) + sizeof(PrivInfo));
  210. im_close_decoder();
  211. }
  212. return;
  213. }
  214. extern "C" FtkInputMethod* ftk_input_method_gpinyin_create()
  215. {
  216. FtkInputMethod* thiz = (FtkInputMethod*)FTK_ZALLOC(sizeof(FtkInputMethod) + sizeof(PrivInfo));
  217. if(thiz != NULL)
  218. {
  219. thiz->ref = 1;
  220. thiz->name = _("Google PinYin");
  221. thiz->set_type = ftk_input_method_gpinyin_set_type;
  222. thiz->focus_in = ftk_input_method_gpinyin_focus_in;
  223. thiz->focus_out = ftk_input_method_gpinyin_focus_out;
  224. thiz->handle_event = ftk_input_method_gpinyin_handle_event;
  225. thiz->destroy = ftk_input_method_gpinyin_destroy;
  226. ftk_input_method_gpinyin_init(thiz);
  227. }
  228. return thiz;
  229. }