1 /** @file scim_table_imengine.cpp
2 * implementation of class TableInstance.
6 * Smart Common Input Method
8 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
9 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * $Id: scim_table_imengine.cpp,v 1.12 2006/01/12 08:43:29 suzhe Exp $
27 * Modifications by Samsung Electronics Co., Ltd.
29 * 1.Added auto commit feature for mobile user
32 #define Uses_STL_AUTOPTR
33 #define Uses_STL_FUNCTIONAL
34 #define Uses_STL_VECTOR
35 #define Uses_STL_IOSTREAM
36 #define Uses_STL_FSTREAM
37 #define Uses_STL_ALGORITHM
39 #define Uses_STL_UTILITY
40 #define Uses_STL_IOMANIP
42 #define Uses_SCIM_UTILITY
43 #define Uses_SCIM_IMENGINE
44 #define Uses_SCIM_ICONV
45 #define Uses_SCIM_CONFIG_BASE
46 #define Uses_SCIM_CONFIG_PATH
47 #define Uses_SCIM_LOOKUP_TABLE
50 #include <sys/types.h>
56 #include <Ecore_IMF.h>
58 #include "scim_table_imengine.h"
59 #include "scim_table_private.h"
61 #define scim_module_init table_LTX_scim_module_init
62 #define scim_module_exit table_LTX_scim_module_exit
63 #define scim_imengine_module_init table_LTX_scim_imengine_module_init
64 #define scim_imengine_module_create_factory table_LTX_scim_imengine_module_create_factory
66 #define SCIM_TABLE_SAVE_PERIOD 300
68 #define SCIM_TABLE_MAX_TABLE_NUMBER 256
69 #define SCIM_TABLE_MAX_INPUTTED_KEYS 16
71 #define SCIM_CONFIG_IMENGINE_TABLE_FULL_WIDTH_PUNCT_KEY "/IMEngine/Table/FullWidthPunctKey"
72 #define SCIM_CONFIG_IMENGINE_TABLE_FULL_WIDTH_LETTER_KEY "/IMEngine/Table/FullWidthLetterKey"
73 #define SCIM_CONFIG_IMENGINE_TABLE_MODE_SWITCH_KEY "/IMEngine/Table/ModeSwitchKey"
74 #define SCIM_CONFIG_IMENGINE_TABLE_ADD_PHRASE_KEY "/IMEngine/Table/AddPhraseKey"
75 #define SCIM_CONFIG_IMENGINE_TABLE_DEL_PHRASE_KEY "/IMEngine/Table/DeletePhraseKey"
76 #define SCIM_CONFIG_IMENGINE_TABLE_SHOW_PROMPT "/IMEngine/Table/ShowPrompt"
77 #define SCIM_CONFIG_IMENGINE_TABLE_USER_TABLE_BINARY "/IMEngine/Table/UserTableBinary"
78 #define SCIM_CONFIG_IMENGINE_TABLE_USER_PHRASE_FIRST "/IMEngine/Table/UserPhraseFirst"
79 #define SCIM_CONFIG_IMENGINE_TABLE_LONG_PHRASE_FIRST "/IMEngine/Table/LongPhraseFirst"
80 #define SCIM_CONFIG_IMENGINE_TABLE_SHOW_KEY_HINT "/IMEngine/Table/ShowKeyHint"
82 #define SCIM_PROP_STATUS "/IMEngine/Table/Status"
83 #define SCIM_PROP_LETTER "/IMEngine/Table/Letter"
84 #define SCIM_PROP_PUNCT "/IMEngine/Table/Punct"
86 #define SCIM_FULL_LETTER_ICON (SCIM_ICONDIR "/full-letter.png")
87 #define SCIM_HALF_LETTER_ICON (SCIM_ICONDIR "/half-letter.png")
88 #define SCIM_FULL_PUNCT_ICON (SCIM_ICONDIR "/full-punct.png")
89 #define SCIM_HALF_PUNCT_ICON (SCIM_ICONDIR "/half-punct.png")
91 #define SCIM_TABLE_ICON_FILE (SCIM_ICONDIR "/table.png")
96 static unsigned int _scim_number_of_tables = 0;
98 static Pointer <TableFactory> _scim_table_factories [SCIM_TABLE_MAX_TABLE_NUMBER];
100 static std::vector<String> _scim_sys_table_list;
101 static std::vector<String> _scim_user_table_list;
103 static ConfigPointer _scim_config;
104 char g_common_symbol[]={'#','$','%','^','&','*','@'};
107 _get_table_list (std::vector<String> &table_list, const String &path)
111 DIR *dir = opendir (path.c_str ());
113 struct dirent *file = readdir (dir);
114 while (file != NULL) {
115 struct stat filestat;
116 String absfn = path + SCIM_PATH_DELIM_STRING + file->d_name;
117 stat (absfn.c_str (), &filestat);
119 if (S_ISREG (filestat.st_mode))
120 table_list.push_back (absfn);
122 file = readdir (dir);
129 void scim_module_init (void)
131 bindtextdomain (GETTEXT_PACKAGE, SCIM_TABLE_LOCALEDIR);
132 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
135 void scim_module_exit (void)
137 for (int i=0; i<_scim_number_of_tables; ++i)
138 _scim_table_factories [i].reset ();
140 _scim_config.reset ();
143 unsigned int scim_imengine_module_init (const ConfigPointer &config)
145 _scim_config = config;
147 _get_table_list (_scim_sys_table_list, SCIM_TABLE_SYSTEM_TABLE_DIR);
148 _get_table_list (_scim_user_table_list, scim_get_home_dir () + SCIM_TABLE_USER_TABLE_DIR);
150 _scim_number_of_tables = _scim_sys_table_list.size () + _scim_user_table_list.size ();
152 return _scim_number_of_tables;
155 IMEngineFactoryPointer scim_imengine_module_create_factory (unsigned int index)
157 if (index >= _scim_number_of_tables) return 0;
159 TableFactory *factory = 0;
162 factory = new TableFactory (_scim_config);
164 if (index < _scim_sys_table_list.size ())
165 factory->load_table (_scim_sys_table_list [index], false);
167 factory->load_table (_scim_user_table_list [index - _scim_sys_table_list.size ()], true);
169 if (!factory->valid ())
170 throw IMEngineError ("Table load failed!");
172 return IMEngineFactoryPointer (factory);
176 return IMEngineFactoryPointer (0);
181 // implementation of Table
182 TableFactory::TableFactory (const ConfigPointer &config)
184 m_is_user_table (false),
185 m_show_prompt (false),
186 m_show_key_hint (false),
187 m_user_table_binary (false),
188 m_user_phrase_first (false),
189 m_long_phrase_first (false),
190 m_last_time ((time_t)0),
191 m_status_property (SCIM_PROP_STATUS, ""),
192 m_letter_property (SCIM_PROP_LETTER, _("Full/Half Letter")),
193 m_punct_property (SCIM_PROP_PUNCT, _("Full/Half Punct"))
197 m_status_property.set_tip (_("The status of the current input method. Click to change it."));
198 m_letter_property.set_tip (_("The input mode of the letters. Click to toggle between half and full."));
199 m_punct_property.set_tip (_("The input mode of the puncutations. Click to toggle between half and full."));
201 if (!m_config.null ())
202 m_reload_signal_connection = m_config->signal_connect_reload (slot (this, &TableFactory::init));
206 TableFactory::init (const ConfigPointer &config)
210 SCIM_DEBUG_IMENGINE (1) << "Load configuration.\n";
212 if (!config.null ()) {
213 //Read full width punctuation keys
214 str = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_FULL_WIDTH_PUNCT_KEY), String (""));
216 scim_string_to_key_list (m_full_width_punct_keys, str);
218 //Read full width letter keys
219 str = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_FULL_WIDTH_LETTER_KEY), String (""));
221 scim_string_to_key_list (m_full_width_letter_keys, str);
223 //Read mode switch keys
224 str = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_MODE_SWITCH_KEY), String (""));
226 scim_string_to_key_list (m_mode_switch_keys, str);
228 //Read add phrase keys
229 str = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_ADD_PHRASE_KEY), String ("Control+a,Control+equal"));
231 scim_string_to_key_list (m_add_phrase_keys, str);
233 //Read delete phrase keys
234 str = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_DEL_PHRASE_KEY), String ("Control+d,Control+minus"));
236 scim_string_to_key_list (m_del_phrase_keys, str);
238 m_show_prompt = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_SHOW_PROMPT), false);
240 m_show_key_hint = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_SHOW_KEY_HINT), false);
242 m_user_phrase_first = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_USER_PHRASE_FIRST), false);
244 m_long_phrase_first = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_LONG_PHRASE_FIRST), false);
246 m_user_table_binary = config->read (String (SCIM_CONFIG_IMENGINE_TABLE_USER_TABLE_BINARY), false);
249 m_last_time = time (NULL);
252 TableFactory::~TableFactory ()
255 m_reload_signal_connection.disconnect ();
259 TableFactory::get_name () const
261 return m_table.get_name (scim_get_current_locale ());
265 TableFactory::get_authors () const
267 return m_table.get_author ();
271 TableFactory::get_credits () const
273 return WideString ();
277 TableFactory::get_help () const
281 std::vector<KeyEvent> keys, keys2;
283 String full_width_letter;
284 String full_width_punct;
289 keys = m_full_width_letter_keys;
290 keys2 = m_table.get_full_width_letter_keys ();
291 keys.insert (keys.end (), keys2.begin (), keys2.end ());
292 keys.erase (std::unique (keys.begin (), keys.end ()), keys.end ());
293 scim_key_list_to_string (full_width_letter, keys);
295 keys = m_full_width_punct_keys;
296 keys2 = m_table.get_full_width_punct_keys ();
297 keys.insert (keys.end (), keys2.begin (), keys2.end ());
298 keys.erase (std::unique (keys.begin (), keys.end ()), keys.end ());
299 scim_key_list_to_string (full_width_punct, keys);
301 keys = m_mode_switch_keys;
302 keys2 = m_table.get_mode_switch_keys ();
303 keys.insert (keys.end (), keys2.begin (), keys2.end ());
304 keys.erase (std::unique (keys.begin (), keys.end ()), keys.end ());
305 scim_key_list_to_string (mode_switch, keys);
307 scim_key_list_to_string (add_phrase, m_add_phrase_keys);
308 scim_key_list_to_string (del_phrase, m_del_phrase_keys);
310 return utf8_mbstowcs (
311 String (_("Hot Keys:\n\n ")) +
312 full_width_letter + String (":\n") +
313 String (_(" Switch between full/half width letter mode.\n\n ")) +
314 full_width_punct + String (":\n") +
315 String (_(" Switch between full/half width punctuation mode.\n\n ")) +
316 mode_switch + String (":\n") +
317 String (_(" Switch between Forward/Input mode.\n\n ")) +
318 add_phrase + String (":\n") +
319 String (_(" Add a new phrase.\n\n ")) +
320 del_phrase + String (":\n") +
321 String (_(" Delete the selected phrase.\n\n")) +
322 String (_(" Control+Down:\n Move lookup cursor to next shorter phrase\n"
323 " Only available when LongPhraseFirst option is set.\n\n")) +
324 String (_(" Control+Up:\n Move lookup cursor to previous longer phrase\n"
325 " Only available when LongPhraseFirst option is set.\n\n")) +
326 String (_(" Esc:\n reset the input method.\n\n\n")) +
327 String (_("How to add a phrase:\n"
328 " Input the new phrase as normal, then press the\n"
329 " hot key. A hint will be shown to let you input a key\n"
330 " for this phrase.\n"
331 " Input a key then press the space bar.\n"
332 " A hint will be shown to indicate whether\n"
333 " the phrase was added sucessfully.\n"))
338 TableFactory::get_uuid () const
340 return m_table.get_uuid ();
344 TableFactory::get_icon_file () const
346 String file = m_table.get_icon_file ();
348 return file.length () ? file : String (SCIM_TABLE_ICON_FILE);
351 IMEngineInstancePointer
352 TableFactory::create_instance (const String& encoding, int id)
354 return new TableInstance (this, encoding, id);
358 TableFactory::load_table (const String &table_file, bool user_table)
360 if (!table_file.length ()) return false;
362 m_table_filename = table_file;
363 m_is_user_table = user_table;
366 if (!m_table.init ("", m_table_filename, "")) return false;
368 if (!m_table.init (m_table_filename,
369 get_sys_table_user_file (),
370 get_sys_table_freq_file ()))
374 set_languages (m_table.get_languages ());
376 return m_table.valid ();
380 TableFactory::refresh (bool rightnow)
382 time_t cur_time = time (NULL);
384 if (rightnow || cur_time < m_last_time || cur_time - m_last_time > SCIM_TABLE_SAVE_PERIOD) {
385 m_last_time = cur_time;
391 TableFactory::save ()
393 if (!m_table.valid () || !m_table.updated ()) return;
396 m_table.save ("", m_table_filename, "", m_user_table_binary);
398 m_table.save ("", get_sys_table_user_file (), get_sys_table_freq_file (), m_user_table_binary);
402 TableFactory::get_sys_table_freq_file ()
405 String::size_type pos;
407 if (m_table_filename.length ()) {
408 pos = m_table_filename.rfind (SCIM_PATH_DELIM);
410 if (pos != String::npos)
411 tf = m_table_filename.substr (pos+1);
413 tf = m_table_filename;
415 fn = scim_get_home_dir () + SCIM_TABLE_SYSTEM_UPDATE_TABLE_DIR;
417 if (access (fn.c_str (), R_OK | W_OK) != 0) {
418 if (!scim_make_dir (fn))
422 fn = fn + SCIM_PATH_DELIM_STRING + tf + ".freq";
428 TableFactory::get_sys_table_user_file ()
431 String::size_type pos;
433 if (m_table_filename.length ()) {
434 pos = m_table_filename.rfind (SCIM_PATH_DELIM);
436 if (pos != String::npos)
437 tf = m_table_filename.substr (pos+1);
439 tf = m_table_filename;
441 fn = scim_get_home_dir () + SCIM_TABLE_SYSTEM_UPDATE_TABLE_DIR;
443 if (access (fn.c_str (), R_OK | W_OK) != 0) {
444 if (!scim_make_dir (fn))
448 fn = fn + SCIM_PATH_DELIM_STRING + tf + ".user";
454 // implementation of TableInstance
455 TableInstance::TableInstance (TableFactory *factory,
456 const String& encoding,
458 : IMEngineInstanceBase (factory, encoding, id),
460 m_double_quotation_state (false),
461 m_single_quotation_state (false),
464 m_lookup_table_always_on (false),
465 m_inputing_caret (0),
469 m_full_width_letter [0] = m_factory->m_table.is_def_full_width_letter ();
470 m_full_width_letter [1] = false;
472 m_full_width_punct [0] = m_factory->m_table.is_def_full_width_punct ();
473 m_full_width_punct [1] = false;
475 char buf [2] = { 0, 0 };
477 std::vector <KeyEvent> keys = m_factory->m_table.get_select_keys ();
478 std::vector <WideString> labels;
480 for (size_t i = 0; i < keys.size (); ++i) {
481 buf [0] = keys [i].get_ascii_code ();
482 labels.push_back (utf8_mbstowcs (buf));
485 m_lookup_table.set_candidate_labels (labels);
486 m_lookup_table.set_page_size (keys.size ());
487 m_lookup_table.show_cursor ();
490 for (int i = 0;i < sizeof(g_common_symbol)/sizeof(char);i++) {
491 char _str[2]={g_common_symbol[i],0};
492 m_common_lookup_table.append_candidate (utf8_mbstowcs ((const char*)_str),attrs);
496 TableInstance::~TableInstance ()
501 TableInstance::process_key_event (const KeyEvent& rawkey)
503 KeyEvent key = rawkey.map_to_layout (m_factory->m_table.get_keyboard_layout ());
507 if (!m_focused) return false;
509 // capture the mode switch key events
510 if (match_key_event (m_factory->m_mode_switch_keys, key) ||
511 match_key_event (m_factory->m_table.get_mode_switch_keys (), key)) {
512 m_forward = !m_forward;
513 refresh_status_property ();
514 refresh_letter_property ();
515 refresh_punct_property ();
520 // toggle full width punctuation mode
521 else if (match_key_event (m_factory->m_full_width_punct_keys, key) ||
522 match_key_event (m_factory->m_table.get_full_width_punct_keys (), key)) {
523 trigger_property (SCIM_PROP_PUNCT);
527 // toggle full width letter mode
528 else if (match_key_event (m_factory->m_full_width_letter_keys, key) ||
529 match_key_event (m_factory->m_table.get_full_width_letter_keys (), key)) {
530 trigger_property (SCIM_PROP_LETTER);
534 // discard the key release event.
535 else if (key.is_key_release ()) {
539 // process the key press event, if not in forward mode.
540 else if (!m_forward) {
541 // First reset add phrase mode.
542 if (m_add_phrase_mode > 1) {
543 m_add_phrase_mode = 0;
544 refresh_aux_string ();
548 if (key.code == SCIM_KEY_Escape && key.mask == 0) {
549 if (m_inputted_keys.size () == 0 && m_add_phrase_mode != 1)
558 else if (key.code == SCIM_KEY_Left && key.mask == 0)
562 else if (key.code == SCIM_KEY_Right && key.mask == 0)
563 ret = caret_right ();
566 else if (key.code == SCIM_KEY_Home && key.mask == 0)
570 else if (key.code == SCIM_KEY_End && key.mask == 0)
573 //lookup table cursor up
574 else if (key.code == SCIM_KEY_Up && key.mask == 0)
575 ret = lookup_cursor_up ();
577 //lookup table cursor down
578 else if (key.code == SCIM_KEY_Down && key.mask == 0)
579 ret = lookup_cursor_down ();
581 //lookup table cursor up to longer phrase
582 else if (key.code == SCIM_KEY_Up && key.mask == SCIM_KEY_ControlMask &&
583 m_factory->m_long_phrase_first && !m_factory->m_user_phrase_first)
584 ret = lookup_cursor_up_to_longer ();
586 //lookup table cursor down
587 else if (key.code == SCIM_KEY_Down && key.mask == SCIM_KEY_ControlMask &&
588 m_factory->m_long_phrase_first && !m_factory->m_user_phrase_first)
589 ret = lookup_cursor_down_to_shorter ();
592 else if (key.code == SCIM_KEY_BackSpace && key.mask == 0)
596 else if (key.code == SCIM_KEY_Delete && key.mask == 0)
600 else if (!m_inputted_keys.size () && m_last_committed.length () &&
601 match_key_event (m_factory->m_add_phrase_keys, key)) {
602 m_add_phrase_mode = 1;
603 refresh_aux_string ();
608 else if (match_key_event (m_factory->m_del_phrase_keys, key)) {
609 if (delete_phrase ())
617 //select lookup table
618 int pos = m_factory->m_table.get_select_key_pos (key);
620 // If there is a new empty key (a split char was inserted),
621 // then try to select lookup table first.
622 // Otherwise try to insert the char first.
623 if (m_inputted_keys.size () && !m_inputted_keys [m_inputing_key].length ()) {
624 if (pos >= 0 && pos < m_lookup_table.get_current_page_size ())
625 ret = lookup_select (pos);
628 if (!ret && (key.mask & (~ (SCIM_KEY_ShiftMask + SCIM_KEY_CapsLockMask))) == 0)
629 ret = insert (key.get_ascii_code ());
632 if ((key.mask & (~ (SCIM_KEY_ShiftMask + SCIM_KEY_CapsLockMask))) == 0 &&
633 test_insert (key.get_ascii_code ()))
634 ret = insert (key.get_ascii_code ());
636 if (!ret && pos >= 0 && pos < m_lookup_table.get_current_page_size ())
637 ret = lookup_select (pos);
639 // insert char finally.
640 if (!ret && (key.mask & (~ (SCIM_KEY_ShiftMask + SCIM_KEY_CapsLockMask))) == 0)
641 ret = insert (key.get_ascii_code ());
644 //lookup table page up
645 if (!ret && match_key_event (m_factory->m_table.get_page_up_keys (), key))
646 ret = lookup_page_up ();
648 //lookup table page down
649 if (!ret && match_key_event (m_factory->m_table.get_page_down_keys (), key))
650 ret = lookup_page_down ();
653 if (!ret && match_key_event (m_factory->m_table.get_commit_keys (), key))
657 if (!ret && match_key_event (m_factory->m_table.get_forward_keys (), key))
662 if (!ret && (key.mask & (~ (SCIM_KEY_ShiftMask + SCIM_KEY_CapsLockMask))) == 0 &&
663 key.get_ascii_code ())
664 ret = post_process (key.get_ascii_code ());
672 TableInstance::select_candidate (unsigned int item)
675 if (m_inputted_keys.size () == 0
676 && m_lookup_table.number_of_candidates() == 0
677 && item < sizeof(g_common_symbol)/sizeof(char)) {
678 char _str[2]={g_common_symbol[item],0};
679 commit_string(utf8_mbstowcs(_str));
682 lookup_select (item);
686 TableInstance::update_lookup_table_page_size (unsigned int page_size)
689 m_lookup_table.set_page_size (page_size);
693 TableInstance::lookup_table_page_up ()
699 TableInstance::lookup_table_page_down ()
705 TableInstance::move_preedit_caret (unsigned int pos)
710 for (i=0; i<m_converted_strings.size (); ++i) {
711 if (pos >= len && pos < len + m_converted_strings [i].length ()) {
713 m_inputing_caret = m_inputted_keys [i].length ();
715 m_converted_strings.erase (m_converted_strings.begin () + i, m_converted_strings.end ());
716 m_converted_indexes.erase (m_converted_indexes.begin () + i, m_converted_indexes.end ());
718 refresh_lookup_table ();
720 refresh_aux_string ();
724 len += m_converted_strings [i].length ();
727 if (m_factory->m_table.is_auto_fill () &&
728 m_inputing_key == m_inputted_keys.size () - 1 &&
729 m_inputing_caret == m_inputted_keys [m_inputing_key].length () &&
730 m_converted_strings.size () == m_inputing_key &&
731 m_lookup_table.number_of_candidates ()) {
733 uint32 offset = m_lookup_table_indexes [m_lookup_table.get_cursor_pos ()];
734 size_t phlen = m_factory->m_table.get_phrase_length (offset);
736 if (pos >= len && pos < len + phlen) {
737 m_inputing_caret = 0;
738 refresh_lookup_table (true, false);
743 if (m_converted_strings.size ()) {
745 if (pos < len) ++pos;
748 for (i=m_converted_strings.size (); i<m_inputted_keys.size (); ++i) {
749 if (pos >= len && pos <= len + m_inputted_keys [i].length ()) {
751 m_inputing_caret = pos - len;
753 refresh_lookup_table (true, false);
755 refresh_aux_string ();
759 len += (m_inputted_keys [i].length () +1);
765 TableInstance::reset ()
767 if (m_inputted_keys.size () && m_preedit_string.size()) {
768 commit_string (m_preedit_string);
770 m_double_quotation_state = false;
771 m_single_quotation_state = false;
773 m_lookup_table.clear ();
775 std::vector<String> ().swap (m_inputted_keys);
777 std::vector<WideString> ().swap (m_converted_strings);
779 std::vector<uint32> ().swap (m_converted_indexes);
781 std::vector<uint32> ().swap (m_lookup_table_indexes);
783 m_add_phrase_mode = 0;
785 m_last_committed = WideString ();
787 m_inputing_caret = 0;
790 m_iconv.set_encoding (get_encoding ());
791 if (m_lookup_table_always_on) {
792 refresh_lookup_table (true, false);
796 hide_preedit_string ();
801 TableInstance::focus_in ()
805 if (m_add_phrase_mode != 1) {
806 m_last_committed = WideString ();
807 m_add_phrase_mode = 0;
810 //refresh_lookup_table (true, false);
812 refresh_aux_string ();
813 initialize_properties ();
817 TableInstance::focus_out ()
824 TableInstance::trigger_property (const String &property)
826 if (property == SCIM_PROP_STATUS) {
827 m_forward = !m_forward;
828 refresh_status_property ();
829 refresh_letter_property ();
830 refresh_punct_property ();
832 } else if (property == SCIM_PROP_LETTER && m_factory->m_table.is_use_full_width_letter ()) {
833 m_full_width_letter [m_forward?1:0] =
834 !m_full_width_letter [m_forward?1:0];
835 refresh_letter_property ();
836 } else if (property == SCIM_PROP_PUNCT && m_factory->m_table.is_use_full_width_punct ()) {
837 m_full_width_punct [m_forward?1:0] =
838 !m_full_width_punct [m_forward?1:0];
839 refresh_punct_property ();
844 TableInstance::set_layout (unsigned int layout)
848 case ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL:
849 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
850 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
851 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
852 refresh_lookup_table (true, false);
853 m_lookup_table_always_on = true;
855 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
856 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
857 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
858 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
859 hide_lookup_table ();
860 m_lookup_table_always_on = false;
866 TableInstance::initialize_properties ()
868 PropertyList proplist;
870 proplist.push_back (m_factory->m_status_property);
872 if (m_factory->m_table.is_use_full_width_letter ())
873 proplist.push_back (m_factory->m_letter_property);
875 if (m_factory->m_table.is_use_full_width_punct ())
876 proplist.push_back (m_factory->m_punct_property);
878 register_properties (proplist);
880 refresh_status_property ();
881 refresh_letter_property ();
882 refresh_punct_property ();
886 TableInstance::refresh_status_property ()
890 m_factory->m_status_property.set_label (_("En"));
892 m_factory->m_status_property.set_label (utf8_wcstombs (m_factory->m_table.get_status_prompt ()));
894 update_property (m_factory->m_status_property);
899 TableInstance::refresh_letter_property ()
901 if (m_focused && m_factory->m_table.is_use_full_width_letter ()) {
902 m_factory->m_letter_property.set_icon (
903 m_full_width_letter [m_forward?1:0] ? SCIM_FULL_LETTER_ICON : SCIM_HALF_LETTER_ICON);
904 update_property (m_factory->m_letter_property);
909 TableInstance::refresh_punct_property ()
911 if (m_focused && m_factory->m_table.is_use_full_width_punct ()) {
912 m_factory->m_punct_property.set_icon (
913 m_full_width_punct [m_forward?1:0] ? SCIM_FULL_PUNCT_ICON : SCIM_HALF_PUNCT_ICON);
914 update_property (m_factory->m_punct_property);
919 TableInstance::caret_left ()
921 if (m_inputted_keys.size ()) {
922 if (m_inputing_caret > 0) {
924 refresh_lookup_table (true, false);
925 } else if (m_inputing_key > 0) {
927 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
929 if (m_converted_strings.size () > m_inputing_key) {
930 m_converted_strings.pop_back ();
931 m_converted_indexes.pop_back ();
932 refresh_lookup_table ();
934 refresh_lookup_table (true, false);
941 refresh_aux_string ();
948 TableInstance::caret_right ()
950 if (m_inputted_keys.size ()) {
951 if (m_inputing_caret < m_inputted_keys [m_inputing_key].size ()) {
953 } else if (m_inputing_key < m_inputted_keys.size () - 1) {
955 m_inputing_caret = 0;
957 return caret_home ();
959 refresh_lookup_table (true, false);
961 refresh_aux_string ();
968 TableInstance::caret_home ()
970 if (m_inputted_keys.size ()) {
972 m_inputing_caret = 0;
974 if (m_converted_strings.size ()) {
975 m_converted_strings.clear ();
976 m_converted_indexes.clear ();
977 refresh_lookup_table ();
979 refresh_lookup_table (true, false);
983 refresh_aux_string ();
990 TableInstance::caret_end ()
992 if (m_inputted_keys.size ()) {
993 m_inputing_key = m_inputted_keys.size () - 1;
994 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
996 refresh_lookup_table (true, false);
998 refresh_aux_string ();
1005 TableInstance::test_insert (char key)
1007 if (m_factory->m_table.is_valid_char (key)) {
1009 if (m_inputted_keys.size ()) {
1010 newkey = m_inputted_keys [m_inputing_key];
1011 newkey.insert (newkey.begin () + m_inputing_caret, key);
1013 newkey.push_back (key);
1016 return m_factory->m_table.is_defined_key (newkey);
1022 TableInstance::insert (char ch)
1024 if (!ch) return false;
1027 uint32 old_inputing_key = m_inputing_key;
1028 bool insert_ok = false;
1030 if (m_inputted_keys.size () - m_converted_strings.size () >
1031 SCIM_TABLE_MAX_INPUTTED_KEYS)
1034 // If current inputing key is empty, then the last inputing key is the previous key.
1035 if (m_inputted_keys.size () && m_inputing_key && !m_inputted_keys [m_inputing_key].length ())
1036 -- old_inputing_key;
1038 if (m_factory->m_table.is_split_char (ch)) {
1039 // split char is invalid during add phrase mode.
1040 if (m_add_phrase_mode == 1)
1042 else if (m_inputted_keys.size () == 0)
1044 else if (m_inputing_key == m_inputted_keys.size () -1 &&
1045 m_inputted_keys [m_inputing_key].length () &&
1046 m_inputing_caret == m_inputted_keys [m_inputing_key].length ()) {
1048 m_inputing_caret = 0;
1049 m_inputted_keys.insert (m_inputted_keys.begin () + m_inputing_key, String ());
1055 } else if (m_factory->m_table.is_valid_char (ch)) {
1056 if (m_add_phrase_mode == 1) {
1058 if (!m_inputted_keys.size ()) {
1059 m_inputted_keys.push_back (String (""));
1060 m_inputing_caret = 0;
1061 } else if (m_inputted_keys [0].length () >= m_factory->m_table.get_max_key_length ()) {
1065 m_inputted_keys [0].insert (m_inputted_keys [0].begin () + m_inputing_caret, ch);
1068 } else if (m_inputted_keys.size ()) {
1069 newkey = m_inputted_keys [m_inputing_key];
1070 newkey.insert (newkey.begin () + m_inputing_caret, ch);
1072 if ((m_factory->m_table.is_auto_split () == false ||
1073 m_factory->m_table.is_defined_key (newkey)) &&
1074 newkey.length () <= m_factory->m_table.get_max_key_length ()) {
1075 m_inputted_keys [m_inputing_key] = newkey;
1078 } else if (m_inputing_caret == m_inputted_keys [m_inputing_key].length ()) {
1080 newkey.push_back (ch);
1082 if (m_factory->m_table.is_defined_key (newkey)) {
1084 m_inputing_caret = 1;
1085 m_inputted_keys.insert (m_inputted_keys.begin () + m_inputing_key, newkey);
1088 } else if (m_inputing_caret == 0) {
1090 newkey.push_back (ch);
1092 if (m_factory->m_table.is_defined_key (newkey)) {
1093 m_inputing_caret = 1;
1094 m_inputted_keys.insert (m_inputted_keys.begin () + m_inputing_key, newkey);
1098 } else if (!m_factory->m_table.is_multi_wildcard_char (ch)) {
1100 newkey.push_back (ch);
1102 if (m_factory->m_table.is_defined_key (newkey)) {
1103 m_inputted_keys.push_back (newkey);
1105 m_inputing_caret = 1;
1112 //Do some extra work in normal mode.
1113 if (m_add_phrase_mode != 1) {
1115 if (m_factory->m_table.is_auto_select () &&
1116 m_converted_strings.size () == old_inputing_key &&
1117 old_inputing_key + 1 == m_inputing_key &&
1118 m_lookup_table.number_of_candidates () &&
1119 m_inputted_keys [m_inputing_key].length ()) {
1120 lookup_to_converted (m_lookup_table.get_cursor_pos ());
1123 //discard invalid key
1124 if (m_factory->m_table.is_discard_invalid_key () &&
1125 m_converted_strings.size () == old_inputing_key &&
1126 old_inputing_key + 1 == m_inputing_key &&
1127 m_lookup_table.number_of_candidates () == 0 &&
1128 m_inputted_keys [m_inputing_key].length ()) {
1129 m_inputted_keys.erase (m_inputted_keys.begin () + old_inputing_key);
1133 if (m_converted_strings.size () == m_inputing_key) {
1134 refresh_lookup_table (false, true);
1136 // If auto commit is true, then do auto select when
1137 // there is only one candidate for this key.
1138 if (m_lookup_table.number_of_candidates () == 1 &&
1139 m_factory->m_table.is_auto_commit () &&
1140 !m_factory->m_table.is_defined_key (
1141 m_inputted_keys [m_inputing_key],
1142 GT_SEARCH_ONLY_LONGER)) {
1143 lookup_to_converted (m_lookup_table.get_cursor_pos ());
1144 refresh_lookup_table ();
1146 refresh_lookup_table (true, false);
1150 if (m_inputted_keys.size () > SCIM_TABLE_MAX_INPUTTED_KEYS ||
1151 m_factory->m_table.is_auto_commit ())
1152 commit_converted ();
1154 // If it's a key end char, then append an empty key.
1155 if (m_factory->m_table.is_key_end_char (ch) &&
1156 m_inputing_key == m_inputted_keys.size () -1 &&
1157 m_inputted_keys [m_inputing_key].length () &&
1158 m_inputing_caret == m_inputted_keys [m_inputing_key].length ()) {
1160 m_inputing_caret = 0;
1161 m_inputted_keys.insert (m_inputted_keys.begin () + m_inputing_key, String ());
1166 refresh_aux_string ();
1175 TableInstance::erase (bool backspace)
1177 if (m_inputted_keys.size ()) {
1178 if (backspace && (m_inputing_key > 0 || m_inputing_caret > 0)) {
1179 if (m_inputing_caret > 0) {
1181 m_inputted_keys [m_inputing_key].erase (m_inputing_caret, 1);
1183 if (m_inputted_keys [m_inputing_key].length () == 0)
1184 m_inputted_keys.erase (m_inputted_keys.begin () + m_inputing_key);
1187 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
1189 if (m_inputing_caret > 0) {
1191 m_inputted_keys [m_inputing_key].erase (m_inputing_caret, 1);
1195 if (m_inputted_keys [m_inputing_key].length () == 0) {
1196 m_inputted_keys.erase (m_inputted_keys.begin () + m_inputing_key);
1198 if (m_inputing_key > 0) {
1200 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
1203 } else if (!backspace) {
1204 if (m_inputing_caret < m_inputted_keys [m_inputing_key].length ()) {
1205 m_inputted_keys [m_inputing_key].erase (m_inputing_caret, 1);
1207 if (m_inputted_keys [m_inputing_key].length () == 0) {
1208 m_inputted_keys.erase (m_inputted_keys.begin () + m_inputing_key);
1210 if (m_inputing_key == m_inputted_keys.size () && m_inputing_key > 0) {
1212 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
1218 if (m_inputted_keys.size () == 1 && m_inputted_keys [0].length () == 0) {
1219 m_inputted_keys.clear ();
1221 m_inputing_caret = 0;
1224 if (m_add_phrase_mode != 1) {
1225 if (m_converted_strings.size () > m_inputing_key) {
1226 m_converted_strings.erase (m_converted_strings.begin () + m_inputing_key, m_converted_strings.end ());
1227 m_converted_indexes.erase (m_converted_indexes.begin () + m_inputing_key, m_converted_indexes.end ());
1229 refresh_lookup_table ();
1233 refresh_aux_string ();
1240 TableInstance::space_hit ()
1242 if (m_inputted_keys.size ()) {
1243 if (m_add_phrase_mode == 1) {
1244 if (m_factory->m_table.add_phrase (m_inputted_keys [0], m_last_committed)) {
1245 m_add_phrase_mode = 2;
1246 m_factory->refresh (true);
1248 m_add_phrase_mode = 3;
1251 m_inputted_keys.clear ();
1252 m_last_committed = WideString ();
1253 m_inputing_caret = m_inputing_key = 0;
1255 if (m_converted_strings.size () == 0 && m_lookup_table.number_of_candidates () == 0)
1258 if (m_lookup_table.number_of_candidates () && m_converted_strings.size () < m_inputted_keys.size ()) {
1259 lookup_to_converted (m_lookup_table.get_cursor_pos ());
1260 refresh_lookup_table ();
1263 if (m_converted_strings.size () == m_inputted_keys.size () ||
1264 (m_converted_strings.size () == m_inputted_keys.size () - 1 &&
1265 m_inputted_keys [m_inputing_key].length () == 0))
1266 commit_converted ();
1270 refresh_aux_string ();
1278 TableInstance::enter_hit ()
1280 if (m_inputted_keys.size ()) {
1281 if (m_add_phrase_mode == 1) {
1282 if (m_factory->m_table.add_phrase (m_inputted_keys [0], m_last_committed)) {
1283 m_add_phrase_mode = 2;
1284 m_factory->refresh (true);
1286 m_add_phrase_mode = 3;
1289 m_inputted_keys.clear ();
1290 m_last_committed = WideString ();
1291 m_inputing_caret = m_inputing_key = 0;
1294 refresh_aux_string ();
1301 m_last_committed = WideString ();
1307 TableInstance::lookup_cursor_up ()
1309 if (m_inputted_keys.size () && m_lookup_table.number_of_candidates ()) {
1310 m_lookup_table.cursor_up ();
1311 refresh_lookup_table (true, false);
1313 refresh_aux_string ();
1320 TableInstance::lookup_cursor_down ()
1322 if (m_inputted_keys.size () && m_lookup_table.number_of_candidates ()) {
1323 m_lookup_table.cursor_down ();
1324 refresh_lookup_table (true, false);
1326 refresh_aux_string ();
1333 TableInstance::lookup_cursor_up_to_longer ()
1335 if (m_inputted_keys.size () && m_lookup_table.number_of_candidates ()) {
1336 //Get current lookup table cursor
1337 uint32 cursor = m_lookup_table.get_cursor_pos ();
1338 //Get current phrase length
1339 uint32 curlen = m_factory->m_table.get_phrase_length (m_lookup_table_indexes [cursor]);
1342 m_lookup_table.cursor_up ();
1343 cursor = m_lookup_table.get_cursor_pos ();
1344 if (curlen < m_factory->m_table.get_phrase_length (m_lookup_table_indexes [cursor]))
1348 refresh_lookup_table (true, false);
1350 refresh_aux_string ();
1357 TableInstance::lookup_cursor_down_to_shorter ()
1359 if (m_inputted_keys.size () && m_lookup_table.number_of_candidates ()) {
1360 uint32 entries = m_lookup_table.number_of_candidates ();
1361 //Get current lookup table cursor
1362 uint32 cursor = m_lookup_table.get_cursor_pos ();
1363 //Get current phrase length
1364 uint32 curlen = m_factory->m_table.get_phrase_length (m_lookup_table_indexes [cursor]);
1367 m_lookup_table.cursor_down ();
1368 cursor = m_lookup_table.get_cursor_pos ();
1369 if (curlen > m_factory->m_table.get_phrase_length (m_lookup_table_indexes [cursor]))
1371 } while (cursor < entries - 1);
1373 refresh_lookup_table (true, false);
1375 refresh_aux_string ();
1382 TableInstance::lookup_page_up ()
1384 if (m_inputted_keys.size () &&
1385 m_lookup_table.get_current_page_size () <
1386 m_lookup_table.number_of_candidates ()) {
1388 m_lookup_table.page_up ();
1389 refresh_lookup_table (true, false);
1391 refresh_aux_string ();
1398 TableInstance::lookup_page_down ()
1400 if (m_inputted_keys.size () &&
1401 m_lookup_table.get_current_page_size () <
1402 m_lookup_table.number_of_candidates ()) {
1404 if (!m_lookup_table.page_down ())
1405 while (m_lookup_table.page_up ()) NULL;
1407 refresh_lookup_table (true, false);
1409 refresh_aux_string ();
1416 TableInstance::lookup_select (int index)
1418 if (m_inputted_keys.size ()) {
1419 if (m_lookup_table.number_of_candidates () == 0)
1422 index += m_lookup_table.get_current_page_start ();
1424 lookup_to_converted (index);
1426 if (m_converted_strings.size () == m_inputted_keys.size () ||
1427 (m_converted_strings.size () == m_inputted_keys.size () - 1 &&
1428 m_inputted_keys [m_inputing_key].length () == 0))
1429 commit_converted ();
1431 refresh_lookup_table ();
1433 refresh_aux_string ();
1442 TableInstance::post_process (char key)
1444 // Auto select and commit the candidate item when an invalid key is pressed.
1445 if (m_factory->m_table.is_auto_commit () &&
1446 m_converted_strings.size () == m_inputing_key &&
1447 m_inputing_key + 1 == m_inputted_keys.size () &&
1448 m_inputing_caret == m_inputted_keys [m_inputing_key].length () &&
1449 m_lookup_table.number_of_candidates ()) {
1451 lookup_to_converted (m_lookup_table.get_cursor_pos ());
1452 commit_converted ();
1454 refresh_lookup_table ();
1456 refresh_aux_string ();
1459 if (m_inputted_keys.size ()) return true;
1461 if ((ispunct (key) && m_full_width_punct [m_forward?1:0]) ||
1462 ((isalnum (key) || key == 0x20) && m_full_width_letter [m_forward?1:0])) {
1465 str.push_back (0x3002);
1466 else if (key == '\\')
1467 str.push_back (0x3001);
1468 else if (key == '^') {
1469 str.push_back (0x2026);
1470 str.push_back (0x2026);
1471 } else if (key == '\"') {
1472 if (!m_double_quotation_state)
1473 str.push_back (0x201c);
1475 str.push_back (0x201d);
1476 m_double_quotation_state = !m_double_quotation_state;
1477 } else if (key == '\'') {
1478 if (!m_single_quotation_state)
1479 str.push_back (0x2018);
1481 str.push_back (0x2019);
1482 m_single_quotation_state = !m_single_quotation_state;
1484 str.push_back (scim_wchar_to_full_width (key));
1487 commit_string (str);
1489 m_last_committed = WideString ();
1498 TableInstance::delete_phrase ()
1500 if (m_lookup_table.number_of_candidates ()) {
1501 int pos = m_lookup_table.get_cursor_pos ();
1502 uint32 offset = m_lookup_table_indexes [pos];
1504 if (m_factory->m_table.delete_phrase (offset)) {
1505 m_factory->refresh (true);
1506 refresh_lookup_table ();
1514 TableInstance::lookup_to_converted (int index)
1516 if (index < 0 || index >= m_lookup_table.number_of_candidates ())
1519 uint32 offset = m_lookup_table_indexes [index];
1520 WideString str = m_factory->m_table.get_phrase (offset);
1522 m_converted_strings.push_back (str);
1523 m_converted_indexes.push_back (offset);
1525 if (m_inputing_key < m_converted_strings.size ()) {
1526 m_inputing_key = m_converted_strings.size ();
1527 if (m_inputing_key >= m_inputted_keys.size ())
1528 m_inputted_keys.push_back (String (""));
1529 m_inputing_caret = 0;
1534 TableInstance::commit_converted ()
1536 if (m_converted_strings.size ()) {
1539 for (size_t i=0; i<m_converted_strings.size (); ++i)
1540 res += m_converted_strings [i];
1542 // Hide preedit string before committing string,
1543 // to prevent some buggy clients from inserting the string into wrong place.
1544 // Preedit string will be refreshed after return from commit_converted ().
1545 hide_preedit_string ();
1546 commit_string (res);
1548 if (utf8_wcstombs (m_last_committed).length () >= 255)
1549 m_last_committed = WideString ();
1551 m_last_committed += res;
1553 m_inputted_keys.erase (m_inputted_keys.begin (), m_inputted_keys.begin () + m_converted_strings.size ());
1554 m_inputing_key -= m_converted_strings.size ();
1556 if (m_inputted_keys.size () == 1 && m_inputted_keys [0].length () == 0) {
1557 m_inputted_keys.clear ();
1559 m_inputing_caret = 0;
1562 if (m_inputted_keys.size ()) {
1563 m_inputing_key = m_inputted_keys.size () - 1;
1564 m_inputing_caret = m_inputted_keys [m_inputing_key].length ();
1567 if (m_factory->m_table.is_dynamic_adjust ()){
1568 for (size_t i = 0; i < m_converted_indexes.size (); ++i) {
1569 uint32 freq = m_factory->m_table.get_phrase_frequency (m_converted_indexes [i]);
1570 if (freq < SCIM_GT_MAX_PHRASE_FREQ) {
1571 uint32 delta = ((SCIM_GT_MAX_PHRASE_FREQ - freq) >> SCIM_GT_PHRASE_FREQ_DELTA_SHIFT);
1572 freq += (delta ? delta : 1);
1573 m_factory->m_table.set_phrase_frequency (m_converted_indexes [i], freq);
1576 m_factory->refresh (false);
1579 m_converted_strings.clear ();
1580 m_converted_indexes.clear ();
1585 TableInstance::refresh_preedit ()
1587 WideString preedit_string;
1594 if (m_inputted_keys.size () == 0) {
1595 hide_preedit_string ();
1599 for (i = 0; i<m_converted_strings.size (); ++i)
1600 preedit_string += m_converted_strings [i];
1602 int inputted_keys = m_inputted_keys.size ();
1604 if (m_inputted_keys [inputted_keys - 1].length () == 0)
1607 // Fill the preedit string.
1608 if (m_factory->m_table.is_auto_fill () &&
1609 m_converted_strings.size () == inputted_keys - 1 &&
1610 m_inputing_caret == m_inputted_keys [m_inputing_key].length () &&
1611 m_lookup_table.number_of_candidates ()) {
1613 uint32 offset = m_lookup_table_indexes [m_lookup_table.get_cursor_pos ()];
1614 WideString str = m_factory->m_table.get_phrase (offset);
1616 start = preedit_string.length ();
1617 preedit_string += str;
1618 length = str.length ();
1619 caret = preedit_string.length ();
1621 i = m_converted_strings.size ();
1622 caret = start = preedit_string.length ();
1624 for (i = m_converted_strings.size (); i < inputted_keys; ++i) {
1625 if (m_factory->m_table.is_show_key_prompt ()) {
1626 preedit_string += m_factory->m_table.get_key_prompt (m_inputted_keys [i]);
1627 if (i == m_inputing_key)
1628 caret += (m_factory->m_table.get_key_prompt (m_inputted_keys [i].substr (0, m_inputing_caret))).length ();
1630 preedit_string += utf8_mbstowcs (m_inputted_keys [i]);
1631 if (i == m_inputing_key)
1632 caret += m_inputing_caret;
1635 if (i == m_converted_strings.size ())
1636 length = preedit_string.length () - start;
1638 if (i < inputted_keys - 1)
1639 preedit_string.push_back ((ucs4_t)' ');
1641 if (i < m_inputing_key)
1642 caret = preedit_string.length ();
1645 m_preedit_string = preedit_string;
1646 if (preedit_string.length () == 0) {
1647 hide_preedit_string ();
1651 AttributeList attrs;
1656 attrs.push_back (Attribute(0, start, SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_UNDERLINE));
1657 attrs.push_back (Attribute(start, length, SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_HIGHLIGHT));
1659 if (end < preedit_string.length())
1660 attrs.push_back (Attribute(end, preedit_string.length()- end, SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_UNDERLINE));
1662 update_preedit_string (preedit_string, attrs);
1663 update_preedit_caret (caret);
1665 show_preedit_string ();
1669 TableInstance::refresh_lookup_table (bool show, bool refresh)
1671 m_lookup_table.set_page_size (m_factory->m_table.get_select_keys ().size ());
1674 std::vector <uint32> phrases;
1677 m_lookup_table.clear ();
1678 m_lookup_table_indexes.clear ();
1680 if (m_converted_strings.size () < m_inputted_keys.size ()) {
1682 String key = m_inputted_keys [m_converted_strings.size ()];
1684 if (key.length () &&
1685 m_factory->m_table.find (phrases,
1687 m_factory->m_user_phrase_first,
1688 m_factory->m_long_phrase_first)) {
1690 bool show_full_hint = m_factory->m_table.is_wildcard_key (key);
1691 std::set<WideString> candiadtes;
1692 for (size_t i = 0; i < phrases.size (); ++i) {
1693 str = m_factory->m_table.get_phrase (phrases [i]);
1695 if (m_iconv.test_convert (str)) {
1696 if (m_factory->m_show_key_hint) {
1697 String hint = m_factory->m_table.get_key (phrases [i]);
1700 str += utf8_mbstowcs (hint);
1701 else if (hint.length () > key.length ())
1702 str += utf8_mbstowcs (hint.substr (key.length ()));
1705 AttributeList attrs;
1707 if (m_factory->m_table.is_user_phrase (phrases [i]))
1708 attrs.push_back (Attribute (0, str.length (), SCIM_ATTR_FOREGROUND, SCIM_RGB_COLOR(32, 32, 255)));
1710 m_lookup_table.append_candidate (str, attrs);
1712 if (candiadtes.find (str) != candiadtes.end())
1714 candiadtes.insert (str);
1715 m_lookup_table.append_candidate (str);
1716 m_lookup_table_indexes.push_back (phrases [i]);
1724 if (m_lookup_table.number_of_candidates () &&
1725 (m_factory->m_table.is_always_show_lookup () ||
1726 m_inputing_key < m_inputted_keys.size () - 1 ||
1727 m_inputing_caret < m_inputted_keys [m_inputing_key].length () ||
1728 m_converted_strings.size () < m_inputted_keys.size () - 1)) {
1729 update_lookup_table (m_lookup_table);
1731 if(m_inputted_keys.size ())
1733 m_lookup_table.clear ();
1734 update_lookup_table (m_lookup_table);
1737 update_lookup_table (m_common_lookup_table);
1739 show_lookup_table ();
1744 TableInstance::refresh_aux_string ()
1747 AttributeList attributes;
1749 if (m_add_phrase_mode == 1) {
1750 prompt = utf8_mbstowcs (_("Input a key string for phrase: ")) + m_last_committed;
1751 } else if (m_add_phrase_mode == 2) {
1752 prompt = utf8_mbstowcs (_("Success."));
1753 attributes.push_back (Attribute (0, prompt.length (), SCIM_ATTR_FOREGROUND, SCIM_RGB_COLOR(32, 255, 32)));
1754 } else if (m_add_phrase_mode == 3) {
1755 prompt = utf8_mbstowcs (_("Failed."));
1756 attributes.push_back (Attribute (0, prompt.length (), SCIM_ATTR_FOREGROUND, SCIM_RGB_COLOR(255, 32, 32)));
1758 if (!m_factory->m_show_prompt || m_inputted_keys.size () == 0) {
1763 if (!m_factory->m_table.is_show_key_prompt ())
1764 prompt = m_factory->m_table.get_key_prompt (m_inputted_keys [m_inputing_key]);
1766 if (m_lookup_table.number_of_candidates () && ! m_factory->m_show_key_hint) {
1767 prompt += utf8_mbstowcs (" <");
1768 unsigned int att_start = prompt.length ();
1770 if (m_factory->m_table.is_show_key_prompt ())
1771 prompt += m_factory->m_table.get_key_prompt (m_factory->m_table.get_key (
1772 m_lookup_table_indexes [m_lookup_table.get_cursor_pos ()]));
1774 prompt += utf8_mbstowcs (m_factory->m_table.get_key (
1775 m_lookup_table_indexes [m_lookup_table.get_cursor_pos ()]));
1777 unsigned int att_length = prompt.length () - att_start;
1778 prompt += utf8_mbstowcs (">");
1779 attributes.push_back (Attribute (att_start, att_length, SCIM_ATTR_FOREGROUND, SCIM_RGB_COLOR(128, 128, 255)));
1783 if (prompt.length ()) {
1784 update_aux_string (prompt, attributes);
1792 TableInstance::match_key_event (const std::vector<KeyEvent>& keyvec,
1793 const KeyEvent& key)
1795 std::vector<KeyEvent>::const_iterator kit;
1797 for (kit = keyvec.begin (); kit != keyvec.end (); ++kit) {
1798 if (key.code == kit->code && key.mask == kit->mask)
1799 if (!(key.mask & SCIM_KEY_ReleaseMask) || m_prev_key.code == key.code)
1805 vi:ts=4:nowrap:ai:expandtab