e3557e8d91c7dd8da9563f31935bc0cf95fe34a1
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / scim / src / sunpinyin_imengine.cpp
1 /*
2  * Copyright (c) 2007 Kov Chai <tchaikov@gmail.com>
3  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4  *
5  * The contents of this file are subject to the terms of either the GNU Lesser
6  * General Public License Version 2.1 only ("LGPL") or the Common Development and
7  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
8  * file except in compliance with the License. You can obtain a copy of the CDDL at
9  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
10  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the 
11  * specific language governing permissions and limitations under the License. When
12  * distributing the software, include this License Header Notice in each file and
13  * include the full text of the License in the License file as well as the
14  * following notice:
15  * 
16  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
17  * (CDDL)
18  * For Covered Software in this distribution, this License shall be governed by the
19  * laws of the State of California (excluding conflict-of-law provisions).
20  * Any litigation relating to this License shall be subject to the jurisdiction of
21  * the Federal Courts of the Northern District of California and the state courts
22  * of the State of California, with venue lying in Santa Clara County, California.
23  * 
24  * Contributor(s):
25  * 
26  * If you wish your version of this file to be governed by only the CDDL or only
27  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
28  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
29  * license." If you don't indicate a single choice of license, a recipient has the
30  * option to distribute your version of this file under either the CDDL or the LGPL
31  * Version 2.1, or to extend the choice of license to its licensees as provided
32  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
33  * Version 2 license, then the option applies only if the new code is made subject
34  * to such option by the copyright holder. 
35  *
36  * Modifications by Samsung Electronics Co., Ltd.
37  *
38  * 1.Added always candidate show feature
39  * 2.Added auto commit feature for mobile user
40  */
41
42 #define Uses_STL_AUTOPTR
43 #define Uses_STL_FUNCTIONAL
44 #define Uses_STL_VECTOR
45 #define Uses_STL_IOSTREAM
46 #define Uses_STL_FSTREAM
47 #define Uses_STL_ALGORITHM
48 #define Uses_STL_MAP
49 #define Uses_STL_UTILITY
50 #define Uses_STL_IOMANIP
51 #define Uses_C_STDIO
52 #define Uses_SCIM_UTILITY
53 #define Uses_SCIM_IMENGINE
54 #define Uses_SCIM_ICONV
55 #define Uses_SCIM_CONFIG_BASE
56 #define Uses_SCIM_CONFIG_PATH
57 #define Uses_SCIM_LOOKUP_TABLE
58 #define Uses_SCIM_DEBUG
59
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <unistd.h>
63
64 #include <Ecore_IMF.h>
65
66 #include <imi_options.h>
67 #include <imi_view.h>
68 #include <ic_history.h>
69
70 #include <scim.h>
71
72 #include "imi_scimwin.h"
73 #include "sunpinyin_utils.h"
74 #include "sunpinyin_keycode.h"
75 #include "sunpinyin_lookup_table.h"
76 #include "sunpinyin_imengine.h"
77 #include "sunpinyin_imengine_config_keys.h"
78 #include "sunpinyin_private.h"
79
80 #define SCIM_PROP_STATUS                  "/IMEngine/SunPinyin/Status"
81 #define SCIM_PROP_LETTER                  "/IMEngine/SunPinyin/Letter"
82 #define SCIM_PROP_PUNCT                   "/IMEngine/SunPinyin/Punct"
83
84 #ifndef SCIM_SUNPINYIN_DATADIR
85     #define SCIM_SUNPINYIN_DATADIR            "/usr/share/scim/sunpinyin"
86 #endif
87
88 #ifndef SCIM_ICONDIR
89     #define SCIM_ICONDIR                      "/usr/share/scim/icons"
90 #endif
91
92 #ifndef SCIM_SUNPINYIN_ICON_FILE
93     #define SCIM_SUNPINYIN_ICON_FILE       (SCIM_ICONDIR "/sunpinyin_logo.png")
94 #endif
95
96 #define SCIM_FULL_LETTER_ICON              (SCIM_ICONDIR "/full-letter.png")
97 #define SCIM_HALF_LETTER_ICON              (SCIM_ICONDIR "/half-letter.png")
98 #define SCIM_FULL_PUNCT_ICON               (SCIM_ICONDIR "/full-punct.png")
99 #define SCIM_HALF_PUNCT_ICON               (SCIM_ICONDIR "/half-punct.png")
100
101 using namespace scim;
102
103 static IMEngineFactoryPointer _scim_pinyin_factory (0); 
104
105 static ConfigPointer _scim_config (0);
106
107 static Property _status_property   (SCIM_PROP_STATUS, "");
108 static Property _letter_property   (SCIM_PROP_LETTER, "");
109 static Property _punct_property    (SCIM_PROP_PUNCT, "");
110
111 static char g_common_symbol[]={'#','$','%','^','&','*','@'};
112
113 extern "C" {
114     void scim_module_init (void)
115     {
116         SCIM_DEBUG_IMENGINE (3) << "scim_module_init\n";
117         bindtextdomain (GETTEXT_PACKAGE, SCIM_SUNPINYIN_LOCALEDIR);
118         bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
119     }
120
121     void scim_module_exit (void)
122     {
123         _scim_pinyin_factory.reset ();
124         _scim_config.reset ();
125     }
126
127     uint32 scim_imengine_module_init (const ConfigPointer &config)
128     {
129         SCIM_DEBUG_IMENGINE (3) << "module_init\n";
130         _status_property.set_tip (_("The status of the current input method. Click to change it."));
131         _status_property.set_label ("英");
132         
133         _letter_property.set_icon (SCIM_HALF_LETTER_ICON);
134         _letter_property.set_tip (_("The input mode of the letters. Click to toggle between half and full."));
135         _letter_property.set_label (_("Full/Half Letter"));
136
137         _punct_property.set_icon (SCIM_HALF_PUNCT_ICON);
138         _punct_property.set_tip (_("The input mode of the puncutations. Click to toggle between half and full."));
139         _punct_property.set_label (_("Full/Half Punct"));
140
141         _scim_config = config;
142         return 1;
143     }
144
145     IMEngineFactoryPointer scim_imengine_module_create_factory (uint32 engine)
146     {
147         SCIM_DEBUG_IMENGINE (3) << "entering scim_imengine_module_create_factory()\n";
148         if (engine != 0) return IMEngineFactoryPointer (0);
149         if (_scim_pinyin_factory.null ()) {
150             SunPyFactory *factory = new SunPyFactory (_scim_config); 
151             if (factory->valid ())
152                 _scim_pinyin_factory = factory;
153             else
154                 delete factory;
155         }
156         return _scim_pinyin_factory;
157     }
158 }
159
160 // implementation of SunPyFactory
161 SunPyFactory::SunPyFactory (const ConfigPointer &config)
162     : m_config (config),
163       m_valid (false)
164 {
165     SCIM_DEBUG_IMENGINE (3) << "SunPyFactory()\n";
166     set_languages ("zh_CN");
167     m_name = utf8_mbstowcs ("SunPinyin");
168     m_valid = init ();
169     m_reload_signal_connection = m_config->signal_connect_reload (slot (this, &SunPyFactory::reload_config));
170     m_hotkey_profile = new CHotkeyProfile();
171 }
172
173 bool
174 SunPyFactory::init ()
175 {
176     bool valid = true;
177     
178     if (m_config) {
179         valid = load_user_config();
180     }
181     
182     // postpone the load_user_data() to the ctor of SunPyInstance
183     return valid;
184 }
185
186 bool
187 SunPyFactory::load_user_config()
188 {
189     // Load configurations.
190
191     return true;
192 }
193
194 SunPyFactory::~SunPyFactory ()
195 {
196     SCIM_DEBUG_IMENGINE (3) << "~SunPyFactory()\n";
197     m_reload_signal_connection.disconnect ();
198     delete m_hotkey_profile;
199 }
200
201 WideString
202 SunPyFactory::get_name () const
203 {
204     return m_name;
205 }
206
207 WideString
208 SunPyFactory::get_authors () const
209 {
210     return utf8_mbstowcs (
211                 String (_("Lei Zhang, <Phill.Zhang@sun.com>; Shuguagn Yan, <Ervin.Yan@sun.com>")));
212 }
213
214 WideString
215 SunPyFactory::get_credits () const
216 {
217     return utf8_mbstowcs (
218         String (_("Ported by Kov Chai, <tchaikov@gmail.com>")));
219 }
220
221 WideString
222 SunPyFactory::get_help () const
223 {
224     String help =
225         String (_("Hot Keys:"
226                   "\n\n  Shift+Alt:\n"
227                   "    Switch between English/Chinese mode."
228                   "\n\n  Control+period:\n"
229                   "    Switch between full/half width punctuation mode."
230                   "\n\n  Shift+space:\n"
231                   "    Switch between full/half width letter mode."
232                   "\n\n  PageUp:\n"
233                   "    Page up in lookup table."
234                   "\n\n  PageDown:\n"
235                   "    Page down in lookup table."
236                   "\n\n  Esc:\n"
237                   "    Cancel current syllable.\n"));
238     return utf8_mbstowcs (help);
239 }
240
241 String
242 SunPyFactory::get_uuid () const
243 {
244     return String ("org.tizen.ise-engine-sunpinyin");
245 }
246
247 String
248 SunPyFactory::get_icon_file () const
249 {
250     return String (SCIM_SUNPINYIN_ICON_FILE);
251 }
252
253 IMEngineInstancePointer
254 SunPyFactory::create_instance (const String& encoding, int id)
255 {
256     SCIM_DEBUG_IMENGINE (3) <<  "SunPyFactory::create_instance(" << id << ")\n";    
257     return new SunPyInstance (this, m_hotkey_profile, encoding, id);
258 }
259
260 void
261 SunPyFactory::reload_config (const ConfigPointer &config)
262 {
263     m_config = config;
264     m_valid = init ();
265 }
266
267 // implementation of SunPyInstance
268 SunPyInstance::SunPyInstance (SunPyFactory *factory,
269                               CHotkeyProfile *hotkey_profile,
270                               const String& encoding,
271                               int id)
272     : IMEngineInstanceBase (factory, encoding, id),
273       m_factory (factory),
274       m_pv (0),
275       m_wh (0),
276       m_hotkey_profile (hotkey_profile),
277       m_lookup_table (0),
278       m_common_lookup_table(0),
279       m_focused (false),
280       m_lookup_table_always_on (false)
281 {
282     SCIM_DEBUG_IMENGINE (3) << get_id() << ": SunPyInstance()\n";
283     create_session(hotkey_profile);
284     if (!m_pv) return;
285     m_reload_signal_connection = factory->m_config->signal_connect_reload (slot (this, &SunPyInstance::reload_config));
286     init_lookup_table_labels ();
287 }
288
289 SunPyInstance::~SunPyInstance ()
290 {
291     SCIM_DEBUG_IMENGINE (3) <<  get_id() << ": ~SunPyInstance()\n";
292     m_reload_signal_connection.disconnect ();
293     destroy_session();
294 }
295
296 static CKeyEvent
297 translate_key(const KeyEvent& key)
298 {
299     // XXX: may need to move this logic into CKeyEvent
300     if (!(key.code & 0xff00) && isprint(key.code) && !isspace(key.code) && !(key.mask & IM_CTRL_MASK)) {
301         // we only care about key_val here
302         return CKeyEvent(0, key.code, key.mask);
303     } else {
304         // what matters is key_code, but ibus sents me key_code as key_val
305         return CKeyEvent(key.code, 0, key.mask);
306     }
307 }
308
309 bool
310 SunPyInstance::process_key_event (const KeyEvent& key)
311 {
312     SCIM_DEBUG_IMENGINE (3) <<  get_id() << ": process_key_event(" << m_focused << ", "  <<
313         key.code << ", " <<
314         key.mask << ", " <<
315         key.layout << ")\n";
316         
317     if (!m_focused) return false;
318
319     CKeyEvent ev = translate_key(key);
320     
321     if ( !m_pv->getStatusAttrValue(CScimWinHandler::STATUS_ID_CN) ) {
322         // we are in English input mode
323         if ( !m_hotkey_profile->isModeSwitchKey(ev) ) {
324             m_hotkey_profile->rememberLastKey(ev);
325             return false;
326         }
327     }
328     return ( key.is_key_release() ||
329              m_pv->onKeyEvent(ev) );
330 }
331
332 void
333 SunPyInstance::select_candidate (unsigned int item)
334 {
335     if(m_lookup_table->number_of_candidates() == 0 && item < sizeof(g_common_symbol)/sizeof(char)) {
336         char _str[2]={g_common_symbol[item],0};
337         commit_string(utf8_mbstowcs(_str));
338         return;
339     }
340     m_pv->onCandidateSelectRequest(item);
341 //  m_pv->makeSelection(item);
342 }
343
344 void
345 SunPyInstance::update_lookup_table_page_size (unsigned int page_size)
346 {
347     if (page_size > 0) {
348         SCIM_DEBUG_IMENGINE (3) << ": update_lookup_table_page_size(" << page_size << ")\n";
349         m_pv->setCandiWindowSize(page_size);
350         m_lookup_table->set_page_size(page_size);
351     }
352 }
353
354 void
355 SunPyInstance::lookup_table_page_up ()
356 {
357     lookup_page_up();
358     m_pv->onCandidatePageRequest(-1, true);
359 }
360
361 void
362 SunPyInstance::lookup_page_up()
363 {
364     m_lookup_table->page_up();
365     //    m_lookup_table->set_page_size(m_pv->s_CandiWindowSize);
366 }
367
368 void
369 SunPyInstance::lookup_page_down()
370 {
371     m_lookup_table->page_down();
372     //    m_lookup_table->set_page_size(m_pv->s_CandiWindowSize);
373 }
374
375 void
376 SunPyInstance::lookup_table_page_down ()
377 {
378     // XXX, it would be great, if View class expose a page_up() method
379     //    m_pv->onKeyEvent(IM_VK_PAGE_DOWN, 0, 0);
380     // classic View overrides this method
381     // but modern View uses the default dummy implementation
382     lookup_page_down ();
383     m_pv->onCandidatePageRequest(1, true);
384 }
385
386 void
387 SunPyInstance::move_preedit_caret (unsigned int /*pos*/)
388 {
389 }
390
391 void
392 SunPyInstance::reset ()
393 {
394     SCIM_DEBUG_IMENGINE (3) << get_id() << ": reset()\n";
395     flush();
396     m_lookup_table->clear ();
397     hide_preedit_string ();
398     //hide_aux_string ();
399     //m_pv->updateWindows(m_pv->clearIC());
400     //refresh_all_properties ();
401     if (m_lookup_table_always_on) {
402         if (m_focused)
403             show_lookup_table ();
404     } else {
405         hide_lookup_table ();
406     }
407     m_pv->updateWindows(CIMIView::PREEDIT_MASK | CIMIView::CANDIDATE_MASK);
408 }
409
410 void
411 SunPyInstance::focus_in ()
412 {
413     SCIM_DEBUG_IMENGINE(3) << get_id() << ": focus_in ()\n";
414     m_focused = true;
415     //show_lookup_table ();
416     initialize_all_properties ();
417     
418     hide_preedit_string ();
419     //hide_aux_string ();
420     
421     init_lookup_table_labels ();
422     
423     //hide_aux_string ();
424
425     m_pv->updateWindows(CIMIView::PREEDIT_MASK | CIMIView::CANDIDATE_MASK);
426 }
427
428 void
429 SunPyInstance::focus_out ()
430 {
431     SCIM_DEBUG_IMENGINE(3) << get_id() << ": focus_out ()\n";
432     m_focused = false;
433 }
434
435 void
436 SunPyInstance::flush ()
437 {
438     SCIM_DEBUG_IMENGINE(3) << get_id() << ": flush ()\n";
439     m_pv->onCandidateSelectRequest(0);
440 }
441
442 void
443 SunPyInstance::trigger_property (const String &property)
444 {
445     SCIM_DEBUG_IMENGINE (3) << get_id() << ": trigger_property(" << property << ")\n";
446     
447     if (property == SCIM_PROP_STATUS) {
448         const int is_CN = m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_CN);
449         m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, is_CN?0:1);
450     } else if (property == SCIM_PROP_LETTER) {
451         const int is_fullsymbol = m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL);
452         m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, is_fullsymbol?0:1);
453     } else if (property == SCIM_PROP_PUNCT) {
454         const int is_fullpunc = m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC);
455         m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, is_fullpunc?0:1);
456     }
457 }
458
459 void
460 SunPyInstance::set_layout (unsigned int layout)
461 {
462     switch (layout)
463     {
464         case ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL:
465         case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
466         case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
467         case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
468             show_lookup_table ();
469             m_lookup_table_always_on = true;
470             break;
471         case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
472         case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
473         case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
474         case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
475             hide_lookup_table ();
476             m_lookup_table_always_on = false;
477             break;
478     }
479 }
480
481 void
482 SunPyInstance::init_lookup_table_labels ()
483 {
484     m_pv->setCandiWindowSize(10);
485     m_lookup_table->set_page_size (10);
486     m_lookup_table->show_cursor ();
487 }
488
489 void
490 SunPyInstance::initialize_all_properties ()
491 {
492     PropertyList proplist;
493
494     proplist.push_back (_status_property);
495     proplist.push_back (_letter_property);
496     proplist.push_back (_punct_property);
497
498     register_properties (proplist);
499     refresh_all_properties ();
500 }
501
502 void
503 SunPyInstance::refresh_all_properties ()
504 {
505     SCIM_DEBUG_IMENGINE (3) << get_id() << ": refresh_all_properties()\n";
506     m_wh->updateStatus(CIMIWinHandler::STATUS_ID_CN,
507                        m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_CN));
508     m_wh->updateStatus(CIMIWinHandler::STATUS_ID_FULLPUNC,
509                        m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC));
510     m_wh->updateStatus(CIMIWinHandler::STATUS_ID_FULLSYMBOL, 
511                        m_pv->getStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL));
512 }
513
514
515 void
516 SunPyInstance::refresh_status_property(bool cn)
517 {
518     SCIM_DEBUG_IMENGINE (3) << get_id() << ": refresh_status_property(" << cn << ")\n";
519     if (!cn) {
520         reset();
521     }
522     _status_property.set_label(cn ? "中" : "英");
523     update_property(_status_property);
524 }
525
526 void
527 SunPyInstance::refresh_fullsymbol_property(bool full)
528 {
529     SCIM_DEBUG_IMENGINE (3) << get_id() << ": refresh_fullsimbol_property(" << full << ")\n";
530     _letter_property.set_icon(
531         full ? SCIM_FULL_LETTER_ICON : SCIM_HALF_LETTER_ICON);
532     update_property(_letter_property);
533 }
534
535 void
536 SunPyInstance::refresh_fullpunc_property(bool full)
537 {
538     _punct_property.set_icon(
539         full ? SCIM_FULL_PUNCT_ICON : SCIM_HALF_PUNCT_ICON);
540     update_property(_punct_property);
541 }
542
543 void
544 SunPyInstance::create_session(CHotkeyProfile *hotkey_profile)
545 {
546     SCIM_DEBUG_IMENGINE (3) << get_id() <<  ": create_session()\n";
547     AttributeList attrs;
548     CSunpinyinSessionFactory& factory = CSunpinyinSessionFactory::getFactory();
549     factory.setPinyinScheme(CSunpinyinSessionFactory::QUANPIN);
550     factory.setCandiWindowSize(10);
551     m_pv = factory.createSession();
552     if (!m_pv) {
553         SCIM_DEBUG_IMENGINE (3) << get_id() <<  " factory.createSession() failed\n";
554         return;
555     }
556     
557     m_pv->setHotkeyProfile(hotkey_profile);
558
559     m_lookup_table = new SunLookupTable();
560     m_common_lookup_table = new CommonLookupTable();
561     for(int i = 0;i < sizeof(g_common_symbol)/sizeof(char);i++) {
562         char _str[2]={g_common_symbol[i],0};
563         m_common_lookup_table->append_candidate (utf8_mbstowcs ((const char*)_str),attrs);
564     }
565     m_wh = new CScimWinHandler(this, m_lookup_table);
566     m_pv->attachWinHandler(m_wh);
567 }
568
569 void
570 SunPyInstance::destroy_session()
571 {
572     SCIM_DEBUG_IMENGINE (3) << get_id() <<  ": destroy_session()\n";
573     
574     // wh and ic are not pointers, I don't think it's necessary to delete them
575     // either
576     delete m_pv;
577     delete m_wh;
578     delete m_lookup_table;
579     delete m_common_lookup_table;
580     
581     m_pv = 0;
582     m_wh = 0;
583     m_lookup_table = 0;
584 }
585
586 AttributeList
587 SunPyInstance::build_preedit_attribs (const IPreeditString* ppd)
588 {
589     AttributeList attrs;
590     const int sz = ppd->charTypeSize();
591     for (int i = 0; i < sz; ) {
592         const int ct = ppd->charTypeAt(i);
593         if (ct & IPreeditString::ILLEGAL) {
594             const int start = i;
595             for (++i; (i<sz) && (ppd->charTypeAt(i) & IPreeditString::ILLEGAL); ++i) ;
596             attrs.push_back( Attribute(start, i-start,
597                                        SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_REVERSE));
598         } else if (ct & IPreeditString::NORMAL_CHAR) {
599             if (ct & IPreeditString::USER_CHOICE) {
600                 const int start = i;
601                 for (++i; (i<sz) && (ppd->charTypeAt(i) & IPreeditString::USER_CHOICE); ++i) ;
602                 attrs.push_back( Attribute(start, i-start,
603                                            SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_UNDERLINE));
604             } else {
605                 ++i;
606             }
607         } else {
608             ++i;
609         }
610     }
611     return attrs;
612 }
613
614 void
615 SunPyInstance::redraw_preedit_string (const IPreeditString* ppd)
616 {
617     SCIM_DEBUG_IMENGINE (3) << get_id() <<  ": redraw_preedit_string()\n";
618     if (ppd->size() != 0) {
619         AttributeList attrs;
620         const int caret = ppd->caret();
621         if (caret > 0 && caret <= ppd->size()) {
622             attrs.push_back( Attribute(ppd->candi_start(),
623                                        ppd->charTypeSize(),
624                                        SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_REVERSE));
625         }
626         update_preedit_string( wstr_to_widestr(ppd->string(), ppd->size()) );
627         show_preedit_string ();
628         update_preedit_caret (caret);
629     } else {
630         hide_preedit_string ();
631     }
632 }
633
634 void
635 SunPyInstance::redraw_lookup_table(const ICandidateList* pcl)
636 {
637     SCIM_DEBUG_IMENGINE (3) << get_id() << ": redraw_lookup_table()\n";
638     
639     m_lookup_table->update(*pcl);
640     if (m_lookup_table->number_of_candidates()) {
641         update_lookup_table(*m_lookup_table);
642     } else {
643         update_lookup_table(*m_common_lookup_table);
644     }
645 }
646
647 void
648 SunPyInstance::reload_config(const ConfigPointer &config)
649 {
650     SCIM_DEBUG_IMENGINE (3) << get_id() << ": reload_config()\n";
651     reset();
652     if (m_factory->valid()) {
653         m_factory->load_user_config();
654     }
655 }