1 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
4 * Smart Common Input Method
6 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22 * Boston, MA 02111-1307 USA
24 * $Id: scim_backend.cpp,v 1.38.2.1 2006/09/24 16:00:52 suzhe Exp $
28 #define Uses_SCIM_FILTER_MANAGER
29 #define Uses_SCIM_BACKEND
30 #define Uses_SCIM_IMENGINE
31 #define Uses_SCIM_IMENGINE_MODULE
32 #define Uses_SCIM_CONFIG_PATH
33 #define Uses_STL_ALGORITHM
34 #define Uses_SCIM_PANEL_AGENT
39 #include "scim_private.h"
41 #include "scim_stl_map.h"
42 #include "isf_query_utility.h"
47 #if SCIM_USE_STL_EXT_HASH_MAP
48 typedef __gnu_cxx::hash_map <String, IMEngineFactoryPointer, scim_hash_string > IMEngineFactoryRepository;
49 #elif SCIM_USE_STL_HASH_MAP
50 typedef std::hash_map <String, IMEngineFactoryPointer, scim_hash_string > IMEngineFactoryRepository;
52 typedef std::map <String, IMEngineFactoryPointer> IMEngineFactoryRepository;
55 typedef std::vector <IMEngineFactoryPointer> IMEngineFactoryPointerVector;
62 LocaleEqual (const String &lhs) : m_lhs (lhs) { }
64 bool operator () (const String &rhs) const {
65 if (m_lhs == rhs) return true;
66 if (scim_get_locale_language (m_lhs) == scim_get_locale_language (rhs) &&
67 scim_get_locale_encoding (m_lhs) == scim_get_locale_encoding (rhs) &&
68 m_lhs.find ('.') != String::npos && rhs.find ('.') != String::npos)
74 class IMEngineFactoryPointerLess
77 bool operator () (const IMEngineFactoryPointer &lhs, const IMEngineFactoryPointer &rhs) const {
78 return (lhs->get_language () < rhs->get_language ()) ||
79 (lhs->get_language () == rhs->get_language () && lhs->get_name () < rhs->get_name ());
83 class BackEndBase::BackEndBaseImpl
85 IMEngineFactoryRepository m_factory_repository;
86 String m_supported_unicode_locales;
87 ConfigPointer m_config;
90 BackEndBaseImpl (const ConfigPointer &config)
95 /* Set the default supported locales. */
96 locales = scim_global_config_read (SCIM_GLOBAL_CONFIG_SUPPORTED_UNICODE_LOCALES, String ("en_US.UTF-8"));
98 std::vector <String> locale_list;
99 std::vector <String> real_list;
101 scim_split_string_list (locale_list, locales);
103 for (std::vector <String>::iterator i = locale_list.begin (); i!= locale_list.end (); ++i) {
104 *i = scim_validate_locale (*i);
105 if (i->length () && scim_get_locale_encoding (*i) == "UTF-8" &&
106 std::find_if (real_list.begin (), real_list.end (), LocaleEqual (*i)) == real_list.end ())
107 real_list.push_back (*i);
110 m_supported_unicode_locales = scim_combine_string_list (real_list);
115 m_factory_repository.clear ();
118 void dump_factories ()
120 IMEngineFactoryRepository::const_iterator it;
121 std::cout << "Factories in backend:" << std::endl;
122 for (it = m_factory_repository.begin (); it != m_factory_repository.end (); ++it) {
123 if (it->second.null ())
124 std::cout << "\t" << it->first << ": null" << std::endl;
126 std::cout << "\t" << it->first << ": valid" << std::endl;
130 String get_all_locales () const
134 std::vector <String> locale_list;
135 std::vector <String> real_list;
137 IMEngineFactoryRepository::const_iterator it;
139 for (it = m_factory_repository.begin (); it != m_factory_repository.end (); ++it) {
140 if (locale.length () == 0)
141 locale += it->second->get_locales ();
143 locale += (String (",") + it->second->get_locales ());
146 if (m_supported_unicode_locales.length ())
147 locale += (String (",") + m_supported_unicode_locales);
149 scim_split_string_list (locale_list, locale);
151 for (std::vector <String>::iterator i = locale_list.begin (); i!= locale_list.end (); i++) {
152 locale = scim_validate_locale (*i);
153 if (locale.length () &&
154 std::find_if (real_list.begin (), real_list.end (), LocaleEqual (locale)) == real_list.end ())
155 real_list.push_back (locale);
158 return scim_combine_string_list (real_list);
161 IMEngineFactoryPointer get_factory (const String &uuid) const
163 IMEngineFactoryRepository::const_iterator it = m_factory_repository.find (uuid);
165 if (it != m_factory_repository.end ())
168 return IMEngineFactoryPointer (0);
171 uint32 get_factories_for_encoding (std::vector<IMEngineFactoryPointer> &factories,
172 const String &encoding) const
174 IMEngineFactoryRepository::const_iterator it;
178 for (it = m_factory_repository.begin (); it != m_factory_repository.end (); ++it) {
179 if ((encoding.length () == 0 || it->second->validate_encoding (encoding)))
180 factories.push_back (it->second);
183 sort_factories (factories);
185 return factories.size ();
188 uint32 get_factories_for_language (std::vector<IMEngineFactoryPointer> &factories,
189 const String &language) const
191 IMEngineFactoryRepository::const_iterator it;
195 for (it = m_factory_repository.begin (); it != m_factory_repository.end (); ++it) {
196 if ((language.length () == 0 || it->second->get_language () == language))
197 factories.push_back (it->second);
200 sort_factories (factories);
202 return factories.size ();
205 uint32 get_factory_list (std::vector<String> &uuids) const
207 IMEngineFactoryRepository::const_iterator it;
208 for (it = m_factory_repository.begin (); it != m_factory_repository.end (); ++it)
209 uuids.push_back(it->first);
211 return m_factory_repository.size ();
214 IMEngineFactoryPointer get_default_factory (const String &language, const String &encoding) const
216 if (!language.length ()) return IMEngineFactoryPointer ();
218 IMEngineFactoryPointerVector factories;
220 if (get_factories_for_encoding (factories, encoding) > 0) {
221 IMEngineFactoryPointer lang_first;
222 IMEngineFactoryPointerVector::iterator it;
226 def_uuid = m_config->read (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) +
227 String ("/") + String ("~other"),
230 /* Match by Normalized language exactly. */
231 for (it = factories.begin (); it != factories.end (); ++it) {
232 if (scim_get_normalized_language ((*it)->get_language ()) == language && lang_first.null ())
235 if ((*it)->get_uuid () == def_uuid)
239 if (!lang_first.null ())
242 /* Match by short language name. */
243 for (it = factories.begin (); it != factories.end (); ++it)
244 if ((*it)->get_language () == language.substr (0,2))
247 return factories [0];
250 return IMEngineFactoryPointer ();
253 void set_default_factory (const String &language, const String &uuid)
255 if (!language.length () || !uuid.length ()) return;
257 IMEngineFactoryPointerVector factories;
258 if (get_factories_for_encoding (factories, "") > 0) {
259 IMEngineFactoryPointerVector::iterator it;
260 for (it = factories.begin (); it != factories.end (); ++it) {
261 if ((*it)->get_uuid () == uuid) {
262 m_config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other"), uuid);
270 IMEngineFactoryPointer get_next_factory (const String &language, const String &encoding, const String &cur_uuid) const
272 IMEngineFactoryPointerVector factories;
274 if (get_factories_for_encoding (factories, encoding) > 0) {
275 IMEngineFactoryPointer lang_first;
276 IMEngineFactoryPointerVector::iterator it, itl;
278 for (it = factories.begin (); it != factories.end (); ++it) {
279 if ((language.length () == 0 || (*it)->get_language () == language) && lang_first.null ())
282 if ((*it)->get_uuid () == cur_uuid) {
283 for (itl = it + 1; itl != factories.end (); ++itl) {
284 if (language.length () == 0 || (*itl)->get_language () == language)
287 if (!lang_first.null ()) return lang_first;
289 return factories [0];
294 return IMEngineFactoryPointer ();
297 IMEngineFactoryPointer get_previous_factory (const String &language, const String &encoding, const String &cur_uuid) const
299 IMEngineFactoryPointerVector factories;
301 if (get_factories_for_encoding (factories, encoding) > 0) {
302 IMEngineFactoryPointer lang_last;
303 IMEngineFactoryPointerVector::iterator it, itl;
305 for (it = factories.begin (); it != factories.end (); ++it) {
306 if ((language.length () == 0 || (*it)->get_language () == language))
310 for (it = factories.begin (); it != factories.end (); ++it) {
311 if ((*it)->get_uuid () == cur_uuid) {
312 for (itl = it; itl != factories.begin (); --itl) {
313 if (language.length () == 0 || (*(itl-1))->get_language () == language)
317 if (!lang_last.null ()) return lang_last;
319 return factories [factories.size () - 1];
324 return IMEngineFactoryPointer ();
327 bool add_factory (const IMEngineFactoryPointer &factory)
329 if (!factory.null ()) {
330 String uuid = factory->get_uuid ();
332 if (uuid.length ()) {
333 m_factory_repository [uuid] = factory;
341 void add_specific_factory (const String &uuid, const IMEngineFactoryPointer &factory)
343 m_factory_repository [uuid] = factory;
348 void sort_factories (std::vector<IMEngineFactoryPointer> &factories) const
350 std::sort (factories.begin (), factories.end (), IMEngineFactoryPointerLess ());
354 BackEndBase::BackEndBase (const ConfigPointer &config)
355 : m_impl (new BackEndBase::BackEndBaseImpl (config))
359 BackEndBase::~BackEndBase ()
365 BackEndBase::get_all_locales () const
367 return m_impl->get_all_locales ();
370 IMEngineFactoryPointer
371 BackEndBase::get_factory (const String &uuid) const
373 return m_impl->get_factory (uuid);
377 BackEndBase::get_factories_for_encoding (std::vector<IMEngineFactoryPointer> &factories, const String &encoding) const
379 return m_impl->get_factories_for_encoding (factories, encoding);
383 BackEndBase::get_factories_for_language (std::vector<IMEngineFactoryPointer> &factories, const String &language) const
385 return m_impl->get_factories_for_language (factories, language);
389 BackEndBase::get_factory_list (std::vector<String> &uuids) const
391 return m_impl->get_factory_list (uuids);
394 IMEngineFactoryPointer
395 BackEndBase::get_default_factory (const String &language, const String &encoding) const
397 return m_impl->get_default_factory (language, encoding);
401 BackEndBase::set_default_factory (const String &language, const String &uuid)
403 m_impl->set_default_factory (language, uuid);
406 IMEngineFactoryPointer
407 BackEndBase::get_next_factory (const String &language, const String &encoding, const String &cur_uuid) const
409 return m_impl->get_next_factory (language, encoding, cur_uuid);
412 IMEngineFactoryPointer
413 BackEndBase::get_previous_factory (const String &language, const String &encoding, const String &cur_uuid) const
415 return m_impl->get_previous_factory (language, encoding, cur_uuid);
419 BackEndBase::add_factory (const IMEngineFactoryPointer &factory)
421 return m_impl->add_factory (factory);
425 BackEndBase::add_specific_factory (const String &uuid,
426 const IMEngineFactoryPointer &factory)
428 m_impl->add_specific_factory (uuid, factory);
433 BackEndBase::clear ()
439 BackEndBase::dump_factories ()
441 m_impl->dump_factories ();
444 /* Implementation of CommonBackEnd. */
445 struct CommonBackEnd::CommonBackEndImpl {
446 std::vector<IMEngineModule *> m_engine_modules;
447 FilterManager *m_filter_manager;
448 std::vector<String> m_disabled_factories;
449 std::vector<String> m_modules;
450 std::map <String, String> m_factory_module_repository;
452 CommonBackEndImpl () : m_filter_manager (0) { }
455 CommonBackEnd::CommonBackEnd (const ConfigPointer &config,
456 const std::vector<String> &modules)
457 : BackEndBase (config),
458 m_impl (new CommonBackEndImpl)
462 CommonBackEnd::~CommonBackEnd ()
466 for (unsigned int i = 0; i < m_impl->m_engine_modules.size (); i++) {
467 if (m_impl->m_engine_modules [i]) {
468 m_impl->m_engine_modules [i]->unload ();
469 delete m_impl->m_engine_modules [i];
470 m_impl->m_engine_modules [i] = NULL;
473 delete m_impl->m_filter_manager;
478 CommonBackEnd::initialize (const ConfigPointer &config,
479 const std::vector<String> &modules,
480 const bool is_load_resource,
481 const bool is_load_info)
483 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << "...\n";
485 IMEngineFactoryPointer factory;
486 std::vector<String> new_modules = modules;
488 int all_factories_count = 0;
489 int module_factories_count = 0;
491 if (config.null ()) return;
493 /* Get disabled factories list. */
494 m_impl->m_disabled_factories = scim_global_config_read (SCIM_GLOBAL_CONFIG_DISABLED_IMENGINE_FACTORIES, m_impl->m_disabled_factories);
496 /* Put socket module to the end of list. */
497 if (new_modules.size () > 1) {
498 for (std::vector<String>::iterator it = new_modules.begin (); it != new_modules.end (); ++it) {
499 if (*it == "socket") {
500 new_modules.erase (it);
501 new_modules.push_back ("socket");
507 /* Try to load all IMEngine modules */
509 m_impl->m_filter_manager = new FilterManager (config);
510 } catch (const std::exception & err) {
511 std::cerr << err.what () << "\n";
515 factory = new ComposeKeyFactory ();
517 if (all_factories_count == 0 ||
518 std::find (m_impl->m_disabled_factories.begin (),
519 m_impl->m_disabled_factories.end (),
520 factory->get_uuid ()) == m_impl->m_disabled_factories.end ()) {
521 factory = m_impl->m_filter_manager->attach_filters_to_factory (factory);
522 add_factory (factory);
526 /*for (size_t i = 0; i < new_modules.size (); ++i)
527 add_module_info (config, new_modules [i]);*/
528 add_module_info_from_cache_file (config, new_modules);
532 /* load IMEngine modules */
533 for (size_t i = 0; i < new_modules.size (); ++i) {
534 module_factories_count = add_module (config, new_modules [i], is_load_resource);
535 all_factories_count += module_factories_count;
540 CommonBackEnd::add_module (const ConfigPointer &config,
542 bool is_load_resource)
544 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << module << "\n";
546 IMEngineFactoryPointer factory;
547 IMEngineModule *engine_module = NULL;
548 int module_factories_count = 0;
549 bool first_load = false;
551 if (config.null ()) return 0;
553 if (module.length () > 0) {
554 /* Check if the module is already loaded */
555 if (std::find (m_impl->m_modules.begin (), m_impl->m_modules.end (), module) == m_impl->m_modules.end ()) {
556 engine_module = new IMEngineModule;
557 m_impl->m_engine_modules.push_back (engine_module);
558 m_impl->m_modules.push_back (module);
559 engine_module->load (module, config);
562 for (size_t i = 0; i < m_impl->m_modules.size (); i++) {
563 if (m_impl->m_modules [i] == module) {
564 engine_module = m_impl->m_engine_modules [i];
570 if (engine_module && engine_module->valid ()) {
571 size_t number = engine_module->number_of_factories ();
572 for (size_t j = 0; j < number; ++j) {
574 /* Try to load a IMEngine Factory. */
576 factory = engine_module->create_factory (j);
577 } catch (const std::exception & err) {
578 std::cerr << err.what () << "\n";
582 if (!factory.null ()) {
583 /* Check if it's disabled. */
584 if (std::find (m_impl->m_disabled_factories.begin (),
585 m_impl->m_disabled_factories.end (),
586 factory->get_uuid ()) == m_impl->m_disabled_factories.end ()) {
588 /* Add it into disabled list to prevent from loading again. */
589 /*m_impl->m_disabled_factories.push_back (factory->get_uuid ());*/
591 if (is_load_resource)
592 factory->load_resource ();
594 /* Only load filter for none socket IMEngines. */
595 if (module != "socket")
596 factory = m_impl->m_filter_manager->attach_filters_to_factory (factory);
598 add_factory (factory);
600 module_factories_count ++;
602 SCIM_DEBUG_BACKEND (1) << " Loading IMEngine Factory " << j << " : " << "OK\n";
604 SCIM_DEBUG_BACKEND (1) << " Loading IMEngine Factory " << j << " : " << "Disabled\n";
608 std::cerr << " Loading IMEngine Factory " << module << "(" << j << ") is Failed!!!\n";
611 if (module_factories_count) {
612 SCIM_DEBUG_BACKEND (1) << module << " IMEngine module is successfully loaded.\n";
614 std::cerr << "No Factory loaded from " << module << " IMEngine module!!!\n";
616 engine_module->unload ();
619 std::cerr << __func__ << ": Failed to load " << module << " IMEngine module!!!\n";
620 engine_module->unload ();
624 return module_factories_count;
628 CommonBackEnd::add_module_info (const ConfigPointer &config, const String module_name)
630 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << module_name << "\n";
632 if (module_name.length () <= 0 || module_name == "socket")
635 IMEngineFactoryPointer factory;
636 IMEngineModule ime_module;
638 ime_module.load (module_name, config);
640 if (ime_module.valid ()) {
641 for (size_t j = 0; j < ime_module.number_of_factories (); ++j) {
643 factory = ime_module.create_factory (j);
648 if (!factory.null ()) {
649 if (m_impl->m_factory_module_repository.find (factory->get_uuid ())
650 == m_impl->m_factory_module_repository.end ()) {
651 add_specific_factory (factory->get_uuid (), IMEngineFactoryPointer (0));
652 m_impl->m_factory_module_repository[factory->get_uuid ()] = module_name;
659 std::cerr << __func__ << ": Failed to load " << module_name << " IMEngine module!!!\n";
662 ime_module.unload ();
666 CommonBackEnd::add_factory_by_uuid (const ConfigPointer &config, const String uuid)
668 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << uuid << "\n";
670 if (m_impl->m_factory_module_repository.find (uuid) == m_impl->m_factory_module_repository.end ())
673 String module = m_impl->m_factory_module_repository[uuid];
674 add_module (config, module, true);
678 CommonBackEnd::release_module (const std::vector<String> &use_uuids, const String del_uuid)
680 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << del_uuid << "\n";
682 if (m_impl->m_factory_module_repository.find (del_uuid) == m_impl->m_factory_module_repository.end ())
685 String module = m_impl->m_factory_module_repository[del_uuid];
686 std::vector<String> uuids;
687 std::map <String, String>::iterator it = m_impl->m_factory_module_repository.begin ();
690 for (; it != m_impl->m_factory_module_repository.end (); it++) {
691 if (it->second == module)
692 uuids.push_back (it->first);
695 for (unsigned int i = 0; i < uuids.size (); i++) {
696 for (unsigned int j = 0; j < use_uuids.size (); j++) {
697 if (uuids[i] == use_uuids[j])
702 /* unload the module */
703 std::vector<String>::iterator it2 = uuids.begin ();
704 for (; it2 != uuids.end (); it2++)
705 add_specific_factory (*it2, IMEngineFactoryPointer (0));
707 std::vector<String>::iterator it3 = m_impl->m_modules.begin ();
708 for (; it3 != m_impl->m_modules.end (); it3++) {
709 if (*it3 == module) {
710 m_impl->m_modules.erase (it3);
715 std::vector<IMEngineModule *>::iterator it4 = m_impl->m_engine_modules.begin ();
716 for (; it4 != m_impl->m_engine_modules.end (); it4++) {
717 if ((*it4)->get_module_name () == module) {
718 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << module << "\n";
721 m_impl->m_engine_modules.erase (it4);
729 CommonBackEnd::add_module_info_from_cache_file (const ConfigPointer &config, std::vector<String> &modules)
731 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << "...\n";
733 FILE *engine_list_file = NULL;
734 FILE *user_engine_file = NULL;
736 bool isFirst = false;
737 std::vector<String> current_modules;
739 current_modules.clear ();
741 String user_file_name = String (USER_ENGINE_FILE_NAME);
742 String sys_file_name = String (SYS_ENGINE_FILE_NAME);
744 engine_list_file = fopen (user_file_name.c_str (), "r");
745 if (engine_list_file == NULL) {
746 std::cerr << user_file_name << " doesn't exist.\n";
749 engine_list_file = fopen (sys_file_name.c_str (), "r");
750 if (engine_list_file == NULL) {
751 std::cerr << sys_file_name << " doesn't exist.\n";
757 * If we start the system firstly, the engine list file in user directory
758 * doesn't exit, we should create it.
761 user_engine_file = fopen (user_file_name.c_str (), "a");
762 if (user_engine_file == NULL)
763 std::cerr << "failed to open " << user_file_name << "\n";
766 while (fgets (buf, MAXLINE, engine_list_file) != NULL) {
767 if (isFirst && user_engine_file != NULL) {
768 if (fputs (buf, user_engine_file) == EOF)
769 std::cerr << "failed to write " << user_file_name << "\n";
773 isf_get_ise_info_from_string (buf, info);
774 std::vector<String>::iterator iter = std::find (modules.begin (), modules.end (), info.module);
775 if (info.mode == TOOLBAR_KEYBOARD_MODE && iter != modules.end ()) {
776 if (m_impl->m_factory_module_repository.find (info.uuid) == m_impl->m_factory_module_repository.end ()) {
777 add_specific_factory (info.uuid, IMEngineFactoryPointer (0));
778 m_impl->m_factory_module_repository[info.uuid] = info.module;
781 std::vector<String>::iterator iter2 = std::find (current_modules.begin (), current_modules.end (), info.module);
782 if (iter2 == current_modules.end ())
783 current_modules.push_back (info.module);
787 if (isFirst && user_engine_file != NULL)
788 fclose (user_engine_file);
789 fclose (engine_list_file);
792 update_module_info (config, current_modules, modules);
796 CommonBackEnd::update_module_info (const ConfigPointer &config,
797 std::vector<String> ¤t_modules,
798 std::vector<String> &modules)
800 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << "...\n";
802 std::vector<String> imengine_list;
803 scim_get_imengine_module_list (imengine_list);
804 for (size_t i = 0; i < imengine_list.size (); ++i) {
805 if (std::find (modules.begin (), modules.end (), imengine_list [i]) != modules.end ()
806 && std::find (current_modules.begin (), current_modules.end (), imengine_list [i]) == current_modules.end ())
807 add_imengine_module_info (imengine_list [i], config);
812 CommonBackEnd::add_imengine_module_info (const String module_name, const ConfigPointer &config)
814 SCIM_DEBUG_BACKEND (1) << __FUNCTION__ << " : " << module_name << "\n";
816 if (module_name.length () <= 0 || module_name == "socket")
819 IMEngineFactoryPointer factory;
820 IMEngineModule ime_module;
822 String filename = String (USER_ENGINE_FILE_NAME);
823 FILE *engine_list_file = fopen (filename.c_str (), "a");
824 if (engine_list_file == NULL) {
825 std::cerr << "failed to open " << filename << "\n";
829 ime_module.load (module_name, config);
831 if (ime_module.valid ()) {
832 for (size_t j = 0; j < ime_module.number_of_factories (); ++j) {
834 factory = ime_module.create_factory (j);
839 if (!factory.null ()) {
840 String uuid = factory->get_uuid ();
841 String name = utf8_wcstombs (factory->get_name ());
842 String language = isf_get_normalized_language (factory->get_language ());
843 String icon = factory->get_icon_file ();
847 snprintf (mode, sizeof (mode), "%d", (int)TOOLBAR_KEYBOARD_MODE);
848 snprintf (option, sizeof (option), "%d", 0);
850 String line = isf_combine_ise_info_string (name, uuid, module_name, language,
851 icon, String (mode), String (option), factory->get_locales ());
852 if (fputs (line.c_str (), engine_list_file) < 0) {
853 std::cerr << "write to ise cache file failed:" << line << "\n";
857 add_specific_factory (uuid, IMEngineFactoryPointer (0));
858 m_impl->m_factory_module_repository[uuid] = module_name;
864 std::cerr << __func__ << ": Failed to load " << module_name << " IMEngine module!!!\n";
867 ime_module.unload ();
868 fclose (engine_list_file);
872 } /* namespace scim */
875 vi:ts=4:nowrap:ai:expandtab