1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2004 - 2005 Hiroyuki Ikezoe <poincare@ikezoe.net>
4 * Copyright (C) 2004 - 2005 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 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <errno.h>
35
36 #include "factory.h"
37 #include "imengine.h"
38 #include "utils.h"
39
40 #include <fcitx/context.h>
41 #include <fcitx-config/xdg.h>
42 #include <fcitx-config/fcitx-config.h>
43 #include <fcitx-utils/log.h>
44 #include <fcitx/module/clipboard/fcitx-clipboard.h>
45
46 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
47
48 #define UTF8_BRACKET_CORNER_BEGIN "\xE3\x80\x8C"
49 #define UTF8_BRACKET_CORNER_END "\xE3\x80\x8D"
50 #define UTF8_BRACKET_WIDE_BEGIN "\xEF\xBC\xBB"
51 #define UTF8_BRACKET_WIDE_END "\xEF\xBC\xBD"
52 #define UTF8_MIDDLE_DOT "\xE3\x83\xBB"
53 #define UTF8_SLASH_WIDE "\xEF\xBC\x8F"
54
55 #define ACTION_CONFIG_CIRCLE_INPUT_MODE_KEY "CircleInputModeKey"
56 #define ACTION_CONFIG_CIRCLE_KANA_MODE_KEY "CircleKanaModeKey"
57 #define ACTION_CONFIG_CIRCLE_LATIN_HIRAGANA_MODE_KEY "CircleLatinHiraganaModeKey"
58 #define ACTION_CONFIG_CIRCLE_TYPING_METHOD_KEY "CircleTypingMethodKey"
59 #define ACTION_CONFIG_LATIN_MODE_KEY "LatinModeKey"
60 #define ACTION_CONFIG_WIDE_LATIN_MODE_KEY "WideLatinModeKey"
61 #define ACTION_CONFIG_HIRAGANA_MODE_KEY "HiraganaModeKey"
62 #define ACTION_CONFIG_KATAKANA_MODE_KEY "KatakanaModeKey"
63 #define ACTION_CONFIG_HALF_KATAKANA_MODE_KEY "HalfKatakanaModeKey"
64 #define ACTION_CONFIG_CANCEL_PSEUDO_ASCII_MODE_KEY "CancelPseudoAsciiModeKey"
65
66 #define ACTION_CONFIG_INSERT_SPACE_KEY "InsertSpaceKey"
67 #define ACTION_CONFIG_INSERT_ALT_SPACE_KEY "InsertAltSpaceKey"
68 #define ACTION_CONFIG_INSERT_HALF_SPACE_KEY "InsertHalfSpaceKey"
69 #define ACTION_CONFIG_INSERT_WIDE_SPACE_KEY "InsertWideSpaceKey"
70 #define ACTION_CONFIG_BACKSPACE_KEY "BackSpaceKey"
71 #define ACTION_CONFIG_DELETE_KEY "DeleteKey"
72 #define ACTION_CONFIG_COMMIT_KEY "CommitKey"
73 #define ACTION_CONFIG_COMMIT_REVERSE_LEARN_KEY "CommitReverseLearnKey"
74 #define ACTION_CONFIG_CONVERT_KEY "ConvertKey"
75 #define ACTION_CONFIG_PREDICT_KEY "PredictKey"
76 #define ACTION_CONFIG_CANCEL_KEY "CancelKey"
77 #define ACTION_CONFIG_CANCEL_ALL_KEY "CancelAllKey"
78
79 #define ACTION_CONFIG_MOVE_CARET_FIRST_KEY "MoveCaretFirstKey"
80 #define ACTION_CONFIG_MOVE_CARET_LAST_KEY "MoveCaretLastKey"
81 #define ACTION_CONFIG_MOVE_CARET_FORWARD_KEY "MoveCaretForwardKey"
82 #define ACTION_CONFIG_MOVE_CARET_BACKWARD_KEY "MoveCaretBackwardKey"
83
84 #define ACTION_CONFIG_SELECT_FIRST_SEGMENT_KEY "SelectFirstSegmentKey"
85 #define ACTION_CONFIG_SELECT_LAST_SEGMENT_KEY "SelectLastSegmentKey"
86 #define ACTION_CONFIG_SELECT_NEXT_SEGMENT_KEY "SelectNextSegmentKey"
87 #define ACTION_CONFIG_SELECT_PREV_SEGMENT_KEY "SelectPrevSegmentKey"
88 #define ACTION_CONFIG_SHRINK_SEGMENT_KEY "ShrinkSegmentKey"
89 #define ACTION_CONFIG_EXPAND_SEGMENT_KEY "ExpandSegmentKey"
90 #define ACTION_CONFIG_COMMIT_FIRST_SEGMENT_KEY "CommitFirstSegmentKey"
91 #define ACTION_CONFIG_COMMIT_SELECTED_SEGMENT_KEY "CommitSelectedSegmentKey"
92 #define ACTION_CONFIG_COMMIT_FIRST_SEGMENT_REVERSE_LEARN_KEY "CommitFirstSegmentReverseLearnKey"
93 #define ACTION_CONFIG_COMMIT_SELECTED_SEGMENT_REVERSE_LEARN_KEY "CommitSelectedSegmentReverseLearnKey"
94
95 #define ACTION_CONFIG_SELECT_FIRST_CANDIDATE_KEY "SelectFirstCandidateKey"
96 #define ACTION_CONFIG_SELECT_LAST_CANDIDATE_KEY "SelectLastCandidateKey"
97 #define ACTION_CONFIG_SELECT_NEXT_CANDIDATE_KEY "SelectNextCandidateKey"
98 #define ACTION_CONFIG_SELECT_PREV_CANDIDATE_KEY "SelectPrevCandidateKey"
99 #define ACTION_CONFIG_SELECT_NEXT_CANDIDATE_ALTER_KEY "SelectNextCandidateKeyAlter"
100 #define ACTION_CONFIG_SELECT_PREV_CANDIDATE_ALTER_KEY "SelectPrevCandidateKeyAlter"
101 #define ACTION_CONFIG_CANDIDATES_PAGE_UP_KEY "CandidatesPageUpKey"
102 #define ACTION_CONFIG_CANDIDATES_PAGE_DOWN_KEY "CandidatesPageDownKey"
103 #define ACTION_CONFIG_SELECT_CANDIDATE_1_KEY "SelectCandidates1Key"
104 #define ACTION_CONFIG_SELECT_CANDIDATE_2_KEY "SelectCandidates2Key"
105 #define ACTION_CONFIG_SELECT_CANDIDATE_3_KEY "SelectCandidates3Key"
106 #define ACTION_CONFIG_SELECT_CANDIDATE_4_KEY "SelectCandidates4Key"
107 #define ACTION_CONFIG_SELECT_CANDIDATE_5_KEY "SelectCandidates5Key"
108 #define ACTION_CONFIG_SELECT_CANDIDATE_6_KEY "SelectCandidates6Key"
109 #define ACTION_CONFIG_SELECT_CANDIDATE_7_KEY "SelectCandidates7Key"
110 #define ACTION_CONFIG_SELECT_CANDIDATE_8_KEY "SelectCandidates8Key"
111 #define ACTION_CONFIG_SELECT_CANDIDATE_9_KEY "SelectCandidates9Key"
112 #define ACTION_CONFIG_SELECT_CANDIDATE_10_KEY "SelectCandidates10Key"
113
114 #define ACTION_CONFIG_CONV_CHAR_TYPE_FORWARD_KEY "ConvertCharTypeForwardKey"
115 #define ACTION_CONFIG_CONV_CHAR_TYPE_BACKWARD_KEY "ConvertCharTypeBackwardKey"
116 #define ACTION_CONFIG_CONV_TO_HIRAGANA_KEY "ConvertToHiraganaKey"
117 #define ACTION_CONFIG_CONV_TO_KATAKANA_KEY "ConvertToKatakanaKey"
118 #define ACTION_CONFIG_CONV_TO_HALF_KEY "ConvertToHalfKey"
119 #define ACTION_CONFIG_CONV_TO_HALF_KATAKANA_KEY "ConvertToHalfKatakanaKey"
120 #define ACTION_CONFIG_CONV_TO_WIDE_LATIN_KEY "ConvertToWideLatinKey"
121 #define ACTION_CONFIG_CONV_TO_LATIN_KEY "ConvertToLatinKey"
122
123 #define ACTION_CONFIG_RECONVERT_KEY "ReconvertKey"
124
125 #define ACTION_CONFIG_DICT_ADMIN_KEY "DictAdminKey"
126 #define ACTION_CONFIG_ADD_WORD_KEY "AddWordKey"
127
128 #define N_(x) (x)
129
AnthyInstance(FcitxInstance * instance)130 AnthyInstance::AnthyInstance (FcitxInstance* instance) :
131 m_owner(instance),
132 m_preedit (*this),
133 m_preedit_string_visible (false),
134 m_input (FcitxInstanceGetInputState(m_owner)),
135 m_lookup_table (FcitxInputStateGetCandidateList(m_input)),
136 m_lookup_table_visible (false),
137 m_n_conv_key_pressed (0),
138 m_prev_input_mode (FCITX_ANTHY_MODE_HIRAGANA),
139 m_last_key (),
140 m_aux_up (FcitxInputStateGetAuxUp(m_input)),
141 m_aux_down (FcitxInputStateGetAuxDown(m_input)),
142 m_cursor_pos (0),
143 m_client_preedit_msg (FcitxInputStateGetClientPreedit(m_input)),
144 m_preedit_msg (FcitxInputStateGetPreedit(m_input)),
145 m_profile (FcitxInstanceGetProfile(m_owner)),
146 m_status_installed (false),
147 m_ui_update (false)
148 {
149 memset(&m_config, 0, sizeof(FcitxAnthyConfig));
150
151 }
152
~AnthyInstance()153 AnthyInstance::~AnthyInstance ()
154 {
155 FcitxConfigFree(&m_config.gconfig);
156 if (m_status_installed) {
157 #define FINALIZE_MENU(VARNAME) \
158 FcitxUIUnRegisterMenu(m_owner, &VARNAME); \
159 fcitx_utils_free(VARNAME.name); \
160 fcitx_utils_free(VARNAME.candStatusBind); \
161 FcitxMenuFinalize(&VARNAME);
162
163 FINALIZE_MENU(m_input_mode_menu);
164 FINALIZE_MENU(m_typing_method_menu);
165 FINALIZE_MENU(m_conversion_mode_menu);
166 FINALIZE_MENU(m_period_style_menu);
167 FINALIZE_MENU(m_symbol_style_menu);
168 }
169
170 if (m_config.m_custom_romaji_table) {
171 delete m_config.m_custom_romaji_table;
172 m_config.m_custom_romaji_table = NULL;
173 }
174
175 if (m_config.m_custom_kana_table) {
176 delete m_config.m_custom_kana_table;
177 m_config.m_custom_kana_table = NULL;
178 }
179
180 if (m_config.m_custom_nicola_table) {
181 delete m_config.m_custom_nicola_table;
182 m_config.m_custom_nicola_table = NULL;
183 }
184 }
185
186 // FIXME!
187 bool
is_nicola_thumb_shift_key(const KeyEvent & key)188 AnthyInstance::is_nicola_thumb_shift_key (const KeyEvent &key)
189 {
190 if (get_typing_method () != FCITX_ANTHY_TYPING_METHOD_NICOLA)
191 return false;
192
193 if (util_match_key_event (m_config.m_left_thumb_keys, key, 0xFFFF) ||
194 util_match_key_event (m_config.m_right_thumb_keys, key, 0xFFFF))
195 {
196 return true;
197 }
198
199 return false;
200 }
201
202 bool
process_key_event_input(const KeyEvent & key)203 AnthyInstance::process_key_event_input (const KeyEvent &key)
204 {
205 // prediction while typing
206 if (m_config.m_predict_on_input && key.is_release &&
207 m_preedit.is_preediting () && !m_preedit.is_converting ())
208 {
209 m_preedit.predict ();
210 m_preedit.get_candidates (m_lookup_table);
211 }
212
213 if (!m_preedit.can_process_key_event (key)) {
214 return false;
215 }
216
217 if (m_preedit.is_converting ()) {
218 if (is_realtime_conversion ()) {
219 action_revert ();
220 } else if (!is_nicola_thumb_shift_key (key)) {
221 action_commit (m_config.m_learn_on_auto_commit);
222 }
223 }
224
225 bool need_commit = m_preedit.process_key_event (key);
226
227 if (need_commit) {
228 if (is_realtime_conversion () &&
229 get_input_mode () != FCITX_ANTHY_MODE_LATIN &&
230 get_input_mode () != FCITX_ANTHY_MODE_WIDE_LATIN)
231 {
232 m_preedit.convert (FCITX_ANTHY_CANDIDATE_DEFAULT,
233 is_single_segment ());
234 }
235 action_commit (m_config.m_learn_on_auto_commit);
236 } else {
237 if (is_realtime_conversion ()) {
238 m_preedit.convert (FCITX_ANTHY_CANDIDATE_DEFAULT,
239 is_single_segment ());
240 m_preedit.select_segment (-1);
241 }
242 //show_preedit_string ();
243 m_preedit_string_visible = true;
244 set_preedition ();
245 }
246
247 return true;
248 }
249
250 bool
process_key_event_lookup_keybind(const KeyEvent & key)251 AnthyInstance::process_key_event_lookup_keybind (const KeyEvent& key)
252 {
253 std::map<std::string, Action>::iterator it;
254
255 if (key.is_release)
256 return false;
257
258 m_last_key = key;
259
260 /* try to find a "insert a blank" action to be not stolen a blank key
261 * when entering the pseudo ascii mode.
262 */
263 if (get_pseudo_ascii_mode () != 0 &&
264 m_config.m_romaji_pseudo_ascii_blank_behavior &&
265 m_preedit.is_pseudo_ascii_mode ()) {
266 it = m_actions.find("INSERT_SPACE");
267 if (it != m_actions.end()) {
268 it->second.perform (this, key);
269 return true;
270 }
271 }
272
273 for (it = m_actions.begin();
274 it != m_actions.end();
275 it++)
276 {
277 if (it->second.perform (this, key)) {
278 m_last_key = KeyEvent ();
279 return true;
280 }
281 }
282
283 int choose = FcitxHotkeyCheckChooseKey(key.sym, key.state & (FcitxKeyState_Ctrl_Alt_Shift | FcitxKeyState_Super), DIGIT_STR_CHOOSE);
284 if (choose >= 0) {
285 INPUT_RETURN_VALUE retVal = FcitxCandidateWordChooseByIndex(m_lookup_table, choose);
286 if (retVal != IRV_TO_PROCESS) {
287 m_last_key = KeyEvent ();
288 return true;
289 }
290 }
291
292 m_last_key = KeyEvent ();
293
294 return false;
295 }
296
297 bool
process_key_event_latin_mode(const KeyEvent & key)298 AnthyInstance::process_key_event_latin_mode (const KeyEvent &key)
299 {
300 if (key.is_release)
301 return false;
302
303 if (util_key_is_keypad (key)) {
304 std::string str;
305 std::string wide;
306 util_keypad_to_string (str, key);
307 if (m_config.m_ten_key_type == FCITX_ANTHY_TEN_KEY_TYPE_WIDE)
308 util_convert_to_wide (wide, str);
309 else
310 wide = str;
311 if (wide.length () > 0) {
312 commit_string (wide);
313 return true;
314 } else {
315 return false;
316 }
317 } else {
318 // for Multi/Dead key
319 return false;
320 }
321 }
322
323 bool
process_key_event_wide_latin_mode(const KeyEvent & key)324 AnthyInstance::process_key_event_wide_latin_mode (const KeyEvent &key)
325 {
326 if (key.is_release)
327 return false;
328
329 std::string str;
330 std::string wide;
331 util_keypad_to_string (str, key);
332 if (util_key_is_keypad (key) && m_config.m_ten_key_type == FCITX_ANTHY_TEN_KEY_TYPE_HALF)
333 wide = str;
334 else
335 util_convert_to_wide (wide, str);
336 if (wide.length () > 0) {
337 commit_string (wide);
338 return true;
339 }
340
341 return false;
342 }
343
344 bool
process_key_event(const KeyEvent & key)345 AnthyInstance::process_key_event (const KeyEvent& key)
346 {
347 // FIXME!
348 // for NICOLA thumb shift key
349 if (get_typing_method () == FCITX_ANTHY_TYPING_METHOD_NICOLA &&
350 is_nicola_thumb_shift_key (key))
351 {
352 if (process_key_event_input (key))
353 return true;
354 }
355
356 // lookup user defined key bindings
357 if (process_key_event_lookup_keybind (key))
358 return true;
359
360 if (FcitxHotkeyIsHotKeyDigit(key.sym, key.state)
361 && FcitxCandidateWordGetListSize(m_lookup_table) > 0
362 ) {
363 return false;
364 }
365
366 // for Latin mode
367 if (m_preedit.get_input_mode () == FCITX_ANTHY_MODE_LATIN)
368 return process_key_event_latin_mode (key);
369
370 // for wide Latin mode
371 if (m_preedit.get_input_mode () == FCITX_ANTHY_MODE_WIDE_LATIN)
372 return process_key_event_wide_latin_mode (key);
373
374 // for other mode
375 if (get_typing_method () != FCITX_ANTHY_TYPING_METHOD_NICOLA ||
376 !is_nicola_thumb_shift_key (key))
377 {
378 if (process_key_event_input (key))
379 return true;
380 }
381
382 if (m_preedit.is_preediting ())
383 return true;
384 else
385 return false;
386 }
387
388 void
move_preedit_caret(unsigned int pos)389 AnthyInstance::move_preedit_caret (unsigned int pos)
390 {
391 m_preedit.set_caret_pos_by_char (pos);
392 // TODO
393 }
394
395 void
select_candidate_no_direct(unsigned int item)396 AnthyInstance::select_candidate_no_direct (unsigned int item)
397 {
398 if (m_preedit.is_predicting () && !m_preedit.is_converting ())
399 action_predict ();
400
401 // update lookup table
402 m_cursor_pos = item;
403
404 // update preedit
405 m_preedit.select_candidate (m_cursor_pos);
406 set_preedition ();
407
408 set_lookup_table();
409 FcitxCandidateWordSetFocus(m_lookup_table, m_cursor_pos);
410
411 // update aux string
412 if (m_config.m_show_candidates_label)
413 set_aux_string ();
414 }
415
416 void
select_candidate(unsigned int item)417 AnthyInstance::select_candidate (unsigned int item)
418 {
419 select_candidate_no_direct (item);
420
421 unset_lookup_table ();
422 action_select_next_segment();
423 }
424
425 void
update_lookup_table_page_size(unsigned int page_size)426 AnthyInstance::update_lookup_table_page_size (unsigned int page_size)
427 {
428 FcitxCandidateWordSetPageSize(m_lookup_table, page_size);
429 }
430
431 void
reset_im()432 AnthyInstance::reset_im ()
433 {
434 FcitxInstanceCleanInputWindow(m_owner);
435
436 m_preedit.clear ();
437 unset_lookup_table ();
438
439 m_preedit_string_visible = false;
440 set_preedition ();
441 }
442
443 void
init()444 AnthyInstance::init ()
445 {
446 boolean flag = true;
447 FcitxInstanceSetContext(m_owner, CONTEXT_IM_KEYBOARD_LAYOUT, "jp");
448 FcitxInstanceSetContext(m_owner, CONTEXT_DISABLE_AUTOENG, &flag);
449 FcitxInstanceSetContext(m_owner, CONTEXT_DISABLE_QUICKPHRASE, &flag);
450 FcitxInstanceSetContext(m_owner, CONTEXT_DISABLE_FULLWIDTH, &flag);
451 FcitxInstanceSetContext(m_owner, CONTEXT_DISABLE_AUTO_FIRST_CANDIDATE_HIGHTLIGHT, &flag);
452 FcitxInstanceCleanInputWindow(m_owner);
453 if (m_preedit_string_visible) {
454 set_preedition ();
455 }
456
457 if (m_lookup_table_visible && is_selecting_candidates ()) {
458 if (m_config.m_show_candidates_label &&
459 FcitxCandidateWordGetListSize(m_lookup_table))
460 {
461 set_aux_string ();
462 }
463 set_lookup_table ();
464 }
465
466 install_properties ();
467 }
468
469 bool
support_client_preedit(void)470 AnthyInstance::support_client_preedit(void)
471 {
472 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(m_owner);
473 if (ic && ((ic->contextCaps & CAPACITY_PREEDIT) == 0 || !m_profile->bUsePreedit))
474 return false;
475 else
476 return true;
477 }
478
479
480 void
set_preedition(void)481 AnthyInstance::set_preedition (void)
482 {
483 FcitxMessagesSetMessageCount(m_preedit_msg, 0);
484 FcitxMessagesSetMessageCount(m_client_preedit_msg, 0);
485 m_preedit.update_preedit();
486 if (!support_client_preedit())
487 FcitxInputStateSetShowCursor(m_input, true);
488 FcitxInputStateSetCursorPos(m_input, m_preedit.get_caret_pos());
489 FcitxInputStateSetClientCursorPos(m_input, m_preedit.get_caret_pos());
490 m_ui_update = true;
491 }
492
493 void
update_ui(void)494 AnthyInstance::update_ui (void)
495 {
496 if (m_ui_update) {
497 m_ui_update = false;
498 FcitxUIUpdateInputWindow(m_owner);
499 }
500 }
501
502 void
set_aux_string(void)503 AnthyInstance::set_aux_string (void)
504 {
505 if (!FcitxCandidateWordGetListSize(m_lookup_table))
506 return;
507
508 char buf[256];
509 sprintf (buf, _("(%d / %d)"), m_cursor_pos + 1,
510 FcitxCandidateWordGetListSize(m_lookup_table));
511 update_aux_string (buf);
512 }
513
514 int
set_lookup_table(void)515 AnthyInstance::set_lookup_table (void)
516 {
517 FcitxCandidateWordSetChoose(m_lookup_table, DIGIT_STR_CHOOSE);
518 FcitxCandidateWordSetPageSize(m_lookup_table, m_config.m_page_size);
519
520 // if (!is_selecting_candidates ()) {
521 if (is_realtime_conversion () &&
522 m_preedit.get_selected_segment () < 0)
523 {
524 // select latest segment
525 int n = m_preedit.get_nr_segments ();
526 if (n < 1)
527 return 0;
528 m_preedit.select_segment (n - 1);
529 }
530
531 // prepare candidates
532 m_preedit.get_candidates (m_lookup_table);
533
534 if (FcitxCandidateWordPageCount(m_lookup_table) == 0)
535 return 0;
536
537 // update preedit
538 m_preedit.select_candidate (m_cursor_pos);
539 set_preedition ();
540
541 bool beyond_threshold =
542 m_config.m_n_triggers_to_show_cand_win > 0 &&
543 (int) m_n_conv_key_pressed >= m_config.m_n_triggers_to_show_cand_win;
544
545 int len = FcitxCandidateWordGetListSize(m_lookup_table);
546
547 if (!m_lookup_table_visible &&
548 (m_preedit.is_predicting () || beyond_threshold))
549 {
550 m_lookup_table_visible = true;
551 m_n_conv_key_pressed = 0;
552
553 if (m_config.m_show_candidates_label) {
554 set_aux_string ();
555 }
556 } else if (!m_lookup_table_visible) {
557 FcitxCandidateWordReset(m_lookup_table);
558 }
559
560 m_ui_update = true;
561
562 return len;
563 }
564
565 void
unset_lookup_table(void)566 AnthyInstance::unset_lookup_table (void)
567 {
568 FcitxCandidateWordReset(m_lookup_table);
569 m_lookup_table_visible = false;
570 m_n_conv_key_pressed = 0;
571 m_cursor_pos = 0;
572
573 FcitxMessagesSetMessageCount(m_aux_up, 0);
574 }
575
576 AnthyStatus input_mode_status[] = {
577 {"", "\xe3\x81\x82", N_("Hiragana") },
578 {"", "\xe3\x82\xa2", N_("Katakana") },
579 {"", "\xef\xbd\xb1", N_("Half width katakana") },
580 {"", "A", N_("Direct input") },
581 {"", "\xef\xbc\xa1", N_("Wide latin") },
582 };
583
584 AnthyStatus typing_method_status[] = {
585 {"", N_("Romaji"), N_("Romaji") },
586 {"", N_("Kana"), N_("Kana") },
587 {"", N_("Nicola"), N_("Thumb shift") },
588 };
589
590 AnthyStatus conversion_mode_status[] = {
591 {"", "\xE9\x80\xA3", N_("Multi segment") },
592 {"", "\xE5\x8D\x98", N_("Single segment") },
593 {"", "\xE9\x80\x90", N_("Convert as you type (Multi segment)") },
594 {"", "\xE9\x80\x90", N_("Convert as you type (Single segment)") },
595 };
596
597 AnthyStatus period_style_status[] = {
598 {"anthy-period-wide-latin", "\xEF\xBC\x8C\xEF\xBC\x8E", "\xEF\xBC\x8C\xEF\xBC\x8E" },
599 {"anthy-period-latin", ",.", ",." },
600 {"anthy-period-japanese", "\xE3\x80\x81\xE3\x80\x82", "\xE3\x80\x81\xE3\x80\x82" },
601 {"anthy-period-wide-japanese", "\xEF\xBC\x8C\xE3\x80\x82", "\xEF\xBC\x8C\xE3\x80\x82" },
602 };
603
604 AnthyStatus symbol_style_status[] = {
605 {"anthy-symbol", UTF8_BRACKET_CORNER_BEGIN
606 UTF8_BRACKET_CORNER_END
607 UTF8_MIDDLE_DOT,
608 UTF8_BRACKET_CORNER_BEGIN
609 UTF8_BRACKET_CORNER_END
610 UTF8_MIDDLE_DOT },
611 {"anthy-symbol", UTF8_BRACKET_CORNER_BEGIN
612 UTF8_BRACKET_CORNER_END
613 UTF8_SLASH_WIDE,
614 UTF8_BRACKET_CORNER_BEGIN
615 UTF8_BRACKET_CORNER_END
616 UTF8_SLASH_WIDE },
617 {"anthy-symbol", UTF8_BRACKET_WIDE_BEGIN
618 UTF8_BRACKET_WIDE_END
619 UTF8_MIDDLE_DOT,
620 UTF8_BRACKET_WIDE_BEGIN
621 UTF8_BRACKET_WIDE_END
622 UTF8_MIDDLE_DOT
623 },
624 {"anthy-symbol", UTF8_BRACKET_WIDE_BEGIN
625 UTF8_BRACKET_WIDE_END
626 UTF8_SLASH_WIDE,
627 UTF8_BRACKET_WIDE_BEGIN
628 UTF8_BRACKET_WIDE_END
629 UTF8_SLASH_WIDE
630 },
631 };
632
633 const char*
GetInputModeIconName(void * arg)634 GetInputModeIconName(void* arg)
635 {
636 AnthyInstance* anthy = (AnthyInstance*) arg;
637 return anthy->get_input_mode_icon();
638 }
639
640 const char*
GetTypingMethodIconName(void * arg)641 GetTypingMethodIconName(void* arg)
642 {
643 AnthyInstance* anthy = (AnthyInstance*) arg;
644 return anthy->get_typing_method_icon();
645 }
646
647 const char*
GetConversionModeIconName(void * arg)648 GetConversionModeIconName(void* arg)
649 {
650 AnthyInstance* anthy = (AnthyInstance*) arg;
651 return anthy->get_conversion_mode_icon();
652 }
653
654 const char*
GetPeriodStyleIconName(void * arg)655 GetPeriodStyleIconName(void* arg)
656 {
657 AnthyInstance* anthy = (AnthyInstance*) arg;
658 return anthy->get_period_style_icon();
659 }
660
661 const char*
GetSymbolStyleIconName(void * arg)662 GetSymbolStyleIconName(void* arg)
663 {
664 AnthyInstance* anthy = (AnthyInstance*) arg;
665 return anthy->get_symbol_style_icon();
666 }
667
get_input_mode_icon()668 const char* AnthyInstance::get_input_mode_icon()
669 {
670 return input_mode_status[m_config.m_input_mode].icon;
671 }
672
get_typing_method_icon()673 const char* AnthyInstance::get_typing_method_icon()
674 {
675 return typing_method_status[m_config.m_typing_method].icon;
676 }
677
get_conversion_mode_icon()678 const char* AnthyInstance::get_conversion_mode_icon()
679 {
680 return conversion_mode_status[m_config.m_conversion_mode].icon;
681 }
682
get_period_style_icon()683 const char* AnthyInstance::get_period_style_icon()
684 {
685 return period_style_status[m_config.m_period_comma_style].icon;
686 }
687
get_symbol_style_icon()688 const char* AnthyInstance::get_symbol_style_icon()
689 {
690 return symbol_style_status[m_config.m_symbol_style].icon;
691 }
692
get_input_mode_name()693 const char * AnthyInstance::get_input_mode_name()
694 {
695 return _(input_mode_status[m_config.m_input_mode].description);
696 }
697
698
699 #define DEFINE_MENU_ACTION(NAME, TYPE, FUNC) \
700 void Update##NAME##Menu(struct _FcitxUIMenu *menu) \
701 { \
702 AnthyInstance* anthy = (AnthyInstance*) menu->priv; \
703 menu->mark = anthy->get_##FUNC(); \
704 } \
705 boolean NAME##MenuAction(struct _FcitxUIMenu *menu, int index) \
706 { \
707 AnthyInstance* anthy = (AnthyInstance*) menu->priv; \
708 anthy->set_##FUNC((TYPE) index); \
709 anthy->save_config(); \
710 return true; \
711 }
712
DEFINE_MENU_ACTION(InputMode,InputMode,input_mode)713 DEFINE_MENU_ACTION(InputMode, InputMode, input_mode)
714 DEFINE_MENU_ACTION(TypingMethod, TypingMethod, typing_method)
715 DEFINE_MENU_ACTION(ConversionMode, ConversionMode, conversion_mode)
716 DEFINE_MENU_ACTION(PeriodStyle, PeriodCommaStyle, period_style)
717 DEFINE_MENU_ACTION(SymbolStyle, SymbolStyle, symbol_style)
718
719 void AnthyInstance::set_period_style(PeriodCommaStyle period)
720 {
721 m_config.m_period_comma_style = period;
722 FcitxUISetStatusString(m_owner,
723 "anthy-period-style",
724 _(period_style_status[period].label),
725 _(period_style_status[period].description));
726
727 switch (m_config.m_period_comma_style)
728 {
729 case FCITX_ANTHY_PERIOD_COMMA_WIDELATIN:
730 m_preedit.set_comma_style (FCITX_ANTHY_COMMA_WIDE);
731 m_preedit.set_period_style (FCITX_ANTHY_PERIOD_WIDE);
732 break;
733 case FCITX_ANTHY_PERIOD_COMMA_LATIN:
734 m_preedit.set_comma_style (FCITX_ANTHY_COMMA_HALF);
735 m_preedit.set_period_style (FCITX_ANTHY_PERIOD_HALF);
736 break;
737 case FCITX_ANTHY_PERIOD_COMMA_WIDELATIN_JAPANESE:
738 m_preedit.set_comma_style (FCITX_ANTHY_COMMA_WIDE);
739 m_preedit.set_period_style (FCITX_ANTHY_PERIOD_JAPANESE);
740 break;
741 case FCITX_ANTHY_PERIOD_COMMA_JAPANESE:
742 default:
743 m_preedit.set_comma_style (FCITX_ANTHY_COMMA_JAPANESE);
744 m_preedit.set_period_style (FCITX_ANTHY_PERIOD_JAPANESE);
745 break;
746 }
747 }
748
set_symbol_style(SymbolStyle symbol)749 void AnthyInstance::set_symbol_style(SymbolStyle symbol)
750 {
751 m_config.m_symbol_style = symbol;
752 FcitxUISetStatusString(m_owner,
753 "anthy-symbol-style",
754 _(symbol_style_status[symbol].label),
755 _(symbol_style_status[symbol].description));
756 switch (m_config.m_symbol_style)
757 {
758 case FCITX_ANTHY_SYMBOL_STYLE_WIDEBRACKET_WIDESLASH:
759 m_preedit.set_bracket_style (FCITX_ANTHY_BRACKET_JAPANESE);
760 m_preedit.set_slash_style (FCITX_ANTHY_SLASH_WIDE);
761 break;
762 case FCITX_ANTHY_SYMBOL_STYLE_CORNERBRACKET_WIDESLASH:
763 m_preedit.set_bracket_style (FCITX_ANTHY_BRACKET_WIDE);
764 m_preedit.set_slash_style (FCITX_ANTHY_SLASH_WIDE);
765 break;
766 case FCITX_ANTHY_SYMBOL_STYLE_CORNERBRACKET_MIDDLEDOT:
767 m_preedit.set_bracket_style (FCITX_ANTHY_BRACKET_WIDE);
768 m_preedit.set_slash_style (FCITX_ANTHY_SLASH_JAPANESE);
769 break;
770 case FCITX_ANTHY_SYMBOL_STYLE_JAPANESE:
771 default:
772 m_preedit.set_bracket_style (FCITX_ANTHY_BRACKET_JAPANESE);
773 m_preedit.set_slash_style (FCITX_ANTHY_SLASH_JAPANESE);
774 break;
775 }
776 }
777
778
779 void
install_properties(void)780 AnthyInstance::install_properties (void)
781 {
782 if (!m_status_installed) {
783 m_status_installed = true;
784
785 #define INIT_MENU(VARNAME, NAME, I18NNAME, STATUS_NAME, STATUS_ARRAY, SIZE) \
786 FcitxUIRegisterComplexStatus(m_owner, this, \
787 STATUS_NAME, \
788 I18NNAME, \
789 I18NNAME, \
790 NULL, \
791 Get##NAME##IconName \
792 ); \
793 FcitxMenuInit(&VARNAME); \
794 VARNAME.name = strdup(I18NNAME); \
795 VARNAME.candStatusBind = strdup(STATUS_NAME); \
796 VARNAME.UpdateMenu = Update##NAME##Menu; \
797 VARNAME.MenuAction = NAME##MenuAction; \
798 VARNAME.priv = this; \
799 VARNAME.isSubMenu = false; \
800 for (int i = 0; i < SIZE; i ++) \
801 FcitxMenuAddMenuItem(&VARNAME, _(STATUS_ARRAY[i].label), MENUTYPE_SIMPLE, NULL); \
802 FcitxUIRegisterMenu(m_owner, &VARNAME); \
803 FcitxUISetStatusVisable(m_owner, STATUS_NAME, false);
804
805 INIT_MENU(m_input_mode_menu, InputMode, _("Input Mode"), "anthy-input-mode", input_mode_status, FCITX_ANTHY_MODE_LAST);
806 INIT_MENU(m_typing_method_menu, TypingMethod, _("Typing Method"), "anthy-typing-method", typing_method_status, FCITX_ANTHY_TYPING_METHOD_LAST);
807 INIT_MENU(m_conversion_mode_menu, ConversionMode, _("Conversion Mode"), "anthy-conversion-mode", conversion_mode_status, FCITX_ANTHY_CONVERSION_MODE_LAST);
808 INIT_MENU(m_period_style_menu, PeriodStyle, _("Period Style"), "anthy-period-style", period_style_status, FCITX_ANTHY_PERIOD_COMMA_LAST);
809 INIT_MENU(m_symbol_style_menu, SymbolStyle, _("Symbol Style"), "anthy-symbol-style", symbol_style_status, FCITX_ANTHY_SYMBOL_STYLE_LAST);
810 }
811
812 if (m_config.m_show_input_mode_label )
813
814 set_input_mode(get_input_mode ());
815 set_conversion_mode (m_config.m_conversion_mode);
816 set_typing_method (get_typing_method ());
817 set_period_style (get_period_style());
818 set_symbol_style (get_symbol_style());
819 }
820
821 void
set_input_mode(InputMode mode)822 AnthyInstance::set_input_mode (InputMode mode)
823 {
824 if (mode >= FCITX_ANTHY_MODE_LAST)
825 return;
826 if (mode != get_input_mode ()) {
827 m_config.m_input_mode = mode;
828 m_preedit.set_input_mode (mode);
829 set_preedition ();
830 }
831
832 FcitxUISetStatusString(m_owner,
833 "anthy-input-mode",
834 _(input_mode_status[mode].label),
835 _(input_mode_status[mode].description));
836
837 FcitxInstanceShowCurrentIMInfo(m_owner);
838 }
839
840 void
set_conversion_mode(ConversionMode mode)841 AnthyInstance::set_conversion_mode (ConversionMode mode)
842 {
843 if (mode >= FCITX_ANTHY_CONVERSION_MODE_LAST)
844 return;
845
846 m_config.m_conversion_mode = mode;
847
848 FcitxUISetStatusString(m_owner,
849 "anthy-conversion-mode",
850 _(conversion_mode_status[mode].label),
851 _(conversion_mode_status[mode].description));
852 }
853
854 void
set_typing_method(TypingMethod method)855 AnthyInstance::set_typing_method (TypingMethod method)
856 {
857 if (method != get_typing_method ()) {
858 m_preedit.set_typing_method (method);
859 m_preedit.set_pseudo_ascii_mode (get_pseudo_ascii_mode ());
860 }
861
862 m_config.m_typing_method = method;
863
864 FcitxUISetStatusString(m_owner,
865 "anthy-typing-method",
866 _(typing_method_status[method].label),
867 _(typing_method_status[method].description));
868 }
869
870 void
set_period_style(PeriodStyle period,CommaStyle comma)871 AnthyInstance::set_period_style (PeriodStyle period,
872 CommaStyle comma)
873 {
874 std::string label;
875
876 switch (comma) {
877 case FCITX_ANTHY_COMMA_JAPANESE:
878 label = "\xE3\x80\x81";
879 break;
880 case FCITX_ANTHY_COMMA_WIDE:
881 label = "\xEF\xBC\x8C";
882 break;
883 case FCITX_ANTHY_COMMA_HALF:
884 label = ",";
885 break;
886 default:
887 break;
888 }
889
890 switch (period) {
891 case FCITX_ANTHY_PERIOD_JAPANESE:
892 label += "\xE3\x80\x82";
893 break;
894 case FCITX_ANTHY_PERIOD_WIDE:
895 label += "\xEF\xBC\x8E";
896 break;
897 case FCITX_ANTHY_PERIOD_HALF:
898 label += ".";
899 break;
900 default:
901 break;
902 }
903
904 if (label.length () > 0) {
905 #if 0
906 PropertyList::iterator it = std::find (m_properties.begin (),
907 m_properties.end (),
908 SCIM_PROP_PERIOD_STYLE);
909 if (it != m_properties.end ()) {
910 it->set_label (label.c_str ());
911 update_property (*it);
912 }
913 #endif
914 }
915
916 if (period != m_preedit.get_period_style ())
917 m_preedit.set_period_style (period);
918 if (comma != m_preedit.get_comma_style ())
919 m_preedit.set_comma_style (comma);
920 }
921
922 void
set_symbol_style(BracketStyle bracket,SlashStyle slash)923 AnthyInstance::set_symbol_style (BracketStyle bracket,
924 SlashStyle slash)
925 {
926 std::string label;
927
928 switch (bracket) {
929 case FCITX_ANTHY_BRACKET_JAPANESE:
930 label = UTF8_BRACKET_CORNER_BEGIN UTF8_BRACKET_CORNER_END;
931 break;
932 case FCITX_ANTHY_BRACKET_WIDE:
933 label = UTF8_BRACKET_WIDE_BEGIN UTF8_BRACKET_WIDE_END;
934 break;
935 default:
936 break;
937 }
938
939 switch (slash) {
940 case FCITX_ANTHY_SLASH_JAPANESE:
941 label += UTF8_MIDDLE_DOT;
942 break;
943 case FCITX_ANTHY_SLASH_WIDE:
944 label += UTF8_SLASH_WIDE;
945 break;
946 default:
947 break;
948 }
949
950 if (label.length () > 0) {
951 #if 0
952 PropertyList::iterator it = std::find (m_properties.begin (),
953 m_properties.end (),
954 SCIM_PROP_SYMBOL_STYLE);
955 if (it != m_properties.end ()) {
956 it->set_label (label.c_str ());
957 update_property (*it);
958 }
959 #endif
960 }
961
962 if (bracket != m_preedit.get_bracket_style ())
963 m_preedit.set_bracket_style (bracket);
964 if (slash != m_preedit.get_slash_style ())
965 m_preedit.set_slash_style (slash);
966 }
967
968 bool
is_selecting_candidates(void)969 AnthyInstance::is_selecting_candidates (void)
970 {
971 if (FcitxCandidateWordGetListSize(m_lookup_table))
972 return true;
973 else
974 return false;
975 }
976
reset(void)977 void AnthyInstance::reset(void )
978 {
979 FcitxIM* im = FcitxInstanceGetCurrentIM(m_owner);
980 #define RESET_STATUS(CONFIG_NAME, STATUS_NAME) \
981 if (m_config.CONFIG_NAME && im && strcmp(im->uniqueName, "anthy") == 0) \
982 FcitxUISetStatusVisable(m_owner, STATUS_NAME, true); \
983 else \
984 FcitxUISetStatusVisable(m_owner, STATUS_NAME, false);
985
986 RESET_STATUS(m_show_input_mode_label, "anthy-input-mode")
987 RESET_STATUS(m_show_typing_method_label, "anthy-typing-method")
988 RESET_STATUS(m_show_conv_mode_label, "anthy-conversion-mode")
989 RESET_STATUS(m_show_period_style_label, "anthy-period-style")
990 RESET_STATUS(m_show_symbol_style_label, "anthy-symbol-style")
991 }
992
993 bool
action_convert(void)994 AnthyInstance::action_convert (void)
995 {
996 if (!m_preedit.is_preediting ())
997 return false;
998
999 if (!m_preedit.is_converting ()) {
1000 // show conversion string
1001 m_preedit.finish ();
1002 m_preedit.convert (FCITX_ANTHY_CANDIDATE_DEFAULT,
1003 is_single_segment ());
1004 set_preedition ();
1005 m_n_conv_key_pressed++;
1006 set_lookup_table ();
1007 return true;
1008 }
1009
1010 return false;
1011 }
1012
1013 bool
action_predict(void)1014 AnthyInstance::action_predict (void)
1015 {
1016 if (!m_preedit.is_preediting ())
1017 return false;
1018
1019 if (m_preedit.is_converting ())
1020 return false;
1021
1022 if (!m_preedit.is_predicting ())
1023 m_preedit.predict ();
1024
1025 m_preedit.select_candidate (0);
1026 set_preedition ();
1027 m_n_conv_key_pressed++;
1028 set_lookup_table ();
1029 select_candidate_no_direct (0);
1030
1031 return true;
1032 }
1033
1034
1035 bool
action_revert(void)1036 AnthyInstance::action_revert (void)
1037 {
1038 if (m_preedit.is_reconverting ()) {
1039 m_preedit.revert ();
1040 commit_string (m_preedit.get_string ());
1041 reset_im ();
1042 return true;
1043 }
1044
1045 if (!m_preedit.is_preediting ())
1046 return false;
1047
1048 if (!m_preedit.is_converting ()) {
1049 reset_im ();
1050 return true;
1051 }
1052
1053 if (is_selecting_candidates ()) {
1054 FcitxCandidateWordReset(m_lookup_table);
1055 }
1056
1057 unset_lookup_table ();
1058 m_preedit.revert ();
1059 set_preedition ();
1060
1061 return true;
1062 }
1063
1064 bool
action_cancel_all(void)1065 AnthyInstance::action_cancel_all (void)
1066 {
1067 if (!m_preedit.is_preediting ())
1068 return false;
1069
1070 reset_im ();
1071 return true;
1072 }
1073
1074 bool
action_commit(bool learn,bool do_real_commit)1075 AnthyInstance::action_commit (bool learn, bool do_real_commit)
1076 {
1077 if (!m_preedit.is_preediting ())
1078 return false;
1079
1080 if (m_preedit.is_converting ()) {
1081 if (do_real_commit)
1082 commit_string (m_preedit.get_string ());
1083 if (learn)
1084 m_preedit.commit ();
1085 } else {
1086 m_preedit.finish ();
1087 if (do_real_commit)
1088 commit_string (m_preedit.get_string ());
1089 }
1090
1091 reset_im ();
1092
1093 return true;
1094 }
1095
1096 bool
action_commit_follow_preference(void)1097 AnthyInstance::action_commit_follow_preference (void)
1098 {
1099 return action_commit (m_config.m_learn_on_manual_commit);
1100 }
1101
1102 bool
action_commit_reverse_preference(void)1103 AnthyInstance::action_commit_reverse_preference (void)
1104 {
1105 return action_commit (!m_config.m_learn_on_manual_commit);
1106 }
1107
1108 bool
action_back(void)1109 AnthyInstance::action_back (void)
1110 {
1111 if (!m_preedit.is_preediting ())
1112 return false;
1113
1114 if (m_preedit.is_converting ()) {
1115 action_revert ();
1116 if (!is_realtime_conversion ())
1117 return true;
1118 }
1119
1120 m_preedit.erase ();
1121
1122 if (m_preedit.get_length () > 0) {
1123 if (is_realtime_conversion ()) {
1124 m_preedit.convert (FCITX_ANTHY_CANDIDATE_DEFAULT,
1125 is_single_segment ());
1126 m_preedit.select_segment (-1);
1127 }
1128 set_preedition ();
1129 } else {
1130 reset_im ();
1131 }
1132
1133 return true;
1134 }
1135
1136 bool
action_delete(void)1137 AnthyInstance::action_delete (void)
1138 {
1139 if (!m_preedit.is_preediting ())
1140 return false;
1141
1142 if (m_preedit.is_converting ()) {
1143 action_revert ();
1144 if (!is_realtime_conversion ())
1145 return true;
1146 }
1147
1148 m_preedit.erase (false);
1149
1150 if (m_preedit.get_length () > 0) {
1151 if (is_realtime_conversion ()) {
1152 m_preedit.convert (FCITX_ANTHY_CANDIDATE_DEFAULT,
1153 is_single_segment ());
1154 m_preedit.select_segment (-1);
1155 }
1156 set_preedition ();
1157 } else {
1158 reset_im ();
1159 }
1160
1161 return true;
1162 }
1163
1164 bool
action_insert_space(void)1165 AnthyInstance::action_insert_space (void)
1166 {
1167 std::string str;
1168 bool is_wide = false, retval = false;
1169
1170 if (m_preedit.is_preediting () && !m_config.m_romaji_pseudo_ascii_blank_behavior)
1171 return false;
1172
1173 if (m_config.m_space_type == FCITX_ANTHY_SPACE_TYPE_FOLLOWMODE) {
1174 InputMode mode = get_input_mode ();
1175 if (mode == FCITX_ANTHY_MODE_LATIN ||
1176 mode == FCITX_ANTHY_MODE_HALF_KATAKANA ||
1177 m_preedit.is_pseudo_ascii_mode ())
1178 {
1179 is_wide = false;
1180 } else {
1181 is_wide = true;
1182 }
1183 } else if (m_config.m_space_type == FCITX_ANTHY_SPACE_TYPE_WIDE) {
1184 is_wide = true;
1185 }
1186
1187 if (is_wide) {
1188 str = "\xE3\x80\x80";
1189 retval = true;
1190 } else if (get_typing_method () == FCITX_ANTHY_TYPING_METHOD_NICOLA || // FIXME! it's a ad-hoc solution.
1191 m_preedit.is_pseudo_ascii_mode () ||
1192 (m_last_key.sym != FcitxKey_space &&
1193 m_last_key.sym != FcitxKey_KP_Space))
1194 {
1195 str = " ";
1196 retval = true;
1197 }
1198
1199 if (retval) {
1200 if (m_preedit.is_pseudo_ascii_mode ()) {
1201 m_preedit.append (m_last_key, str);
1202 // show_preedit_string ();
1203 m_preedit_string_visible = true;
1204 set_preedition ();
1205 } else {
1206 commit_string (str);
1207 }
1208 }
1209
1210 return retval;
1211 }
1212
1213 bool
action_insert_alternative_space(void)1214 AnthyInstance::action_insert_alternative_space (void)
1215 {
1216 bool is_wide = false;
1217
1218 if (m_preedit.is_preediting ())
1219 return false;
1220
1221 if (m_config.m_space_type == FCITX_ANTHY_SPACE_TYPE_FOLLOWMODE) {
1222 InputMode mode = get_input_mode ();
1223 if (mode == FCITX_ANTHY_MODE_LATIN ||
1224 mode == FCITX_ANTHY_MODE_HALF_KATAKANA)
1225 {
1226 is_wide = true;
1227 } else {
1228 is_wide = false;
1229 }
1230 } else if (m_config.m_space_type != FCITX_ANTHY_SPACE_TYPE_WIDE) {
1231 is_wide = true;
1232 }
1233
1234 if (is_wide) {
1235 commit_string ("\xE3\x80\x80");
1236 return true;
1237 } else if (get_typing_method () == FCITX_ANTHY_TYPING_METHOD_NICOLA || // FIXME! it's a ad-hoc solution.
1238 (m_last_key.sym != FcitxKey_space &&
1239 m_last_key.sym != FcitxKey_KP_Space))
1240 {
1241 commit_string (" ");
1242 return true;
1243 }
1244
1245 return false;
1246 }
1247
1248 bool
action_insert_half_space(void)1249 AnthyInstance::action_insert_half_space (void)
1250 {
1251 if (m_preedit.is_preediting ())
1252 return false;
1253
1254 if (m_last_key.sym != FcitxKey_space &&
1255 m_last_key.sym != FcitxKey_KP_Space)
1256 {
1257 commit_string (" ");
1258 return true;
1259 }
1260
1261 return false;
1262 }
1263
1264 bool
action_insert_wide_space(void)1265 AnthyInstance::action_insert_wide_space (void)
1266 {
1267 if (m_preedit.is_preediting ())
1268 return false;
1269
1270 commit_string ("\xE3\x80\x80");
1271
1272 return true;
1273 }
1274
1275 bool
action_move_caret_backward(void)1276 AnthyInstance::action_move_caret_backward (void)
1277 {
1278 if (!m_preedit.is_preediting ())
1279 return false;
1280 if (m_preedit.is_converting ())
1281 return false;
1282
1283 m_preedit.move_caret(-1);
1284 set_preedition ();
1285
1286 return true;
1287 }
1288
1289 bool
action_move_caret_forward(void)1290 AnthyInstance::action_move_caret_forward (void)
1291 {
1292 if (!m_preedit.is_preediting ())
1293 return false;
1294 if (m_preedit.is_converting ())
1295 return false;
1296
1297 m_preedit.move_caret(1);
1298 set_preedition ();
1299
1300 return true;
1301 }
1302
1303 bool
action_move_caret_first(void)1304 AnthyInstance::action_move_caret_first (void)
1305 {
1306 if (!m_preedit.is_preediting ())
1307 return false;
1308 if (m_preedit.is_converting ())
1309 return false;
1310
1311 m_preedit.set_caret_pos_by_char (0);
1312 set_preedition ();
1313
1314 return true;
1315 }
1316
1317 bool
action_move_caret_last(void)1318 AnthyInstance::action_move_caret_last (void)
1319 {
1320 if (!m_preedit.is_preediting ())
1321 return false;
1322 if (m_preedit.is_converting ())
1323 return false;
1324
1325 m_preedit.set_caret_pos_by_char (m_preedit.get_length_by_char ());
1326 set_preedition ();
1327
1328 return true;
1329 }
1330
1331 bool
action_select_prev_segment(void)1332 AnthyInstance::action_select_prev_segment (void)
1333 {
1334 if (!m_preedit.is_converting ())
1335 return false;
1336
1337 unset_lookup_table ();
1338
1339 int idx = m_preedit.get_selected_segment ();
1340 if (idx - 1 < 0) {
1341 int n = m_preedit.get_nr_segments ();
1342 if (n <= 0) return false;
1343 m_preedit.select_segment (n - 1);
1344 } else {
1345 m_preedit.select_segment (idx - 1);
1346 }
1347 set_preedition ();
1348
1349 return true;
1350 }
1351
1352 bool
action_select_next_segment(void)1353 AnthyInstance::action_select_next_segment (void)
1354 {
1355 if (!m_preedit.is_converting ())
1356 return false;
1357
1358 unset_lookup_table ();
1359
1360 int idx = m_preedit.get_selected_segment ();
1361 if (idx < 0) {
1362 m_preedit.select_segment(0);
1363 } else {
1364 int n = m_preedit.get_nr_segments ();
1365 if (n <= 0)
1366 return false;
1367 if (idx + 1 >= n)
1368 m_preedit.select_segment(0);
1369 else
1370 m_preedit.select_segment(idx + 1);
1371 }
1372 set_preedition ();
1373
1374 return true;
1375 }
1376
1377 bool
action_select_first_segment(void)1378 AnthyInstance::action_select_first_segment (void)
1379 {
1380 if (!m_preedit.is_converting ())
1381 return false;
1382
1383 unset_lookup_table ();
1384
1385 m_preedit.select_segment(0);
1386 set_preedition ();
1387
1388 return true;
1389 }
1390
1391 bool
action_select_last_segment(void)1392 AnthyInstance::action_select_last_segment (void)
1393 {
1394 if (!m_preedit.is_converting ())
1395 return false;
1396
1397 int n = m_preedit.get_nr_segments ();
1398 if (n <= 0) return false;
1399
1400 unset_lookup_table ();
1401
1402 m_preedit.select_segment(n - 1);
1403 set_preedition ();
1404
1405 return true;
1406 }
1407
1408 bool
action_shrink_segment(void)1409 AnthyInstance::action_shrink_segment (void)
1410 {
1411 if (!m_preedit.is_converting ())
1412 return false;
1413
1414 unset_lookup_table ();
1415
1416 m_preedit.resize_segment (-1);
1417 set_preedition ();
1418
1419 return true;
1420 }
1421
1422 bool
action_expand_segment(void)1423 AnthyInstance::action_expand_segment (void)
1424 {
1425 if (!m_preedit.is_converting ())
1426 return false;
1427
1428 unset_lookup_table ();
1429
1430 m_preedit.resize_segment (1);
1431 set_preedition ();
1432
1433 return true;
1434 }
1435
1436 bool
action_commit_first_segment(void)1437 AnthyInstance::action_commit_first_segment (void)
1438 {
1439 if (!m_preedit.is_converting ()) {
1440 if (m_preedit.is_preediting ()) {
1441 return action_commit (m_config.m_learn_on_manual_commit);
1442 } else {
1443 return false;
1444 }
1445 }
1446
1447 unset_lookup_table ();
1448
1449 commit_string (m_preedit.get_segment_string (0));
1450 if (m_config.m_learn_on_manual_commit)
1451 m_preedit.commit (0);
1452 else
1453 m_preedit.clear (0);
1454
1455 set_preedition ();
1456
1457 return true;
1458 }
1459
1460 bool
action_commit_selected_segment(void)1461 AnthyInstance::action_commit_selected_segment (void)
1462 {
1463 if (!m_preedit.is_converting ()) {
1464 if (m_preedit.is_preediting ()) {
1465 return action_commit (m_config.m_learn_on_manual_commit);
1466 } else {
1467 return false;
1468 }
1469 }
1470
1471 unset_lookup_table ();
1472
1473 for (int i = 0; i <= m_preedit.get_selected_segment (); i++)
1474 commit_string (m_preedit.get_segment_string (i));
1475 if (m_config.m_learn_on_manual_commit)
1476 m_preedit.commit (m_preedit.get_selected_segment ());
1477 else
1478 m_preedit.clear (m_preedit.get_selected_segment ());
1479
1480 set_preedition ();
1481
1482 return true;
1483 }
1484
1485 bool
action_commit_first_segment_reverse_preference(void)1486 AnthyInstance::action_commit_first_segment_reverse_preference (void)
1487 {
1488 if (!m_preedit.is_converting ()) {
1489 if (m_preedit.is_preediting ()) {
1490 return action_commit (!m_config.m_learn_on_manual_commit);
1491 } else {
1492 return false;
1493 }
1494 }
1495
1496 unset_lookup_table ();
1497
1498 commit_string (m_preedit.get_segment_string (0));
1499 if (!m_config.m_learn_on_manual_commit)
1500 m_preedit.commit (0);
1501 else
1502 m_preedit.clear (0);
1503
1504 set_preedition ();
1505
1506 return true;
1507 }
1508
1509 bool
action_commit_selected_segment_reverse_preference(void)1510 AnthyInstance::action_commit_selected_segment_reverse_preference (void)
1511 {
1512 if (!m_preedit.is_converting ()) {
1513 if (m_preedit.is_preediting ()) {
1514 return action_commit (!m_config.m_learn_on_manual_commit);
1515 } else {
1516 return false;
1517 }
1518 }
1519
1520 unset_lookup_table ();
1521
1522 for (int i = 0; i <= m_preedit.get_selected_segment (); i++)
1523 commit_string (m_preedit.get_segment_string (i));
1524 if (!m_config.m_learn_on_manual_commit)
1525 m_preedit.commit (m_preedit.get_selected_segment ());
1526 else
1527 m_preedit.clear (m_preedit.get_selected_segment ());
1528
1529 set_preedition ();
1530
1531 return true;
1532 }
1533
1534 bool
action_select_next_candidate(void)1535 AnthyInstance::action_select_next_candidate (void)
1536 {
1537 if (!m_preedit.is_converting ())
1538 return false;
1539
1540 //if (!is_selecting_candidates ())
1541 int end = set_lookup_table ();
1542
1543 if (m_cursor_pos >= end - 1)
1544 m_cursor_pos = 0;
1545 else
1546 m_cursor_pos ++;
1547 m_n_conv_key_pressed++;
1548
1549 select_candidate_no_direct (m_cursor_pos);
1550 return true;
1551 }
1552
1553 bool
action_select_prev_candidate(void)1554 AnthyInstance::action_select_prev_candidate (void)
1555 {
1556 if (!m_preedit.is_converting ()) return false;
1557 //if (!is_selecting_candidates ())
1558 int end = set_lookup_table ();
1559
1560 if (end < 0)
1561 end = 0;
1562 if (m_cursor_pos == 0)
1563 m_cursor_pos = end - 1;
1564 else
1565 m_cursor_pos --;
1566 m_n_conv_key_pressed++;
1567
1568 FcitxCandidateWordSetFocus(m_lookup_table, m_cursor_pos);
1569
1570 select_candidate_no_direct (m_cursor_pos);
1571
1572 return true;
1573 }
1574
1575 bool
action_select_first_candidate(void)1576 AnthyInstance::action_select_first_candidate (void)
1577 {
1578 if (!m_preedit.is_converting ()) return false;
1579 if (!is_selecting_candidates ()) return false;
1580
1581 m_cursor_pos = 0;
1582 m_n_conv_key_pressed++;
1583 select_candidate_no_direct (m_cursor_pos);
1584 return true;
1585 }
1586
1587 bool
action_select_last_candidate(void)1588 AnthyInstance::action_select_last_candidate (void)
1589 {
1590 if (!m_preedit.is_converting ()) return false;
1591 if (!is_selecting_candidates ()) return false;
1592
1593 int end = FcitxCandidateWordGetListSize(m_lookup_table) - 1;
1594 if (end < 0)
1595 end = 0;
1596 m_cursor_pos = 0;
1597 m_n_conv_key_pressed++;
1598 select_candidate_no_direct (m_cursor_pos);
1599 return true;
1600 }
1601
1602 bool
action_candidates_page_up(void)1603 AnthyInstance::action_candidates_page_up(void)
1604 {
1605 if (!m_preedit.is_converting ()) return false;
1606 if (!is_selecting_candidates ()) return false;
1607 if (!m_lookup_table_visible) return false;
1608
1609 if (m_cursor_pos - m_config.m_page_size >= 0) {
1610 m_cursor_pos -= m_config.m_page_size;
1611 select_candidate_no_direct (m_cursor_pos);
1612 }
1613
1614 return true;
1615 }
1616
1617 bool
action_candidates_page_down(void)1618 AnthyInstance::action_candidates_page_down (void)
1619 {
1620 if (!m_preedit.is_converting ()) return false;
1621 if (!is_selecting_candidates ()) return false;
1622 if (!m_lookup_table_visible) return false;
1623
1624 int end = FcitxCandidateWordGetListSize(m_lookup_table);
1625
1626 if (m_cursor_pos + m_config.m_page_size < end) {
1627 m_cursor_pos += m_config.m_page_size;
1628 select_candidate_no_direct (m_cursor_pos);
1629 }
1630
1631 return true;
1632 }
1633
1634 bool
action_select_candidate(unsigned int i)1635 AnthyInstance::action_select_candidate (unsigned int i)
1636 {
1637 // FIXME! m_lookup_table_visible should be set as true also on predicting
1638 if (!m_lookup_table_visible && !m_preedit.is_predicting ())
1639 return false;
1640
1641 if (m_preedit.is_predicting () && !m_preedit.is_converting () &&
1642 m_config.m_use_direct_key_on_predict)
1643 {
1644 m_preedit.get_candidates (m_lookup_table);
1645 select_candidate (i);
1646 return true;
1647 } else if (m_preedit.is_converting () && is_selecting_candidates ()) {
1648 select_candidate (i);
1649 return true;
1650 }
1651
1652 return false;
1653 }
1654
1655 bool
action_circle_input_mode(void)1656 AnthyInstance::action_circle_input_mode (void)
1657 {
1658 InputMode mode = get_input_mode ();
1659
1660 mode = (InputMode) ((mode + 1) % FCITX_ANTHY_MODE_LAST);
1661
1662 set_input_mode (mode);
1663 save_config();
1664
1665 return true;
1666 }
1667
1668 bool
action_circle_typing_method(void)1669 AnthyInstance::action_circle_typing_method (void)
1670 {
1671 TypingMethod method;
1672
1673 method = get_typing_method ();
1674 method = (TypingMethod) ((method + 1) % FCITX_ANTHY_TYPING_METHOD_NICOLA);
1675
1676 set_typing_method (method);
1677 save_config();
1678
1679 return true;
1680 }
1681
1682 bool
action_circle_kana_mode(void)1683 AnthyInstance::action_circle_kana_mode (void)
1684 {
1685 InputMode mode;
1686
1687 if (get_input_mode () == FCITX_ANTHY_MODE_LATIN ||
1688 get_input_mode () == FCITX_ANTHY_MODE_WIDE_LATIN)
1689 {
1690 mode = FCITX_ANTHY_MODE_HIRAGANA;
1691 } else {
1692 switch (get_input_mode ()) {
1693 case FCITX_ANTHY_MODE_HIRAGANA:
1694 mode = FCITX_ANTHY_MODE_KATAKANA;
1695 break;
1696 case FCITX_ANTHY_MODE_KATAKANA:
1697 mode = FCITX_ANTHY_MODE_HALF_KATAKANA;
1698 break;
1699 case FCITX_ANTHY_MODE_HALF_KATAKANA:
1700 default:
1701 mode = FCITX_ANTHY_MODE_HIRAGANA;
1702 break;
1703 }
1704 }
1705
1706 set_input_mode (mode);
1707 save_config();
1708
1709 return true;
1710 }
1711
1712 bool
action_circle_latin_hiragana_mode(void)1713 AnthyInstance::action_circle_latin_hiragana_mode (void)
1714 {
1715 InputMode mode = get_input_mode ();
1716
1717 if (mode == FCITX_ANTHY_MODE_LATIN)
1718 {
1719 mode = FCITX_ANTHY_MODE_HIRAGANA;
1720 } else if (mode == FCITX_ANTHY_MODE_HIRAGANA)
1721 {
1722 mode = FCITX_ANTHY_MODE_LATIN;
1723 }
1724
1725 set_input_mode (mode);
1726 save_config();
1727
1728 return true;
1729 }
1730
1731 bool
action_latin_mode(void)1732 AnthyInstance::action_latin_mode (void)
1733 {
1734 set_input_mode (FCITX_ANTHY_MODE_LATIN);
1735 save_config();
1736 return true;
1737 }
1738
1739 bool
action_wide_latin_mode(void)1740 AnthyInstance::action_wide_latin_mode (void)
1741 {
1742 set_input_mode (FCITX_ANTHY_MODE_WIDE_LATIN);
1743 save_config();
1744 return true;
1745 }
1746
1747 bool
action_hiragana_mode(void)1748 AnthyInstance::action_hiragana_mode (void)
1749 {
1750 set_input_mode (FCITX_ANTHY_MODE_HIRAGANA);
1751 save_config();
1752 return true;
1753 }
1754
1755 bool
action_katakana_mode(void)1756 AnthyInstance::action_katakana_mode (void)
1757 {
1758 set_input_mode (FCITX_ANTHY_MODE_KATAKANA);
1759 save_config();
1760 return true;
1761 }
1762
1763 bool
action_half_katakana_mode(void)1764 AnthyInstance::action_half_katakana_mode (void)
1765 {
1766 set_input_mode (FCITX_ANTHY_MODE_HALF_KATAKANA);
1767 save_config();
1768 return true;
1769 }
1770
1771 bool
action_cancel_pseudo_ascii_mode(void)1772 AnthyInstance::action_cancel_pseudo_ascii_mode (void)
1773 {
1774 if (!m_preedit.is_preediting ())
1775 return false;
1776 if (!m_preedit.is_pseudo_ascii_mode ())
1777 return false;
1778
1779 m_preedit.reset_pseudo_ascii_mode ();
1780
1781 return true;
1782 }
1783
1784 bool
convert_kana(CandidateType type)1785 AnthyInstance::convert_kana (CandidateType type)
1786 {
1787 if (!m_preedit.is_preediting ())
1788 return false;
1789
1790 if (m_preedit.is_reconverting ())
1791 return false;
1792
1793 unset_lookup_table ();
1794
1795 if (m_preedit.is_converting ()) {
1796 int idx = m_preedit.get_selected_segment ();
1797 if (idx < 0) {
1798 action_revert ();
1799 m_preedit.finish ();
1800 m_preedit.convert (type, true);
1801 } else {
1802 m_preedit.select_candidate (type);
1803 }
1804 } else {
1805 m_preedit.finish ();
1806 m_preedit.convert (type, true);
1807 }
1808
1809 set_preedition ();
1810
1811 return true;
1812 }
1813
1814 bool
action_convert_to_hiragana(void)1815 AnthyInstance::action_convert_to_hiragana (void)
1816 {
1817 return convert_kana (FCITX_ANTHY_CANDIDATE_HIRAGANA);
1818 }
1819
1820 bool
action_convert_to_katakana(void)1821 AnthyInstance::action_convert_to_katakana (void)
1822 {
1823 return convert_kana (FCITX_ANTHY_CANDIDATE_KATAKANA);
1824 }
1825
1826 bool
action_convert_to_half(void)1827 AnthyInstance::action_convert_to_half (void)
1828 {
1829 return convert_kana (FCITX_ANTHY_CANDIDATE_HALF);
1830 }
1831
1832 bool
action_convert_to_half_katakana(void)1833 AnthyInstance::action_convert_to_half_katakana (void)
1834 {
1835 return convert_kana (FCITX_ANTHY_CANDIDATE_HALF_KATAKANA);
1836 }
1837
1838 bool
action_convert_to_latin(void)1839 AnthyInstance::action_convert_to_latin (void)
1840 {
1841 return convert_kana (FCITX_ANTHY_CANDIDATE_LATIN);
1842 }
1843
1844 bool
action_convert_to_wide_latin(void)1845 AnthyInstance::action_convert_to_wide_latin (void)
1846 {
1847 return convert_kana (FCITX_ANTHY_CANDIDATE_WIDE_LATIN);
1848 }
1849
1850 bool
action_convert_char_type_forward(void)1851 AnthyInstance::action_convert_char_type_forward (void)
1852 {
1853 if (!m_preedit.is_preediting ())
1854 return false;
1855
1856 unset_lookup_table ();
1857
1858 if (m_preedit.is_converting ()) {
1859 int idx = m_preedit.get_selected_segment ();
1860 if (idx < 0) {
1861 action_revert ();
1862 m_preedit.finish ();
1863 m_preedit.convert (FCITX_ANTHY_CANDIDATE_HIRAGANA, true);
1864 } else {
1865 int cand = m_preedit.get_selected_candidate ();
1866 switch (cand)
1867 {
1868 case FCITX_ANTHY_CANDIDATE_HIRAGANA:
1869 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_KATAKANA);
1870 break;
1871 case FCITX_ANTHY_CANDIDATE_KATAKANA:
1872 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HALF_KATAKANA);
1873 break;
1874 case FCITX_ANTHY_CANDIDATE_HALF_KATAKANA:
1875 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_WIDE_LATIN);
1876 break;
1877 case FCITX_ANTHY_CANDIDATE_WIDE_LATIN:
1878 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_LATIN);
1879 break;
1880 case FCITX_ANTHY_CANDIDATE_LATIN:
1881 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HIRAGANA);
1882 break;
1883 default:
1884 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HIRAGANA);
1885 break;
1886 }
1887 }
1888 } else {
1889 m_preedit.finish ();
1890 m_preedit.convert (FCITX_ANTHY_CANDIDATE_HIRAGANA, true);
1891 }
1892
1893 set_preedition ();
1894
1895 return true;
1896 }
1897
1898 bool
action_convert_char_type_backward(void)1899 AnthyInstance::action_convert_char_type_backward (void)
1900 {
1901 if (!m_preedit.is_preediting ())
1902 return false;
1903
1904 unset_lookup_table ();
1905
1906 if (m_preedit.is_converting ()) {
1907 int idx = m_preedit.get_selected_segment ();
1908 if (idx < 0) {
1909 action_revert ();
1910 m_preedit.finish ();
1911 m_preedit.convert (FCITX_ANTHY_CANDIDATE_HIRAGANA, true);
1912 } else {
1913 int cand = m_preedit.get_selected_candidate ();
1914 switch (cand)
1915 {
1916 case FCITX_ANTHY_CANDIDATE_HIRAGANA:
1917 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_LATIN);
1918 break;
1919 case FCITX_ANTHY_CANDIDATE_KATAKANA:
1920 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HIRAGANA);
1921 break;
1922 case FCITX_ANTHY_CANDIDATE_HALF_KATAKANA:
1923 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_KATAKANA);
1924 break;
1925 case FCITX_ANTHY_CANDIDATE_WIDE_LATIN:
1926 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HALF_KATAKANA);
1927 break;
1928 case FCITX_ANTHY_CANDIDATE_LATIN:
1929 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_WIDE_LATIN);
1930 break;
1931 default:
1932 m_preedit.select_candidate (FCITX_ANTHY_CANDIDATE_HIRAGANA);
1933 break;
1934 }
1935 }
1936 } else {
1937 m_preedit.finish ();
1938 m_preedit.convert (FCITX_ANTHY_CANDIDATE_HIRAGANA, true);
1939 }
1940
1941 set_preedition ();
1942
1943 return true;
1944 }
1945
1946 bool
action_reconvert(void)1947 AnthyInstance::action_reconvert (void)
1948 {
1949 if (m_preedit.is_preediting ())
1950 return false;
1951
1952 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(m_owner);
1953
1954 if (!ic || !(ic->contextCaps & CAPACITY_SURROUNDING_TEXT)) {
1955 return true;
1956 }
1957 uint cursor_pos = 0;
1958 uint anchor_pos = 0;
1959 int32_t relative_selected_length = 0;
1960
1961 char* str = NULL;
1962 if (!FcitxInstanceGetSurroundingText(m_owner, ic, &str, &cursor_pos, &anchor_pos)) {
1963 return true;
1964 }
1965
1966 const std::string surrounding_text(str);
1967
1968 if (cursor_pos == anchor_pos) {
1969 const char* primary = NULL;
1970
1971 if ((primary = FcitxClipboardGetPrimarySelection(m_owner, NULL)) != NULL) {
1972 uint new_anchor_pos = 0;
1973 const std::string primary_text(primary);
1974 if (util_surrounding_get_anchor_pos_from_selection(
1975 surrounding_text, primary_text,
1976 cursor_pos, &new_anchor_pos)) {
1977 anchor_pos = new_anchor_pos;
1978 } else {
1979 return true;
1980 }
1981 } else {
1982 // There is no selection text.
1983 return true;
1984 }
1985 }
1986
1987 if (!util_surrounding_get_safe_delta(cursor_pos, anchor_pos,
1988 &relative_selected_length)) {
1989 return true;
1990 }
1991
1992 const uint32_t selection_start = std::min(cursor_pos, anchor_pos);
1993 const uint32_t selection_length = abs(relative_selected_length);
1994 std::string text = util_utf8_string_substr(surrounding_text, selection_start, selection_length);
1995
1996 FcitxInstanceDeleteSurroundingText(m_owner, ic,
1997 cursor_pos > anchor_pos ? -relative_selected_length : 0,
1998 selection_length);
1999
2000 m_preedit.convert(text);
2001 set_preedition ();
2002 set_lookup_table ();
2003
2004 return true;
2005 }
2006
2007 bool
action_add_word(void)2008 AnthyInstance::action_add_word (void)
2009 {
2010 util_launch_program (m_config.m_add_word_command);
2011
2012 return true;
2013 }
2014
2015 bool
action_launch_dict_admin_tool(void)2016 AnthyInstance::action_launch_dict_admin_tool (void)
2017 {
2018 util_launch_program (m_config.m_dict_admin_command);
2019
2020 return true;
2021 }
2022
2023 #if 0
2024 void
2025 AnthyInstance::action_regist_word (void)
2026 {
2027 }
2028 #endif
2029
2030 TypingMethod
get_typing_method(void)2031 AnthyInstance::get_typing_method (void)
2032 {
2033 return m_preedit.get_typing_method ();
2034 }
2035
2036 InputMode
get_input_mode(void)2037 AnthyInstance::get_input_mode (void)
2038 {
2039 return m_preedit.get_input_mode ();
2040 }
2041
2042 bool
is_single_segment(void)2043 AnthyInstance::is_single_segment (void)
2044 {
2045 if (m_config.m_conversion_mode == FCITX_ANTHY_CONVERSION_SINGLE_SEGMENT ||
2046 m_config.m_conversion_mode == FCITX_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE)
2047 return true;
2048 else
2049 return false;
2050 }
2051
2052 bool
is_realtime_conversion(void)2053 AnthyInstance::is_realtime_conversion (void)
2054 {
2055 if (m_config.m_conversion_mode == FCITX_ANTHY_CONVERSION_MULTI_SEGMENT_IMMEDIATE ||
2056 m_config.m_conversion_mode == FCITX_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE)
2057 return true;
2058 else
2059 return false;
2060 }
2061
2062 int
get_pseudo_ascii_mode(void)2063 AnthyInstance::get_pseudo_ascii_mode (void)
2064 {
2065 int retval = 0;
2066 TypingMethod m = get_typing_method ();
2067
2068 if (m == FCITX_ANTHY_TYPING_METHOD_ROMAJI) {
2069 if (m_config.m_romaji_pseudo_ascii_mode)
2070 retval |= FCITX_ANTHY_PSEUDO_ASCII_TRIGGERED_CAPITALIZED;
2071 }
2072
2073 return retval;
2074 }
2075
commit_string(std::string str)2076 void AnthyInstance::commit_string(std::string str)
2077 {
2078 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(m_owner);
2079 FcitxInstanceCommitString(m_owner, ic, str.c_str());
2080 }
2081
2082 #define APPEND_ACTION(key, func) \
2083 { \
2084 FcitxHotkey* hk = NULL; \
2085 std::string name = #key; \
2086 FcitxHotkeyFree(m_config.m_key_profile.m_hk_##key); \
2087 if (loaded) { \
2088 std::string str = (ACTION_CONFIG_##key##_KEY); \
2089 std::string keystr; \
2090 style.get_string (keystr, "KeyBindings", str); \
2091 FcitxHotkeySetKey(keystr.c_str(), m_config.m_key_profile.m_hk_##key); \
2092 hk = m_config.m_key_profile.m_hk_##key; \
2093 } else \
2094 hk = m_config.m_key_default.m_hk_##key; \
2095 PMF f; \
2096 f = &AnthyInstance::func; \
2097 m_actions[name] = Action (name, hk, f); \
2098 }
2099
2100 CONFIG_DESC_DEFINE(GetFcitxAnthyConfigDesc, "fcitx-anthy.desc")
2101
CONFIG_BINDING_BEGIN(FcitxAnthyConfig)2102 CONFIG_BINDING_BEGIN(FcitxAnthyConfig)
2103 CONFIG_BINDING_REGISTER("General", "CandidateLayout", m_candidate_layout)
2104 CONFIG_BINDING_REGISTER("General", "InputMode", m_input_mode)
2105 CONFIG_BINDING_REGISTER("General", "TypingMethod", m_typing_method)
2106 CONFIG_BINDING_REGISTER("General", "ConversionMode", m_conversion_mode)
2107 CONFIG_BINDING_REGISTER("General", "PeriodStyle", m_period_comma_style)
2108 CONFIG_BINDING_REGISTER("General", "SymbolStyle", m_symbol_style)
2109 CONFIG_BINDING_REGISTER("General", "PageSize", m_page_size)
2110 CONFIG_BINDING_REGISTER("General", "LearnOnManualCommit", m_learn_on_manual_commit)
2111 CONFIG_BINDING_REGISTER("General", "LearnOnAutoCommit", m_learn_on_auto_commit)
2112 CONFIG_BINDING_REGISTER("General", "AllowSplit", m_romaji_allow_split)
2113 CONFIG_BINDING_REGISTER("General", "UseDirectKeyOnPredict", m_use_direct_key_on_predict)
2114 CONFIG_BINDING_REGISTER("General", "NTriggersToShowCandWin", m_n_triggers_to_show_cand_win)
2115 CONFIG_BINDING_REGISTER("General", "ShowCandidatesLabel", m_show_candidates_label)
2116 CONFIG_BINDING_REGISTER("General", "ShowInputMode", m_show_input_mode_on_focus)
2117
2118 CONFIG_BINDING_REGISTER("Interface", "ShowInputMode", m_show_input_mode_label)
2119 CONFIG_BINDING_REGISTER("Interface", "ShowTypingMethod", m_show_typing_method_label)
2120 CONFIG_BINDING_REGISTER("Interface", "ShowConversionMode", m_show_conv_mode_label)
2121 CONFIG_BINDING_REGISTER("Interface", "ShowPeriodStyle", m_show_period_style_label)
2122 CONFIG_BINDING_REGISTER("Interface", "ShowSymbolStyle", m_show_symbol_style_label)
2123
2124 CONFIG_BINDING_REGISTER("KeyProfile", "KeyBindingProfile", m_key_profile_enum)
2125 CONFIG_BINDING_REGISTER("KeyProfile", "RomajiTable", m_romaji_table_enum)
2126 CONFIG_BINDING_REGISTER("KeyProfile", "KanaTable", m_kana_table_enum)
2127 CONFIG_BINDING_REGISTER("KeyProfile", "NicolaTable", m_nicola_table_enum)
2128 CONFIG_BINDING_REGISTER("KeyProfile", "CustomKeyBindingProfile", m_key_theme_file)
2129 CONFIG_BINDING_REGISTER("KeyProfile", "CustomRomajiTable", m_romaji_fundamental_table)
2130 CONFIG_BINDING_REGISTER("KeyProfile", "CustomKanaTable", m_kana_fundamental_table)
2131 CONFIG_BINDING_REGISTER("KeyProfile", "CustomNicolaTable", m_nicola_fundamental_table)
2132
2133 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CIRCLE_INPUT_MODE_KEY, m_key_default.m_hk_CIRCLE_INPUT_MODE)
2134 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CIRCLE_KANA_MODE_KEY, m_key_default.m_hk_CIRCLE_KANA_MODE)
2135 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CIRCLE_LATIN_HIRAGANA_MODE_KEY, m_key_default.m_hk_CIRCLE_LATIN_HIRAGANA_MODE)
2136 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CIRCLE_TYPING_METHOD_KEY, m_key_default.m_hk_CIRCLE_TYPING_METHOD)
2137 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_LATIN_MODE_KEY, m_key_default.m_hk_LATIN_MODE)
2138 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_WIDE_LATIN_MODE_KEY, m_key_default.m_hk_WIDE_LATIN_MODE)
2139 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_HIRAGANA_MODE_KEY, m_key_default.m_hk_HIRAGANA_MODE)
2140 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_KATAKANA_MODE_KEY, m_key_default.m_hk_KATAKANA_MODE)
2141 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_HALF_KATAKANA_MODE_KEY, m_key_default.m_hk_HALF_KATAKANA_MODE)
2142 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CANCEL_PSEUDO_ASCII_MODE_KEY, m_key_default.m_hk_CANCEL_PSEUDO_ASCII_MODE)
2143
2144 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_INSERT_SPACE_KEY, m_key_default.m_hk_INSERT_SPACE)
2145 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_INSERT_ALT_SPACE_KEY, m_key_default.m_hk_INSERT_ALT_SPACE)
2146 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_INSERT_HALF_SPACE_KEY, m_key_default.m_hk_INSERT_HALF_SPACE)
2147 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_INSERT_WIDE_SPACE_KEY, m_key_default.m_hk_INSERT_WIDE_SPACE)
2148 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_BACKSPACE_KEY, m_key_default.m_hk_BACKSPACE)
2149 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_DELETE_KEY, m_key_default.m_hk_DELETE)
2150 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_KEY, m_key_default.m_hk_COMMIT)
2151 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_REVERSE_LEARN_KEY, m_key_default.m_hk_COMMIT_REVERSE_LEARN)
2152 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONVERT_KEY, m_key_default.m_hk_CONVERT)
2153 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_PREDICT_KEY, m_key_default.m_hk_PREDICT)
2154 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CANCEL_KEY, m_key_default.m_hk_CANCEL)
2155 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CANCEL_ALL_KEY, m_key_default.m_hk_CANCEL_ALL)
2156
2157 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_MOVE_CARET_FIRST_KEY, m_key_default.m_hk_MOVE_CARET_FIRST)
2158 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_MOVE_CARET_LAST_KEY, m_key_default.m_hk_MOVE_CARET_LAST)
2159 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_MOVE_CARET_FORWARD_KEY, m_key_default.m_hk_MOVE_CARET_FORWARD)
2160 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_MOVE_CARET_BACKWARD_KEY, m_key_default.m_hk_MOVE_CARET_BACKWARD)
2161
2162 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_FIRST_SEGMENT_KEY, m_key_default.m_hk_SELECT_FIRST_SEGMENT)
2163 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_LAST_SEGMENT_KEY, m_key_default.m_hk_SELECT_LAST_SEGMENT)
2164 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_NEXT_SEGMENT_KEY, m_key_default.m_hk_SELECT_NEXT_SEGMENT)
2165 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_PREV_SEGMENT_KEY, m_key_default.m_hk_SELECT_PREV_SEGMENT)
2166 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SHRINK_SEGMENT_KEY, m_key_default.m_hk_SHRINK_SEGMENT)
2167 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_EXPAND_SEGMENT_KEY, m_key_default.m_hk_EXPAND_SEGMENT)
2168 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_FIRST_SEGMENT_KEY, m_key_default.m_hk_COMMIT_FIRST_SEGMENT)
2169 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_SELECTED_SEGMENT_KEY, m_key_default.m_hk_COMMIT_SELECTED_SEGMENT)
2170 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_FIRST_SEGMENT_REVERSE_LEARN_KEY, m_key_default.m_hk_COMMIT_FIRST_SEGMENT_REVERSE_LEARN)
2171 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_COMMIT_SELECTED_SEGMENT_REVERSE_LEARN_KEY, m_key_default.m_hk_COMMIT_SELECTED_SEGMENT_REVERSE_LEARN)
2172
2173 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_FIRST_CANDIDATE_KEY, m_key_default.m_hk_SELECT_FIRST_CANDIDATE)
2174 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_LAST_CANDIDATE_KEY, m_key_default.m_hk_SELECT_LAST_CANDIDATE)
2175 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_NEXT_CANDIDATE_KEY, m_key_default.m_hk_SELECT_NEXT_CANDIDATE)
2176 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_PREV_CANDIDATE_KEY, m_key_default.m_hk_SELECT_PREV_CANDIDATE)
2177 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_NEXT_CANDIDATE_ALTER_KEY, m_key_default.m_hk_SELECT_NEXT_CANDIDATE_ALTER)
2178 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_SELECT_PREV_CANDIDATE_ALTER_KEY, m_key_default.m_hk_SELECT_PREV_CANDIDATE_ALTER)
2179 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CANDIDATES_PAGE_UP_KEY, m_key_default.m_hk_CANDIDATES_PAGE_UP)
2180 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CANDIDATES_PAGE_DOWN_KEY, m_key_default.m_hk_CANDIDATES_PAGE_DOWN)
2181
2182 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_CHAR_TYPE_FORWARD_KEY, m_key_default.m_hk_CONV_CHAR_TYPE_FORWARD)
2183 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_CHAR_TYPE_BACKWARD_KEY, m_key_default.m_hk_CONV_CHAR_TYPE_BACKWARD)
2184 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_HIRAGANA_KEY, m_key_default.m_hk_CONV_TO_HIRAGANA)
2185 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_KATAKANA_KEY, m_key_default.m_hk_CONV_TO_KATAKANA)
2186 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_HALF_KEY, m_key_default.m_hk_CONV_TO_HALF)
2187 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_HALF_KATAKANA_KEY, m_key_default.m_hk_CONV_TO_HALF_KATAKANA)
2188 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_WIDE_LATIN_KEY, m_key_default.m_hk_CONV_TO_WIDE_LATIN)
2189 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_CONV_TO_LATIN_KEY, m_key_default.m_hk_CONV_TO_LATIN)
2190
2191 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_RECONVERT_KEY, m_key_default.m_hk_RECONVERT)
2192
2193 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_DICT_ADMIN_KEY, m_key_default.m_hk_DICT_ADMIN)
2194 CONFIG_BINDING_REGISTER("Key", ACTION_CONFIG_ADD_WORD_KEY, m_key_default.m_hk_ADD_WORD)
2195 CONFIG_BINDING_REGISTER("Key", "LeftThumbKey", m_left_thumb_keys)
2196 CONFIG_BINDING_REGISTER("Key", "RightThumbKey", m_right_thumb_keys)
2197 CONFIG_BINDING_REGISTER("Key", "KanaLayoutRoKey", m_kana_layout_ro_key)
2198 CONFIG_BINDING_REGISTER("Key", "NicolaTime", m_nicola_time)
2199
2200 CONFIG_BINDING_REGISTER("Command", "AddWord", m_add_word_command)
2201 CONFIG_BINDING_REGISTER("Command", "DictAdmin", m_dict_admin_command)
2202 CONFIG_BINDING_END()
2203
2204 std::string AnthyInstance::get_key_profile()
2205 {
2206 const char* key_profile[] = {
2207 "",
2208 "atok.sty",
2209 "canna.sty",
2210 "msime.sty",
2211 "vje-delta.sty",
2212 "wnn.sty",
2213 m_config.m_key_theme_file
2214 };
2215
2216 if (m_config.m_key_profile_enum >= ARRAY_LEN(key_profile))
2217 m_config.m_key_profile_enum = 0;
2218
2219 return key_profile[m_config.m_key_profile_enum] ? key_profile[m_config.m_key_profile_enum] : "" ;
2220 }
2221
2222
get_romaji_table()2223 std::string AnthyInstance::get_romaji_table()
2224 {
2225 const char* key_profile[] = {
2226 "",
2227 "atok.sty",
2228 "azik.sty",
2229 "canna.sty",
2230 "msime.sty",
2231 "vje-delta.sty",
2232 "wnn.sty",
2233 m_config.m_romaji_fundamental_table
2234 };
2235
2236 if (m_config.m_romaji_table_enum >= ARRAY_LEN(key_profile))
2237 m_config.m_romaji_table_enum = 0;
2238
2239 return key_profile[m_config.m_romaji_table_enum];
2240 }
2241
2242
get_kana_table()2243 std::string AnthyInstance::get_kana_table()
2244 {
2245 const char* key_profile[] = {
2246 "",
2247 "101kana.sty",
2248 "tsuki-2-203-101.sty",
2249 "tsuki-2-203-106.sty",
2250 "qkana.sty",
2251 m_config.m_kana_fundamental_table
2252 };
2253
2254 if (m_config.m_kana_table_enum >= ARRAY_LEN(key_profile))
2255 m_config.m_kana_table_enum = 0;
2256
2257 return key_profile[m_config.m_kana_table_enum];
2258 }
2259
2260
get_nicola_table()2261 std::string AnthyInstance::get_nicola_table()
2262 {
2263 const char* key_profile[] = {
2264 "",
2265 "nicola-a.sty",
2266 "nicola-f.sty",
2267 "nicola-j.sty",
2268 "oasys100j.sty"
2269 "tron-dvorak.sty",
2270 "tron-qwerty-jp.sty",
2271 m_config.m_nicola_fundamental_table
2272 };
2273
2274 if (m_config.m_nicola_table_enum >= ARRAY_LEN(key_profile))
2275 m_config.m_nicola_table_enum = 0;
2276
2277 return key_profile[m_config.m_nicola_table_enum];
2278 }
2279
load_config()2280 bool AnthyInstance::load_config()
2281 {
2282 FcitxConfigFileDesc *configDesc = GetFcitxAnthyConfigDesc();
2283 if (!configDesc)
2284 return false;
2285
2286 FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-anthy.config", "r", NULL);
2287
2288 if (!fp) {
2289 if (errno == ENOENT)
2290 save_config();
2291 }
2292 FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc);
2293
2294 FcitxAnthyConfigConfigBind(&m_config, cfile, configDesc);
2295 FcitxConfigBindSync(&m_config.gconfig);
2296
2297 if (fp)
2298 fclose(fp);
2299
2300 configure();
2301 return true;
2302 }
2303
save_config()2304 void AnthyInstance::save_config()
2305 {
2306 FcitxConfigFileDesc *configDesc = GetFcitxAnthyConfigDesc();
2307 FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-anthy.config", "w", NULL);
2308 FcitxConfigSaveConfigFileFp(fp, &m_config.gconfig, configDesc);
2309 if (fp)
2310 fclose(fp);
2311 }
2312
get_file_name(const std::string & name)2313 char* AnthyInstance::get_file_name(const std::string& name)
2314 {
2315 char* retFile = NULL;
2316 FILE* fp = FcitxXDGGetFileWithPrefix("anthy", name.c_str(), "r", &retFile);
2317 if (fp) {
2318 fclose(fp);
2319 }
2320 return retFile;
2321 }
2322
configure()2323 void AnthyInstance::configure()
2324 {
2325 StyleFile style;
2326 std::string file;
2327 bool loaded = false;
2328
2329 // load key bindings
2330 char* filename = get_file_name(get_key_profile());
2331 if (filename)
2332 loaded = style.load (filename);
2333
2334 fcitx_utils_free(filename);
2335
2336 // clear old actions
2337 m_actions.clear ();
2338 // convert key
2339 APPEND_ACTION (CONVERT, action_convert);
2340 APPEND_ACTION (PREDICT, action_predict);
2341
2342 // candidates keys
2343 APPEND_ACTION (CANDIDATES_PAGE_UP, action_candidates_page_up);
2344 APPEND_ACTION (CANDIDATES_PAGE_DOWN, action_candidates_page_down);
2345 APPEND_ACTION (SELECT_FIRST_CANDIDATE, action_select_first_candidate);
2346 APPEND_ACTION (SELECT_LAST_CANDIDATE, action_select_last_candidate);
2347 APPEND_ACTION (SELECT_NEXT_CANDIDATE, action_select_next_candidate);
2348 APPEND_ACTION (SELECT_PREV_CANDIDATE, action_select_prev_candidate);
2349 APPEND_ACTION (SELECT_NEXT_CANDIDATE_ALTER, action_select_next_candidate);
2350 APPEND_ACTION (SELECT_PREV_CANDIDATE_ALTER, action_select_prev_candidate);
2351
2352 // segment keys
2353 APPEND_ACTION (SELECT_FIRST_SEGMENT, action_select_first_segment);
2354 APPEND_ACTION (SELECT_LAST_SEGMENT, action_select_last_segment);
2355 APPEND_ACTION (SELECT_NEXT_SEGMENT, action_select_next_segment);
2356 APPEND_ACTION (SELECT_PREV_SEGMENT, action_select_prev_segment);
2357 APPEND_ACTION (SHRINK_SEGMENT, action_shrink_segment);
2358 APPEND_ACTION (EXPAND_SEGMENT, action_expand_segment);
2359 APPEND_ACTION (COMMIT_FIRST_SEGMENT, action_commit_first_segment);
2360 APPEND_ACTION (COMMIT_SELECTED_SEGMENT, action_commit_selected_segment);
2361 APPEND_ACTION (COMMIT_FIRST_SEGMENT_REVERSE_LEARN,
2362 action_commit_first_segment_reverse_preference);
2363 APPEND_ACTION (COMMIT_SELECTED_SEGMENT_REVERSE_LEARN,
2364 action_commit_selected_segment_reverse_preference);
2365
2366 // direct convert keys
2367 APPEND_ACTION (CONV_CHAR_TYPE_FORWARD, action_convert_char_type_forward);
2368 APPEND_ACTION (CONV_CHAR_TYPE_BACKWARD, action_convert_char_type_backward);
2369 APPEND_ACTION (CONV_TO_HIRAGANA, action_convert_to_hiragana);
2370 APPEND_ACTION (CONV_TO_KATAKANA, action_convert_to_katakana);
2371 APPEND_ACTION (CONV_TO_HALF, action_convert_to_half);
2372 APPEND_ACTION (CONV_TO_HALF_KATAKANA, action_convert_to_half_katakana);
2373 APPEND_ACTION (CONV_TO_LATIN, action_convert_to_latin);
2374 APPEND_ACTION (CONV_TO_WIDE_LATIN, action_convert_to_wide_latin);
2375
2376 // pseudo ascii mode
2377 APPEND_ACTION (CANCEL_PSEUDO_ASCII_MODE,action_cancel_pseudo_ascii_mode);
2378
2379 // caret keys
2380 APPEND_ACTION (MOVE_CARET_FIRST, action_move_caret_first);
2381 APPEND_ACTION (MOVE_CARET_LAST, action_move_caret_last);
2382 APPEND_ACTION (MOVE_CARET_FORWARD, action_move_caret_forward);
2383 APPEND_ACTION (MOVE_CARET_BACKWARD, action_move_caret_backward);
2384
2385 // edit keys
2386 APPEND_ACTION (BACKSPACE, action_back);
2387 APPEND_ACTION (DELETE, action_delete);
2388 APPEND_ACTION (COMMIT, action_commit_follow_preference);
2389 APPEND_ACTION (COMMIT_REVERSE_LEARN, action_commit_reverse_preference);
2390 APPEND_ACTION (CANCEL, action_revert);
2391 APPEND_ACTION (CANCEL_ALL, action_cancel_all);
2392 APPEND_ACTION (INSERT_SPACE, action_insert_space);
2393 APPEND_ACTION (INSERT_ALT_SPACE, action_insert_alternative_space);
2394 APPEND_ACTION (INSERT_HALF_SPACE, action_insert_half_space);
2395 APPEND_ACTION (INSERT_WIDE_SPACE, action_insert_wide_space);
2396
2397 // mode keys
2398 APPEND_ACTION (CIRCLE_INPUT_MODE, action_circle_input_mode);
2399 APPEND_ACTION (CIRCLE_KANA_MODE, action_circle_kana_mode);
2400 APPEND_ACTION (CIRCLE_LATIN_HIRAGANA_MODE,action_circle_latin_hiragana_mode);
2401 APPEND_ACTION (CIRCLE_TYPING_METHOD, action_circle_typing_method);
2402 APPEND_ACTION (LATIN_MODE, action_latin_mode);
2403 APPEND_ACTION (WIDE_LATIN_MODE, action_wide_latin_mode);
2404 APPEND_ACTION (HIRAGANA_MODE, action_hiragana_mode);
2405 APPEND_ACTION (KATAKANA_MODE, action_katakana_mode);
2406 APPEND_ACTION (HALF_KATAKANA_MODE, action_half_katakana_mode);
2407
2408 // dict keys
2409 APPEND_ACTION (DICT_ADMIN, action_launch_dict_admin_tool);
2410 APPEND_ACTION (ADD_WORD, action_add_word);
2411
2412 // reconvert
2413 APPEND_ACTION (RECONVERT, action_reconvert);
2414
2415 // load custom romaji table
2416 if (m_config.m_custom_romaji_table) {
2417 delete m_config.m_custom_romaji_table;
2418 m_config.m_custom_romaji_table = NULL;
2419 }
2420 const char *section_romaji = "RomajiTable/FundamentalTable";
2421 filename = get_file_name(get_romaji_table());
2422 if (filename && style.load (filename)) {
2423 m_config.m_custom_romaji_table = style.get_key2kana_table (section_romaji);
2424 }
2425 fcitx_utils_free(filename);
2426
2427 // load custom kana table
2428 if (m_config.m_custom_kana_table) {
2429 delete m_config.m_custom_kana_table;
2430 m_config.m_custom_kana_table = NULL;
2431 }
2432 const char *section_kana = "KanaTable/FundamentalTable";
2433 filename = get_file_name(get_kana_table());
2434 if (filename && style.load (filename)) {
2435 m_config.m_custom_kana_table = style.get_key2kana_table (section_kana);
2436 }
2437 fcitx_utils_free(filename);
2438
2439 // load custom NICOLA table
2440 if (m_config.m_custom_nicola_table) {
2441 delete m_config.m_custom_nicola_table;
2442 m_config.m_custom_nicola_table = NULL;
2443 }
2444 const char *section_nicola = "NICOLATable/FundamentalTable";
2445 filename = get_file_name(get_nicola_table());
2446 if (filename && style.load (filename)) {
2447 m_config.m_custom_nicola_table = style.get_key2kana_table (section_nicola);
2448 }
2449 fcitx_utils_free(filename);
2450
2451 // set romaji settings
2452 m_preedit.set_symbol_width (m_config.m_romaji_half_symbol);
2453 m_preedit.set_number_width (m_config.m_romaji_half_number);
2454
2455 // set input mode
2456 m_preedit.set_input_mode (m_config.m_input_mode);
2457
2458 // set typing method and pseudo ASCII mode
2459 m_preedit.set_typing_method (m_config.m_typing_method);
2460 m_preedit.set_pseudo_ascii_mode (get_pseudo_ascii_mode ());
2461
2462 // set period style
2463 set_period_style(m_config.m_period_comma_style);
2464
2465 // set symbol style
2466 set_symbol_style(m_config.m_symbol_style);
2467
2468 // setup toolbar
2469 install_properties ();
2470 }
2471
update_aux_string(const std::string & str)2472 void AnthyInstance::update_aux_string(const std::string& str)
2473 {
2474 FcitxMessages* aux;
2475 aux = m_aux_up;
2476 FcitxMessagesSetMessageCount(aux, 0);
2477 FcitxMessagesAddMessageAtLast(aux, MSG_TIPS, "%s", str.c_str());
2478 m_ui_update = true;
2479 }
2480
reset_cursor(int cursor)2481 void AnthyInstance::reset_cursor(int cursor)
2482 {
2483 if (cursor >= 0)
2484 m_cursor_pos = cursor;
2485 else
2486 cursor = 0;
2487 }
2488
auto_commit(FcitxIMCloseEventType type)2489 void AnthyInstance::auto_commit(FcitxIMCloseEventType type)
2490 {
2491 if (type == CET_LostFocus) {
2492 action_commit(m_config.m_learn_on_auto_commit, false);
2493 } else if (type == CET_ChangeByUser) {
2494 reset_im();
2495 } else if (type == CET_ChangeByInactivate) {
2496 FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(m_owner);
2497 if (config->bSendTextWhenSwitchEng)
2498 action_commit(m_config.m_learn_on_manual_commit);
2499 else
2500 reset_im();
2501 }
2502 }
2503
2504 /*
2505 vi:ts=4:nowrap:ai:expandtab
2506 */
2507