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_module.cpp,v 1.26 2005/05/24 12:22:51 suzhe Exp $
28 #define Uses_SCIM_MODULE
29 #define Uses_STL_ALGORITHM
30 #include "scim_private.h"
34 #include <sys/types.h>
37 #include <scim_panel_common.h>
38 #include "isf_query_utility.h"
42 typedef void (*ModuleInitFunc) (void);
43 typedef void (*ModuleExitFunc) (void);
45 struct Module::ModuleImpl
53 ModuleImpl () : handle (0), init (0), exit (0) { }
56 static std::vector <ModuleInitFunc> _scim_modules;
59 _scim_get_module_paths (std::vector <String> &paths, const String &type)
61 const char *module_path_env;
63 std::vector <String> module_paths;
64 std::vector <String>::iterator it;
68 module_paths.push_back (String (SCIM_MODULE_PATH));
70 module_path_env = getenv ("SCIM_MODULE_PATH");
72 if (module_path_env) {
73 module_paths.push_back (String (module_path_env));
76 // append version to the end of the paths
77 for (it = module_paths.begin (); it != module_paths.end (); ++it) {
80 tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) +
81 String (SCIM_BINARY_VERSION) +
82 String (SCIM_PATH_DELIM_STRING) + type;
84 paths.push_back (tmp_dir);
86 tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) + type;
87 paths.push_back (tmp_dir);
92 scim_get_module_list (std::vector <String>& mod_list, const String& type)
95 std::vector<String> mname;
96 std::vector<String> paths;
100 if (type.compare("Helper") == 0) {
101 isf_db_select_module_name_by_mode(TOOLBAR_HELPER_MODE, mname);
102 for (i = 0; i < mname.size(); i++)
103 mod_list.push_back(mname[i]);
105 else if (type.compare("IMEngine") == 0) {
106 isf_db_select_module_name_by_mode(TOOLBAR_KEYBOARD_MODE, mname);
107 for (i = 0; i < mname.size(); i++)
108 mod_list.push_back(mname[i]);
111 if (stat ("/usr/lib/scim-1.0/1.4.0/IMEngine/socket.so", &sb) == 0) {
112 if (S_ISREG(sb.st_mode))
113 mod_list.push_back("socket");
117 _scim_get_module_paths (paths, type);
119 for (std::vector<String>::iterator i = paths.begin (); i!= paths.end (); ++i) {
120 DIR *dir = opendir (i->c_str ());
122 struct dirent *file = readdir (dir);
125 struct stat filestat;
126 String absfn = *i + String (SCIM_PATH_DELIM_STRING) + file->d_name;
127 if (stat (absfn.c_str (), &filestat) == 0) {
128 if (S_ISREG (filestat.st_mode)) {
129 String mod_name = String (file->d_name);
130 mod_list.push_back (mod_name.substr (0, mod_name.find_last_of ('.')));
133 file = readdir (dir);
139 std::sort (mod_list.begin (), mod_list.end ());
140 mod_list.erase (std::unique (mod_list.begin (), mod_list.end ()), mod_list.end ());
141 return mod_list.size ();
145 : m_impl (new ModuleImpl)
150 Module::Module (const String &name, const String &type)
151 : m_impl (new ModuleImpl)
156 if (!load (name, type))
157 std::cerr << "Load name:" << name << " type:" << type << " is failed!!!";
168 _concatenate_ltdl_prefix (const String &name, const String &symbol)
170 String prefix (name);
172 for (size_t i=0; i<prefix.length (); i++)
173 if (!isalnum ((int)prefix[i]))
176 return prefix + String ("_LTX_") + symbol;
180 Module::load (const String &name, const String &type)
182 // If cannot unload original module (it's resident), then return false.
187 std::vector<String> mpath;
188 std::vector <String> paths;
189 std::vector <String>::iterator it;
193 lt_dlhandle new_handle = 0;
195 ModuleInitFunc new_init;
196 ModuleExitFunc new_exit;
198 if (type.compare("Helper") == 0) {
199 isf_db_select_module_path_by_mode(TOOLBAR_HELPER_MODE, mpath);
200 mpath.push_back(String(SCIM_MODULE_PATH) + String(SCIM_PATH_DELIM_STRING) + String(SCIM_BINARY_VERSION)
201 + String(SCIM_PATH_DELIM_STRING) + String("Helper"));
202 for (i = 0; i < mpath.size(); i++) {
203 module_path = mpath[i] + String (SCIM_PATH_DELIM_STRING) + name;
204 new_handle = lt_dlopenext (module_path.c_str ());
209 else if (type.compare("IMEngine") == 0 && name.compare("socket")) {
210 mpath.push_back(String(SCIM_MODULE_PATH) + String(SCIM_PATH_DELIM_STRING) + String(SCIM_BINARY_VERSION)
211 + String(SCIM_PATH_DELIM_STRING) + String("IMEngine"));
212 for (i = 0; i < mpath.size(); i++) {
213 module_path = mpath[i] + String (SCIM_PATH_DELIM_STRING) + name;
214 new_handle = lt_dlopenext (module_path.c_str ());
220 _scim_get_module_paths (paths, type);
222 for (it = paths.begin (); it != paths.end (); ++it) {
223 module_path = *it + String (SCIM_PATH_DELIM_STRING) + name;
224 new_handle = lt_dlopenext (module_path.c_str ());
231 new_handle = lt_dlopenext (name.c_str ());
239 // Try to load the symbol scim_module_init
240 l_symbol = "scim_module_init";
241 new_init = (ModuleInitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
243 // If symbol load failed, try to add LTX prefix and load again.
244 // This will occurred when name.la is missing.
246 l_symbol = _concatenate_ltdl_prefix (name, l_symbol);
247 new_init = (ModuleInitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
249 // Failed again? Try to prepend a under score to the symbol name.
251 l_symbol.insert (l_symbol.begin (),'_');
252 new_init = (ModuleInitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
256 // Could not load the module!
258 lt_dlclose (new_handle);
262 // Try to load the symbol scim_module_exit
263 l_symbol = "scim_module_exit";
264 new_exit = (ModuleExitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
266 // If symbol load failed, try to add LTX prefix and load again.
267 // This will occurred when name.la is missing.
269 l_symbol = _concatenate_ltdl_prefix (name, l_symbol);
270 new_exit = (ModuleExitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
272 // Failed again? Try to prepend a under score to the symbol name.
274 l_symbol.insert (l_symbol.begin (),'_');
275 new_exit = (ModuleExitFunc) lt_dlsym (new_handle, l_symbol.c_str ());
279 //Check if the module is already loaded.
280 if (std::find (_scim_modules.begin (), _scim_modules.end (), new_init)
281 != _scim_modules.end ()) {
282 lt_dlclose (new_handle);
287 _scim_modules.push_back (new_init);
289 const lt_dlinfo *info = lt_dlgetinfo (new_handle);
291 m_impl->handle = new_handle;
292 m_impl->init = new_init;
293 m_impl->exit = new_exit;
294 m_impl->path = String (info->filename);
304 lt_dlclose (new_handle);
313 if (!m_impl || !m_impl->handle)
320 try { m_impl->exit (); } catch (...) { }
323 lt_dlclose (m_impl->handle);
325 std::vector <ModuleInitFunc>::iterator it =
326 std::find (_scim_modules.begin (), _scim_modules.end (), m_impl->init);
328 if (it != _scim_modules.end ())
329 _scim_modules.erase (it);
334 m_impl->path = String ();
335 m_impl->name = String ();
341 Module::make_resident () const
343 if (m_impl && m_impl->handle) {
344 return lt_dlmakeresident (m_impl->handle) == 0;
350 Module::is_resident () const
352 if (m_impl && m_impl->handle) {
353 return lt_dlisresident (m_impl->handle) == 1;
359 Module::valid () const
361 return (m_impl && m_impl->handle && m_impl->init);
365 Module::get_path () const
371 Module::symbol (const String & sym) const
375 if (m_impl->handle) {
376 String l_symbol = sym;
377 func = lt_dlsym (m_impl->handle, l_symbol.c_str ());
379 l_symbol = _concatenate_ltdl_prefix (m_impl->name, l_symbol);
380 func = lt_dlsym (m_impl->handle, l_symbol.c_str ());
382 l_symbol.insert (l_symbol.begin (), '_');
383 func = lt_dlsym (m_impl->handle, l_symbol.c_str ());
393 vi:ts=4:nowrap:ai:expandtab