PageRenderTime 88ms CodeModel.GetById 42ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://ftk.googlecode.com/
C++ | 279 lines | 200 code | 50 blank | 29 comment | 31 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/*
 26 * History:
 27 * ================================================================
 28 * 2011-04-10 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_log.h"
 33#include "ftk_util.h"
 34#include "ftk_event.h"
 35#include "ftk_globals.h"
 36#include "pinyinime.h"
 37#include "ftk_file_system.h"
 38#include "ftk_input_method_gpinyin.h"
 39
 40using namespace ime_pinyin;
 41
 42typedef struct _PrivInfo
 43{
 44	int raw_text_size;
 45
 46	FtkWidget* editor;
 47	FtkInputType input_type;
 48	FtkCommitInfo commit_info;
 49	char16 utf16[FTK_IM_WORD_LENGTH];
 50	char utf8[FTK_IM_WORD_LENGTH << 2];
 51}PrivInfo;
 52
 53static Ret  ftk_input_method_gpinyin_handle_event(FtkInputMethod* thiz, FtkEvent* event);
 54
 55static Ret  ftk_input_method_gpinyin_init(FtkInputMethod* thiz)
 56{
 57	Ret ret = RET_FAIL;
 58	char dict_filename[FTK_MAX_PATH+1];
 59	char user_dict_filename[FTK_MAX_PATH+1];
 60
 61	ftk_snprintf(dict_filename, FTK_MAX_PATH, "%s/data/gpinyin.dat", DATA_DIR);
 62	if(!ftk_file_exist(dict_filename))
 63	{
 64		ftk_snprintf(dict_filename, FTK_MAX_PATH, "%s/data/gpinyin.dat", LOCAL_DATA_DIR);
 65		ftk_snprintf(user_dict_filename, FTK_MAX_PATH, "%s/data/gpinyin_user.dat", LOCAL_DATA_DIR);
 66	}
 67	else
 68	{
 69		ftk_snprintf(user_dict_filename, FTK_MAX_PATH, "%s/data/gpinyin_user.dat", DATA_DIR);
 70	}
 71
 72	ret = im_open_decoder(dict_filename, user_dict_filename) ? RET_OK : RET_FAIL;
 73	im_set_max_lens(FTK_IM_RAW_TEXT_LENGTH, FTK_IM_WORD_LENGTH);
 74
 75	return ret;
 76}
 77
 78static Ret  ftk_input_method_gpinyin_reset(FtkInputMethod* thiz)
 79{
 80	im_reset_search();
 81
 82	return RET_OK;
 83}
 84
 85static Ret  ftk_input_method_gpinyin_activate(FtkInputMethod* thiz)
 86{
 87	ftk_wnd_manager_add_global_listener(ftk_default_wnd_manager(),
 88		(FtkListener)ftk_input_method_gpinyin_handle_event, thiz);
 89
 90	ftk_logd("%s\n", __func__);
 91
 92	return RET_OK;
 93}
 94
 95static Ret  ftk_input_method_gpinyin_deactivate(FtkInputMethod* thiz)
 96{
 97	ftk_wnd_manager_remove_global_listener(ftk_default_wnd_manager(), 
 98		(FtkListener)ftk_input_method_gpinyin_handle_event, thiz);
 99	ftk_input_method_gpinyin_reset(thiz);
100
101	ftk_logd("%s\n", __func__);
102
103	return RET_OK;
104}
105
106static Ret  ftk_input_method_gpinyin_focus_in(FtkInputMethod* thiz, FtkWidget* editor)
107{
108	DECL_PRIV(thiz, priv);
109	return_val_if_fail(priv != NULL && editor != NULL, RET_FAIL);
110
111	priv->editor = editor;
112
113	return ftk_input_method_gpinyin_activate(thiz);
114}
115
116static Ret  ftk_input_method_gpinyin_focus_out(FtkInputMethod* thiz)
117{
118	DECL_PRIV(thiz, priv);
119	return_val_if_fail(priv != NULL, RET_FAIL);
120
121	priv->editor = NULL;
122	
123	return ftk_input_method_gpinyin_deactivate(thiz);
124}
125
126static Ret  ftk_input_method_gpinyin_set_type(FtkInputMethod* thiz, FtkInputType input_type)
127{
128	DECL_PRIV(thiz, priv);
129	return_val_if_fail(priv != NULL, RET_FAIL);
130
131	priv->input_type = input_type;
132
133	return RET_OK;
134}
135
136#define IS_IME_CHAR(c) ((c < 0xff) && (((c) >= 'a' && (c) <= 'z') || (c) == '\''))
137
138static Ret  ftk_input_method_gpinyin_handle_event(FtkInputMethod* thiz, FtkEvent* event)
139{
140	Ret ret = RET_OK;
141	DECL_PRIV(thiz, priv);
142	return_val_if_fail(priv != NULL && event != NULL, RET_FAIL);
143	
144	switch(event->type)
145	{
146		case FTK_EVT_KEY_DOWN:
147		{
148			FtkEvent evt;
149			int matched_nr = 0;
150			int code = event->u.key.code;
151		
152			if((code != FTK_KEY_BACKSPACE) && !IS_IME_CHAR(code))
153			{
154				break;
155			}
156
157			if(code == FTK_KEY_BACKSPACE)
158			{
159				if(priv->raw_text_size == 0)
160				{
161					break;
162				}
163				else
164				{
165					priv->raw_text_size--;
166					priv->commit_info.raw_text[priv->raw_text_size] = '\0';
167				}
168			}
169			
170			if(priv->raw_text_size >= FTK_IM_RAW_TEXT_LENGTH)
171			{
172				ret = RET_REMOVE;
173				break;
174			}
175
176			if(IS_IME_CHAR(code))
177			{
178				priv->commit_info.raw_text[priv->raw_text_size++] = 0xff & (event->u.key.code);
179				priv->commit_info.raw_text[priv->raw_text_size] = '\0';
180			}
181
182			priv->commit_info.candidate_nr = 0;
183			if(priv->raw_text_size > 0)
184			{
185				matched_nr = im_search(priv->commit_info.raw_text, strlen(priv->commit_info.raw_text));
186			}
187			else
188			{
189				im_reset_search();
190			}
191
192			if(matched_nr > 0)
193			{
194				int i = 0;
195				int n = 0;
196				int offset = 0;
197				FtkCommitInfo* info = &(priv->commit_info);
198
199				info->candidate_nr = 0;
200				info->candidates[0] = '\0';
201				for(i = 0; i < matched_nr; i++)
202				{
203					im_get_candidate(i, priv->utf16, FTK_IM_WORD_LENGTH);
204					utf16_to_utf8(priv->utf16, FTK_IM_WORD_LENGTH, priv->utf8, FTK_IM_WORD_LENGTH << 2);
205					
206					n = strlen(priv->utf8);
207					if((offset + n + 1) < FTK_IM_CANDIDATE_BUFF_LENGTH 
208						&& info->candidate_nr < FTK_IM_MAX_CANDIDATES)
209					{
210						info->candidate_nr++;
211						strcpy(info->candidates+offset, priv->utf8);
212						offset += n + 1;
213						ftk_logd("%d/%d %s\n", i, matched_nr, priv->utf8);
214					}
215					else
216					{
217						break;
218					}
219				}
220			}
221			else
222			{
223				priv->commit_info.candidate_nr = (priv->raw_text_size) > 0 ? 1 : 0;
224				strcpy(priv->commit_info.candidates, priv->commit_info.raw_text);
225			}
226			evt.type = FTK_EVT_IM_PREEDIT;
227			evt.u.extra = &(priv->commit_info);
228			evt.widget = priv->editor;
229
230			ftk_widget_event(priv->editor, &evt);
231			
232			ret = RET_REMOVE;
233
234			break;
235		}
236		case FTK_EVT_IM_ACT_COMMIT:
237		{
238			priv->raw_text_size = 0;
239			priv->commit_info.raw_text[priv->raw_text_size] = '\0';
240
241			break;
242		}
243		default:break;
244	}
245
246	return ret;
247}
248
249static void ftk_input_method_gpinyin_destroy(FtkInputMethod* thiz)
250{
251	if(thiz != NULL)
252	{
253		FTK_ZFREE(thiz, sizeof(FtkInputMethod) + sizeof(PrivInfo));
254		im_close_decoder();
255	}
256
257	return;
258}
259
260extern "C" FtkInputMethod* ftk_input_method_gpinyin_create()
261{
262	FtkInputMethod* thiz = (FtkInputMethod*)FTK_ZALLOC(sizeof(FtkInputMethod) + sizeof(PrivInfo));
263
264	if(thiz != NULL)
265	{
266		thiz->ref  = 1;
267		thiz->name = _("Google PinYin");	
268		thiz->set_type     = ftk_input_method_gpinyin_set_type;
269		thiz->focus_in     = ftk_input_method_gpinyin_focus_in;
270		thiz->focus_out    = ftk_input_method_gpinyin_focus_out;
271		thiz->handle_event = ftk_input_method_gpinyin_handle_event;
272		thiz->destroy      = ftk_input_method_gpinyin_destroy;
273	
274		ftk_input_method_gpinyin_init(thiz);
275
276	}
277
278	return thiz;
279}