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 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 /*
22 * The original code is scim_uim_imengine.cpp in scim-uim-0.1.3.
23 * Copyright (C) 2004 James Su <suzhe@tsinghua.org.cn>
24 */
25
26 #define Uses_SCIM_UTILITY
27 #define Uses_SCIM_IMENGINE
28 #define Uses_SCIM_LOOKUP_TABLE
29 #define Uses_SCIM_CONFIG_BASE
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38
39 #include <scim.h>
40 #include "scim_anthy_factory.h"
41 #include "scim_anthy_imengine.h"
42 #include "scim_anthy_prefs.h"
43 #include "scim_anthy_intl.h"
44 #include "scim_anthy_utils.h"
45 #include "scim_anthy_helper.h"
46
47 #define SCIM_PROP_PREFIX "/IMEngine/Anthy"
48 #define SCIM_PROP_INPUT_MODE "/IMEngine/Anthy/InputMode"
49 #define SCIM_PROP_INPUT_MODE_HIRAGANA "/IMEngine/Anthy/InputMode/Hiragana"
50 #define SCIM_PROP_INPUT_MODE_KATAKANA "/IMEngine/Anthy/InputMode/Katakana"
51 #define SCIM_PROP_INPUT_MODE_HALF_KATAKANA "/IMEngine/Anthy/InputMode/HalfKatakana"
52 #define SCIM_PROP_INPUT_MODE_LATIN "/IMEngine/Anthy/InputMode/Latin"
53 #define SCIM_PROP_INPUT_MODE_WIDE_LATIN "/IMEngine/Anthy/InputMode/WideLatin"
54
55 #define SCIM_PROP_CONV_MODE "/IMEngine/Anthy/ConvMode"
56 #define SCIM_PROP_CONV_MODE_MULTI_SEG "/IMEngine/Anthy/ConvMode/MultiSegment"
57 #define SCIM_PROP_CONV_MODE_SINGLE_SEG "/IMEngine/Anthy/ConvMode/SingleSegment"
58 #define SCIM_PROP_CONV_MODE_MULTI_REAL_TIME "/IMEngine/Anthy/ConvMode/MultiRealTime"
59 #define SCIM_PROP_CONV_MODE_SINGLE_REAL_TIME "/IMEngine/Anthy/ConvMode/SingleRealTime"
60
61 #define SCIM_PROP_TYPING_METHOD "/IMEngine/Anthy/TypingMethod"
62 #define SCIM_PROP_TYPING_METHOD_ROMAJI "/IMEngine/Anthy/TypingMethod/RomaKana"
63 #define SCIM_PROP_TYPING_METHOD_KANA "/IMEngine/Anthy/TypingMethod/Kana"
64 #define SCIM_PROP_TYPING_METHOD_NICOLA "/IMEngine/Anthy/TypingMethod/NICOLA"
65
66 #define SCIM_PROP_PERIOD_STYLE "/IMEngine/Anthy/PeriodType"
67 #define SCIM_PROP_PERIOD_STYLE_JAPANESE "/IMEngine/Anthy/PeriodType/Japanese"
68 #define SCIM_PROP_PERIOD_STYLE_WIDE_LATIN "/IMEngine/Anthy/PeriodType/WideRatin"
69 #define SCIM_PROP_PERIOD_STYLE_LATIN "/IMEngine/Anthy/PeriodType/Ratin"
70 #define SCIM_PROP_PERIOD_STYLE_WIDE_LATIN_JAPANESE \
71 "/IMEngine/Anthy/PeriodType/WideRatin_Japanese"
72
73 #define SCIM_PROP_SYMBOL_STYLE "/IMEngine/Anthy/SymbolType"
74 #define SCIM_PROP_SYMBOL_STYLE_JAPANESE "/IMEngine/Anthy/SymbolType/Japanese"
75 #define SCIM_PROP_SYMBOL_STYLE_BRACKET_SLASH "/IMEngine/Anthy/SymbolType/WideBracket_WideSlash"
76 #define SCIM_PROP_SYMBOL_STYLE_CORNER_BRACKET_SLASH \
77 "/IMEngine/Anthy/SymbolType/CornerBracket_WideSlash"
78 #define SCIM_PROP_SYMBOL_STYLE_BRACKET_MIDDLE_DOT \
79 "/IMEngine/Anthy/SymbolType/WideBracket_MiddleDot"
80
81 #define SCIM_PROP_DICT "/IMEngine/Anthy/Dictionary"
82 #define SCIM_PROP_DICT_ADD_WORD "/IMEngine/Anthy/Dictionary/AddWord"
83 #define SCIM_PROP_DICT_LAUNCH_ADMIN_TOOL "/IMEngine/Anthy/Dictionary/LaunchAdminTool"
84
85 #define UTF8_BRACKET_CORNER_BEGIN "\xE3\x80\x8C"
86 #define UTF8_BRACKET_CORNER_END "\xE3\x80\x8D"
87 #define UTF8_BRACKET_WIDE_BEGIN "\xEF\xBC\xBB"
88 #define UTF8_BRACKET_WIDE_END "\xEF\xBC\xBD"
89 #define UTF8_MIDDLE_DOT "\xE3\x83\xBB"
90 #define UTF8_SLASH_WIDE "\xEF\xBC\x8F"
91
AnthyInstance(AnthyFactory * factory,const String & encoding,int id)92 AnthyInstance::AnthyInstance (AnthyFactory *factory,
93 const String &encoding,
94 int id)
95 : IMEngineInstanceBase (factory, encoding, id),
96 m_factory (factory),
97 m_on_init (true),
98 m_preedit (*this),
99 m_preedit_string_visible (false),
100 m_lookup_table_visible (false),
101 m_n_conv_key_pressed (0),
102 m_prev_input_mode (SCIM_ANTHY_MODE_HIRAGANA),
103 m_conv_mode (SCIM_ANTHY_CONVERSION_MULTI_SEGMENT),
104 m_helper_started (false),
105 m_timeout_id_seq (0)
106 {
107 SCIM_DEBUG_IMENGINE(1) << "Create Anthy Instance : ";
108
109 reload_config (m_factory->m_config);
110 m_factory->append_config_listener (this);
111 m_on_init = false;
112 }
113
~AnthyInstance()114 AnthyInstance::~AnthyInstance ()
115 {
116 if (m_helper_started)
117 stop_helper (String (SCIM_ANTHY_HELPER_UUID));
118
119 m_factory->remove_config_listener (this);
120 }
121
122 // FIXME!
123 bool
is_nicola_thumb_shift_key(const KeyEvent & key)124 AnthyInstance::is_nicola_thumb_shift_key (const KeyEvent &key)
125 {
126 if (get_typing_method () != SCIM_ANTHY_TYPING_METHOD_NICOLA)
127 return false;
128
129 if (util_match_key_event (m_factory->m_left_thumb_keys, key, 0xFFFF) ||
130 util_match_key_event (m_factory->m_right_thumb_keys, key, 0xFFFF))
131 {
132 return true;
133 }
134
135 return false;
136 }
137
138 bool
process_key_event_input(const KeyEvent & key)139 AnthyInstance::process_key_event_input (const KeyEvent &key)
140 {
141 // prediction while typing
142 if (m_factory->m_predict_on_input && key.is_key_release () &&
143 m_preedit.is_preediting () && !m_preedit.is_converting ())
144 {
145 CommonLookupTable table;
146 m_preedit.predict ();
147 m_preedit.get_candidates (table);
148 if (table.number_of_candidates () > 0) {
149 table.show_cursor (false);
150 update_lookup_table (table);
151 show_lookup_table ();
152 } else {
153 hide_lookup_table ();
154 }
155 }
156
157 if (!m_preedit.can_process_key_event (key)) {
158 return false;
159 }
160
161 if (m_preedit.is_converting ()) {
162 if (is_realtime_conversion ()) {
163 action_revert ();
164 } else if (!is_nicola_thumb_shift_key (key)) {
165 action_commit (m_factory->m_learn_on_auto_commit);
166 }
167 }
168
169 bool need_commit = m_preedit.process_key_event (key);
170
171 if (need_commit) {
172 if (is_realtime_conversion () &&
173 get_input_mode () != SCIM_ANTHY_MODE_LATIN &&
174 get_input_mode () != SCIM_ANTHY_MODE_WIDE_LATIN)
175 {
176 m_preedit.convert (SCIM_ANTHY_CANDIDATE_DEFAULT,
177 is_single_segment ());
178 }
179 action_commit (m_factory->m_learn_on_auto_commit);
180 } else {
181 if (is_realtime_conversion ()) {
182 m_preedit.convert (SCIM_ANTHY_CANDIDATE_DEFAULT,
183 is_single_segment ());
184 m_preedit.select_segment (-1);
185 }
186 show_preedit_string ();
187 m_preedit_string_visible = true;
188 set_preedition ();
189 }
190
191 return true;
192 }
193
194 bool
process_key_event_lookup_keybind(const KeyEvent & key)195 AnthyInstance::process_key_event_lookup_keybind (const KeyEvent& key)
196 {
197 std::vector<Action>::iterator it;
198
199 m_last_key = key;
200
201 /* try to find a "insert a blank" action to be not stolen a blank key
202 * when entering the pseudo ascii mode.
203 */
204 if (get_pseudo_ascii_mode () != 0 &&
205 m_factory->m_romaji_pseudo_ascii_blank_behavior &&
206 m_preedit.is_pseudo_ascii_mode ()) {
207 for (it = m_factory->m_actions.begin();
208 it != m_factory->m_actions.end();
209 it++) {
210 if (it->match_action_name ("INSERT_SPACE") &&
211 it->perform (this, key)) {
212 return true;
213 }
214 }
215 }
216 for (it = m_factory->m_actions.begin();
217 it != m_factory->m_actions.end();
218 it++)
219 {
220 if (it->perform (this, key)) {
221 m_last_key = KeyEvent ();
222 return true;
223 }
224 }
225
226 m_last_key = KeyEvent ();
227
228 return false;
229 }
230
231 bool
process_key_event_latin_mode(const KeyEvent & key)232 AnthyInstance::process_key_event_latin_mode (const KeyEvent &key)
233 {
234 if (key.is_key_release ())
235 return false;
236
237 if (util_key_is_keypad (key)) {
238 String str;
239 WideString wide;
240 util_keypad_to_string (str, key);
241 if (m_factory->m_ten_key_type == "Wide")
242 util_convert_to_wide (wide, str);
243 else
244 wide = utf8_mbstowcs (str);
245 if (wide.length () > 0) {
246 commit_string (wide);
247 return true;
248 } else {
249 return false;
250 }
251 } else {
252 // for Multi/Dead key
253 return false;
254 }
255 }
256
257 bool
process_key_event_wide_latin_mode(const KeyEvent & key)258 AnthyInstance::process_key_event_wide_latin_mode (const KeyEvent &key)
259 {
260 if (key.is_key_release ())
261 return false;
262
263 String str;
264 WideString wide;
265 util_keypad_to_string (str, key);
266 if (util_key_is_keypad (key) && m_factory->m_ten_key_type == "Half")
267 wide = utf8_mbstowcs (str);
268 else
269 util_convert_to_wide (wide, str);
270 if (wide.length () > 0) {
271 commit_string (wide);
272 return true;
273 }
274
275 return false;
276 }
277
278 bool
process_key_event(const KeyEvent & key)279 AnthyInstance::process_key_event (const KeyEvent& key)
280 {
281 SCIM_DEBUG_IMENGINE(2) << "process_key_event.\n";
282
283 // FIXME!
284 // for NICOLA thumb shift key
285 if (get_typing_method () == SCIM_ANTHY_TYPING_METHOD_NICOLA &&
286 is_nicola_thumb_shift_key (key))
287 {
288 if (process_key_event_input (key))
289 return true;
290 }
291
292 // lookup user defined key bindings
293 if (process_key_event_lookup_keybind (key))
294 return true;
295
296 // for Latin mode
297 if (m_preedit.get_input_mode () == SCIM_ANTHY_MODE_LATIN)
298 return process_key_event_latin_mode (key);
299
300 // for wide Latin mode
301 if (m_preedit.get_input_mode () == SCIM_ANTHY_MODE_WIDE_LATIN)
302 return process_key_event_wide_latin_mode (key);
303
304 // for other mode
305 if (get_typing_method () != SCIM_ANTHY_TYPING_METHOD_NICOLA ||
306 !is_nicola_thumb_shift_key (key))
307 {
308 if (process_key_event_input (key))
309 return true;
310 }
311
312 if (m_preedit.is_preediting ())
313 return true;
314 else
315 return false;
316 }
317
318 void
move_preedit_caret(unsigned int pos)319 AnthyInstance::move_preedit_caret (unsigned int pos)
320 {
321 m_preedit.set_caret_pos (pos);
322 update_preedit_caret (m_preedit.get_caret_pos());
323 }
324
325 void
select_candidate_no_direct(unsigned int item)326 AnthyInstance::select_candidate_no_direct (unsigned int item)
327 {
328 SCIM_DEBUG_IMENGINE(2) << "select_candidate_no_direct.\n";
329
330 if (m_preedit.is_predicting () && !m_preedit.is_converting ())
331 action_predict ();
332
333 if (!is_selecting_candidates ())
334 return;
335
336 // update lookup table
337 m_lookup_table.set_cursor_pos_in_current_page (item);
338 update_lookup_table (m_lookup_table);
339
340 // update preedit
341 m_preedit.select_candidate (m_lookup_table.get_cursor_pos ());
342 set_preedition ();
343
344 // update aux string
345 if (m_factory->m_show_candidates_label)
346 set_aux_string ();
347 }
348
349 void
select_candidate(unsigned int item)350 AnthyInstance::select_candidate (unsigned int item)
351 {
352 SCIM_DEBUG_IMENGINE(2) << "select_candidate.\n";
353
354 select_candidate_no_direct (item);
355
356 if (m_factory->m_close_cand_win_on_select) {
357 unset_lookup_table ();
358 action_select_next_segment();
359 }
360 }
361
362 void
update_lookup_table_page_size(unsigned int page_size)363 AnthyInstance::update_lookup_table_page_size (unsigned int page_size)
364 {
365 SCIM_DEBUG_IMENGINE(2) << "update_lookup_table_page_size.\n";
366
367 m_lookup_table.set_page_size (page_size);
368 }
369
370 void
lookup_table_page_up()371 AnthyInstance::lookup_table_page_up ()
372 {
373 if (!is_selecting_candidates () ||
374 !m_lookup_table.get_current_page_start ())
375 {
376 return;
377 }
378
379 SCIM_DEBUG_IMENGINE(2) << "lookup_table_page_up.\n";
380
381 m_lookup_table.page_up ();
382
383 update_lookup_table (m_lookup_table);
384 }
385
386 void
lookup_table_page_down()387 AnthyInstance::lookup_table_page_down ()
388 {
389 int page_start = m_lookup_table.get_current_page_start ();
390 int page_size = m_lookup_table.get_current_page_size ();
391 int num = m_lookup_table.number_of_candidates ();
392
393 if (!is_selecting_candidates () || page_start + page_size >= num)
394 return;
395
396 SCIM_DEBUG_IMENGINE(2) << "lookup_table_page_down.\n";
397
398 m_lookup_table.page_down ();
399
400 update_lookup_table (m_lookup_table);
401 }
402
403 void
reset()404 AnthyInstance::reset ()
405 {
406 SCIM_DEBUG_IMENGINE(2) << "reset.\n";
407
408 m_preedit.clear ();
409 m_lookup_table.clear ();
410 unset_lookup_table ();
411
412 hide_preedit_string ();
413 m_preedit_string_visible = false;
414 set_preedition ();
415 }
416
417 void
focus_in()418 AnthyInstance::focus_in ()
419 {
420 SCIM_DEBUG_IMENGINE(2) << "focus_in.\n";
421
422 if (m_preedit_string_visible) {
423 set_preedition ();
424 show_preedit_string ();
425 } else {
426 hide_preedit_string ();
427 }
428
429 if (m_lookup_table_visible && is_selecting_candidates ()) {
430 if (m_factory->m_show_candidates_label &&
431 m_lookup_table.number_of_candidates() > 0)
432 {
433 set_aux_string ();
434 show_aux_string ();
435 } else {
436 hide_aux_string ();
437 }
438 update_lookup_table (m_lookup_table);
439 show_lookup_table ();
440 } else {
441 hide_aux_string ();
442 hide_lookup_table ();
443 }
444
445 install_properties ();
446
447 if (!m_helper_started)
448 start_helper (String (SCIM_ANTHY_HELPER_UUID));
449
450 Transaction send;
451 send.put_command (SCIM_TRANS_CMD_REQUEST);
452 send.put_command (SCIM_TRANS_CMD_FOCUS_IN);
453 send_helper_event (String (SCIM_ANTHY_HELPER_UUID), send);
454 }
455
456 void
focus_out()457 AnthyInstance::focus_out ()
458 {
459 SCIM_DEBUG_IMENGINE(2) << "focus_out.\n";
460
461 if (m_preedit.is_preediting ()) {
462 if (m_factory->m_behavior_on_focus_out == "Clear")
463 reset ();
464 else if (m_factory->m_behavior_on_focus_out == "Commit")
465 action_commit (m_factory->m_learn_on_auto_commit);
466 else
467 action_commit (m_factory->m_learn_on_auto_commit);
468 }
469
470 Transaction send;
471 send.put_command (SCIM_TRANS_CMD_REQUEST);
472 send.put_command (SCIM_TRANS_CMD_FOCUS_OUT);
473 send_helper_event (String (SCIM_ANTHY_HELPER_UUID), send);
474 }
475
476 void
set_preedition(void)477 AnthyInstance::set_preedition (void)
478 {
479 update_preedit_string (m_preedit.get_string (),
480 m_preedit.get_attribute_list ());
481 update_preedit_caret (m_preedit.get_caret_pos());
482 }
483
484 void
set_aux_string(void)485 AnthyInstance::set_aux_string (void)
486 {
487 char buf[256];
488 sprintf (buf, _("Candidates (%d/%d)"),
489 m_lookup_table.get_cursor_pos () + 1,
490 m_lookup_table.number_of_candidates ());
491 update_aux_string (utf8_mbstowcs (buf));
492 }
493
494 void
set_lookup_table(void)495 AnthyInstance::set_lookup_table (void)
496 {
497 m_n_conv_key_pressed++;
498
499 if (!is_selecting_candidates ()) {
500 if (is_realtime_conversion () &&
501 m_preedit.get_selected_segment () < 0)
502 {
503 // select latest segment
504 int n = m_preedit.get_nr_segments ();
505 if (n < 1)
506 return;
507 m_preedit.select_segment (n - 1);
508 }
509
510 // prepare candidates
511 m_preedit.get_candidates (m_lookup_table);
512
513 if (m_lookup_table.number_of_candidates () == 0)
514 return;
515
516 // set position
517 update_lookup_table (m_lookup_table);
518
519 // update preedit
520 m_preedit.select_candidate (m_lookup_table.get_cursor_pos ());
521 set_preedition ();
522
523 }
524
525 bool beyond_threshold =
526 m_factory->m_n_triggers_to_show_cand_win > 0 &&
527 (int) m_n_conv_key_pressed >= m_factory->m_n_triggers_to_show_cand_win;
528
529 if (!m_lookup_table_visible &&
530 (m_preedit.is_predicting () || beyond_threshold))
531 {
532 show_lookup_table ();
533 m_lookup_table_visible = true;
534 m_n_conv_key_pressed = 0;
535
536 if (m_factory->m_show_candidates_label) {
537 set_aux_string ();
538 show_aux_string ();
539 }
540 } else if (!m_lookup_table_visible) {
541 hide_lookup_table ();
542 }
543 }
544
545 void
unset_lookup_table(void)546 AnthyInstance::unset_lookup_table (void)
547 {
548 m_lookup_table.clear ();
549 hide_lookup_table ();
550 m_lookup_table_visible = false;
551 m_n_conv_key_pressed = 0;
552
553 update_aux_string (utf8_mbstowcs (""));
554 hide_aux_string ();
555 }
556
557 void
install_properties(void)558 AnthyInstance::install_properties (void)
559 {
560 if (m_properties.size () <= 0) {
561 Property prop;
562
563 if (m_factory->m_show_input_mode_label) {
564 prop = Property (SCIM_PROP_INPUT_MODE,
565 "\xE3\x81\x82", String (""), _("Input mode"));
566 m_properties.push_back (prop);
567
568 prop = Property (SCIM_PROP_INPUT_MODE_HIRAGANA,
569 _("Hiragana"), String (""), _("Hiragana"));
570 m_properties.push_back (prop);
571
572 prop = Property (SCIM_PROP_INPUT_MODE_KATAKANA,
573 _("Katakana"), String (""), _("Katakana"));
574 m_properties.push_back (prop);
575
576 prop = Property (SCIM_PROP_INPUT_MODE_HALF_KATAKANA,
577 _("Half width katakana"), String (""),
578 _("Half width katakana"));
579 m_properties.push_back (prop);
580
581 prop = Property (SCIM_PROP_INPUT_MODE_LATIN,
582 _("Latin"), String (""), _("Direct input"));
583 m_properties.push_back (prop);
584
585 prop = Property (SCIM_PROP_INPUT_MODE_WIDE_LATIN,
586 _("Wide latin"), String (""), _("Wide latin"));
587 m_properties.push_back (prop);
588 }
589
590 if (m_factory->m_show_typing_method_label) {
591 prop = Property (SCIM_PROP_TYPING_METHOD,
592 "\xEF\xBC\xB2", String (""), _("Typing method"));
593 m_properties.push_back (prop);
594
595 prop = Property (SCIM_PROP_TYPING_METHOD_ROMAJI,
596 _("Romaji"), String (""), _("Romaji"));
597 m_properties.push_back (prop);
598
599 prop = Property (SCIM_PROP_TYPING_METHOD_KANA,
600 _("Kana"), String (""), _("Kana"));
601 m_properties.push_back (prop);
602
603 prop = Property (SCIM_PROP_TYPING_METHOD_NICOLA,
604 _("Thumb shift"), String (""), _("Thumb shift"));
605 m_properties.push_back (prop);
606 }
607
608 if (m_factory->m_show_conv_mode_label) {
609 prop = Property (SCIM_PROP_CONV_MODE,
610 "\xE9\x80\xA3", String (""),
611 _("Conversion mode"));
612 m_properties.push_back (prop);
613
614 prop = Property (SCIM_PROP_CONV_MODE_MULTI_SEG,
615 _("Multi segment"), String (""),
616 _("Multi segment"));
617 m_properties.push_back (prop);
618
619 prop = Property (SCIM_PROP_CONV_MODE_SINGLE_SEG,
620 _("Single segment"), String (""),
621 _("Single segment"));
622 m_properties.push_back (prop);
623
624 prop = Property (SCIM_PROP_CONV_MODE_MULTI_REAL_TIME,
625 _("Convert as you type (Multi segment)"),
626 String (""),
627 _("Convert as you type (Multi segment)"));
628 m_properties.push_back (prop);
629
630 prop = Property (SCIM_PROP_CONV_MODE_SINGLE_REAL_TIME,
631 _("Convert as you type (Single segment)"),
632 String (""),
633 _("Convert as you type (Single segment)"));
634 m_properties.push_back (prop);
635 }
636
637 if (m_factory->m_show_period_style_label) {
638 prop = Property (SCIM_PROP_PERIOD_STYLE,
639 "\xE3\x80\x81\xE3\x80\x82", String (""),
640 _("Period style"));
641 m_properties.push_back (prop);
642
643 prop = Property (SCIM_PROP_PERIOD_STYLE_JAPANESE,
644 "\xE3\x80\x81\xE3\x80\x82", String (""),
645 "\xE3\x80\x81\xE3\x80\x82");
646 m_properties.push_back (prop);
647
648 prop = Property (SCIM_PROP_PERIOD_STYLE_WIDE_LATIN_JAPANESE,
649 "\xEF\xBC\x8C\xE3\x80\x82", String (""),
650 "\xEF\xBC\x8C\xE3\x80\x82");
651 m_properties.push_back (prop);
652
653 prop = Property (SCIM_PROP_PERIOD_STYLE_WIDE_LATIN,
654 "\xEF\xBC\x8C\xEF\xBC\x8E", String (""),
655 "\xEF\xBC\x8C\xEF\xBC\x8E");
656 m_properties.push_back (prop);
657
658 prop = Property (SCIM_PROP_PERIOD_STYLE_LATIN,
659 ",.", String (""), ",.");
660 m_properties.push_back (prop);
661 }
662
663 if (m_factory->m_show_symbol_style_label) {
664 prop = Property (SCIM_PROP_SYMBOL_STYLE,
665 UTF8_BRACKET_CORNER_BEGIN
666 UTF8_BRACKET_CORNER_END
667 UTF8_MIDDLE_DOT,
668 String (""),
669 _("Symbol style"));
670 m_properties.push_back (prop);
671
672 prop = Property (SCIM_PROP_SYMBOL_STYLE_JAPANESE,
673 UTF8_BRACKET_CORNER_BEGIN
674 UTF8_BRACKET_CORNER_END
675 UTF8_MIDDLE_DOT,
676 String (""),
677 UTF8_BRACKET_CORNER_BEGIN
678 UTF8_BRACKET_CORNER_END
679 UTF8_MIDDLE_DOT);
680 m_properties.push_back (prop);
681
682 prop = Property (SCIM_PROP_SYMBOL_STYLE_CORNER_BRACKET_SLASH,
683 UTF8_BRACKET_CORNER_BEGIN
684 UTF8_BRACKET_CORNER_END
685 UTF8_SLASH_WIDE,
686 String (""),
687 UTF8_BRACKET_CORNER_BEGIN
688 UTF8_BRACKET_CORNER_END
689 UTF8_SLASH_WIDE);
690 m_properties.push_back (prop);
691
692 prop = Property (SCIM_PROP_SYMBOL_STYLE_BRACKET_MIDDLE_DOT,
693 UTF8_BRACKET_WIDE_BEGIN
694 UTF8_BRACKET_WIDE_END
695 UTF8_MIDDLE_DOT,
696 String (""),
697 UTF8_BRACKET_WIDE_BEGIN
698 UTF8_BRACKET_WIDE_END
699 UTF8_MIDDLE_DOT);
700 m_properties.push_back (prop);
701
702 prop = Property (SCIM_PROP_SYMBOL_STYLE_BRACKET_SLASH,
703 UTF8_BRACKET_WIDE_BEGIN
704 UTF8_BRACKET_WIDE_END
705 UTF8_SLASH_WIDE,
706 String (""),
707 UTF8_BRACKET_WIDE_BEGIN
708 UTF8_BRACKET_WIDE_END
709 UTF8_SLASH_WIDE);
710 m_properties.push_back (prop);
711 }
712
713 if (m_factory->m_show_dict_label) {
714 prop = Property (SCIM_PROP_DICT,
715 String(""), //_("Dictionary"),
716 String (SCIM_ICONDIR "/" "scim-anthy-dict.png"),
717 _("Dictionary menu"));
718 m_properties.push_back (prop);
719
720 if (m_factory->m_show_dict_admin_label) {
721 prop = Property (SCIM_PROP_DICT_LAUNCH_ADMIN_TOOL,
722 _("Edit the dictionary"),
723 String (SCIM_ICONDIR "/" "scim-anthy-dict.png"),
724 _("Launch the dictionary administration tool."));
725 m_properties.push_back (prop);
726 }
727
728 if (m_factory->m_show_add_word_label) {
729 prop = Property (SCIM_PROP_DICT_ADD_WORD,
730 _("Add a word"),
731 String (SCIM_ICONDIR "/" "scim-anthy-dict.png"),
732 _("Add a word to the dictionary."));
733 m_properties.push_back (prop);
734 }
735 }
736 }
737
738 set_input_mode(get_input_mode ());
739 set_conversion_mode (m_conv_mode);
740 set_typing_method (get_typing_method ());
741 set_period_style (m_preedit.get_period_style (),
742 m_preedit.get_comma_style ());
743 set_symbol_style (m_preedit.get_bracket_style (),
744 m_preedit.get_slash_style ());
745
746 register_properties (m_properties);
747 }
748
749 void
set_input_mode(InputMode mode)750 AnthyInstance::set_input_mode (InputMode mode)
751 {
752 const char *label = "";
753
754 switch (mode) {
755 case SCIM_ANTHY_MODE_HIRAGANA:
756 label = "\xE3\x81\x82";
757 break;
758 case SCIM_ANTHY_MODE_KATAKANA:
759 label = "\xE3\x82\xA2";
760 break;
761 case SCIM_ANTHY_MODE_HALF_KATAKANA:
762 label = "_\xEF\xBD\xB1";
763 break;
764 case SCIM_ANTHY_MODE_LATIN:
765 label = "_A";
766 break;
767 case SCIM_ANTHY_MODE_WIDE_LATIN:
768 label = "\xEF\xBC\xA1";
769 break;
770 default:
771 break;
772 }
773
774 if (label && *label && m_factory->m_show_input_mode_label) {
775 PropertyList::iterator it = std::find (m_properties.begin (),
776 m_properties.end (),
777 SCIM_PROP_INPUT_MODE);
778 if (it != m_properties.end ()) {
779 it->set_label (label);
780 update_property (*it);
781 }
782 }
783
784 if (mode != get_input_mode ()) {
785 m_preedit.set_input_mode (mode);
786 set_preedition ();
787 }
788 }
789
790 void
set_conversion_mode(ConversionMode mode)791 AnthyInstance::set_conversion_mode (ConversionMode mode)
792 {
793 const char *label = "";
794
795 switch (mode) {
796 case SCIM_ANTHY_CONVERSION_MULTI_SEGMENT:
797 label = "\xE9\x80\xA3";
798 break;
799 case SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT:
800 label = "\xE5\x8D\x98";
801 break;
802 case SCIM_ANTHY_CONVERSION_MULTI_SEGMENT_IMMEDIATE:
803 label = "\xE9\x80\x90 \xE9\x80\xA3";
804 break;
805 case SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE:
806 label = "\xE9\x80\x90 \xE5\x8D\x98";
807 break;
808 default:
809 break;
810 }
811
812 if (label && *label /*&& m_factory->m_show_input_mode_label*/) {
813 PropertyList::iterator it = std::find (m_properties.begin (),
814 m_properties.end (),
815 SCIM_PROP_CONV_MODE);
816 if (it != m_properties.end ()) {
817 it->set_label (label);
818 update_property (*it);
819 }
820 }
821
822 m_conv_mode = mode;
823 }
824
825 void
set_typing_method(TypingMethod method)826 AnthyInstance::set_typing_method (TypingMethod method)
827 {
828 const char *label = "";
829
830 switch (method) {
831 case SCIM_ANTHY_TYPING_METHOD_ROMAJI:
832 label = "\xEF\xBC\xB2";
833 break;
834 case SCIM_ANTHY_TYPING_METHOD_KANA:
835 label = "\xE3\x81\x8B";
836 break;
837 case SCIM_ANTHY_TYPING_METHOD_NICOLA:
838 label = "\xE8\xA6\xAA";
839 break;
840 default:
841 break;
842 }
843
844 if (label && *label && m_factory->m_show_typing_method_label) {
845 PropertyList::iterator it = std::find (m_properties.begin (),
846 m_properties.end (),
847 SCIM_PROP_TYPING_METHOD);
848 if (it != m_properties.end ()) {
849 it->set_label (label);
850 update_property (*it);
851 }
852 }
853
854 if (method != get_typing_method ()) {
855 Key2KanaTable *fundamental_table = NULL;
856
857 if (method == SCIM_ANTHY_TYPING_METHOD_ROMAJI) {
858 fundamental_table = m_factory->m_custom_romaji_table;
859 } else if (method == SCIM_ANTHY_TYPING_METHOD_KANA) {
860 fundamental_table = m_factory->m_custom_kana_table;
861 }
862 m_preedit.set_typing_method (method);
863 m_preedit.set_pseudo_ascii_mode (get_pseudo_ascii_mode ());
864 }
865 }
866
867 void
set_period_style(PeriodStyle period,CommaStyle comma)868 AnthyInstance::set_period_style (PeriodStyle period,
869 CommaStyle comma)
870 {
871 String label;
872
873 switch (comma) {
874 case SCIM_ANTHY_COMMA_JAPANESE:
875 label = "\xE3\x80\x81";
876 break;
877 case SCIM_ANTHY_COMMA_WIDE:
878 label = "\xEF\xBC\x8C";
879 break;
880 case SCIM_ANTHY_COMMA_HALF:
881 label = ",";
882 break;
883 default:
884 break;
885 }
886
887 switch (period) {
888 case SCIM_ANTHY_PERIOD_JAPANESE:
889 label += "\xE3\x80\x82";
890 break;
891 case SCIM_ANTHY_PERIOD_WIDE:
892 label += "\xEF\xBC\x8E";
893 break;
894 case SCIM_ANTHY_PERIOD_HALF:
895 label += ".";
896 break;
897 default:
898 break;
899 }
900
901 if (label.length () > 0) {
902 PropertyList::iterator it = std::find (m_properties.begin (),
903 m_properties.end (),
904 SCIM_PROP_PERIOD_STYLE);
905 if (it != m_properties.end ()) {
906 it->set_label (label.c_str ());
907 update_property (*it);
908 }
909 }
910
911 if (period != m_preedit.get_period_style ())
912 m_preedit.set_period_style (period);
913 if (comma != m_preedit.get_comma_style ())
914 m_preedit.set_comma_style (comma);
915 }
916
917 void
set_symbol_style(BracketStyle bracket,SlashStyle slash)918 AnthyInstance::set_symbol_style (BracketStyle bracket,
919 SlashStyle slash)
920 {
921 String label;
922
923 switch (bracket) {
924 case SCIM_ANTHY_BRACKET_JAPANESE:
925 label = UTF8_BRACKET_CORNER_BEGIN UTF8_BRACKET_CORNER_END;
926 break;
927 case SCIM_ANTHY_BRACKET_WIDE:
928 label = UTF8_BRACKET_WIDE_BEGIN UTF8_BRACKET_WIDE_END;
929 break;
930 default:
931 break;
932 }
933
934 switch (slash) {
935 case SCIM_ANTHY_SLASH_JAPANESE:
936 label += UTF8_MIDDLE_DOT;
937 break;
938 case SCIM_ANTHY_SLASH_WIDE:
939 label += UTF8_SLASH_WIDE;
940 break;
941 default:
942 break;
943 }
944
945 if (label.length () > 0) {
946 PropertyList::iterator it = std::find (m_properties.begin (),
947 m_properties.end (),
948 SCIM_PROP_SYMBOL_STYLE);
949 if (it != m_properties.end ()) {
950 it->set_label (label.c_str ());
951 update_property (*it);
952 }
953 }
954
955 if (bracket != m_preedit.get_bracket_style ())
956 m_preedit.set_bracket_style (bracket);
957 if (slash != m_preedit.get_slash_style ())
958 m_preedit.set_slash_style (slash);
959 }
960
961 bool
is_selecting_candidates(void)962 AnthyInstance::is_selecting_candidates (void)
963 {
964 if (m_lookup_table.number_of_candidates ())
965 return true;
966 else
967 return false;
968 }
969
970 bool
action_do_nothing(void)971 AnthyInstance::action_do_nothing (void)
972 {
973 return true;
974 }
975
976 bool
action_convert(void)977 AnthyInstance::action_convert (void)
978 {
979 if (!m_preedit.is_preediting ())
980 return false;
981
982 if (!m_preedit.is_converting ()) {
983 // show conversion string
984 m_preedit.finish ();
985 m_preedit.convert (SCIM_ANTHY_CANDIDATE_DEFAULT,
986 is_single_segment ());
987 set_preedition ();
988 set_lookup_table ();
989 return true;
990 }
991
992 return false;
993 }
994
995 bool
action_predict(void)996 AnthyInstance::action_predict (void)
997 {
998 if (!m_preedit.is_preediting ())
999 return false;
1000
1001 if (m_preedit.is_converting ())
1002 return false;
1003
1004 if (!m_preedit.is_predicting ())
1005 m_preedit.predict ();
1006
1007 m_preedit.select_candidate (0);
1008 set_preedition ();
1009 set_lookup_table ();
1010 select_candidate_no_direct (0);
1011
1012 return true;
1013 }
1014
1015
1016 bool
action_revert(void)1017 AnthyInstance::action_revert (void)
1018 {
1019 if (m_preedit.is_reconverting ()) {
1020 m_preedit.revert ();
1021 commit_string (m_preedit.get_string ());
1022 reset ();
1023 return true;
1024 }
1025
1026 if (!m_preedit.is_preediting ())
1027 return false;
1028
1029 if (!m_preedit.is_converting ()) {
1030 reset ();
1031 return true;
1032 }
1033
1034 if (is_selecting_candidates ()) {
1035 m_lookup_table.clear ();
1036 if (m_lookup_table_visible) {
1037 unset_lookup_table ();
1038 return true;
1039 }
1040 }
1041
1042 unset_lookup_table ();
1043 m_preedit.revert ();
1044 set_preedition ();
1045
1046 return true;
1047 }
1048
1049 bool
action_cancel_all(void)1050 AnthyInstance::action_cancel_all (void)
1051 {
1052 if (!m_preedit.is_preediting ())
1053 return false;
1054
1055 reset ();
1056 return true;
1057 }
1058
1059 bool
action_commit(bool learn)1060 AnthyInstance::action_commit (bool learn)
1061 {
1062 if (!m_preedit.is_preediting ())
1063 return false;
1064
1065 if (m_preedit.is_converting ()) {
1066 commit_string (m_preedit.get_string ());
1067 if (learn)
1068 m_preedit.commit ();
1069 } else {
1070 m_preedit.finish ();
1071 commit_string (m_preedit.get_string ());
1072 }
1073
1074 reset ();
1075
1076 return true;
1077 }
1078
1079 bool
action_commit_follow_preference(void)1080 AnthyInstance::action_commit_follow_preference (void)
1081 {
1082 return action_commit (m_factory->m_learn_on_manual_commit);
1083 }
1084
1085 bool
action_commit_reverse_preference(void)1086 AnthyInstance::action_commit_reverse_preference (void)
1087 {
1088 return action_commit (!m_factory->m_learn_on_manual_commit);
1089 }
1090
1091 bool
action_back(void)1092 AnthyInstance::action_back (void)
1093 {
1094 if (!m_preedit.is_preediting ())
1095 return false;
1096
1097 if (m_preedit.is_converting ()) {
1098 action_revert ();
1099 if (!is_realtime_conversion ())
1100 return true;
1101 }
1102
1103 m_preedit.erase ();
1104
1105 if (m_preedit.get_length () > 0) {
1106 if (is_realtime_conversion ()) {
1107 m_preedit.convert (SCIM_ANTHY_CANDIDATE_DEFAULT,
1108 is_single_segment ());
1109 m_preedit.select_segment (-1);
1110 }
1111 set_preedition ();
1112 } else {
1113 reset ();
1114 }
1115
1116 return true;
1117 }
1118
1119 bool
action_delete(void)1120 AnthyInstance::action_delete (void)
1121 {
1122 if (!m_preedit.is_preediting ())
1123 return false;
1124
1125 if (m_preedit.is_converting ()) {
1126 action_revert ();
1127 if (!is_realtime_conversion ())
1128 return true;
1129 }
1130
1131 m_preedit.erase (false);
1132
1133 if (m_preedit.get_length () > 0) {
1134 if (is_realtime_conversion ()) {
1135 m_preedit.convert (SCIM_ANTHY_CANDIDATE_DEFAULT,
1136 is_single_segment ());
1137 m_preedit.select_segment (-1);
1138 }
1139 set_preedition ();
1140 } else {
1141 reset ();
1142 }
1143
1144 return true;
1145 }
1146
1147 bool
action_insert_space(void)1148 AnthyInstance::action_insert_space (void)
1149 {
1150 String str;
1151 bool is_wide = false, retval = false;
1152
1153 if (m_preedit.is_preediting () && !m_factory->m_romaji_pseudo_ascii_blank_behavior)
1154 return false;
1155
1156 if (m_factory->m_space_type == "FollowMode") {
1157 InputMode mode = get_input_mode ();
1158 if (mode == SCIM_ANTHY_MODE_LATIN ||
1159 mode == SCIM_ANTHY_MODE_HALF_KATAKANA ||
1160 m_preedit.is_pseudo_ascii_mode ())
1161 {
1162 is_wide = false;
1163 } else {
1164 is_wide = true;
1165 }
1166 } else if (m_factory->m_space_type == "Wide") {
1167 is_wide = true;
1168 }
1169
1170 if (is_wide) {
1171 str = "\xE3\x80\x80";
1172 retval = true;
1173 } else if (get_typing_method () == SCIM_ANTHY_TYPING_METHOD_NICOLA || // FIXME! it's a ad-hoc solution.
1174 m_preedit.is_pseudo_ascii_mode () ||
1175 (m_last_key.code != SCIM_KEY_space &&
1176 m_last_key.code != SCIM_KEY_KP_Space))
1177 {
1178 str = " ";
1179 retval = true;
1180 }
1181
1182 if (retval) {
1183 if (m_preedit.is_pseudo_ascii_mode ()) {
1184 m_preedit.append (m_last_key, str);
1185 show_preedit_string ();
1186 m_preedit_string_visible = true;
1187 set_preedition ();
1188 } else {
1189 commit_string (utf8_mbstowcs (str));
1190 }
1191 }
1192
1193 return retval;
1194 }
1195
1196 bool
action_insert_alternative_space(void)1197 AnthyInstance::action_insert_alternative_space (void)
1198 {
1199 bool is_wide = false;
1200
1201 if (m_preedit.is_preediting ())
1202 return false;
1203
1204 if (m_factory->m_space_type == "FollowMode") {
1205 InputMode mode = get_input_mode ();
1206 if (mode == SCIM_ANTHY_MODE_LATIN ||
1207 mode == SCIM_ANTHY_MODE_HALF_KATAKANA)
1208 {
1209 is_wide = true;
1210 } else {
1211 is_wide = false;
1212 }
1213 } else if (m_factory->m_space_type != "Wide") {
1214 is_wide = true;
1215 }
1216
1217 if (is_wide) {
1218 commit_string (utf8_mbstowcs ("\xE3\x80\x80"));
1219 return true;
1220 } else if (get_typing_method () == SCIM_ANTHY_TYPING_METHOD_NICOLA || // FIXME! it's a ad-hoc solution.
1221 (m_last_key.code != SCIM_KEY_space &&
1222 m_last_key.code != SCIM_KEY_KP_Space))
1223 {
1224 commit_string (utf8_mbstowcs (" "));
1225 return true;
1226 }
1227
1228 return false;
1229 }
1230
1231 bool
action_insert_half_space(void)1232 AnthyInstance::action_insert_half_space (void)
1233 {
1234 if (m_preedit.is_preediting ())
1235 return false;
1236
1237 if (m_last_key.code != SCIM_KEY_space &&
1238 m_last_key.code != SCIM_KEY_KP_Space)
1239 {
1240 commit_string (utf8_mbstowcs (" "));
1241 return true;
1242 }
1243
1244 return false;
1245 }
1246
1247 bool
action_insert_wide_space(void)1248 AnthyInstance::action_insert_wide_space (void)
1249 {
1250 if (m_preedit.is_preediting ())
1251 return false;
1252
1253 commit_string (utf8_mbstowcs ("\xE3\x80\x80"));
1254
1255 return true;
1256 }
1257
1258 bool
action_move_caret_backward(void)1259 AnthyInstance::action_move_caret_backward (void)
1260 {
1261 if (!m_preedit.is_preediting ())
1262 return false;
1263 if (m_preedit.is_converting ())
1264 return false;
1265
1266 m_preedit.move_caret(-1);
1267 set_preedition ();
1268
1269 return true;
1270 }
1271
1272 bool
action_move_caret_forward(void)1273 AnthyInstance::action_move_caret_forward (void)
1274 {
1275 if (!m_preedit.is_preediting ())
1276 return false;
1277 if (m_preedit.is_converting ())
1278 return false;
1279
1280 m_preedit.move_caret(1);
1281 set_preedition ();
1282
1283 return true;
1284 }
1285
1286 bool
action_move_caret_first(void)1287 AnthyInstance::action_move_caret_first (void)
1288 {
1289 if (!m_preedit.is_preediting ())
1290 return false;
1291 if (m_preedit.is_converting ())
1292 return false;
1293
1294 m_preedit.set_caret_pos (0);
1295 set_preedition ();
1296
1297 return true;
1298 }
1299
1300 bool
action_move_caret_last(void)1301 AnthyInstance::action_move_caret_last (void)
1302 {
1303 if (!m_preedit.is_preediting ())
1304 return false;
1305 if (m_preedit.is_converting ())
1306 return false;
1307
1308 m_preedit.set_caret_pos (m_preedit.get_length ());
1309 set_preedition ();
1310
1311 return true;
1312 }
1313
1314 bool
action_select_prev_segment(void)1315 AnthyInstance::action_select_prev_segment (void)
1316 {
1317 if (!m_preedit.is_converting ())
1318 return false;
1319
1320 unset_lookup_table ();
1321
1322 int idx = m_preedit.get_selected_segment ();
1323 if (idx - 1 < 0) {
1324 int n = m_preedit.get_nr_segments ();
1325 if (n <= 0) return false;
1326 m_preedit.select_segment (n - 1);
1327 } else {
1328 m_preedit.select_segment (idx - 1);
1329 }
1330 set_preedition ();
1331
1332 return true;
1333 }
1334
1335 bool
action_select_next_segment(void)1336 AnthyInstance::action_select_next_segment (void)
1337 {
1338 if (!m_preedit.is_converting ())
1339 return false;
1340
1341 unset_lookup_table ();
1342
1343 int idx = m_preedit.get_selected_segment ();
1344 if (idx < 0) {
1345 m_preedit.select_segment(0);
1346 } else {
1347 int n = m_preedit.get_nr_segments ();
1348 if (n <= 0)
1349 return false;
1350 if (idx + 1 >= n)
1351 m_preedit.select_segment(0);
1352 else
1353 m_preedit.select_segment(idx + 1);
1354 }
1355 set_preedition ();
1356
1357 return true;
1358 }
1359
1360 bool
action_select_first_segment(void)1361 AnthyInstance::action_select_first_segment (void)
1362 {
1363 if (!m_preedit.is_converting ())
1364 return false;
1365
1366 unset_lookup_table ();
1367
1368 m_preedit.select_segment(0);
1369 set_preedition ();
1370
1371 return true;
1372 }
1373
1374 bool
action_select_last_segment(void)1375 AnthyInstance::action_select_last_segment (void)
1376 {
1377 if (!m_preedit.is_converting ())
1378 return false;
1379
1380 int n = m_preedit.get_nr_segments ();
1381 if (n <= 0) return false;
1382
1383 unset_lookup_table ();
1384
1385 m_preedit.select_segment(n - 1);
1386 set_preedition ();
1387
1388 return true;
1389 }
1390
1391 bool
action_shrink_segment(void)1392 AnthyInstance::action_shrink_segment (void)
1393 {
1394 if (!m_preedit.is_converting ())
1395 return false;
1396
1397 unset_lookup_table ();
1398
1399 m_preedit.resize_segment (-1);
1400 set_preedition ();
1401
1402 return true;
1403 }
1404
1405 bool
action_expand_segment(void)1406 AnthyInstance::action_expand_segment (void)
1407 {
1408 if (!m_preedit.is_converting ())
1409 return false;
1410
1411 unset_lookup_table ();
1412
1413 m_preedit.resize_segment (1);
1414 set_preedition ();
1415
1416 return true;
1417 }
1418
1419 bool
action_commit_first_segment(void)1420 AnthyInstance::action_commit_first_segment (void)
1421 {
1422 if (!m_preedit.is_converting ()) {
1423 if (m_preedit.is_preediting ()) {
1424 return action_commit (m_factory->m_learn_on_manual_commit);
1425 } else {
1426 return false;
1427 }
1428 }
1429
1430 unset_lookup_table ();
1431
1432 commit_string (m_preedit.get_segment_string (0));
1433 if (m_factory->m_learn_on_manual_commit)
1434 m_preedit.commit (0);
1435 else
1436 m_preedit.clear (0);
1437
1438 set_preedition ();
1439
1440 return true;
1441 }
1442
1443 bool
action_commit_selected_segment(void)1444 AnthyInstance::action_commit_selected_segment (void)
1445 {
1446 if (!m_preedit.is_converting ()) {
1447 if (m_preedit.is_preediting ()) {
1448 return action_commit (m_factory->m_learn_on_manual_commit);
1449 } else {
1450 return false;
1451 }
1452 }
1453
1454 unset_lookup_table ();
1455
1456 for (int i = 0; i <= m_preedit.get_selected_segment (); i++)
1457 commit_string (m_preedit.get_segment_string (i));
1458 if (m_factory->m_learn_on_manual_commit)
1459 m_preedit.commit (m_preedit.get_selected_segment ());
1460 else
1461 m_preedit.clear (m_preedit.get_selected_segment ());
1462
1463 set_preedition ();
1464
1465 return true;
1466 }
1467
1468 bool
action_commit_first_segment_reverse_preference(void)1469 AnthyInstance::action_commit_first_segment_reverse_preference (void)
1470 {
1471 if (!m_preedit.is_converting ()) {
1472 if (m_preedit.is_preediting ()) {
1473 return action_commit (!m_factory->m_learn_on_manual_commit);
1474 } else {
1475 return false;
1476 }
1477 }
1478
1479 unset_lookup_table ();
1480
1481 commit_string (m_preedit.get_segment_string (0));
1482 if (!m_factory->m_learn_on_manual_commit)
1483 m_preedit.commit (0);
1484 else
1485 m_preedit.clear (0);
1486
1487 set_preedition ();
1488
1489 return true;
1490 }
1491
1492 bool
action_commit_selected_segment_reverse_preference(void)1493 AnthyInstance::action_commit_selected_segment_reverse_preference (void)
1494 {
1495 if (!m_preedit.is_converting ()) {
1496 if (m_preedit.is_preediting ()) {
1497 return action_commit (!m_factory->m_learn_on_manual_commit);
1498 } else {
1499 return false;
1500 }
1501 }
1502
1503 unset_lookup_table ();
1504
1505 for (int i = 0; i <= m_preedit.get_selected_segment (); i++)
1506 commit_string (m_preedit.get_segment_string (i));
1507 if (!m_factory->m_learn_on_manual_commit)
1508 m_preedit.commit (m_preedit.get_selected_segment ());
1509 else
1510 m_preedit.clear (m_preedit.get_selected_segment ());
1511
1512 set_preedition ();
1513
1514 return true;
1515 }
1516
1517 bool
action_select_next_candidate(void)1518 AnthyInstance::action_select_next_candidate (void)
1519 {
1520 if (!m_preedit.is_converting ())
1521 return false;
1522
1523 //if (!is_selecting_candidates ())
1524 set_lookup_table ();
1525
1526 int end = m_lookup_table.number_of_candidates () - 1;
1527 if (m_lookup_table.get_cursor_pos () == end) {
1528 m_lookup_table.set_cursor_pos (0);
1529 } else {
1530 m_lookup_table.cursor_down ();
1531 }
1532
1533 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1534 select_candidate_no_direct (pos_in_page);
1535
1536 return true;
1537 }
1538
1539 bool
action_select_prev_candidate(void)1540 AnthyInstance::action_select_prev_candidate (void)
1541 {
1542 if (!m_preedit.is_converting ()) return false;
1543
1544 //if (!is_selecting_candidates ())
1545 set_lookup_table ();
1546
1547 int end = m_lookup_table.number_of_candidates () - 1;
1548 if (m_lookup_table.get_cursor_pos () == 0)
1549 m_lookup_table.set_cursor_pos (end);
1550 else
1551 m_lookup_table.cursor_up ();
1552
1553 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1554 select_candidate_no_direct (pos_in_page);
1555
1556 return true;
1557 }
1558
1559 bool
action_select_first_candidate(void)1560 AnthyInstance::action_select_first_candidate (void)
1561 {
1562 if (!m_preedit.is_converting ()) return false;
1563 if (!is_selecting_candidates ()) return false;
1564
1565 m_lookup_table.set_cursor_pos (0);
1566
1567 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1568 select_candidate_no_direct (pos_in_page);
1569
1570 return true;
1571 }
1572
1573 bool
action_select_last_candidate(void)1574 AnthyInstance::action_select_last_candidate (void)
1575 {
1576 if (!m_preedit.is_converting ()) return false;
1577 if (!is_selecting_candidates ()) return false;
1578
1579 int end = m_lookup_table.number_of_candidates () - 1;
1580 m_lookup_table.set_cursor_pos (end);
1581
1582 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1583 select_candidate_no_direct (pos_in_page);
1584
1585 return true;
1586 }
1587
1588 bool
action_candidates_page_up(void)1589 AnthyInstance::action_candidates_page_up(void)
1590 {
1591 if (!m_preedit.is_converting ()) return false;
1592 if (!is_selecting_candidates ()) return false;
1593 if (!m_lookup_table_visible) return false;
1594
1595 m_lookup_table.page_up ();
1596
1597 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1598 select_candidate_no_direct (pos_in_page);
1599
1600 return true;
1601 }
1602
1603 bool
action_candidates_page_down(void)1604 AnthyInstance::action_candidates_page_down (void)
1605 {
1606 if (!m_preedit.is_converting ()) return false;
1607 if (!is_selecting_candidates ()) return false;
1608 if (!m_lookup_table_visible) return false;
1609
1610 m_lookup_table.page_down ();
1611
1612 int pos_in_page = m_lookup_table.get_cursor_pos_in_current_page ();
1613 select_candidate_no_direct (pos_in_page);
1614
1615 return true;
1616 }
1617
1618 bool
action_select_candidate(unsigned int i)1619 AnthyInstance::action_select_candidate (unsigned int i)
1620 {
1621 // FIXME! m_lookup_table_visible should be set as true also on predicting
1622 if (!m_lookup_table_visible && !m_preedit.is_predicting ())
1623 return false;
1624
1625 if (m_preedit.is_predicting () && !m_preedit.is_converting () &&
1626 m_factory->m_use_direct_key_on_predict)
1627 {
1628 CommonLookupTable table;
1629 m_preedit.get_candidates (table);
1630 if (i < table.number_of_candidates ()) {
1631 select_candidate (i);
1632 return true;
1633 }
1634 } else if (m_preedit.is_converting () && is_selecting_candidates ()) {
1635 select_candidate (i);
1636 return true;
1637 }
1638
1639 return false;
1640 }
1641
1642 bool
action_select_candidate_1(void)1643 AnthyInstance::action_select_candidate_1 (void)
1644 {
1645 return action_select_candidate (0);
1646 }
1647
1648 bool
action_select_candidate_2(void)1649 AnthyInstance::action_select_candidate_2 (void)
1650 {
1651 return action_select_candidate (1);
1652 }
1653
1654 bool
action_select_candidate_3(void)1655 AnthyInstance::action_select_candidate_3 (void)
1656 {
1657 return action_select_candidate (2);
1658 }
1659
1660 bool
action_select_candidate_4(void)1661 AnthyInstance::action_select_candidate_4 (void)
1662 {
1663 return action_select_candidate (3);
1664 }
1665
1666 bool
action_select_candidate_5(void)1667 AnthyInstance::action_select_candidate_5 (void)
1668 {
1669 return action_select_candidate (4);
1670 }
1671
1672 bool
action_select_candidate_6(void)1673 AnthyInstance::action_select_candidate_6 (void)
1674 {
1675 return action_select_candidate (5);
1676 }
1677
1678 bool
action_select_candidate_7(void)1679 AnthyInstance::action_select_candidate_7 (void)
1680 {
1681 return action_select_candidate (6);
1682 }
1683
1684
1685 bool
action_select_candidate_8(void)1686 AnthyInstance::action_select_candidate_8 (void)
1687 {
1688 return action_select_candidate (7);
1689 }
1690
1691 bool
action_select_candidate_9(void)1692 AnthyInstance::action_select_candidate_9 (void)
1693 {
1694 return action_select_candidate (8);
1695 }
1696
1697 bool
action_select_candidate_10(void)1698 AnthyInstance::action_select_candidate_10 (void)
1699 {
1700 return action_select_candidate (9);
1701 }
1702
1703 bool
action_circle_input_mode(void)1704 AnthyInstance::action_circle_input_mode (void)
1705 {
1706 InputMode mode = get_input_mode ();
1707
1708 switch (mode) {
1709 case SCIM_ANTHY_MODE_HIRAGANA:
1710 mode = SCIM_ANTHY_MODE_KATAKANA;
1711 break;
1712 case SCIM_ANTHY_MODE_KATAKANA:
1713 mode = SCIM_ANTHY_MODE_HALF_KATAKANA;
1714 break;
1715 case SCIM_ANTHY_MODE_HALF_KATAKANA:
1716 mode = SCIM_ANTHY_MODE_LATIN;
1717 break;
1718 case SCIM_ANTHY_MODE_LATIN:
1719 mode = SCIM_ANTHY_MODE_WIDE_LATIN;
1720 break;
1721 case SCIM_ANTHY_MODE_WIDE_LATIN:
1722 mode = SCIM_ANTHY_MODE_HIRAGANA;
1723 break;
1724 default:
1725 mode = SCIM_ANTHY_MODE_HIRAGANA;
1726 break;
1727 }
1728
1729 set_input_mode (mode);
1730
1731 return true;
1732 }
1733
1734 bool
action_circle_typing_method(void)1735 AnthyInstance::action_circle_typing_method (void)
1736 {
1737 TypingMethod method;
1738
1739 method = get_typing_method ();
1740 if (method == SCIM_ANTHY_TYPING_METHOD_NICOLA)
1741 method = SCIM_ANTHY_TYPING_METHOD_ROMAJI;
1742 else if (method == SCIM_ANTHY_TYPING_METHOD_KANA)
1743 method = SCIM_ANTHY_TYPING_METHOD_NICOLA;
1744 else
1745 method = SCIM_ANTHY_TYPING_METHOD_KANA;
1746
1747 set_typing_method (method);
1748
1749 return true;
1750 }
1751
1752 bool
action_circle_kana_mode(void)1753 AnthyInstance::action_circle_kana_mode (void)
1754 {
1755 InputMode mode;
1756
1757 if (get_input_mode () == SCIM_ANTHY_MODE_LATIN ||
1758 get_input_mode () == SCIM_ANTHY_MODE_WIDE_LATIN)
1759 {
1760 mode = SCIM_ANTHY_MODE_HIRAGANA;
1761 } else {
1762 switch (get_input_mode ()) {
1763 case SCIM_ANTHY_MODE_HIRAGANA:
1764 mode = SCIM_ANTHY_MODE_KATAKANA;
1765 break;
1766 case SCIM_ANTHY_MODE_KATAKANA:
1767 mode = SCIM_ANTHY_MODE_HALF_KATAKANA;
1768 break;
1769 case SCIM_ANTHY_MODE_HALF_KATAKANA:
1770 default:
1771 mode = SCIM_ANTHY_MODE_HIRAGANA;
1772 break;
1773 }
1774 }
1775
1776 set_input_mode (mode);
1777
1778 return true;
1779 }
1780
1781 bool
action_on_off(void)1782 AnthyInstance::action_on_off (void)
1783 {
1784 if (get_input_mode () == SCIM_ANTHY_MODE_LATIN ||
1785 get_input_mode () == SCIM_ANTHY_MODE_WIDE_LATIN)
1786 {
1787 set_input_mode (m_prev_input_mode);
1788 m_preedit.set_input_mode (m_prev_input_mode);
1789 } else {
1790 m_prev_input_mode = get_input_mode ();
1791 set_input_mode (SCIM_ANTHY_MODE_LATIN);
1792 m_preedit.set_input_mode (SCIM_ANTHY_MODE_LATIN);
1793 }
1794
1795 return true;
1796 }
1797
1798 bool
action_latin_mode(void)1799 AnthyInstance::action_latin_mode (void)
1800 {
1801 set_input_mode (SCIM_ANTHY_MODE_LATIN);
1802 return true;
1803 }
1804
1805 bool
action_wide_latin_mode(void)1806 AnthyInstance::action_wide_latin_mode (void)
1807 {
1808 set_input_mode (SCIM_ANTHY_MODE_WIDE_LATIN);
1809 return true;
1810 }
1811
1812 bool
action_hiragana_mode(void)1813 AnthyInstance::action_hiragana_mode (void)
1814 {
1815 set_input_mode (SCIM_ANTHY_MODE_HIRAGANA);
1816 return true;
1817 }
1818
1819 bool
action_katakana_mode(void)1820 AnthyInstance::action_katakana_mode (void)
1821 {
1822 set_input_mode (SCIM_ANTHY_MODE_KATAKANA);
1823 return true;
1824 }
1825
1826 bool
action_half_katakana_mode(void)1827 AnthyInstance::action_half_katakana_mode (void)
1828 {
1829 set_input_mode (SCIM_ANTHY_MODE_HALF_KATAKANA);
1830 return true;
1831 }
1832
1833 bool
action_cancel_pseudo_ascii_mode(void)1834 AnthyInstance::action_cancel_pseudo_ascii_mode (void)
1835 {
1836 if (!m_preedit.is_preediting ())
1837 return false;
1838 if (!m_preedit.is_pseudo_ascii_mode ())
1839 return false;
1840
1841 m_preedit.reset_pseudo_ascii_mode ();
1842
1843 return true;
1844 }
1845
1846 bool
convert_kana(CandidateType type)1847 AnthyInstance::convert_kana (CandidateType type)
1848 {
1849 if (!m_preedit.is_preediting ())
1850 return false;
1851
1852 if (m_preedit.is_reconverting ())
1853 return false;
1854
1855 unset_lookup_table ();
1856
1857 if (m_preedit.is_converting ()) {
1858 int idx = m_preedit.get_selected_segment ();
1859 if (idx < 0) {
1860 action_revert ();
1861 m_preedit.finish ();
1862 m_preedit.convert (type, true);
1863 } else {
1864 m_preedit.select_candidate (type);
1865 }
1866 } else {
1867 m_preedit.finish ();
1868 m_preedit.convert (type, true);
1869 }
1870
1871 set_preedition ();
1872
1873 return true;
1874 }
1875
1876 bool
action_convert_to_hiragana(void)1877 AnthyInstance::action_convert_to_hiragana (void)
1878 {
1879 return convert_kana (SCIM_ANTHY_CANDIDATE_HIRAGANA);
1880 }
1881
1882 bool
action_convert_to_katakana(void)1883 AnthyInstance::action_convert_to_katakana (void)
1884 {
1885 return convert_kana (SCIM_ANTHY_CANDIDATE_KATAKANA);
1886 }
1887
1888 bool
action_convert_to_half(void)1889 AnthyInstance::action_convert_to_half (void)
1890 {
1891 return convert_kana (SCIM_ANTHY_CANDIDATE_HALF);
1892 }
1893
1894 bool
action_convert_to_half_katakana(void)1895 AnthyInstance::action_convert_to_half_katakana (void)
1896 {
1897 return convert_kana (SCIM_ANTHY_CANDIDATE_HALF_KATAKANA);
1898 }
1899
1900 bool
action_convert_to_latin(void)1901 AnthyInstance::action_convert_to_latin (void)
1902 {
1903 return convert_kana (SCIM_ANTHY_CANDIDATE_LATIN);
1904 }
1905
1906 bool
action_convert_to_wide_latin(void)1907 AnthyInstance::action_convert_to_wide_latin (void)
1908 {
1909 return convert_kana (SCIM_ANTHY_CANDIDATE_WIDE_LATIN);
1910 }
1911
1912 bool
action_convert_char_type_forward(void)1913 AnthyInstance::action_convert_char_type_forward (void)
1914 {
1915 if (!m_preedit.is_preediting ())
1916 return false;
1917
1918 unset_lookup_table ();
1919
1920 if (m_preedit.is_converting ()) {
1921 int idx = m_preedit.get_selected_segment ();
1922 if (idx < 0) {
1923 action_revert ();
1924 m_preedit.finish ();
1925 m_preedit.convert (SCIM_ANTHY_CANDIDATE_HIRAGANA, true);
1926 } else {
1927 int cand = m_preedit.get_selected_candidate ();
1928 switch (cand)
1929 {
1930 case SCIM_ANTHY_CANDIDATE_HIRAGANA:
1931 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_KATAKANA);
1932 break;
1933 case SCIM_ANTHY_CANDIDATE_KATAKANA:
1934 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HALF_KATAKANA);
1935 break;
1936 case SCIM_ANTHY_CANDIDATE_HALF_KATAKANA:
1937 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_WIDE_LATIN);
1938 break;
1939 case SCIM_ANTHY_CANDIDATE_WIDE_LATIN:
1940 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_LATIN);
1941 break;
1942 case SCIM_ANTHY_CANDIDATE_LATIN:
1943 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HIRAGANA);
1944 break;
1945 default:
1946 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HIRAGANA);
1947 break;
1948 }
1949 }
1950 } else {
1951 m_preedit.finish ();
1952 m_preedit.convert (SCIM_ANTHY_CANDIDATE_HIRAGANA, true);
1953 }
1954
1955 set_preedition ();
1956
1957 return true;
1958 }
1959
1960 bool
action_convert_char_type_backward(void)1961 AnthyInstance::action_convert_char_type_backward (void)
1962 {
1963 if (!m_preedit.is_preediting ())
1964 return false;
1965
1966 unset_lookup_table ();
1967
1968 if (m_preedit.is_converting ()) {
1969 int idx = m_preedit.get_selected_segment ();
1970 if (idx < 0) {
1971 action_revert ();
1972 m_preedit.finish ();
1973 m_preedit.convert (SCIM_ANTHY_CANDIDATE_HIRAGANA, true);
1974 } else {
1975 int cand = m_preedit.get_selected_candidate ();
1976 switch (cand)
1977 {
1978 case SCIM_ANTHY_CANDIDATE_HIRAGANA:
1979 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_LATIN);
1980 break;
1981 case SCIM_ANTHY_CANDIDATE_KATAKANA:
1982 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HIRAGANA);
1983 break;
1984 case SCIM_ANTHY_CANDIDATE_HALF_KATAKANA:
1985 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_KATAKANA);
1986 break;
1987 case SCIM_ANTHY_CANDIDATE_WIDE_LATIN:
1988 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HALF_KATAKANA);
1989 break;
1990 case SCIM_ANTHY_CANDIDATE_LATIN:
1991 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_WIDE_LATIN);
1992 break;
1993 default:
1994 m_preedit.select_candidate (SCIM_ANTHY_CANDIDATE_HIRAGANA);
1995 break;
1996 }
1997 }
1998 } else {
1999 m_preedit.finish ();
2000 m_preedit.convert (SCIM_ANTHY_CANDIDATE_HIRAGANA, true);
2001 }
2002
2003 set_preedition ();
2004
2005 return true;
2006 }
2007
2008 bool
action_reconvert(void)2009 AnthyInstance::action_reconvert (void)
2010 {
2011 if (m_preedit.is_preediting ())
2012 return false;
2013
2014 Transaction send;
2015 send.put_command (SCIM_ANTHY_TRANS_CMD_GET_SELECTION);
2016 send_helper_event (String (SCIM_ANTHY_HELPER_UUID), send);
2017
2018 return true;
2019 }
2020
2021 bool
action_add_word(void)2022 AnthyInstance::action_add_word (void)
2023 {
2024 util_launch_program (m_factory->m_add_word_command.c_str ());
2025
2026 return true;
2027 }
2028
2029 bool
action_launch_dict_admin_tool(void)2030 AnthyInstance::action_launch_dict_admin_tool (void)
2031 {
2032 util_launch_program (m_factory->m_dict_admin_command.c_str ());
2033
2034 return true;
2035 }
2036
2037 #if 0
2038 void
2039 AnthyInstance::action_regist_word (void)
2040 {
2041 }
2042 #endif
2043
2044 AnthyFactory *
get_factory(void)2045 AnthyInstance::get_factory (void)
2046 {
2047 return m_factory;
2048 }
2049
2050 TypingMethod
get_typing_method(void)2051 AnthyInstance::get_typing_method (void)
2052 {
2053 return m_preedit.get_typing_method ();
2054 }
2055
2056 InputMode
get_input_mode(void)2057 AnthyInstance::get_input_mode (void)
2058 {
2059 return m_preedit.get_input_mode ();
2060 }
2061
2062 int
timeout_add(uint32 time_msec,timeout_func timeout_fn,void * data,delete_func delete_fn)2063 AnthyInstance::timeout_add (uint32 time_msec, timeout_func timeout_fn,
2064 void *data, delete_func delete_fn)
2065 {
2066 uint32 id = ++m_timeout_id_seq;
2067 m_closures[id] = TimeoutClosure (time_msec, timeout_fn, data, delete_fn);
2068 /*
2069 * FIXME! Obsoleted closures should be removed at somewhere.
2070 * Currenly only NICOLA related timer uses this feature and it will be
2071 * removed each time on key press event so memory leaks doesn't exist.
2072 */
2073
2074 Transaction send;
2075 send.put_command (SCIM_ANTHY_TRANS_CMD_TIMEOUT_ADD);
2076 send.put_data (id);
2077 send.put_data (time_msec);
2078 send_helper_event (String (SCIM_ANTHY_HELPER_UUID), send);
2079
2080 return id;
2081 }
2082
2083 void
timeout_remove(uint32 id)2084 AnthyInstance::timeout_remove (uint32 id)
2085 {
2086 if (m_closures.find (id) == m_closures.end ())
2087 return;
2088
2089 m_closures.erase (id);
2090
2091 Transaction send;
2092 send.put_command (SCIM_ANTHY_TRANS_CMD_TIMEOUT_REMOVE);
2093 send.put_data (id);
2094 send_helper_event (String (SCIM_ANTHY_HELPER_UUID), send);
2095 }
2096
2097 void
trigger_property(const String & property)2098 AnthyInstance::trigger_property (const String &property)
2099 {
2100 String anthy_prop = property.substr (property.find_last_of ('/') + 1);
2101
2102 SCIM_DEBUG_IMENGINE(2)
2103 << "trigger_property : " << property << " - " << anthy_prop << "\n";
2104
2105 // input mode
2106 if (property == SCIM_PROP_INPUT_MODE_HIRAGANA) {
2107 set_input_mode (SCIM_ANTHY_MODE_HIRAGANA);
2108 } else if (property == SCIM_PROP_INPUT_MODE_KATAKANA) {
2109 set_input_mode (SCIM_ANTHY_MODE_KATAKANA);
2110 } else if (property == SCIM_PROP_INPUT_MODE_HALF_KATAKANA) {
2111 set_input_mode (SCIM_ANTHY_MODE_HALF_KATAKANA);
2112 } else if (property == SCIM_PROP_INPUT_MODE_LATIN) {
2113 set_input_mode (SCIM_ANTHY_MODE_LATIN);
2114 } else if (property == SCIM_PROP_INPUT_MODE_WIDE_LATIN) {
2115 set_input_mode (SCIM_ANTHY_MODE_WIDE_LATIN);
2116
2117 // conversion mode
2118 } else if (property == SCIM_PROP_CONV_MODE_MULTI_SEG) {
2119 set_conversion_mode (SCIM_ANTHY_CONVERSION_MULTI_SEGMENT);
2120 } else if (property == SCIM_PROP_CONV_MODE_SINGLE_SEG) {
2121 set_conversion_mode (SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT);
2122 } else if (property == SCIM_PROP_CONV_MODE_MULTI_REAL_TIME) {
2123 set_conversion_mode (SCIM_ANTHY_CONVERSION_MULTI_SEGMENT_IMMEDIATE);
2124 } else if (property == SCIM_PROP_CONV_MODE_SINGLE_REAL_TIME) {
2125 set_conversion_mode (SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE);
2126
2127 // typing method
2128 } else if (property == SCIM_PROP_TYPING_METHOD_ROMAJI) {
2129 set_typing_method (SCIM_ANTHY_TYPING_METHOD_ROMAJI);
2130 } else if (property == SCIM_PROP_TYPING_METHOD_KANA) {
2131 set_typing_method (SCIM_ANTHY_TYPING_METHOD_KANA);
2132 } else if (property == SCIM_PROP_TYPING_METHOD_NICOLA) {
2133 set_typing_method (SCIM_ANTHY_TYPING_METHOD_NICOLA);
2134
2135 // period type
2136 } else if (property == SCIM_PROP_PERIOD_STYLE_JAPANESE) {
2137 set_period_style (SCIM_ANTHY_PERIOD_JAPANESE,
2138 SCIM_ANTHY_COMMA_JAPANESE);
2139 } else if (property == SCIM_PROP_PERIOD_STYLE_WIDE_LATIN_JAPANESE) {
2140 set_period_style (SCIM_ANTHY_PERIOD_JAPANESE,
2141 SCIM_ANTHY_COMMA_WIDE);
2142 } else if (property == SCIM_PROP_PERIOD_STYLE_WIDE_LATIN) {
2143 set_period_style (SCIM_ANTHY_PERIOD_WIDE,
2144 SCIM_ANTHY_COMMA_WIDE);
2145 } else if (property == SCIM_PROP_PERIOD_STYLE_LATIN) {
2146 set_period_style (SCIM_ANTHY_PERIOD_HALF,
2147 SCIM_ANTHY_COMMA_HALF);
2148
2149 // symbol type
2150 } else if (property == SCIM_PROP_SYMBOL_STYLE_JAPANESE) {
2151 set_symbol_style (SCIM_ANTHY_BRACKET_JAPANESE,
2152 SCIM_ANTHY_SLASH_JAPANESE);
2153 } else if (property == SCIM_PROP_SYMBOL_STYLE_CORNER_BRACKET_SLASH) {
2154 set_symbol_style (SCIM_ANTHY_BRACKET_JAPANESE,
2155 SCIM_ANTHY_SLASH_WIDE);
2156 } else if (property == SCIM_PROP_SYMBOL_STYLE_BRACKET_MIDDLE_DOT) {
2157 set_symbol_style (SCIM_ANTHY_BRACKET_WIDE,
2158 SCIM_ANTHY_SLASH_JAPANESE);
2159 } else if (property == SCIM_PROP_SYMBOL_STYLE_BRACKET_SLASH) {
2160 set_symbol_style (SCIM_ANTHY_BRACKET_WIDE,
2161 SCIM_ANTHY_SLASH_WIDE);
2162
2163 // dictionary
2164 } else if (property == SCIM_PROP_DICT_ADD_WORD) {
2165 action_add_word ();
2166 } else if (property == SCIM_PROP_DICT_LAUNCH_ADMIN_TOOL) {
2167 action_launch_dict_admin_tool ();
2168 }
2169 }
2170
2171 void
process_helper_event(const String & helper_uuid,const Transaction & recv)2172 AnthyInstance::process_helper_event (const String &helper_uuid,
2173 const Transaction &recv)
2174 {
2175 TransactionReader reader (recv);
2176 int cmd;
2177
2178 if (helper_uuid != SCIM_ANTHY_HELPER_UUID)
2179 return;
2180
2181 if (!reader.get_command (cmd))
2182 return;
2183
2184 switch (cmd) {
2185 case SCIM_ANTHY_TRANS_CMD_GET_SELECTION:
2186 {
2187 // For reconversion feature, but this code is ad-hoc solution.
2188
2189 WideString selection, surround;
2190 if (!reader.get_data (selection) || selection.empty ())
2191 break;
2192
2193 int cursor;
2194 unsigned int len = selection.length ();
2195 if (!get_surrounding_text (surround, cursor, len, len))
2196 {
2197 // We expect application to delete selection text.
2198 m_preedit.convert(selection);
2199 set_preedition();
2200 set_lookup_table();
2201 }
2202 else
2203 {
2204 // This code will conflict if same string exists at both before and
2205 // after the caret.
2206 if (surround.length () - cursor >= len &&
2207 surround.substr (cursor, len) == selection)
2208 {
2209 delete_surrounding_text (0, len);
2210 m_preedit.convert (selection);
2211 set_preedition ();
2212 set_lookup_table ();
2213 } else if (cursor >= (int) len &&
2214 surround.substr (cursor - len, len) == selection)
2215 {
2216 delete_surrounding_text (0 - len, len);
2217 m_preedit.convert (selection);
2218 set_preedition ();
2219 set_lookup_table ();
2220 }
2221 }
2222 break;
2223 }
2224 case SCIM_ANTHY_TRANS_CMD_TIMEOUT_NOTIFY:
2225 {
2226 uint32 id;
2227 if (reader.get_data (id) &&
2228 m_closures.find (id) != m_closures.end ())
2229 {
2230 m_closures[id].close ();
2231 m_closures.erase (id);
2232 }
2233 break;
2234 }
2235 default:
2236 break;
2237 }
2238 }
2239
2240 void
reload_config(const ConfigPointer & config)2241 AnthyInstance::reload_config (const ConfigPointer &config)
2242 {
2243 // set romaji settings
2244 m_preedit.set_symbol_width (m_factory->m_romaji_half_symbol);
2245 m_preedit.set_number_width (m_factory->m_romaji_half_number);
2246
2247 // set input mode
2248 if (m_on_init || !m_factory->m_show_input_mode_label) {
2249 if (m_factory->m_input_mode == "Hiragana")
2250 m_preedit.set_input_mode (SCIM_ANTHY_MODE_HIRAGANA);
2251 else if (m_factory->m_input_mode == "Katakana")
2252 m_preedit.set_input_mode (SCIM_ANTHY_MODE_KATAKANA);
2253 else if (m_factory->m_input_mode == "HalfKatakana")
2254 m_preedit.set_input_mode (SCIM_ANTHY_MODE_HALF_KATAKANA);
2255 else if (m_factory->m_input_mode == "Latin")
2256 m_preedit.set_input_mode (SCIM_ANTHY_MODE_LATIN);
2257 else if (m_factory->m_input_mode == "WideLatin")
2258 m_preedit.set_input_mode (SCIM_ANTHY_MODE_WIDE_LATIN);
2259 }
2260
2261 // set typing method and pseudo ASCII mode
2262 if (m_on_init || !m_factory->m_show_typing_method_label) {
2263 if (m_factory->m_typing_method == "NICOLA") {
2264 m_preedit.set_typing_method (SCIM_ANTHY_TYPING_METHOD_NICOLA);
2265 } else if (m_factory->m_typing_method == "Kana") {
2266 m_preedit.set_typing_method (SCIM_ANTHY_TYPING_METHOD_KANA);
2267 } else {
2268 m_preedit.set_typing_method (SCIM_ANTHY_TYPING_METHOD_ROMAJI);
2269 }
2270 m_preedit.set_pseudo_ascii_mode (get_pseudo_ascii_mode ());
2271 } else {
2272 m_preedit.set_typing_method (get_typing_method ());
2273 m_preedit.set_pseudo_ascii_mode (get_pseudo_ascii_mode ());
2274 }
2275
2276 // set conversion mode
2277 if (m_on_init || !m_factory->m_show_conv_mode_label) {
2278 if (m_factory->m_conversion_mode == "MultiSeg")
2279 m_conv_mode = SCIM_ANTHY_CONVERSION_MULTI_SEGMENT;
2280 else if (m_factory->m_conversion_mode == "SingleSeg")
2281 m_conv_mode = SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT;
2282 else if (m_factory->m_conversion_mode == "CAYT_MultiSeg")
2283 m_conv_mode = SCIM_ANTHY_CONVERSION_MULTI_SEGMENT_IMMEDIATE;
2284 else if (m_factory->m_conversion_mode == "CAYT_SingleSeg")
2285 m_conv_mode = SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE;
2286 }
2287
2288 // set period style
2289 if (m_on_init || !m_factory->m_show_period_style_label) {
2290 if (m_factory->m_period_style == "WideLatin") {
2291 m_preedit.set_comma_style (SCIM_ANTHY_COMMA_WIDE);
2292 m_preedit.set_period_style (SCIM_ANTHY_PERIOD_WIDE);
2293 } else if (m_factory->m_period_style == "Latin") {
2294 m_preedit.set_comma_style (SCIM_ANTHY_COMMA_HALF);
2295 m_preedit.set_period_style (SCIM_ANTHY_PERIOD_HALF);
2296 } else if (m_factory->m_period_style == "Japanese") {
2297 m_preedit.set_comma_style (SCIM_ANTHY_COMMA_JAPANESE);
2298 m_preedit.set_period_style (SCIM_ANTHY_PERIOD_JAPANESE);
2299 } else if (m_factory->m_period_style == "WideLatin_Japanese") {
2300 m_preedit.set_comma_style (SCIM_ANTHY_COMMA_WIDE);
2301 m_preedit.set_period_style (SCIM_ANTHY_PERIOD_JAPANESE);
2302 } else {
2303 m_preedit.set_comma_style (SCIM_ANTHY_COMMA_JAPANESE);
2304 m_preedit.set_period_style (SCIM_ANTHY_PERIOD_JAPANESE);
2305 }
2306 }
2307
2308 // set symbol style
2309 if (m_on_init || !m_factory->m_show_symbol_style_label) {
2310 if (m_factory->m_symbol_style == "Japanese") {
2311 m_preedit.set_bracket_style (SCIM_ANTHY_BRACKET_JAPANESE);
2312 m_preedit.set_slash_style (SCIM_ANTHY_SLASH_JAPANESE);
2313 } else if (m_factory->m_symbol_style == "WideBracket_WideSlash") {
2314 m_preedit.set_bracket_style (SCIM_ANTHY_BRACKET_WIDE);
2315 m_preedit.set_slash_style (SCIM_ANTHY_SLASH_WIDE);
2316 } else if (m_factory->m_symbol_style == "CornerBracket_WideSlash") {
2317 m_preedit.set_bracket_style (SCIM_ANTHY_BRACKET_JAPANESE);
2318 m_preedit.set_slash_style (SCIM_ANTHY_SLASH_WIDE);
2319 } else if (m_factory->m_symbol_style == "WideBracket_MiddleDot") {
2320 m_preedit.set_bracket_style (SCIM_ANTHY_BRACKET_WIDE);
2321 m_preedit.set_slash_style (SCIM_ANTHY_SLASH_JAPANESE);
2322 } else {
2323 m_preedit.set_bracket_style (SCIM_ANTHY_BRACKET_JAPANESE);
2324 m_preedit.set_slash_style (SCIM_ANTHY_SLASH_JAPANESE);
2325 }
2326 }
2327
2328 // set lookup table
2329 if (m_factory->m_cand_win_page_size > 0)
2330 m_lookup_table.set_page_size (m_factory->m_cand_win_page_size);
2331 else
2332 m_lookup_table.set_page_size (SCIM_ANTHY_CONFIG_CAND_WIN_PAGE_SIZE_DEFAULT);
2333
2334 // setup toolbar
2335 m_properties.clear ();
2336 install_properties ();
2337
2338 // set encoding
2339 m_preedit.set_dict_encoding (m_factory->m_dict_encoding);
2340 }
2341
2342 bool
is_single_segment(void)2343 AnthyInstance::is_single_segment (void)
2344 {
2345 if (m_conv_mode == SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT ||
2346 m_conv_mode == SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE)
2347 return true;
2348 else
2349 return false;
2350 }
2351
2352 bool
is_realtime_conversion(void)2353 AnthyInstance::is_realtime_conversion (void)
2354 {
2355 if (m_conv_mode == SCIM_ANTHY_CONVERSION_MULTI_SEGMENT_IMMEDIATE ||
2356 m_conv_mode == SCIM_ANTHY_CONVERSION_SINGLE_SEGMENT_IMMEDIATE)
2357 return true;
2358 else
2359 return false;
2360 }
2361
2362 int
get_pseudo_ascii_mode(void)2363 AnthyInstance::get_pseudo_ascii_mode (void)
2364 {
2365 int retval = 0;
2366 TypingMethod m = get_typing_method ();
2367
2368 if (m == SCIM_ANTHY_TYPING_METHOD_ROMAJI) {
2369 if (m_factory->m_romaji_pseudo_ascii_mode)
2370 retval |= SCIM_ANTHY_PSEUDO_ASCII_TRIGGERED_CAPITALIZED;
2371 }
2372
2373 return retval;
2374 }
2375
2376 /*
2377 vi:ts=4:nowrap:ai:expandtab
2378 */
2379