1 /***************************************************************************
2 * Copyright (C) 2004 by TAM(Teppei Tamra) *
3 * tam-t@par.odn.ne.jp *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <sys/types.h>
26 #include <dirent.h>
27 #include <set>
28
29 // 国際化のおまじない。
30 #ifdef HAVE_GETTEXT
31 #include <libintl.h>
32 #define _(String) dgettext(GETTEXT_PACKAGE,String)
33 #define N_(String) (String)
34 #else
35 #define _(String) (String)
36 #define N_(String) (String)
37 #define bindtextdomain(Package,Directory)
38 #define textdomain(domain)
39 #define bind_textdomain_codeset(domain,codeset)
40 #endif
41
42 // scimのおまじない。
43 #include "honoka_imengine.h"
44 #include "honokatimer.h"
45 #include "honoka_def.h"
46
47 #define scim_module_init honoka_LTX_scim_module_init
48 #define scim_module_exit honoka_LTX_scim_module_exit
49 #define scim_imengine_module_init honoka_LTX_scim_imengine_module_init
50 #define scim_imengine_module_create_factory honoka_LTX_scim_imengine_module_create_factory
51 #ifndef HONOKA_ICON_FILE
52 #define HONOKA_ICON_FILE (SCIM_ICONDIR "/honoka.png")
53 #endif
54
55 #ifndef PACKAGE_STRING
56 #define PACKAGE_STRING "honoka"
57 #endif
58
59
60
61 static Pointer <HonokaFactory> _honoka_factory;
62 static ConfigPointer _scim_config;
63
64
65 extern "C" {
scim_module_init(void)66 void scim_module_init (void)
67 {
68 bindtextdomain (GETTEXT_PACKAGE, HONOKA_LOCALEDIR);
69 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
70 }
71
scim_module_exit(void)72 void scim_module_exit (void)
73 {
74 _honoka_factory.reset ();
75 _scim_config.reset ();
76 }
77
scim_imengine_module_init(const ConfigPointer & config)78 unsigned int scim_imengine_module_init (const ConfigPointer &config)
79 {
80 _scim_config = config;
81 return 1;
82 }
83
scim_imengine_module_create_factory(unsigned int factory)84 IMEngineFactoryPointer scim_imengine_module_create_factory (unsigned int factory)
85 {
86 if (factory != 0) return NULL;
87 if (_honoka_factory.null ()) {
88 _honoka_factory =
89 new HonokaFactory (utf8_mbstowcs (String (_("Honoka"))),String("ja_JP"));
90 }
91 return _honoka_factory;
92 }
93 }
94
HonokaFactory()95 HonokaFactory::HonokaFactory() {
96 m_name = utf8_mbstowcs(_("Honoka"));
97 set_languages(String("ja_JP"));
98 }
99
~HonokaFactory()100 HonokaFactory::~ HonokaFactory() {
101 }
102
HonokaFactory(const WideString & name,const String & languages)103 HonokaFactory::HonokaFactory(const WideString & name, const String & languages) {
104 if (name.length () <= 8)
105 m_name = name;
106 else
107 m_name.assign (name.begin (), name.begin () + 8);
108 if (languages == String ("default"))
109 set_languages (String (_("ja_JP")));
110 else
111 set_languages (languages);
112 }
113
get_name() const114 WideString HonokaFactory::get_name () const
115 {
116 return m_name;
117 }
118
get_authors() const119 WideString HonokaFactory::get_authors () const
120 {
121 return utf8_mbstowcs (String (_("(C)2004-2006 TAM(Teppei Tamra) <tam-t@par.odn.ne.jp>")));
122 }
123
get_credits() const124 WideString HonokaFactory::get_credits () const
125 {
126 return WideString ();
127 }
128
get_help() const129 WideString HonokaFactory::get_help () const
130 {
131 return utf8_mbstowcs (String(PACKAGE_STRING) + String("\n") + String(_("HONOKA-HELP")));
132 }
133
get_uuid() const134 String HonokaFactory::get_uuid () const
135 {
136 return String ("8bb03c1c-db6c-41b1-91bd-b7fb7dd70343");
137 }
138
get_icon_file() const139 String HonokaFactory::get_icon_file () const
140 {
141 return String (HONOKA_ICON_FILE);
142 }
143
create_instance(const String & encoding,int id)144 IMEngineInstancePointer HonokaFactory::create_instance (const String& encoding, int id)
145 {
146 return new HonokaInstance (this, encoding, id);
147 }
148
149
150
151
152
153 // 現物。
154
155
HonokaInstance(HonokaFactory * factory,const String & encoding,int id)156 HonokaInstance::HonokaInstance (HonokaFactory *factory, const String& encoding, int id)
157 : IMEngineInstanceBase (factory, encoding, id)
158 {
159 m_iconv.set_encoding ("EUC-JP");
160
161 // 初期化へ。
162 loadPlugins();
163 init();
164 }
165
~HonokaInstance()166 HonokaInstance::~HonokaInstance()
167 {
168 if (save_setting) {
169 _scim_config->write(String(HONOKA_PREVIOUS_PREEDITOR),m_preeditor->getName());
170 _scim_config->write(String(HONOKA_PREVIOUS_PREDICTOR),m_predictor->getName());
171 _scim_config->write(String(HONOKA_PREVIOUS_CONVERTOR),m_convertor->getName());
172 }
173 unload();
174 }
175
176 /*!
177 \fn HonokaInstance::split(const String &str,const char &sep)
178 */
split(const String & str,const char & sep)179 vector<String> HonokaInstance::split(const String &str,const char &sep)
180 {
181 vector<String> s;
182 String w;
183 for(unsigned int i = 0;i < str.length();i ++) {
184 if (str[i] == sep) {
185 if (w.length()) {
186 s.push_back(w);
187 w.clear();
188 }
189 } else w = w + str.substr(i,1);
190 }
191 if (w.length()) s.push_back(w);
192 return s;
193 }
194
pluginCheck(HonokaPluginBase * p)195 bool HonokaInstance::pluginCheck(HonokaPluginBase *p) {
196
197 // Convertorの場合。
198 if (p->getPluginType() == "Convertor") {
199 convertors.push_back(static_cast<Convertor *>(p));
200 return true;
201 } else
202 // PreEditorの場合。
203 if (p->getPluginType() == "PreEditor") {
204 preeditors.push_back(static_cast<PreEditor *>(p));
205 return true;
206 } else
207 // Predictorの場合。
208 if (p->getPluginType() == "Predictor") {
209 predictors.push_back(static_cast<Predictor *>(p));
210 return true;
211 }
212 return false;
213 }
214
215
216 /*!
217 \fn HonokaInstance::loadPlugins()
218 */
loadPlugins()219 void HonokaInstance::loadPlugins()
220 {
221 DIR *dir = opendir(HONOKA_PLUGINDIR);
222 if (dir) {
223 struct dirent *entry;
224 //
225 // プラグイン読み込み部分。
226 //
227 set<String> pluginNameList;
228 while((entry = readdir(dir)) != NULL) {
229 // まず名前を決定します。
230 String d = entry->d_name;
231 if ((d.substr(0,6) == "plugin") && (d.substr(d.length() - 3,3) == ".so")) {
232 if (!_scim_config->read(String(HONOKA_CONFIG_PLUGINLOADER_PREFIX) + "/" + d.substr(0,d.length() - 3),true))
233 continue;
234 d = String(HONOKA_PLUGINDIR) + "/" + d;
235 // 実際にロードします。
236 void* plugin = dlopen(d.c_str(), RTLD_LAZY);
237 if (!plugin) continue;
238 // 関数を抜き取ります。
239 createInstanceFunc *getInstance = (createInstanceFunc *)dlsym(plugin,"getHonokaPluginInstance");
240 deleteInstanceFunc *deleteInstance = (deleteInstanceFunc *)dlsym(plugin,"deleteHonokaPluginInstance");
241 getPluginVersionFunc *getPluginVersion = (getPluginVersionFunc *)dlsym(plugin,"getHonokaPluginVersion");
242 // 関数が不足した場合はアンロードします。
243 if ((!getInstance) || (!deleteInstance) || (!getPluginVersion)) {
244 dlclose(plugin);
245 continue;
246 }
247 // バージョンチェックします。
248 if (getPluginVersion() == HONOKA_PLUGIN_VERSION) {
249 // いきなりインスタンスをゲトします。
250 HonokaPluginBase *p = getInstance(_scim_config);
251 // プラグイン情報を得ておきます。
252 HonokaPluginEntry pe;
253 pe.filename = d;
254 pe.createInstance = getInstance;
255 pe.deleteInstance = deleteInstance;
256 pe.getPluginVersion = getPluginVersion;
257 pe.instance = p;
258 pe.name = p->getName();
259 pe.dll = plugin;
260 // 同名のプラグインがあった場合はロードを中止します。
261 if (pluginNameList.find(p->getName()) != pluginNameList.end()) {
262 deleteInstance(p);
263 dlclose(plugin);
264 } else
265 if (p->getPluginType() == "Multiple") {
266 plugins.push_back(pe);
267 pluginNameList.insert(p->getName());
268 for(unsigned int i = 0;i < static_cast<HonokaMultiplePluginBase *>(p)->getPluginCount();i++)
269 pluginCheck(static_cast<HonokaMultiplePluginBase *>(p)->getPluginInstanceAt(i));
270 } else
271 if (pluginCheck(p)) {
272 plugins.push_back(pe);
273 pluginNameList.insert(p->getName());
274 } else {
275 deleteInstance(p);
276 dlclose(plugin);
277 }
278 } else {
279 dlclose(plugin);
280 }
281 }
282 }
283 closedir(dir);
284 }
285
286 acpredictor = new ACPredictor(_scim_config,this);
287 predictors.push_back(acpredictor);
288
289 // プラグインがなければデフォの低機能なベースクラスを使います。
290 if (!convertors.size()) convertors.push_back(new Convertor(_scim_config));
291 if (!preeditors.size()) preeditors.push_back(new PreEditor(_scim_config));
292 if (!predictors.size()) predictors.push_back(new Predictor(_scim_config));
293
294 // 初期利用Convertor/PreEditorを指定します。
295 m_convertor = convertors.at(0);
296 m_preeditor = preeditors.at(0);
297 m_predictor = predictors.at(0);
298
299 m_multi = new MultiConvertor(_scim_config,this);
300
301 return;
302 }
303
304
305 /*!
306 \fn HonokaInstance::unload()
307 */
unload()308 void HonokaInstance::unload()
309 {
310 HonokaTimer::destruct();
311 m_preeditor->reset();
312 for(unsigned int i = 0;i < plugins.size();i ++) {
313 plugins[i].deleteInstance(plugins[i].instance);
314 dlclose(plugins[i].dll);
315 }
316 convertors.clear();
317 preeditors.clear();
318 predictors.clear();
319 delete acpredictor;
320 delete m_multi;
321 plugins.clear();
322 }
323
324 /*!
325 \fn HonokaInstance::init()
326 */
init()327 void HonokaInstance::init()
328 {
329 // 初期化。
330
331 m_conversion = false;
332 m_prediction = false;
333 m_lookup = false;
334
335 while(preeditStack.size()) {
336 preeditStack.pop();
337 }
338
339 // @todo if connected to jserver, should disconnect this.
340
341 alp = _scim_config->read(String(HONOKA_CONFIG_ALP),HONOKA_DEFAULT_ALP);
342 mini_status = _scim_config->read(String(HONOKA_CONFIG_MINISTATUS),HONOKA_DEFAULT_MINISTATUS);
343 numkeyselect = _scim_config->read(String(HONOKA_CONFIG_NUMKEY_SELECT),HONOKA_DEFAULT_NUMKEY_SELECT);
344 prediction = _scim_config->read(String(HONOKA_CONFIG_PREDICTION),HONOKA_DEFAULT_PREDICTION);
345 realtime_prediction = _scim_config->read(String(HONOKA_CONFIG_REALTIME_PREDICTION),HONOKA_DEFAULT_REALTIME_PREDICTION);
346 changeable_splitter = _scim_config->read(String(HONOKA_CONFIG_CHANGEABLE_SPLITTER),HONOKA_DEFAULT_CHANGEABLE_SPLITTER);
347 if (m_predictor->getName() == "Predictor") prediction = false;
348
349 defaultPreEditor = _scim_config->read(String(HONOKA_CONFIG_DEFAULT_PREEDITOR),String(HONOKA_DEFAULT_DEFAULT_PREEDITOR));
350 defaultConvertor = _scim_config->read(String(HONOKA_CONFIG_DEFAULT_CONVERTOR),String(HONOKA_DEFAULT_DEFAULT_CONVERTOR));
351 defaultPredictor = _scim_config->read(String(HONOKA_CONFIG_DEFAULT_PREDICTOR),String(HONOKA_DEFAULT_DEFAULT_PREDICTOR));
352 auto_conversion = _scim_config->read(String(HONOKA_CONFIG_AUTO_CONVERSION),HONOKA_DEFAULT_AUTO_CONVERSION);;
353 predictionDelay = _scim_config->read(String(HONOKA_CONFIG_PREDICTION_DELAY),HONOKA_DEFAULT_PREDICTION_DELAY);
354 save_setting = _scim_config->read(String(HONOKA_CONFIG_SAVE_SETTING),HONOKA_DEFAULT_SAVE_SETTING);
355 select_prediction_direct = _scim_config->read(String(HONOKA_CONFIG_SELECT_PREDICTION_DIRECT),HONOKA_DEFAULT_SELECT_PREDICTION_DIRECT);
356
357 // デフォルトキー設定。
358 scim_string_to_key_list(k_conversion_start,
359 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_START),
360 String(HONOKA_DEFAULT_KEY_CONVERSION_START)));
361 scim_string_to_key_list(k_cancel,
362 _scim_config->read(String(HONOKA_CONFIG_KEY_CANCEL),
363 String(HONOKA_DEFAULT_KEY_CANCEL)));
364 scim_string_to_key_list(k_delete,
365 _scim_config->read(String(HONOKA_CONFIG_KEY_DELETE),
366 String(HONOKA_DEFAULT_KEY_DELETE)));
367 scim_string_to_key_list(k_backspace,
368 _scim_config->read(String(HONOKA_CONFIG_KEY_BACKSPACE),
369 String(HONOKA_DEFAULT_KEY_BACKSPACE)));
370 scim_string_to_key_list(k_commit,
371 _scim_config->read(String(HONOKA_CONFIG_KEY_COMMIT),
372 String(HONOKA_DEFAULT_KEY_COMMIT)));
373 scim_string_to_key_list(k_furigana_commit,
374 _scim_config->read(String(HONOKA_CONFIG_KEY_FURIGANA_COMMIT),
375 String(HONOKA_DEFAULT_KEY_FURIGANA_COMMIT)));
376 scim_string_to_key_list(k_conversion_next,
377 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_NEXT),
378 String(HONOKA_DEFAULT_KEY_CONVERSION_NEXT)));
379 scim_string_to_key_list(k_conversion_prev,
380 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_PREV),
381 String(HONOKA_DEFAULT_KEY_CONVERSION_PREV)));
382 scim_string_to_key_list(k_conversion_expand,
383 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_EXPAND),
384 String(HONOKA_DEFAULT_KEY_CONVERSION_EXPAND)));
385 scim_string_to_key_list(k_conversion_shrink,
386 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_SHRINK),
387 String(HONOKA_DEFAULT_KEY_CONVERSION_SHRINK)));
388 scim_string_to_key_list(k_conversion_forward,
389 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_FORWARD),
390 String(HONOKA_DEFAULT_KEY_CONVERSION_FORWARD)));
391 scim_string_to_key_list(k_conversion_backward,
392 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_BACKWARD),
393 String(HONOKA_DEFAULT_KEY_CONVERSION_BACKWARD)));
394 scim_string_to_key_list(k_forward,
395 _scim_config->read(String(HONOKA_CONFIG_KEY_FORWARD),
396 String(HONOKA_DEFAULT_KEY_FORWARD)));
397 scim_string_to_key_list(k_backward,
398 _scim_config->read(String(HONOKA_CONFIG_KEY_BACKWARD),
399 String(HONOKA_DEFAULT_KEY_BACKWARD)));
400 scim_string_to_key_list(k_home,
401 _scim_config->read(String(HONOKA_CONFIG_KEY_HOME),
402 String(HONOKA_DEFAULT_KEY_HOME)));
403 scim_string_to_key_list(k_end,
404 _scim_config->read(String(HONOKA_CONFIG_KEY_END),
405 String(HONOKA_DEFAULT_KEY_END)));
406 scim_string_to_key_list(k_lookup_popup,
407 _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPOPUP),
408 String(HONOKA_DEFAULT_KEY_LOOKUPPOPUP)));
409 scim_string_to_key_list(k_lookup_pageup,
410 _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPAGEUP),
411 String(HONOKA_DEFAULT_KEY_LOOKUPPAGEUP)));
412 scim_string_to_key_list(k_lookup_pagedown,
413 _scim_config->read(String(HONOKA_CONFIG_KEY_LOOKUPPAGEDOWN),
414 String(HONOKA_DEFAULT_KEY_LOOKUPPAGEDOWN)));
415 scim_string_to_key_list(k_convert_ctype,
416 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_CTYPETOGGLE),
417 String(HONOKA_DEFAULT_KEY_CONVERT_CTYPETOGGLE)));
418 scim_string_to_key_list(k_convert_hiragana,
419 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_HIRAGANA),
420 String(HONOKA_DEFAULT_KEY_CONVERT_HIRAGANA)));
421 scim_string_to_key_list(k_convert_katakana,
422 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_KATAKANA),
423 String(HONOKA_DEFAULT_KEY_CONVERT_KATAKANA)));
424 scim_string_to_key_list(k_convert_half,
425 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_HALF),
426 String(HONOKA_DEFAULT_KEY_CONVERT_HALF)));
427 scim_string_to_key_list(k_convert_wide,
428 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERT_WIDE),
429 String(HONOKA_DEFAULT_KEY_CONVERT_WIDE)));
430
431 scim_string_to_key_list(k_conversion_rensou,
432 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_RENSOU),
433 String(HONOKA_DEFAULT_KEY_CONVERSION_RENSOU)));
434 scim_string_to_key_list(k_conversion_ikeiji,
435 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERSION_IKEIJI),
436 String(HONOKA_DEFAULT_KEY_CONVERSION_IKEIJI)));
437 scim_string_to_key_list(k_select_prediction,
438 _scim_config->read(String(HONOKA_CONFIG_KEY_SELECT_PREDICTION),
439 String(HONOKA_DEFAULT_KEY_SELECT_PREDICTION)));
440 scim_string_to_key_list(k_auto_conversion,
441 _scim_config->read(String(HONOKA_CONFIG_KEY_AUTO_CONVERSION),
442 String(HONOKA_DEFAULT_KEY_AUTO_CONVERSION)));
443 scim_string_to_key_list(k_next_convertor,
444 _scim_config->read(String(HONOKA_CONFIG_KEY_NEXT_CONVERTOR),
445 String(HONOKA_DEFAULT_KEY_NEXT_CONVERTOR)));
446 scim_string_to_key_list(k_prev_convertor,
447 _scim_config->read(String(HONOKA_CONFIG_KEY_PREV_CONVERTOR),
448 String(HONOKA_DEFAULT_KEY_PREV_CONVERTOR)));
449
450 scim_string_to_key_list(k_reconversion,
451 _scim_config->read(String(HONOKA_CONFIG_KEY_RECONVERSION),
452 String(HONOKA_DEFAULT_KEY_RECONVERSION)));
453 scim_string_to_key_list(k_result_to_preedit,
454 _scim_config->read(String(HONOKA_CONFIG_KEY_RESULTTOPREEDIT),
455 String(HONOKA_DEFAULT_KEY_RESULTTOPREEDIT)));
456 scim_string_to_key_list(k_multi_conversion,
457 _scim_config->read(String(HONOKA_CONFIG_KEY_MULTI_CONVERSION),
458 String(HONOKA_DEFAULT_KEY_MULTI_CONVERSION)));
459 scim_string_to_key_list(k_allreset,
460 _scim_config->read(String(HONOKA_CONFIG_KEY_ALLRESET),
461 String(HONOKA_DEFAULT_KEY_ALLRESET)));
462 for(unsigned i = 0;i < 10;i ++) {
463 char a[3];
464 sprintf(a,"%d",i);
465 scim_string_to_key_list(k_selection[i],
466 _scim_config->read(String(HONOKA_CONFIG_KEY_SELECTION_PREFIX) + String(a),
467 String(a)));
468 }
469
470 vector<String> sl;
471
472 sl = split(defaultPreEditor);
473 for(unsigned int i = 0;i < sl.size();i ++) if (changePreEditor(sl[i])) break;
474 sl = split(defaultConvertor);
475 for(unsigned int i = 0;i < sl.size();i ++) if (changeConvertor(sl[i])) break;
476 sl = split(defaultPredictor);
477 for(unsigned int i = 0;i < sl.size();i ++) if (changePredictor(sl[i])) break;
478
479 for(unsigned int i = 0;i < convertors.size();i ++) {
480 HonokaKeyEventList k;
481 scim_string_to_key_list(k,
482 _scim_config->read(String(HONOKA_CONFIG_KEY_CONVERTOR_PREFIX) + String("/") + convertors[i]->getName(),String("")));
483 k_convertor.push_back(k);
484 }
485 for(unsigned int i = 0;i < preeditors.size();i ++) {
486 HonokaKeyEventList k;
487 scim_string_to_key_list(k,
488 _scim_config->read(String(HONOKA_CONFIG_KEY_PREEDITOR_PREFIX) + String("/") + preeditors[i]->getName(),String("")));
489 k_preeditor.push_back(k);
490 }
491 for(unsigned int i = 0;i < predictors.size();i ++) {
492 HonokaKeyEventList k;
493 scim_string_to_key_list(k,
494 _scim_config->read(String(HONOKA_CONFIG_KEY_PREDICTOR_PREFIX) + String("/") + predictors[i]->getName(),String("")));
495 k_predictor.push_back(k);
496 }
497
498 if (save_setting) {
499 changePreEditor(_scim_config->read(String(HONOKA_PREVIOUS_PREEDITOR),String()));
500 changePredictor(_scim_config->read(String(HONOKA_PREVIOUS_PREDICTOR),String()));
501 changeConvertor(_scim_config->read(String(HONOKA_PREVIOUS_CONVERTOR),String()));
502 }
503
504 m_splitter = 0;
505 //if (changable_splitter) changeSplitter(String("AUTO"));
506
507 }
508
509
510
511 /*!
512 \fn HonokaInstance::getConvertedText()
513 */
getConvertedText()514 const WideString HonokaInstance::getConvertedText()
515 {
516 // このかたちでは、変換動作から候補一覧を取得した上でないと結果を得られない。
517 // 直すべきか?。
518 vector<Segment> seglist = m_convertor->getSegmentList();
519 vector<Segment> newsegs;
520 WideString t;
521 for(unsigned int i = 0;i < seglist.size();i ++) {
522 if ((i < m_convertor->getPos()) && (segments.size() > i)) {
523 if ((seglist[i].getKanji() != segments[i].getKanji()) && (seglist[i].getYomi().length() == segments[i].getYomi().length()))
524 newsegs.push_back(segments[i]);
525 else newsegs.push_back(seglist[i]);
526 } else if (i == m_convertor->getPos())
527 newsegs.push_back(Segment(m_convList.kouho[m_convList.pos].kanji,seglist[i].getYomi()));
528 else newsegs.push_back(seglist[i]);
529 }
530 segments = newsegs;
531 for(unsigned int i = 0;i < segments.size();i ++) {
532 t += segments[i].getKanji();
533 }
534 return t;
535 }
536
537
538 /*!
539 \fn HonokaInstance::getConvertedAttributeList()
540 */
getConvertedAttributeList()541 const AttributeList HonokaInstance::getConvertedAttributeList()
542 {
543 AttributeList attr;
544 int c = 0;
545 for(unsigned int i = 0;i < segments.size();i ++) {
546 if (m_convertor->getPos() == i) {
547 Attribute a(c,segments[i].getKanji().length(),SCIM_ATTR_DECORATE,SCIM_ATTR_DECORATE_REVERSE);
548 attr.push_back(a);
549 break;
550 } else c += segments[i].getKanji().length();
551 }
552
553 return attr;
554 }
555
556 /*!
557 \fn HonokaInstance::updateConvertedString()
558 */
updateConvertedString()559 void HonokaInstance::updateConvertedString()
560 {
561 WideString w = getConvertedText();
562 AttributeList a = getConvertedAttributeList();
563 int c = 0;
564 for(unsigned int i = 0;i < segments.size();i ++) {
565 if (m_convertor->getPos() == i) break;
566 else c += segments[i].getKanji().length();
567 }
568 update_preedit_string(w,a);
569 update_preedit_caret(c);
570
571 }
572
573
574 /*!
575 \fn HonokaInstance::changePreEditor(const String &name)
576 */
changePreEditor(const String & name)577 bool HonokaInstance::changePreEditor(const String &name)
578 {
579 // PreEditorを変更するメソッド。
580 for(unsigned int i = 0;i < preeditors.size();i ++) {
581 if (preeditors[i]->getName() == name) {
582 m_preeditor->unSelected();
583 m_preeditor = preeditors[i];
584 m_preeditor->selected();
585 return true;
586 }
587 }
588 return false;
589 }
590
591
592
593 /*!
594 \fn HonokaInstance::changeConvertor(const String &name)
595 */
changeConvertor(const String & name)596 bool HonokaInstance::changeConvertor(const String &name)
597 {
598 // Convertorを変更するメソッド。
599 for(unsigned int i = 0;i < convertors.size();i ++) {
600 if (convertors[i]->getName() == name) {
601 m_convertor->unSelected();
602 m_convertor = convertors[i];
603 m_convertor->selected();
604 return true;
605 }
606 }
607 return false;
608 }
609
610
611 /*!
612 \fn HonokaInstance::changeSplitter(const String &name)
613 */
changeSplitter(const String & name)614 bool HonokaInstance::changeSplitter(const String &name)
615 {
616 // Splitterを変更するメソッド。
617 if (name == "AUTO") {
618 m_splitter = 0;
619 return true;
620 }
621 for(unsigned int i = 0;i < convertors.size();i ++) {
622 if (convertors[i]->getName() == name) {
623 m_splitter = convertors[i];
624 return true;
625 }
626 }
627 return false;
628 }
629
630
631
632 /*!
633 \fn HonokaInstance::changePredictor(const String &name)
634 */
changePredictor(const String & name)635 bool HonokaInstance::changePredictor(const String &name)
636 {
637 // Predictorを変更するメソッド。
638 if (!prediction) return false;
639 for(unsigned int i = 0;i < predictors.size();i ++) {
640 if (predictors[i]->getName() == name) {
641 m_predictor = predictors[i];
642 if (prediction && (!m_predictor->isConnected())) m_predictor->connect();
643 preeditCache.clear();
644 return true;
645 }
646 }
647 return false;
648 }
649
650
651 /*!
652 \fn HonokaInstance::updateProperty()
653 */
updateProperty()654 void HonokaInstance::updateProperty()
655 {
656 // プロパティを更新するメソッド。
657 if (m_proplist.empty()) {
658 Property p;
659 p = Property(HONOKA_PROP_INPUTMODE,"",String(""),_("input mode"));
660 m_proplist.push_back(p);
661 for(unsigned int i = 0;i < preeditors.size();i ++) {
662 p = Property(String(HONOKA_PROP_INPUTMODE) + String("/") + preeditors[i]->getName(),
663 preeditors[i]->getPropertyName(),String(""),_("mode status"));
664 m_proplist.push_back(p);
665 }
666 if (prediction) {
667 p = Property(HONOKA_PROP_PREDICTOR,"",String(""),_("predictor"));
668 m_proplist.push_back(p);
669 for(unsigned int i = 0;i < predictors.size();i ++) {
670 p = Property(String(HONOKA_PROP_PREDICTOR) + String("/") + predictors[i]->getName(),
671 predictors[i]->getPropertyName(),String(""),_("mode status"));
672 m_proplist.push_back(p);
673 }
674 }
675 if (changeable_splitter) {
676 p = Property(HONOKA_PROP_SPLITTER,"",String(""),_("splitter"));
677 m_proplist.push_back(p);
678 p = Property(String(HONOKA_PROP_SPLITTER) + String("/AUTO"),
679 _("Auto"),String(""),_("mode status"));
680 m_proplist.push_back(p);
681 for(unsigned int i = 0;i < convertors.size();i ++) {
682 p = Property(String(HONOKA_PROP_SPLITTER) + String("/") + convertors[i]->getName(),
683 convertors[i]->getPropertyName(),String(""),_("mode status"));
684 m_proplist.push_back(p);
685 }
686 }
687 p = Property(HONOKA_PROP_CONVERTOR,"",String(""),_("convertor"));
688 m_proplist.push_back(p);
689 for(unsigned int i = 0;i < convertors.size();i ++) {
690 p = Property(String(HONOKA_PROP_CONVERTOR) + String("/") + convertors[i]->getName(),
691 convertors[i]->getPropertyName(),String(""),_("mode status"));
692 m_proplist.push_back(p);
693 }
694 p = Property(HONOKA_PROP_MODESTATUS,"",String(""),_("mode status"));
695 m_proplist.push_back(p);
696 p = Property(HONOKA_PROP_CONVERSIONMODE,"",String(""),_("conversion mode"));
697 m_proplist.push_back(p);
698 }
699 PropertyList::iterator it;
700 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_INPUTMODE);
701 if (it != m_proplist.end()) {
702 it->set_label(m_preeditor->getPropertyName() + String(" "));
703 }
704 update_property(*it);
705 if (prediction) {
706 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_PREDICTOR);
707 if (it != m_proplist.end()) {
708 it->set_label(m_predictor->getPropertyName() + String(" "));
709 }
710 update_property(*it);
711 }
712 if (changeable_splitter) {
713 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_SPLITTER);
714 if (it != m_proplist.end()) {
715 if (m_splitter == 0) it->set_label(_("Auto") + String(" "));
716 else it->set_label(m_splitter->getPropertyName() + String(" "));
717 }
718 }
719 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_CONVERTOR);
720 if (it != m_proplist.end()) {
721 it->set_label(m_convertor->getPropertyName() + String(" "));
722 }
723 update_property(*it);
724 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_MODESTATUS);
725 if (it != m_proplist.end()) {
726 if (m_conversion) it->set_label(_("Kanji") + String(" "));
727 else if (m_prediction) it->set_label(_("Yosoku") + String(" "));
728 else it->set_label(m_preeditor->getModeName() + String(" "));
729 }
730 update_property(*it);
731 it = find(m_proplist.begin(),m_proplist.end(),HONOKA_PROP_CONVERSIONMODE);
732 if (it != m_proplist.end()) {
733 if (auto_conversion) it->set_label(_("AUTO") + String(" "));
734 else it->set_label(_("REN") + String(" "));
735 }
736 update_property(*it);
737 register_properties(m_proplist);
738 }
739
740
741 /*!
742 \fn HonokaInstance::updatePreEditor()
743 */
updatePreEditor()744 void HonokaInstance::updatePreEditor()
745 {
746 // PreEditorを更新するメソッド。
747 // 頻繁に呼ばれます。
748 if (PreEditor::getCommitString().length()) {
749 commit_string(PreEditor::getCommitString());
750 PreEditor::resetCommitString();
751 }
752 if (m_preeditor->getTextLength()) {
753 if (auto_conversion && (m_preeditor->getTextLength() == m_preeditor->getPos()))
754 autoConversion();
755 else {
756 show_preedit_string();
757 update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
758 update_preedit_caret(m_preeditor->getPos());
759 }
760 // Prediction
761 if ((!m_conversion) && realtime_prediction && prediction && m_predictor->isConnected() && (!auto_conversion)) {
762 if ((predictionDelay > 0) && (preeditCache != m_preeditor->getText())) {
763 m_lookup_table.clear();
764 m_lookup = false;
765 preeditKeyDelay = HonokaTimer::self()->appendDelayEvent(predictionDelay);
766 hide_lookup_table();
767 } else {
768 if (preeditCache != m_preeditor->getText()) {
769 m_convList = m_predictor->getPredictionList(m_preeditor->getText());
770 m_convList.Yomi = m_preeditor->getText();
771 if (m_convList.count()) {
772 m_lookup_table.clear();
773 for(unsigned int i = 0;i < m_convList.count();i ++) {
774 m_lookup_table.append_candidate(m_convList.kouho.at(i).kanji);
775 }
776 startLookup();
777 } else {
778 //m_lookup_table.clear();
779 hide_lookup_table();
780 }
781 }
782 }
783 } else hide_lookup_table();
784 } else {
785 hide_preedit_string();
786 hide_lookup_table();
787 }
788 // mini_status用コード。怪しい。
789 if (mini_status) {
790 update_aux_string(utf8_mbstowcs(m_preeditor->getModeName()));
791 show_aux_string();
792 } else {
793 hide_aux_string();
794 }
795 preeditCache = m_preeditor->getText();
796 updateProperty();
797 }
798 /*!
799 \fn HonokaInstance::updateConversion()
800 */
updateConversion()801 void HonokaInstance::updateConversion()
802 {
803 // 変換時の表示更新。
804 updateConvertedString();
805 if (m_lookup) {
806 m_lookup_table.set_cursor_pos(m_convList.pos);
807 update_lookup_table(m_lookup_table);
808 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
809 show_aux_string();
810 show_lookup_table();
811 } else {
812 hide_lookup_table();
813 hide_aux_string();
814 }
815 updateProperty();
816 }
817
process_helper_event(const String & helper_uuid,const Transaction & trans)818 void HonokaInstance::process_helper_event (const String &helper_uuid, const Transaction &trans)
819 {
820 WideString t = m_preeditor->getText();
821 if (helper_uuid == HONOKA_TIMER_UUID) {
822 vector<int> e = HonokaTimer::self()->eventFilter(trans);
823 for(unsigned int i = 0;i < e.size();i ++) {
824 timerEvent(e[i]);
825 }
826 }
827 if ((!m_conversion) && (!m_prediction) && (t != m_preeditor->getText())) updatePreEditor();
828 }
829
830
process_key_event(const KeyEvent & key)831 bool HonokaInstance::process_key_event (const KeyEvent& key)
832 {
833 // debug
834 /*
835 String s;
836 scim_key_to_string(s,key);
837 update_aux_string(utf8_mbstowcs(String(key.is_key_release() ? String("R:") : String("P:")) + s));
838 show_aux_string();
839 return true;
840 */
841
842 // キーイベント処理。
843 //if (key.is_key_release()) return false;
844 /*
845 trans.clear();
846 trans.put_command(SCIM_TRANS_CMD_REQUEST);
847 trans.put_command(SCIM_TRANS_CMD_PROCESS_KEY_EVENT);
848 trans.put_data(key);
849 send_helper_event("e135e0ee-5588-423e-a027-f07d769c12a3",trans);
850 */
851
852 KeyEvent ke = key;
853 if (ke.mask & SCIM_KEY_CapsLockMask) ke.mask -= SCIM_KEY_CapsLockMask;
854 if (ke.mask & SCIM_KEY_NumLockMask) ke.mask -= SCIM_KEY_NumLockMask;
855 // if (ke.mask & SCIM_KEY_ScrollLockMask) ke.mask -= SCIM_KEY_ScrollLockMask;
856 if (m_conversion) return process_conversion_key_event(ke);
857 else if (m_prediction) return process_prediction_key_event(ke);
858 else return process_preedit_key_event(ke) ;
859 }
860
861
862 /*!
863 \fn HonokaInstance::process_preedit_key_event(const KeyEvent &key)
864 */
process_preedit_key_event(const KeyEvent & key)865 bool HonokaInstance::process_preedit_key_event(const KeyEvent &key)
866 {
867 if (k_allreset.comp(key)) {
868 unload();
869 loadPlugins();
870 init();
871 m_proplist.clear();
872 updateProperty();
873 updatePreEditor();
874 return true;
875 }
876 if (!m_preeditor->getTextLength()) pStringType = NORMAL;
877 // PreEdit時のキーイベント。
878 // PreEditorのキーイベントフック。
879 if (m_preeditor->keyEventHook(key)) {
880 updatePreEditor();
881 return true;
882 }
883 // フックでfalseかつCommitStringセット時のみ特殊動作。
884 if (PreEditor::getCommitString().length()) {
885 updatePreEditor();
886 return false;
887 }
888
889 // !! ここでreleaseを除去。
890 if (key.is_key_release()) return false;
891
892 // 切り替えキー。
893 for(unsigned int i = 0;i < k_preeditor.size();i ++) {
894 if (k_preeditor[i].comp(key)) {
895 // 同じキーに2種設定があればトグルになると良いと思う。
896 if (preeditors[i] != m_preeditor) {
897 changePreEditor(preeditors[i]->getName());
898 updatePreEditor();
899 return true;
900 }
901 }
902 }
903 for(unsigned int i = 0;i < k_convertor.size();i ++) {
904 if (k_convertor[i].comp(key)) {
905 if (convertors[i] == m_convertor) return true;
906 changeConvertor(convertors[i]->getName());
907 updatePreEditor();
908 return true;
909 }
910 }
911 for(unsigned int i = 0;i < k_predictor.size();i ++) {
912 if (k_predictor[i].comp(key)) {
913 if (predictors[i] == m_predictor) return true;
914 //m_predictor = predictors[i];
915 changePredictor(predictors[i]->getName());
916 updatePreEditor();
917 return true;
918 }
919 }
920
921 // 処理。
922 if (k_reconversion.comp(key)) {
923 WideString w;
924 int c;
925 if (get_surrounding_text(w,c)) {
926 if (w.length()) {
927 // delete_surrounding_text()を使っての削除とかいるね。
928 delete_surrounding_text(0 - w.length(),w.length());
929 startConversion(w);
930 alp_count ++;
931 return true;
932 }
933 }
934 }
935
936 // バッファが空では無い場合。
937 if (m_preeditor->getTextLength()) {
938 if (k_conversion_start.comp(key)) {
939 startConversion(m_preeditor->getText(true));
940 alp_count ++;
941 return true;
942 } else
943 if (k_multi_conversion.comp(key)) {
944 startConversion(m_preeditor->getText(true),true);
945 alp_count ++;
946 return true;
947 } else
948 if (k_commit.comp(key)) {
949 if (auto_conversion) {
950 commit_string(getConvertedText());
951 if (prediction) if (m_predictor->isConnected()) m_predictor->update(getConvertedText(),m_preeditor->getText(true));
952 m_convertor->reset();
953 } else {
954 commit_string(m_preeditor->getText(true));
955 if (prediction) if (m_predictor->isConnected()) m_predictor->update(m_preeditor->getText(true),m_preeditor->getText(true));
956 }
957 m_preeditor->reset();
958 while(preeditStack.size()) {
959 preeditStack.pop();
960 }
961 updatePreEditor();
962 return true;
963 } else
964 if (k_forward.comp(key) || k_backward.comp(key)) {
965 k_backward.comp(key) ? m_preeditor->setPos(m_preeditor->getPos() - 1) : m_preeditor->setPos(m_preeditor->getPos() + 1);
966 updatePreEditor();
967 return true;
968 } else
969 if (k_home.comp(key) || k_end.comp(key)) {
970 k_end.comp(key) ? m_preeditor->setPos(m_preeditor->getTextLength()) : m_preeditor->setPos(0);
971 updatePreEditor();
972 return true;
973 } else
974 if ((k_backspace.comp(key)) || (k_delete.comp(key))) {
975 k_backspace.comp(key) ? m_preeditor->backspace(): m_preeditor->del();
976 if (preeditCache != m_preeditor->getText()) pStringType = NORMAL;
977 updatePreEditor();
978 return true;
979 } else
980 if (k_convert_ctype.comp(key)) {
981 switch(pStringType) {
982 case NORMAL: {
983 pString = m_preeditor->getText();
984 pStringType = HIRA;
985 m_preeditor->kataHira();
986 break;
987 }
988 case HIRA: {
989 m_preeditor->setText(pString);
990 pStringType = KATA;
991 m_preeditor->hiraKata();
992 break;
993 }
994 case KATA: {
995 m_preeditor->setText(pString);
996 pStringType = HALF;
997 m_preeditor->toHalf();
998 break;
999 }
1000 case HALF: {
1001 m_preeditor->setText(pString);
1002 pStringType = WIDE;
1003 m_preeditor->toWide();
1004 break;
1005 }
1006 case WIDE: {
1007 m_preeditor->setText(pString);
1008 pStringType = HIRA;
1009 m_preeditor->kataHira();
1010 break;
1011 }
1012 default: {
1013 break;
1014 }
1015 }
1016 updatePreEditor();
1017 return true;
1018 }
1019 if (k_convert_hiragana.comp(key)) {
1020 m_preeditor->kataHira();
1021 updatePreEditor();
1022 return true;
1023 } else
1024 if (k_convert_katakana.comp(key)) {
1025 m_preeditor->hiraKata();
1026 updatePreEditor();
1027 return true;
1028 } else
1029 if (k_convert_half.comp(key)) {
1030 m_preeditor->toHalf();
1031 updatePreEditor();
1032 return true;
1033 } else
1034 if (k_convert_wide.comp(key)) {
1035 m_preeditor->toWide();
1036 updatePreEditor();
1037 return true;
1038 } else
1039 if (k_select_prediction.comp(key) && prediction) {
1040 if ((!realtime_prediction) && m_predictor->isConnected()) {
1041 m_convList = m_predictor->getPredictionList(m_preeditor->getText());
1042 m_convList.Yomi = m_preeditor->getText();
1043 if (m_convList.count()) {
1044 m_lookup_table.clear();
1045 for(unsigned int i = 0;i < m_convList.count();i ++) {
1046 m_lookup_table.append_candidate(m_convList.kouho.at(i).kanji);
1047 }
1048 startLookup();
1049 }
1050 }
1051 if ((m_convList.kType == PREDICTION) && (m_convList.count()) && (m_convList.Yomi == m_preeditor->getText())) {
1052 return process_prediction_key_event(key);
1053 }
1054 } else
1055 // 数字キーによる直接予測選択。甘いか?。
1056 if (numkeyselect && realtime_prediction && prediction && select_prediction_direct) {
1057 if ((m_convList.kType == PREDICTION) && (m_convList.count()) && (m_convList.Yomi == m_preeditor->getText())) {
1058 for(unsigned int i = 0;i < 10;i ++) {
1059 if (k_selection[i].comp(key)) {
1060 int numc = i - 1;
1061 if (numc < 0) numc = 9;
1062 if (m_convList.count() > numc) {
1063 m_convList.pos = numc;
1064 commit_string(m_convList.kouho.at(m_convList.pos).kanji);
1065 m_preeditor->reset();
1066 updatePreEditor();
1067 return true;
1068 }
1069 }
1070 }
1071 }
1072 }
1073 }
1074
1075 // バッファの存在にかかわらず。
1076 if (k_cancel.comp(key)) {
1077 if (m_preeditor->cancelEvent()) {
1078 updatePreEditor();
1079 return true;
1080 }
1081 if (preeditStack.size()) {
1082 m_preeditor->reset();
1083 m_preeditor->setText(preeditStack.top());
1084 m_preeditor->setPos(preeditStack.top().length());
1085 preeditStack.pop();
1086 } else
1087 if (m_preeditor->getTextLength()) {
1088 m_preeditor->reset();
1089 }
1090 updatePreEditor();
1091 return true;
1092 }
1093
1094 if (k_next_convertor.comp(key) || k_prev_convertor.comp(key)) {
1095 for(unsigned int i = 0;i < convertors.size();i ++) {
1096 if (convertors[i]->getName() == m_convertor->getName()) {
1097 if (k_next_convertor.comp(key)) {
1098 if (i == (convertors.size() - 1)) i = 0;
1099 else i ++;
1100 } else {
1101 if (i == 0) i = convertors.size() - 1;
1102 else i --;
1103 }
1104 changeConvertor(convertors[i]->getName());
1105 updatePreEditor();
1106 return true;
1107 }
1108 }
1109 }
1110
1111 if (k_auto_conversion.comp(key)) {
1112 auto_conversion ? auto_conversion = false : auto_conversion = true;
1113 updatePreEditor();
1114 return true;
1115 }
1116
1117 if (m_preeditor->inputEvent(key)) {
1118 if (preeditCache != m_preeditor->getText()) pStringType = NORMAL;
1119 updatePreEditor();
1120
1121 return true;
1122 } else {
1123 // preeditorで処理できなかった場合はやはりcommitしてアプリケーションに返すべきだ。
1124 if (m_preeditor->getTextLength()) {
1125 if (auto_conversion) {
1126 commit_string(getConvertedText());
1127 m_convertor->reset();
1128 } else commit_string(m_preeditor->getText(true));
1129 }
1130 m_preeditor->reset();
1131 updatePreEditor();
1132 }
1133 if (PreEditor::getCommitString().length()) updatePreEditor();
1134 return false;
1135 }
1136
1137 /*!
1138 \fn HonokaInstance::process_conversion_key_event(const KeyEvent &key)
1139 */
process_conversion_key_event(const KeyEvent & key)1140 bool HonokaInstance::process_conversion_key_event(const KeyEvent &key)
1141 {
1142 preeditCache.clear();
1143 // 変換時のキーイベント処理。
1144 // 喰う!。
1145 if (key.is_key_release()) return true;
1146 if (PreEditor::isThrough(key)) return true;
1147
1148 // 自動候補ポップアップのカウント計算。
1149 if ((alp <= alp_count) && (alp != 0)) {
1150 if (!m_lookup) startLookup();
1151 }
1152
1153 // 候補一覧ポップアップキー
1154 if (k_lookup_popup.comp(key)) {
1155 if (m_lookup) return true;
1156 startLookup();
1157 return true;
1158 } else
1159
1160 // 前ページキー
1161 if (k_lookup_pageup.comp(key)) {
1162 if (m_lookup) {
1163 lookup_table_page_up();
1164 }
1165 } else
1166
1167 // 後ページキー
1168 if (k_lookup_pagedown.comp(key)) {
1169 if (m_lookup) {
1170 lookup_table_page_down();
1171 }
1172 } else
1173
1174 // ふりがな付き確定キー(実験的)
1175 if (k_furigana_commit.comp(key)) {
1176 WideString cm;
1177 for(unsigned int i = 0;i < segments.size();i ++) {
1178 if (segments[i].getKanji() == segments[i].getYomi()) {
1179 cm += segments[i].getKanji();
1180 } else {
1181 for(unsigned int j = 0;segments[i].getYomi().length() - j != 0;j ++) {
1182 if (segments[i].getKanji()[segments[i].getKanji().length() - j - 1] !=
1183 segments[i].getYomi()[segments[i].getYomi().length() - j - 1]) {
1184 cm += segments[i].getKanji().substr(0,segments[i].getKanji().length() - j);
1185 cm += utf8_mbstowcs(String("("));
1186 cm += segments[i].getYomi().substr(0,segments[i].getYomi().length() - j);
1187 cm += utf8_mbstowcs(String(")"));
1188 cm += segments[i].getKanji().substr(segments[i].getKanji().length() - j,segments[i].getKanji().length());
1189 break;
1190 }
1191 }
1192 }
1193 }
1194 commit_string(cm);
1195 m_convertor->updateFrequency();
1196 if (prediction) if (m_predictor->isConnected()) m_predictor->update(getConvertedText(),m_preeditor->getText(true));
1197 m_preeditor->reset();
1198 m_convertor->reset();
1199 m_conversion = false;
1200 updatePreEditor();
1201 m_lookup = false;
1202 alp_count = 1;
1203 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1204 updateProperty();
1205 return true;
1206 } else
1207
1208 // 確定キー
1209 if (k_commit.comp(key)) {
1210 commit_string(getConvertedText());
1211 m_convertor->updateFrequency();
1212 if (prediction) if (m_predictor->isConnected()) m_predictor->update(getConvertedText(),m_preeditor->getText(true));
1213 m_preeditor->reset();
1214 m_convertor->reset();
1215 m_conversion = false;
1216 updatePreEditor();
1217 m_lookup = false;
1218 alp_count = 1;
1219 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1220 updateProperty();
1221 return true;
1222 } else
1223
1224 // 結果をPreEditorに戻すキー。
1225 if (k_result_to_preedit.comp(key)) {
1226 preeditStack.push(m_preeditor->getText(true));
1227 m_preeditor->reset();
1228 m_preeditor->setText(getConvertedText());
1229 m_preeditor->setPos(getConvertedText().length());
1230 m_convertor->updateFrequency();
1231 m_convertor->reset();
1232 m_conversion = false;
1233 m_lookup = false;
1234 alp_count = 1;
1235 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1236 updateProperty();
1237 updatePreEditor();
1238 return true;
1239 } else
1240
1241 // キャンセルキー。
1242 if (k_cancel.comp(key) || k_backspace.comp(key)) {
1243 m_convertor->reset();
1244 m_conversion = false;
1245 m_lookup = false;
1246 alp_count = 0;
1247 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1248 updateProperty();
1249 updatePreEditor();
1250 return true;
1251 } else
1252
1253 // 次候補/前候補キー。
1254 if (k_conversion_next.comp(key) || k_conversion_prev.comp(key)) {
1255 k_conversion_prev.comp(key) ? m_convList.pos --: m_convList.pos ++;
1256 if (m_convList.pos >= m_convList.count()) m_convList.pos = 0;
1257 else if (m_convList.pos < 0) m_convList.pos = m_convList.count() - 1;
1258 alp_count ++;
1259
1260 if (!m_no_update) m_convertor->select(m_convList.pos);
1261 updateConversion();
1262 return true;
1263 } else
1264
1265 // 注目文節拡縮キー。
1266 if (k_conversion_expand.comp(key) || k_conversion_shrink.comp(key)) {
1267 m_no_update = false;
1268 bool r;
1269 k_conversion_shrink.comp(key) ? r = m_convertor->resizeRegion(-1) : r = m_convertor->resizeRegion(1);
1270 if (!r) return true;
1271 m_convList = m_convertor->getResultList();
1272 if (alp == -1) {
1273 startLookup();
1274 } else m_lookup = false;
1275 updateConversion();
1276 alp_count = 1;
1277 return true;
1278 } else
1279
1280 // 連想変換(特殊1)キー
1281 if (k_conversion_rensou.comp(key)) {
1282 m_no_update = false;
1283 m_convList = m_convertor->getResultList(m_convertor->getPos(),SPECIAL1);
1284 if (m_convList.count() == 0) return true;
1285 startLookup();
1286 updateConversion();
1287 alp_count = 1;
1288 return true;
1289 } else
1290
1291 // 異形字変換(特殊2)キー。
1292 if (k_conversion_ikeiji.comp(key)) {
1293 m_no_update = false;
1294 m_convList = m_convertor->getResultList(m_convertor->getPos(),SPECIAL2);
1295 if (m_convList.count() == 0) return true;
1296 startLookup();
1297 updateConversion();
1298 alp_count = 1;
1299 return true;
1300 } else
1301
1302 // 注目文節移動キー。
1303 if (k_conversion_forward.comp(key) || k_conversion_backward.comp(key)) {
1304 m_no_update = false;
1305 k_conversion_backward.comp(key) ? m_convertor->setPos(m_convertor->getPos() - 1) : m_convertor->setPos(m_convertor->getPos() + 1);
1306 m_convList = m_convertor->getResultList();
1307 if (alp == -1) {
1308 startLookup();
1309 } else m_lookup = false;
1310 updateConversion();
1311 alp_count = 1;
1312 return true;
1313 } else
1314
1315 // ひらがな/カタカナ変換キー。
1316 if (k_convert_hiragana.comp(key) || k_convert_katakana.comp(key)) {
1317 WideString res = m_convList.Yomi;
1318 if (k_convert_hiragana.comp(key) && k_convert_katakana.comp(key)) {
1319 PreEditor::convKataHira(res);
1320 if (res == m_convList.kouho[m_convList.pos].kanji) PreEditor::convHiraKata(res);
1321 } else
1322 k_convert_hiragana.comp(key) ? m_preeditor->convKataHira(res) : m_preeditor->convHiraKata(res);
1323 for(unsigned int i = 0;i < m_convList.count();i ++) {
1324 if (res == m_convList.kouho[i].kanji) {
1325 m_convList.pos = i;
1326 if (!m_no_update) m_convertor->select(m_convList.pos);
1327 updateConversion();
1328 break;
1329 }
1330 }
1331 return true;
1332 } else
1333
1334 // 文字種トグルキー
1335 if (k_convert_ctype.comp(key)) {
1336 // m_no_updateをチェックし、文字種リストをでっちあげる。
1337 // 文節毎のエンジン切り替え時は働かない。
1338 if (m_no_update) {
1339 m_convList.pos ++;
1340 if (m_convList.pos >= m_convList.count()) m_convList.pos = 0;
1341 updateConversion();
1342 return true;
1343 }
1344 m_no_update = true;
1345 pString = m_convList.Yomi;
1346 WideString t;
1347 int dp;
1348 m_convList.kouho.clear();
1349 t = pString;
1350 PreEditor::convKataHira(t);
1351 m_convList.kouho.push_back(ResultEntry(t));
1352 t = pString;
1353 PreEditor::convHiraKata(t);
1354 m_convList.kouho.push_back(ResultEntry(t));
1355 t = pString;
1356 PreEditor::convZenHan(t,dp);
1357 m_convList.kouho.push_back(ResultEntry(t));
1358 t = pString;
1359 PreEditor::convHanZen(t,dp);
1360 m_convList.kouho.push_back(ResultEntry(t));
1361 m_lookup = false;
1362 updateConversion();
1363 return true;
1364 } else
1365
1366 // 次/前変換エンジン切り替えキー。
1367 if ((k_next_convertor.comp(key) || k_prev_convertor.comp(key)) && (m_convertor != m_multi)) {
1368 for(unsigned int i = 0;i < convertors.size();i ++) {
1369 if (convertors[i]->getName() == m_convertor->getName()) {
1370 if (k_next_convertor.comp(key)) {
1371 if (i == (convertors.size() - 1)) i = 0;
1372 else i ++;
1373 } else {
1374 if (i == 0) i = convertors.size() - 1;
1375 else i --;
1376 }
1377 changeConvertor(convertors[i]->getName());
1378 if (m_def_convertor != m_convertor) {
1379 m_def_convertor->reset();
1380 startConversion();
1381 }
1382 return true;
1383 }
1384 }
1385 } else
1386
1387 // 数字キーによる候補選択。
1388 if (numkeyselect && m_lookup) {
1389 for(unsigned int i = 0;i < 10;i ++) {
1390 if (k_selection[i].comp(key)) {
1391 int numc = i - 1;
1392 if (numc < 0) numc = 9;
1393 if (m_lookup_table.get_current_page_size() <= numc) return true;
1394 m_convList.pos = numc + m_lookup_table.get_current_page_start();
1395 if (!m_no_update) m_convertor->select(m_convList.pos);
1396 m_no_update = false;
1397 m_convertor->setPos(m_convertor->getPos() + 1);
1398 m_convList = m_convertor->getResultList();
1399 updateConversion();
1400 startLookup();
1401 return true;
1402 }
1403 }
1404 }
1405
1406 // 注目文節の候補を別変換エンジンから取得するキー。
1407 if (m_convertor != m_multi) {
1408 for(unsigned int i = 0;i < k_convertor.size();i ++) {
1409 if (k_convertor[i].comp(key)) {
1410 if (convertors[i] == m_convertor) return true;
1411 if (!convertors[i]->isConnected())
1412 if (!convertors[i]->connect()) return true;
1413 WideString y;
1414 for(unsigned int j = 0;j < segments.size();j ++) y += segments[j].getYomi();
1415 convertors[i]->setYomiText(y);
1416 //convertors[i]->setYomiText(m_preeditor->getText(true));
1417 if (convertors[i]->ren_conversion() <= 0) return true;
1418 m_no_update = true;
1419 MultiConvertor::aline(m_convertor,convertors[i]);
1420 m_convList = convertors[i]->getResultList(m_convertor->getPos());
1421 m_convList.Title = utf8_mbstowcs(String("(") + convertors[i]->getPropertyName() + String(")"));
1422 convertors[i]->reset();
1423 startLookup();
1424 updateConversion();
1425 return true;
1426 }
1427 }
1428 }
1429
1430 // それ以外のキーの場合、表示可能キーなら確定してPreEdit入力を再開。
1431 if (key.get_unicode_code()) {
1432 commit_string(getConvertedText());
1433 m_convertor->updateFrequency();
1434 if (prediction) if (m_predictor->isConnected()) m_predictor->update(getConvertedText(),m_preeditor->getText(true));
1435 m_preeditor->reset();
1436 m_convertor->reset();
1437 m_conversion = false;
1438 m_lookup = false;
1439 alp_count = 0;
1440 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1441 updateProperty();
1442 updatePreEditor();
1443 return process_preedit_key_event(key);
1444 }
1445
1446
1447 return true;
1448 }
1449
1450
1451
1452 /*!
1453 \fn HonokaInstance::process_prediction_key_event(const KeyEvent &key)
1454 */
process_prediction_key_event(const KeyEvent & key)1455 bool HonokaInstance::process_prediction_key_event(const KeyEvent &key)
1456 {
1457 preeditCache.clear();
1458 // 予測選択時のキーイベント処理。
1459 if (key.is_key_release()) return true;
1460 if (!m_prediction) {
1461 m_prediction = true;
1462 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1463 show_aux_string();
1464 update_preedit_string(m_convList.kouho.at(m_convList.pos).kanji);
1465 update_preedit_caret(m_predictor->getPos());
1466 show_preedit_string();
1467 updateProperty();
1468 return true;
1469 }
1470
1471 if (k_lookup_pageup.comp(key)) {
1472 lookup_table_page_up();
1473 return true;
1474 } else
1475 if (k_lookup_pagedown.comp(key)) {
1476 lookup_table_page_down();
1477 return true;
1478 } else
1479 if (k_conversion_next.comp(key) || k_conversion_prev.comp(key) || k_select_prediction.comp(key)) {
1480 k_conversion_prev.comp(key) ? m_convList.pos --: m_convList.pos ++;
1481 if (m_convList.pos >= m_convList.count()) m_convList.pos = 0;
1482 else if (m_convList.pos < 0) m_convList.pos = m_convList.count() - 1;
1483 m_lookup_table.set_cursor_pos(m_convList.pos);
1484 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1485 show_aux_string();
1486 update_lookup_table(m_lookup_table);
1487 update_preedit_string(m_convList.kouho.at(m_convList.pos).kanji);
1488 update_preedit_caret(m_predictor->getPos());
1489 updateProperty();
1490 return true;
1491 } else
1492 if (k_commit.comp(key)) {
1493 m_prediction = false;
1494 commit_string(m_convList.kouho.at(m_convList.pos).kanji);
1495 m_preeditor->reset();
1496 updatePreEditor();
1497 return true;
1498 } else
1499 if (k_cancel.comp(key) || k_backspace.comp(key)) {
1500 m_prediction = false;
1501 updatePreEditor();
1502 return true;
1503 }
1504 if (numkeyselect) {
1505 for(unsigned int i = 0;i < 10;i ++) {
1506 if (k_selection[i].comp(key)) {
1507 int numc = i - 1;
1508 if (numc < 0) numc = 9;
1509 if (m_lookup_table.get_current_page_size() <= numc) return true;
1510 //select_candidate((unsigned int)numc);
1511 m_convList.pos = numc + m_lookup_table.get_current_page_start();
1512 m_prediction = false;
1513 commit_string(m_convList.kouho.at(m_convList.pos).kanji);
1514 m_preeditor->reset();
1515 updatePreEditor();
1516 return true;
1517 }
1518 }
1519 }
1520
1521 if (!key.get_unicode_code()) return true;
1522 m_prediction = false;
1523 commit_string(m_convList.kouho.at(m_convList.pos).kanji);
1524 m_preeditor->reset();
1525 updatePreEditor();
1526 return process_preedit_key_event(key);
1527 }
1528
1529
1530
move_preedit_caret(unsigned int pos)1531 void HonokaInstance::move_preedit_caret (unsigned int pos)
1532 {
1533 //if (!m_conversion) m_preeditor->setPos(pos);
1534 //update_preedit_caret(pos);
1535 }
1536
select_candidate(unsigned int item)1537 void HonokaInstance::select_candidate (unsigned int item)
1538 {
1539 if (!m_lookup_table.number_of_candidates()) return;
1540
1541 int p = m_lookup_table.get_current_page_start() + item;
1542 m_convList.pos = p;
1543 if ((!m_no_update) && (m_conversion)) m_convertor->select(m_convList.pos);
1544 if (m_convList.kType != PREDICTION) {
1545 updateConvertedString();
1546 } else {
1547 update_preedit_string(m_convList.kouho.at(m_convList.pos).kanji);
1548 update_preedit_caret(0);
1549 if (!m_prediction) {
1550 // マウスで選択した場合は予測選択モードに突入。
1551 m_prediction = true;
1552 show_preedit_string();
1553 updateProperty();
1554 }
1555 }
1556 m_lookup_table.set_cursor_pos(m_convList.pos);
1557 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1558 show_aux_string();
1559 update_lookup_table(m_lookup_table);
1560 }
1561
update_lookup_table_page_size(unsigned int page_size)1562 void HonokaInstance::update_lookup_table_page_size (unsigned int page_size)
1563 {
1564 m_lookup_table.set_page_size (page_size);
1565 }
1566
lookup_table_page_up()1567 void HonokaInstance::lookup_table_page_up ()
1568 {
1569 if (!m_lookup_table.number_of_candidates () || !m_lookup_table.get_current_page_start ()) return;
1570
1571 int p = m_convList.pos - m_lookup_table.get_current_page_size();
1572 if (p < 0) p = 0;
1573 m_convList.pos = p;
1574 if ((!m_no_update) && (m_conversion)) m_convertor->select(m_convList.pos);
1575 if (m_conversion) updateConvertedString();
1576 if (m_prediction) {
1577 update_preedit_string(m_convList.kouho[m_convList.pos].kanji);
1578 update_preedit_caret(0);
1579 }
1580 m_lookup_table.set_cursor_pos(m_convList.pos);
1581 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1582 show_aux_string();
1583 update_lookup_table(m_lookup_table);
1584 }
1585
lookup_table_page_down()1586 void HonokaInstance::lookup_table_page_down ()
1587 {
1588 if (!m_lookup_table.number_of_candidates () ||
1589 m_lookup_table.get_current_page_start () + m_lookup_table.get_current_page_size () >=
1590 m_lookup_table.number_of_candidates ())
1591 return;
1592
1593 int p = m_convList.pos + m_lookup_table.get_current_page_size();
1594 if (p >= m_convList.count()) p = m_convList.count() - 1;
1595 m_convList.pos = p;
1596 if ((!m_no_update) && (m_conversion)) m_convertor->select(m_convList.pos);
1597 if (m_conversion) updateConvertedString();
1598 if (m_prediction) {
1599 update_preedit_string(m_convList.kouho[m_convList.pos].kanji);
1600 update_preedit_caret(0);
1601 }
1602 m_lookup_table.set_cursor_pos(m_convList.pos);
1603 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1604 show_aux_string();
1605 update_lookup_table(m_lookup_table);
1606 }
1607
reset()1608 void HonokaInstance::reset ()
1609 {
1610 // Qt-immodule+scim-qtimmではこのメソッドが大量に呼ばれるようだが、他ではどうなのか?。
1611 alp_count = 0;
1612 m_conversion = false;
1613 m_lookup = false;
1614 m_convertor->reset();
1615 m_preeditor->reset();
1616 }
1617
focus_in()1618 void HonokaInstance::focus_in ()
1619 {
1620 if (!m_conversion) updatePreEditor();
1621 else updateProperty();
1622 }
1623
focus_out()1624 void HonokaInstance::focus_out ()
1625 {
1626 // フォーカスを失った時は全てコミット!。
1627 if (m_conversion) {
1628 commit_string(getConvertedText());
1629 m_convertor->updateFrequency();
1630 if (prediction) if (m_predictor->isConnected()) m_predictor->update(getConvertedText(),m_preeditor->getText(true));
1631 m_convertor->reset();
1632 if (m_def_convertor != m_convertor) m_convertor = m_def_convertor;
1633 m_conversion = false;
1634 m_lookup = false;
1635 alp_count = 0;
1636 } else if (m_prediction) {
1637 m_prediction = false;
1638 commit_string(m_convList.kouho.at(m_convList.pos).kanji);
1639 m_preeditor->reset();
1640 }else if (m_preeditor->getTextLength()) {
1641 commit_string(m_preeditor->getText(true));
1642 }
1643 m_preeditor->reset();
1644 updatePreEditor();
1645 }
1646
trigger_property(const String & property)1647 void HonokaInstance::trigger_property (const String &property)
1648 {
1649 String s = HONOKA_PROP_INPUTMODE;
1650 if ((property.length() > s.length()) && (property.substr(0,s.length()) == s)) {
1651 changePreEditor(property.substr(s.length() + 1));
1652 updateProperty();
1653 }
1654
1655 s = HONOKA_PROP_PREDICTOR;
1656 if ((property.length() > s.length()) && (property.substr(0,s.length()) == s)) {
1657 changePredictor(property.substr(s.length() + 1));
1658 updateProperty();
1659 }
1660
1661 s = HONOKA_PROP_CONVERTOR;
1662 if ((property.length() > s.length()) && (property.substr(0,s.length()) == s)) {
1663 changeConvertor(property.substr(s.length() + 1));
1664 if (m_conversion) {
1665 if (m_def_convertor != m_convertor) {
1666 m_def_convertor->reset();
1667 startConversion();
1668 }
1669 }
1670 updateProperty();
1671 }
1672
1673 s = HONOKA_PROP_SPLITTER;
1674 if ((property.length() > s.length()) && (property.substr(0,s.length()) == s)) {
1675 changeSplitter(property.substr(s.length() + 1));
1676 updateProperty();
1677 }
1678
1679 s = HONOKA_PROP_CONVERSIONMODE;
1680 if (property == s) {
1681 auto_conversion ? auto_conversion = false : auto_conversion = true;
1682 updatePreEditor();
1683 }
1684 }
1685
1686
1687
1688
1689
1690
1691 /*!
1692 \fn HonokaInstance::startConversion(WideString s,bool multi)
1693 */
startConversion(WideString s,bool multi)1694 void HonokaInstance::startConversion(WideString s,bool multi)
1695 {
1696 // 変換開始処理。
1697 // 一度lookupは消しておこう。
1698 m_def_convertor = m_convertor;
1699 if (multi) m_convertor = m_multi;
1700 if (!s.length()) s = yomi;
1701 else yomi = s;
1702 vector<Segment> spsegs;
1703 m_lookup = false;
1704 m_lookup_table.clear();
1705 hide_lookup_table();
1706
1707 hide_aux_string();
1708
1709 if (m_splitter && (m_splitter != m_convertor) && (!multi)) {
1710 m_convertor->unSelected();
1711 m_splitter->selected();
1712 if (!m_splitter->isConnected()) {
1713 if (!m_splitter->connect()) {
1714 m_splitter->unSelected();
1715 update_aux_string(utf8_mbstowcs(String(_("could not connect to server."))));
1716 show_aux_string();
1717 return;
1718 }
1719 }
1720 m_splitter->setYomiText(s);
1721 if (m_splitter->ren_conversion() <= 0) {
1722 update_aux_string(utf8_mbstowcs(String(_("The error was received from Converter. "))));
1723 show_aux_string();
1724 return;
1725 }
1726 spsegs = m_splitter->getSegmentList();
1727 m_splitter->reset();
1728 m_splitter->unSelected();
1729 m_convertor->selected();
1730 s.clear();
1731 for(unsigned int i = 0;i < spsegs.size();i ++) s += spsegs[i].getYomi();
1732 }
1733
1734 if (!m_convertor->isConnected()) {
1735 if (!m_convertor->connect()) {
1736 update_aux_string(utf8_mbstowcs(String(_("could not connect to server."))));
1737 show_aux_string();
1738 m_convertor = m_def_convertor;
1739 return;
1740 }
1741 }
1742
1743 m_convertor->setYomiText(s);
1744 if (m_convertor->ren_conversion() <= 0) {
1745 update_aux_string(utf8_mbstowcs(String(_("The error was received from Converter. "))));
1746 show_aux_string();
1747 m_convertor = m_def_convertor;
1748 return;
1749 }
1750
1751 if (m_splitter && (m_splitter != m_convertor) && (!multi)) {
1752 // aline
1753 for(unsigned int i = 0;i < spsegs.size();i ++) {
1754 int bl = spsegs[i].getYomi().length();
1755 int cl = m_convertor->getResultList(i).Yomi.length();
1756 if (bl != cl) {
1757 bool t = m_convertor->resizeRegion(bl - cl);
1758 if (!t) {
1759 update_aux_string(utf8_mbstowcs(String(_("The error was received from Converter. "))));
1760 m_convertor->reset();
1761 show_aux_string();
1762 return;
1763 }
1764 }
1765 m_convertor->setPos(0);
1766 }
1767 }
1768
1769 m_no_update = false;
1770 m_convList.kouho.clear();
1771 m_convList = m_convertor->getResultList();
1772 m_conversion = true;
1773 segments = m_convertor->getSegmentList();
1774
1775 alp_count = 1;
1776
1777 show_preedit_string();
1778 updateConvertedString();
1779 if (alp == -1) {
1780 startLookup();
1781 }
1782 updateProperty();
1783 }
1784
1785
1786 /*!
1787 \fn HonokaInstance::autoConversion()
1788 */
autoConversion()1789 void HonokaInstance::autoConversion()
1790 {
1791 // 自動変換処理コード。
1792 if (!m_convertor->isConnected()) {
1793 if (!m_convertor->connect()) {
1794 update_aux_string(utf8_mbstowcs(String(_("could not connect to server."))));
1795 show_aux_string();
1796 show_preedit_string();
1797 update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
1798 update_preedit_caret(m_preeditor->getPos());
1799 return;
1800 }
1801 }
1802
1803 m_convertor->reset();
1804 m_convertor->setYomiText(m_preeditor->getText(true));
1805 if (m_convertor->ren_conversion() <= 0) {
1806 update_aux_string(utf8_mbstowcs(String(_("could not connect to server."))));
1807 show_aux_string();
1808 show_preedit_string();
1809 update_preedit_string(m_preeditor->getText(),m_preeditor->getAttributeList());
1810 update_preedit_caret(m_preeditor->getPos());
1811 return;
1812 }
1813 segments = m_convertor->getSegmentList();
1814 WideString t;
1815 for(unsigned int i = 0;i < segments.size();i ++) t += segments[i].getKanji();
1816 show_preedit_string();
1817 update_preedit_string(t);
1818 update_preedit_caret(t.length());
1819 }
1820
1821
1822 /*!
1823 \fn HonokaInstance::createLookupTable(ResultList cList)
1824 */
createLookupTable(ResultList cList)1825 void HonokaInstance::createLookupTable(ResultList cList)
1826 {
1827 // 候補一覧を作る。
1828 hide_lookup_table();
1829 m_lookup_table.clear();
1830 if (!cList.count()) return;
1831 for (unsigned int i = 0;i < cList.count();i ++) {
1832 if (cList.kouho.at(i).label.length()) m_lookup_table.append_candidate(cList.kouho.at(i).label);
1833 else m_lookup_table.append_candidate(cList.kouho.at(i).kanji);
1834 }
1835 m_lookup_table.set_cursor_pos(cList.pos);
1836 update_aux_string(cList.Title + getPosPerCount(cList.pos,cList.count()));
1837 show_aux_string();
1838 update_lookup_table(m_lookup_table);
1839 }
1840
1841
1842 /*!
1843 \fn HonokaInstance::startLookup()
1844 */
startLookup()1845 void HonokaInstance::startLookup()
1846 {
1847 // 候補一覧を表示する。
1848 createLookupTable(m_convList);
1849 if (m_convList.count() == 0) {
1850 m_lookup = false;
1851 return;
1852 }
1853 m_lookup = true;
1854 update_aux_string(m_convList.Title + getPosPerCount(m_convList.pos,m_convList.count()));
1855 show_aux_string();
1856 show_lookup_table();
1857 }
1858
1859
1860 /*!
1861 \fn HonokaInstance::getPosPerCount(int p,int c)
1862 */
getPosPerCount(int p,int c)1863 WideString HonokaInstance::getPosPerCount(int p,int c)
1864 {
1865 char data[256];
1866 sprintf(data," [%d/%d]",p + 1,c);
1867 return utf8_mbstowcs(String(data));
1868 }
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 /*!
1879 \fn HonokaInstance::timerEvent(int id)
1880 */
timerEvent(int id)1881 void HonokaInstance::timerEvent(int id)
1882 {
1883 for(unsigned int i = 0;i < preeditors.size();i ++) {
1884 if (preeditors[i]->findTimerEventId(id)) {
1885 preeditors[i]->timerEvent(id);
1886 //if ((!m_conversion) && (!m_prediction)) updatePreEditor();
1887 return;
1888 }
1889 }
1890 for(unsigned int i = 0;i < convertors.size();i ++) {
1891 if (convertors[i]->findTimerEventId(id)) {
1892 convertors[i]->timerEvent(id);
1893 return;
1894 }
1895 }
1896 for(unsigned int i = 0;i < predictors.size();i ++) {
1897 if (predictors[i]->findTimerEventId(id)) {
1898 predictors[i]->timerEvent(id);
1899 return;
1900 }
1901 }
1902 if ((id == preeditKeyDelay) && (!m_conversion) && (!m_prediction)) {
1903 WideString w = m_preeditor->getText();
1904 if (!w.length()) {
1905 hide_lookup_table();
1906 return;
1907 }
1908 m_convList = m_predictor->getPredictionList(w);
1909 m_convList.Yomi = w;
1910 if (m_convList.count()) {
1911 m_lookup_table.clear();
1912 for(unsigned int i = 0;i < m_convList.count();i ++) {
1913 m_lookup_table.append_candidate(m_convList.kouho.at(i).kanji);
1914 }
1915 if (w == m_preeditor->getText()) {
1916 startLookup();
1917 hide_aux_string();
1918 }
1919 else hide_lookup_table();
1920 } else {
1921 //m_lookup_table.clear();
1922 hide_lookup_table();
1923 }
1924 }
1925 }
1926
1927
1928
1929
1930
1931