1 // Copyright 2012~2013, Weng Xuetian <wengxt@gmail.com>
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include <fcitx/instance.h>
31 #include <fcitx/ime.h>
32 #include <fcitx/hook.h>
33 #include <fcitx/module.h>
34 #include <fcitx/keys.h>
35 #include <fcitx-config/xdg.h>
36 #include "fcitx_mozc.h"
37 #include "mozc_connection.h"
38 #include "mozc_response_parser.h"
39 #include "base/init_mozc.h"
40
41 typedef struct _FcitxMozcState {
42 mozc::fcitx::FcitxMozc* mozc;
43 int inUsageState;
44 } FcitxMozcState;
45
46
47 static void* FcitxMozcCreate(FcitxInstance* instance);
48 static void FcitxMozcDestroy(void *arg);
49 static boolean FcitxMozcInit(void *arg); /**< FcitxMozcInit */
50 static void FcitxMozcResetIM(void *arg); /**< FcitxMozcResetIM */
51 static void FcitxMozcReset(void *arg); /**< FcitxMozcResetIM */
52 static INPUT_RETURN_VALUE FcitxMozcDoInput(void *arg, FcitxKeySym, unsigned int); /**< FcitxMozcDoInput */
53 static INPUT_RETURN_VALUE FcitxMozcDoReleaseInput(void *arg, FcitxKeySym, unsigned int); /**< FcitxMozcDoInput */
54 static void FcitxMozcSave(void *arg); /**< FcitxMozcSave */
55 static void FcitxMozcReloadConfig(void *arg); /**< FcitxMozcReloadConfig */
56
57 extern "C" {
58
59 FCITX_EXPORT_API
60 FcitxIMClass ime = {
61 FcitxMozcCreate,
62 FcitxMozcDestroy
63 };
64 FCITX_EXPORT_API
65 int ABI_VERSION = FCITX_ABI_VERSION;
66
67 }
68
CheckLayout(FcitxInstance * instance)69 static inline bool CheckLayout(FcitxInstance* instance)
70 {
71 char *layout = NULL, *variant = NULL;
72 FcitxModuleFunctionArg args;
73 args.args[0] = &layout;
74 args.args[1] = &variant;
75 bool layout_is_jp = false;
76 FcitxModuleInvokeFunctionByName(instance, "fcitx-xkb", 1, args);
77 if (layout && strcmp(layout, "jp") == 0)
78 layout_is_jp = true;
79
80 fcitx_utils_free(layout);
81 fcitx_utils_free(variant);
82
83
84 return layout_is_jp;
85 }
86
FcitxMozcCreate(FcitxInstance * instance)87 static void* FcitxMozcCreate(FcitxInstance* instance)
88 {
89 FcitxMozcState* mozcState = (FcitxMozcState*) fcitx_utils_malloc0(sizeof(FcitxMozcState));
90 bindtextdomain("fcitx-mozc", LOCALEDIR);
91 bind_textdomain_codeset("fcitx-mozc", "UTF-8");
92
93 int argc = 1;
94 char argv0[] = "fcitx_mozc";
95 char *_argv[] = { argv0 };
96 char **argv = _argv;
97 mozc::InitMozc(argv[0], &argc, &argv, true);
98 mozcState->mozc = new mozc::fcitx::FcitxMozc(
99 instance,
100 mozc::fcitx::MozcConnection::CreateMozcConnection(),
101 new mozc::fcitx::MozcResponseParser
102 );
103
104 mozcState->mozc->SetCompositionMode(mozc::commands::HIRAGANA);
105
106 FcitxIMEventHook hk;
107 hk.arg = mozcState;
108 hk.func = FcitxMozcReset;
109
110 FcitxInstanceRegisterResetInputHook(instance, hk);
111
112 FcitxIMIFace iface;
113 memset(&iface, 0, sizeof(FcitxIMIFace));
114 iface.Init = FcitxMozcInit;
115 iface.ResetIM = FcitxMozcResetIM;
116 iface.DoInput = FcitxMozcDoInput;
117 iface.DoReleaseInput = FcitxMozcDoReleaseInput;
118 iface.ReloadConfig = FcitxMozcReloadConfig;
119 iface.Save = FcitxMozcSave;
120
121
122 FcitxInstanceRegisterIMv2(
123 instance,
124 mozcState,
125 "mozc",
126 "Mozc",
127 mozcState->mozc->GetIconFile("mozc.png").c_str(),
128 iface,
129 1,
130 "ja"
131 );
132
133 return mozcState;
134 }
135
FcitxMozcDestroy(void * arg)136 static void FcitxMozcDestroy(void *arg)
137 {
138 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
139 delete mozcState->mozc;
140 free(mozcState);
141 }
142
143 static const FcitxHotkey MOZC_CTRL_ALT_H[2] = {
144 {NULL, FcitxKey_H, FcitxKeyState_Ctrl_Alt},
145 {NULL, FcitxKey_None, 0}
146 };
147
FcitxMozcDoInput(void * arg,FcitxKeySym _sym,unsigned int _state)148 INPUT_RETURN_VALUE FcitxMozcDoInput(void* arg, FcitxKeySym _sym, unsigned int _state)
149 {
150 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
151 FcitxInstance* instance = mozcState->mozc->GetInstance();
152 FcitxInputState* input = FcitxInstanceGetInputState(mozcState->mozc->GetInstance());
153
154 if (mozcState->inUsageState) {
155 if (FcitxHotkeyIsHotKey(_sym, _state, FCITX_ESCAPE)) {
156 mozcState->inUsageState = false;
157 // send a dummy key to let server send us the candidate info back without side effect
158 mozcState->mozc->process_key_event(FcitxKey_VoidSymbol, 0, 0, CheckLayout(instance), false);
159 return IRV_DISPLAY_CANDWORDS;
160 } else {
161 return IRV_DO_NOTHING;
162 }
163 }
164
165 if (FcitxHotkeyIsHotKey(_sym, _state, MOZC_CTRL_ALT_H)) {
166 std::pair< string, string > usage = mozcState->mozc->GetUsage();
167 if (usage.first.size() != 0 || usage.second.size() != 0) {
168 mozcState->inUsageState = true;
169 FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(mozcState->mozc->GetInputState());
170
171 // clear preedit, but keep client preedit
172 FcitxMessages* preedit = FcitxInputStateGetPreedit(input);
173 FcitxMessagesSetMessageCount(preedit, 0);
174 FcitxInputStateSetShowCursor(input, false);
175
176 // clear aux
177 FcitxMessages* auxUp = FcitxInputStateGetAuxUp(input);
178 FcitxMessages* auxDown = FcitxInputStateGetAuxDown(input);
179 FcitxMessagesSetMessageCount(auxUp, 0);
180 FcitxMessagesSetMessageCount(auxDown, 0);
181
182 // clear candidate table
183 FcitxCandidateWordReset(candList);
184 FcitxCandidateWordSetPageSize(candList, 9);
185 #if 0
186 FcitxCandidateWordSetLayoutHint(candList, CLH_Vertical);
187 #endif
188 FcitxCandidateWordSetChoose(candList, "\0\0\0\0\0\0\0\0\0\0");
189 FcitxMessagesAddMessageAtLast(preedit, MSG_TIPS, "%s [%s]", usage.first.c_str(), _("Press Escape to go back"));
190
191 UT_array* lines = fcitx_utils_split_string(usage.second.c_str(), '\n');
192 utarray_foreach(line, lines, char*) {
193 FcitxCandidateWord candWord;
194 candWord.callback = NULL;
195 candWord.extraType = MSG_OTHER;
196 candWord.strExtra = NULL;
197 candWord.priv = NULL;
198 candWord.strWord = strdup(*line);
199 candWord.wordType = MSG_OTHER;
200 candWord.owner = NULL;
201 FcitxCandidateWordAppend(candList, &candWord);
202 }
203 utarray_free(lines);
204 return IRV_DISPLAY_MESSAGE;
205 }
206 }
207
208 FCITX_UNUSED(_sym);
209 FCITX_UNUSED(_state);
210 FcitxKeySym sym = (FcitxKeySym) FcitxInputStateGetKeySym(input);
211 uint32 keycode = FcitxInputStateGetKeyCode(input);
212 uint32 state = FcitxInputStateGetKeyState(input);
213 bool result = mozcState->mozc->process_key_event(sym, keycode, state, CheckLayout(instance), false);
214 if (!result)
215 return IRV_TO_PROCESS;
216 else
217 return IRV_DISPLAY_CANDWORDS;
218 }
219
FcitxMozcDoReleaseInput(void * arg,FcitxKeySym _sym,unsigned int _state)220 INPUT_RETURN_VALUE FcitxMozcDoReleaseInput(void* arg, FcitxKeySym _sym, unsigned int _state)
221 {
222 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
223 FcitxInstance* instance = mozcState->mozc->GetInstance();
224 FcitxInputState* input = FcitxInstanceGetInputState(mozcState->mozc->GetInstance());
225 FCITX_UNUSED(_sym);
226 FCITX_UNUSED(_state);
227
228 if (mozcState->inUsageState) {
229 return IRV_DONOT_PROCESS;
230 }
231
232 FcitxKeySym sym = (FcitxKeySym) FcitxInputStateGetKeySym(input);
233 uint32 keycode = FcitxInputStateGetKeyCode(input);
234 uint32 state = FcitxInputStateGetKeyState(input);
235 bool result = mozcState->mozc->process_key_event(sym, keycode, state, CheckLayout(instance), true);
236 if (!result)
237 return IRV_TO_PROCESS;
238 else
239 return IRV_DISPLAY_CANDWORDS;
240 }
241
242
243
FcitxMozcInit(void * arg)244 boolean FcitxMozcInit(void* arg)
245 {
246 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
247 mozcState->mozc->init();
248 return true;
249 }
250
FcitxMozcReloadConfig(void * arg)251 void FcitxMozcReloadConfig(void* arg)
252 {
253
254 }
255
FcitxMozcSave(void * arg)256 void FcitxMozcSave(void* arg)
257 {
258 FCITX_UNUSED(arg);
259 }
260
FcitxMozcResetIM(void * arg)261 void FcitxMozcResetIM(void* arg)
262 {
263 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
264 mozcState->inUsageState = false;
265 mozcState->mozc->resetim();
266 }
267
FcitxMozcReset(void * arg)268 void FcitxMozcReset(void* arg)
269 {
270 FcitxMozcState* mozcState = (FcitxMozcState*) arg;
271 mozcState->mozc->reset();
272
273 }
274