1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  *  Copyright (C) Hiroyuki Ikezoe <poincare@ikezoe.net>
4  *  Copyright (C) 2004 Takuro Ashie <ashie@homa.ne.jp>
5  *  Copyright (C) 2012 CSSlayer
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, or (at your option)
10  *  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 Free Software
19  *  Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 /*
23  * The original code is scim_uim_imengine.cpp in scim-uim-0.1.3.
24  * Copyright (C) 2004 James Su <suzhe@tsinghua.org.cn>
25  */
26 
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <fcitx/instance.h>
32 #include <libintl.h>
33 #include <fcitx-config/xdg.h>
34 #include <fcitx/hook.h>
35 #include <fcitx-utils/log.h>
36 #include <errno.h>
37 
38 #include "factory.h"
39 #include "imengine.h"
40 
41 static void* FcitxAnthyCreate(FcitxInstance* instance);
42 static void  FcitxAnthyDestory(void* arg);
43 static boolean FcitxAnthyInit(void* arg);
44 static INPUT_RETURN_VALUE  FcitxAnthyDoInput(void* arg, FcitxKeySym sym, unsigned int state);
45 static INPUT_RETURN_VALUE FcitxAnthyDoReleaseInput(void* arg, FcitxKeySym sym, unsigned int state);
46 static void  FcitxAnthyReloadConfig(void* arg);
47 static void  FcitxAnthySave(void* arg);
48 static void  FcitxAnthyReset(void* arg);
49 static void  FcitxAnthyFocusIn(void* arg);
50 static void  FcitxAnthyResetIM(void* arg);
51 static void FcitxAnthyOnClose(void* arg, FcitxIMCloseEventType event);
52 static const char * FcitxAnthyGetSubModeName(void* arg);
53 
54 FCITX_DEFINE_PLUGIN(fcitx_anthy, ime2, FcitxIMClass2) = {
55     FcitxAnthyCreate,
56     FcitxAnthyDestory,
57     NULL,
58     NULL,
59     NULL,
60     NULL,
61     NULL,
62     NULL,
63 };
64 
FcitxAnthyCreate(FcitxInstance * instance)65 void* FcitxAnthyCreate(FcitxInstance* instance)
66 {
67     if (anthy_init())
68         return NULL;
69 
70     AnthyInstance* anthy = new AnthyInstance(instance);
71     if (!anthy->load_config()) {
72         anthy_quit();
73         delete anthy;
74         return NULL;
75     }
76 
77     bindtextdomain("fcitx-anthy", LOCALEDIR);
78     bind_textdomain_codeset("fcitx-anthy", "UTF-8");
79 
80     FcitxIMIFace iface;
81     memset(&iface, 0, sizeof(FcitxIMIFace));
82     iface.Init = FcitxAnthyInit;
83     iface.ResetIM = FcitxAnthyResetIM;
84     iface.DoInput = FcitxAnthyDoInput;
85     iface.DoReleaseInput = FcitxAnthyDoReleaseInput;
86     iface.ReloadConfig = FcitxAnthyReloadConfig;
87     iface.Save = FcitxAnthySave;
88     iface.OnClose = FcitxAnthyOnClose;
89     iface.GetSubModeName = FcitxAnthyGetSubModeName;
90 
91     FcitxInstanceRegisterIMv2(
92         instance,
93         anthy,
94         "anthy",
95         _("Anthy"),
96         "anthy",
97         iface,
98         1,
99         "ja"
100     );
101 
102     FcitxIMEventHook hk;
103     hk.arg = anthy;
104     hk.func = FcitxAnthyReset;
105     FcitxInstanceRegisterResetInputHook(instance, hk);
106     hk.func = FcitxAnthyFocusIn;
107     FcitxInstanceRegisterInputFocusHook(instance, hk);
108 
109     return anthy;
110 }
111 
FcitxAnthyDestory(void * arg)112 void FcitxAnthyDestory(void* arg)
113 {
114     AnthyInstance* anthy = (AnthyInstance*) arg;
115     delete anthy;
116 
117     anthy_quit();
118 }
119 
FcitxAnthyInit(void * arg)120 boolean FcitxAnthyInit(void* arg)
121 {
122     AnthyInstance* anthy = (AnthyInstance*) arg;
123     anthy->init();
124     anthy->update_ui();
125     return true;
126 }
127 
FcitxAnthyResetIM(void * arg)128 void FcitxAnthyResetIM(void* arg)
129 {
130     AnthyInstance* anthy = (AnthyInstance*) arg;
131     anthy->reset_im();
132     anthy->update_ui();
133 }
134 
FcitxAnthyReset(void * arg)135 void FcitxAnthyReset(void* arg)
136 {
137     AnthyInstance* anthy = (AnthyInstance*) arg;
138     anthy->reset();
139     anthy->update_ui();
140 }
141 
FcitxAnthyShowIMInfo(void * arg)142 void FcitxAnthyShowIMInfo(void* arg)
143 {
144     AnthyInstance* anthy = (AnthyInstance*) arg;
145     static FcitxInputContext* ic;
146 
147     // don't show the info again if ic is not changed, this is annoying
148     // when cursor jumps within same application.
149     FcitxInputContext* newic = FcitxInstanceGetCurrentIC(anthy->get_owner());
150     if (newic == ic) {
151         return;
152     }
153 
154     ic = newic;
155     if (!ic) {
156         return;
157     }
158 
159     FcitxIM* im = FcitxInstanceGetCurrentIM(anthy->get_owner());
160     if (im && strcmp(im->uniqueName, "anthy") == 0) {
161         FcitxInstanceShowCurrentIMInfo(anthy->get_owner());
162     }
163 }
164 
FcitxAnthyFocusIn(void * arg)165 void FcitxAnthyFocusIn(void* arg)
166 {
167     AnthyInstance* anthy = (AnthyInstance*) arg;
168     FcitxInstance* instance = anthy->get_owner();
169 
170     if (anthy->get_config()->m_show_input_mode_on_focus &&
171         !FcitxInstanceCheckTimeoutByFunc(instance, FcitxAnthyShowIMInfo)) {
172         FcitxInstanceAddTimeout(instance, 100, FcitxAnthyShowIMInfo, anthy);
173     }
174 }
175 
FcitxAnthySave(void * arg)176 void FcitxAnthySave(void* arg)
177 {
178 }
179 
FcitxAnthyDoInput(void * arg,FcitxKeySym sym,unsigned int state)180 INPUT_RETURN_VALUE FcitxAnthyDoInput(void* arg, FcitxKeySym sym, unsigned int state)
181 {
182     AnthyInstance* anthy = (AnthyInstance*) arg;
183     KeyEvent event;
184     FcitxInputState* input = FcitxInstanceGetInputState(anthy->get_owner());
185     event.sym = (FcitxKeySym) FcitxInputStateGetKeySym(input);
186     event.is_release = false;
187     event.keycode = FcitxInputStateGetKeyCode(input);
188     event.state = FcitxInputStateGetKeyState(input) & FcitxKeyState_SimpleMask;
189     bool result = anthy->process_key_event(event);
190     anthy->update_ui();
191     if (result)
192         return IRV_DO_NOTHING;
193     else
194         return IRV_TO_PROCESS;
195 }
196 
FcitxAnthyDoReleaseInput(void * arg,FcitxKeySym sym,unsigned int state)197 INPUT_RETURN_VALUE FcitxAnthyDoReleaseInput(void* arg, FcitxKeySym sym, unsigned int state)
198 {
199     AnthyInstance* anthy = (AnthyInstance*) arg;
200     KeyEvent event;
201     FcitxInputState* input = FcitxInstanceGetInputState(anthy->get_owner());
202     event.sym = (FcitxKeySym) FcitxInputStateGetKeySym(input);
203     event.keycode = FcitxInputStateGetKeyCode(input);
204     event.is_release = true;
205     event.state = FcitxInputStateGetKeyState(input) & FcitxKeyState_SimpleMask;
206     bool result = anthy->process_key_event(event);
207     anthy->update_ui();
208     if (result)
209         return IRV_DO_NOTHING;
210     else
211         return IRV_TO_PROCESS;
212 }
213 
FcitxAnthyReloadConfig(void * arg)214 void FcitxAnthyReloadConfig(void* arg)
215 {
216     AnthyInstance* anthy = (AnthyInstance*) arg;
217     anthy->load_config();
218     anthy->configure();
219     anthy->update_ui();
220 }
221 
FcitxAnthyOnClose(void * arg,FcitxIMCloseEventType event)222 void FcitxAnthyOnClose(void* arg, FcitxIMCloseEventType event)
223 {
224     AnthyInstance* anthy = (AnthyInstance*) arg;
225     anthy->auto_commit(event);
226 }
227 
FcitxAnthyGetSubModeName(void * arg)228 const char * FcitxAnthyGetSubModeName(void *arg)
229 {
230     AnthyInstance* anthy = (AnthyInstance*) arg;
231     return anthy->get_input_mode_name();
232 }
233 
234 
235 void
SaveAnthyConfig(AnthyInstance * anthy)236 SaveAnthyConfig(AnthyInstance* anthy)
237 {
238     anthy->save_config();
239 }
240 
241 boolean
LoadAnthyConfig(AnthyInstance * anthy)242 LoadAnthyConfig(AnthyInstance* anthy)
243 {
244     anthy->load_config();
245     return true;
246 }
247 
ConfigAnthy(AnthyInstance * anthy)248 void ConfigAnthy(AnthyInstance* anthy) {
249     anthy->configure();
250     anthy->update_ui();
251 }
252