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