1 /***************************************************************************
2  *   Copyright (C) 2010~2012 by CSSlayer                                   *
3  *   wengxt@gmail.com                                                      *
4  *   Copyright (C) 2012~2013 by Yichao Yu                                  *
5  *   yyc1992@gmail.com                                                     *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
21  ***************************************************************************/
22 
23 /**
24  * @addtogroup Fcitx
25  * @{
26  */
27 
28 #ifndef _FCITX_MODULE_H
29 #define _FCITX_MODULE_H
30 #include <fcitx-config/fcitx-config.h>
31 #include <fcitx-utils/utarray.h>
32 #include <fcitx-utils/utils.h>
33 #include <fcitx/addon.h>
34 #include <fcitx/fcitx.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40     struct _FcitxInstance;
41 
42     /**
43      * A misc module in Fcitx, it can register hook, or add it's own event
44      *        to Fcitx main loop.
45      **/
46     typedef struct _FcitxModule {
47         /**
48          * construction function
49          */
50         void* (*Create)(struct _FcitxInstance* instance);
51         /**
52          * set main loop watch fd, no need to implement
53          */
54         void (*SetFD)(void*);
55         /**
56          * main loop event handle, no need to implement
57          */
58         void (*ProcessEvent)(void*);
59         /**
60          * destruct function
61          */
62         void (*Destroy)(void*);
63         /**
64          * reload config, no need to implement
65          */
66         void (*ReloadConfig)(void*);
67     } FcitxModule;
68 
69     /**
70      * the argument to invoke module function
71      **/
72     typedef struct _FcitxModuleFunctionArg {
73         /**
74          * arguments
75          **/
76         void* args[10];
77     } FcitxModuleFunctionArg;
78     typedef void *(*FcitxModuleFunction)(void *self, FcitxModuleFunctionArg);
79 
80     /**
81      * load all modules
82      *
83      * @param instance fcitx instance
84      * @return void
85      **/
86     void FcitxModuleLoad(struct _FcitxInstance* instance);
87 
88     /**
89      * Find a exported function of a addon.
90      *
91      * @param addon addon
92      * @param functionId function index
93      * @return FcitxModuleFunction
94      **/
95     FcitxModuleFunction FcitxModuleFindFunction(FcitxAddon *addon,
96                                                 int func_id);
97 
98     void *FcitxModuleInvokeOnAddon(FcitxAddon *addon, FcitxModuleFunction func,
99                                    FcitxModuleFunctionArg *args);
100     /**
101      * invode inter module function with addon pointer, returns NULL when fails (the function itself can also return NULL)
102      *
103      * @param addon addon
104      * @param functionId function index
105      * @param args arguments
106      * @return void*
107      **/
108     FCITX_DEPRECATED
109     void* FcitxModuleInvokeFunction(FcitxAddon* addon, int functionId,
110                                     FcitxModuleFunctionArg args);
111 #define FcitxModuleInvokeVaArgs(addon, functionId, ARGV...)             \
112     (FcitxModuleInvokeFunction(addon, functionId,                       \
113                                (FcitxModuleFunctionArg){ {ARGV} }))
114 
115     /**
116      * invoke inter module function with addon name, returns NULL when fails (the function itself can also return NULL)
117      *
118      * @param instance fcitx instance
119      * @param name addon name
120      * @param functionId function index
121      * @param args arguments
122      * @return void*
123      **/
124     FCITX_DEPRECATED
125     void* FcitxModuleInvokeFunctionByName(struct _FcitxInstance* instance, const char* name, int functionId, FcitxModuleFunctionArg args);
126 #define FcitxModuleInvokeVaArgsByName(instance, name, functionId, ARGV...) \
127     (FcitxModuleInvokeFunctionByName(instance, name, functionId,        \
128                                      (FcitxModuleFunctionArg){ {ARGV} }))
129 
130 /** call a function provides by other addon */
131 #define InvokeFunction(INST, MODULE, FUNC, ARG)                         \
132     ((MODULE##_##FUNC##_RETURNTYPE)FcitxModuleInvokeFunctionByName(INST, MODULE##_NAME, MODULE##_##FUNC, ARG))
133 
134 #define InvokeVaArgs(INST, MODULE, FUNC, ARGV...)                       \
135     ((MODULE##_##FUNC##_RETURNTYPE)FcitxModuleInvokeFunctionByName(     \
136         INST, MODULE##_NAME, MODULE##_##FUNC,                           \
137         (FcitxModuleFunctionArg){ {ARGV} }))
138 
139 /** add a function to a addon */
140 #define AddFunction(ADDON, Realname)                                    \
141     do {                                                                \
142         FCITX_DEPRECATED void *(AddonFunction) = (void*)Realname;       \
143         utarray_push_back(&ADDON->functionList, &(AddonFunction));      \
144     } while(0)
145 
146     /**
147      * add a function to a addon
148      *
149      * @param addon
150      * @param func
151      **/
152     void FcitxModuleAddFunction(FcitxAddon *addon, FcitxModuleFunction func);
153 
154 #ifdef __cplusplus
155 #define DECLARE_ADDFUNCTIONS(prefix)                                    \
156     extern "C" {                                                        \
157         static inline FcitxAddon*                                       \
158         Fcitx_##prefix##_GetAddon(FcitxInstance *instance);             \
159         static void Fcitx##prefix##AddFunctions(FcitxInstance *instance); \
160     }
161 #else
162 #define DECLARE_ADDFUNCTIONS(prefix)                                    \
163     static inline FcitxAddon*                                           \
164     Fcitx_##prefix##_GetAddon(FcitxInstance *instance);                 \
165     static void Fcitx##prefix##AddFunctions(FcitxInstance *instance);
166 #endif
167 
168 // Well won't work if there are multiple instances, but that will also break
169 // lots of other things anyway.
170 #define DEFINE_GET_ADDON(name, prefix)                           \
171     static inline FcitxAddon*                                    \
172     Fcitx##prefix##GetAddon(FcitxInstance *instance)             \
173     {                                                            \
174         static FcitxAddon *addon = NULL;                         \
175         static FcitxInstance *_instance = NULL;                  \
176         if (fcitx_unlikely(_instance != instance)) {             \
177             _instance = instance;                                \
178             addon = FcitxAddonsGetAddonByName(                   \
179                 FcitxInstanceGetAddons(instance), name);         \
180         }                                                        \
181         return addon;                                            \
182     }
183 
184 #define DEFINE_GET_AND_INVOKE_FUNC(prefix, suffix, id)                  \
185     DEFINE_GET_AND_INVOKE_FUNC_WITH_ERROR(prefix, suffix, id, NULL)
186 #define DEFINE_GET_AND_INVOKE_FUNC_WITH_ERROR(prefix, suffix, id, err_ret) \
187     DEFINE_GET_AND_INVOKE_FUNC_WITH_TYPE_AND_ERROR(prefix, suffix, id,  \
188                                                    intptr_t, (intptr_t)err_ret)
189 
190 #define DEFINE_GET_AND_INVOKE_FUNC_WITH_TYPE_AND_ERROR(prefix, suffix,  \
191                                                        id, type, err_ret) \
192     static inline FcitxModuleFunction                                  \
193     Fcitx##prefix##Find##suffix(FcitxAddon *addon)                     \
194     {                                                                  \
195         static FcitxAddon *_addon = NULL;                              \
196         static FcitxModuleFunction func = NULL;                        \
197         if (fcitx_unlikely(addon != _addon)) {                         \
198             _addon = addon;                                            \
199             func = FcitxModuleFindFunction(addon, id);                 \
200         }                                                              \
201         return func;                                                   \
202     }                                                                  \
203     static inline void*                                                \
204     Fcitx##prefix##Invoke##suffix(FcitxInstance *instance,             \
205                                   FcitxModuleFunctionArg args)         \
206     {                                                                  \
207         static type _on_err = (err_ret);                               \
208         FCITX_DEF_CAST_TO_PTR(on_err, type, _on_err);                  \
209         FcitxAddon *addon = Fcitx##prefix##GetAddon(instance);         \
210         if (fcitx_unlikely(!addon))                                    \
211             return on_err;                                             \
212         FcitxModuleFunction func = Fcitx##prefix##Find##suffix(addon); \
213         if (fcitx_unlikely(!func))                                     \
214             return on_err;                                             \
215         return FcitxModuleInvokeOnAddon(addon, func, &args);           \
216     }
217 
218 #define FCITX_DEF_MODULE_ARGS(var, ARGV...)     \
219     FcitxModuleFunctionArg var = { {ARGV} }
220 
221 #define FCITX_DEF_MODULE_ARGS_LONG(var, arg0, arg1, arg2, arg3, arg4,   \
222                                    arg5, arg6, arg7, ARGV...)           \
223     const void *__fcitx_def_mod_arg_long_##var##_extras[] = {ARGV};     \
224     const size_t __fcitx_def_mod_arg_long_##var##_n =                   \
225         sizeof(__fcitx_def_mod_arg_long_##var##_extras) / sizeof(void*); \
226     FcitxModuleFunctionArg var =                                        \
227     { {arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7,                  \
228        fcitx_utils_size_to_ptr(__fcitx_def_mod_arg_long_##var##_n),     \
229        (void*)(intptr_t)(__fcitx_def_mod_arg_long_##var##_extras)} }
230 
231 #define FCITX_MODULE_FUNCTION_ARGS void *arg, FcitxModuleFunctionArg args
232 #define FCITX_MODULE_SELF(NAME, TYPE) TYPE *NAME = (TYPE*)arg
233 #define FCITX_MODULE_ARG(NAME, TYPE, INDEX)                     \
234     FCITX_DEF_CAST_FROM_PTR(TYPE, NAME, args.args[(INDEX)])
235 
236 #ifdef __cplusplus
237 }
238 #endif
239 
240 #endif
241 /**
242  * @}
243  */
244 // kate: indent-mode cstyle; space-indent on; indent-width 0;
245