1 /***************************************************************************
2  *   Copyright (C) 2010~2010 by CSSlayer                                   *
3  *   wengxt@gmail.com                                                      *
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  *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
19  ***************************************************************************/
20 
21 #include <dlfcn.h>
22 #include <libintl.h>
23 #include <pthread.h>
24 
25 #include "fcitx/fcitx.h"
26 #include "module.h"
27 #include "addon.h"
28 #include "fcitx-config/xdg.h"
29 #include "fcitx-utils/log.h"
30 #include "instance.h"
31 #include "instance-internal.h"
32 #include "addon-internal.h"
33 #include "ime-internal.h"
34 
InitFcitxModules(UT_array * modules)35 void InitFcitxModules(UT_array* modules)
36 {
37     utarray_init(modules, fcitx_ptr_icd);
38 }
39 
40 FCITX_EXPORT_API
FcitxModuleLoad(FcitxInstance * instance)41 void FcitxModuleLoad(FcitxInstance* instance)
42 {
43     UT_array* addons = &instance->addons;
44     FcitxAddon *addon;
45     for (addon = (FcitxAddon *) utarray_front(addons);
46             addon != NULL;
47             addon = (FcitxAddon *) utarray_next(addons, addon)) {
48         if (addon->bEnabled && addon->category == AC_MODULE) {
49             char *modulePath;
50             switch (addon->type) {
51             case AT_SHAREDLIBRARY: {
52                 FILE *fp = FcitxXDGGetLibFile(addon->library, "r", &modulePath);
53                 void *handle;
54                 FcitxModule* module;
55                 void* moduleinstance = NULL;
56                 if (!fp)
57                     break;
58                 fclose(fp);
59                 handle = dlopen(modulePath, RTLD_NOW | RTLD_NODELETE | (addon->loadLocal ? RTLD_LOCAL : RTLD_GLOBAL));
60                 if (!handle) {
61                     FcitxLog(ERROR, _("Module: open %s fail %s") , modulePath , dlerror());
62                     break;
63                 }
64 
65                 if (!FcitxCheckABIVersion(handle, addon->name)) {
66                     FcitxLog(ERROR, "%s ABI Version Error", addon->name);
67                     dlclose(handle);
68                     break;
69                 }
70 
71                 module = FcitxGetSymbol(handle, addon->name, "module");
72                 if (!module || !module->Create) {
73                     FcitxLog(ERROR, _("Module: bad module"));
74                     dlclose(handle);
75                     break;
76                 }
77                 if ((moduleinstance = module->Create(instance)) == NULL) {
78                     dlclose(handle);
79                     break;
80                 }
81                 if (instance->loadingFatalError)
82                     return;
83                 addon->module = module;
84                 addon->addonInstance = moduleinstance;
85                 if (module->ProcessEvent && module->SetFD)
86                     utarray_push_back(&instance->eventmodules, &addon);
87                 utarray_push_back(&instance->modules, &addon);
88             }
89             break;
90             default:
91                 break;
92             }
93             free(modulePath);
94         }
95     }
96 }
97 
98 FCITX_EXPORT_API
99 FcitxModuleFunction
FcitxModuleFindFunction(FcitxAddon * addon,int func_id)100 FcitxModuleFindFunction(FcitxAddon *addon, int func_id)
101 {
102     if (!addon) {
103         FcitxLog(DEBUG, "addon is not valid");
104         return NULL;
105     }
106 
107     /*
108      * Input Methods support lazy load
109      */
110     if (addon->category == AC_INPUTMETHOD) {
111         boolean flag = false;
112         FcitxAddon **pimclass = NULL;
113         for (pimclass = (FcitxAddon**)utarray_front(&addon->owner->imeclasses);
114              pimclass;pimclass = (FcitxAddon**)utarray_next(
115                  &addon->owner->imeclasses, pimclass)) {
116             if (*pimclass == addon) {
117                 flag = true;
118                 break;
119             }
120         }
121         if (!flag && !addon->addonInstance) {
122             FcitxInstanceLoadIM(addon->owner, addon);
123             FcitxInstanceUpdateIMList(addon->owner);
124         }
125     }
126     FcitxModuleFunction *func_p = fcitx_array_eltptr(&addon->functionList,
127                                                      func_id);
128     if (func_p)
129         return *func_p;
130     return NULL;
131 }
132 
133 FCITX_EXPORT_API void*
FcitxModuleInvokeOnAddon(FcitxAddon * addon,FcitxModuleFunction func,FcitxModuleFunctionArg * args)134 FcitxModuleInvokeOnAddon(FcitxAddon *addon, FcitxModuleFunction func,
135                          FcitxModuleFunctionArg *args)
136 {
137     if (!func)
138         return NULL;
139     return func(addon->addonInstance, *args);
140 }
141 
142 static void*
_FcitxModuleInvokeFunction(FcitxAddon * addon,int functionId,FcitxModuleFunctionArg args)143 _FcitxModuleInvokeFunction(FcitxAddon* addon, int functionId,
144                            FcitxModuleFunctionArg args)
145 {
146     FcitxModuleFunction func = FcitxModuleFindFunction(addon, functionId);
147     if (!func) {
148         FcitxLog(DEBUG, "addon %s doesn't have function with id %d",
149                  addon->name, functionId);
150         return NULL;
151     }
152     return func(addon->addonInstance, args);
153 }
154 
155 FCITX_EXPORT_API void*
FcitxModuleInvokeFunction(FcitxAddon * addon,int functionId,FcitxModuleFunctionArg args)156 FcitxModuleInvokeFunction(FcitxAddon* addon, int functionId,
157                           FcitxModuleFunctionArg args)
158 {
159     return _FcitxModuleInvokeFunction(addon, functionId, args);
160 }
161 
162 FCITX_EXPORT_API
FcitxModuleInvokeFunctionByName(FcitxInstance * instance,const char * name,int functionId,FcitxModuleFunctionArg args)163 void* FcitxModuleInvokeFunctionByName(FcitxInstance* instance, const char* name, int functionId, FcitxModuleFunctionArg args)
164 {
165     FcitxAddon* module = FcitxAddonsGetAddonByName(&instance->addons, name);
166 
167     if (module == NULL) {
168         return NULL;
169     } else {
170         return _FcitxModuleInvokeFunction(module, functionId, args);
171     }
172 }
173 
174 FCITX_EXPORT_API void
FcitxModuleAddFunction(FcitxAddon * addon,FcitxModuleFunction func)175 FcitxModuleAddFunction(FcitxAddon *addon, FcitxModuleFunction func)
176 {
177     void *temp = (void*)func;
178     utarray_push_back(&addon->functionList, &temp);
179 }
180 
181 // kate: indent-mode cstyle; space-indent on; indent-width 0;
182