1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Copyright (C) 2004 Hiroyuki Ikezoe
4 * Copyright (C) 2004 Takuro Ashie
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)
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.
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.
21 #include "scim_anthy_key2kana.h"
22 #include "scim_anthy_factory.h"
23 #include "scim_anthy_imengine.h"
24 #include "scim_anthy_utils.h"
26 using namespace scim_anthy;
28 Key2KanaConvertor::Key2KanaConvertor (AnthyInstance & anthy,
29 Key2KanaTableSet & tables)
32 m_is_in_pseudo_ascii_mode (false)
34 set_case_sensitive (false);
35 set_pseudo_ascii_mode (0);
38 Key2KanaConvertor::~Key2KanaConvertor ()
43 Key2KanaConvertor::can_append (const KeyEvent & key,
46 // ignore key release.
47 if (key.is_key_release ())
50 // ignore short cut keys of apllication.
51 if (key.mask & SCIM_KEY_ControlMask ||
52 key.mask & SCIM_KEY_AltMask)
57 if (isprint(key.get_ascii_code ()) &&
58 (ignore_space || !isspace(key.get_ascii_code ())))
61 if (util_key_is_keypad (key))
68 Key2KanaConvertor::append (const KeyEvent & key,
73 if (!can_append (key))
78 util_keypad_to_string (raw, key);
80 if (util_key_is_keypad (key)) {
83 String ten_key_type = m_anthy.get_factory()->m_ten_key_type;
85 // convert key pad string to wide
86 if ((ten_key_type == "FollowMode" &&
87 (m_anthy.get_input_mode () == SCIM_ANTHY_MODE_LATIN ||
88 m_anthy.get_input_mode () == SCIM_ANTHY_MODE_HALF_KATAKANA)) ||
89 ten_key_type == "Half")
91 wide = utf8_mbstowcs (raw);
93 util_convert_to_wide (wide, raw);
96 // join to previous string
97 if (!m_exact_match.is_empty()) {
98 if (!m_exact_match.get_result(0).empty() &&
99 m_exact_match.get_result(1).empty())
101 result = utf8_mbstowcs (m_exact_match.get_result(0));
103 retval = true; /* commit prev pending */
107 if (m_pending.length () > 0)
108 retval = true; /* commit prev pending */
113 m_exact_match.clear ();
118 // the key isn't keypad
119 return append (raw, result, pending);
124 Key2KanaConvertor::append (const String & str,
125 WideString & result, WideString & pending)
127 WideString widestr = utf8_mbstowcs (str);
128 WideString matching_str = m_pending + widestr;
129 Key2KanaRule exact_match;
130 bool has_partial_match = false;
133 if (m_pseudo_ascii_mode != 0 && process_pseudo_ascii_mode (widestr)) {
134 m_pending += widestr;
138 if (!m_case_sensitive) {
139 String half = utf8_wcstombs (matching_str);
140 for (unsigned int i = 0; i < half.length (); i++)
141 half[i] = tolower (half[i]);
142 matching_str = utf8_mbstowcs (half);
145 /* find matched table */
146 if ((m_anthy.get_typing_method () == SCIM_ANTHY_TYPING_METHOD_KANA) &&
147 (m_last_key.mask & /*SCIM_KEY_QuirkKanaRoMask*/ (1<<14)) &&
148 (m_anthy.get_factory()->m_kana_layout_ro_key.length () > 0))
150 // Special treatment for Kana "Ro" key.
151 // This code is a temporary solution. It doesn't care some minor cases.
152 std::vector<String> kana_ro_result;
153 scim_split_string_list (kana_ro_result,
154 m_anthy.get_factory()->m_kana_layout_ro_key);
155 Key2KanaRule kana_ro_rule("\\", kana_ro_result);
156 result = utf8_mbstowcs (kana_ro_rule.get_result (0));
158 m_exact_match.clear ();
159 if (matching_str == utf8_mbstowcs ("\\")) {
166 std::vector<Key2KanaTable*> &tables = m_tables.get_tables();
167 for (unsigned int j = 0; j < tables.size(); j++) {
171 Key2KanaRules &rules = tables[j]->get_table ();
173 for (unsigned int i = 0; i < rules.size(); i++) {
175 String seq = rules[i].get_sequence ();
176 if (!m_case_sensitive) {
177 for (unsigned int j = 0; j < seq.length (); j++)
178 seq[j] = tolower (seq[j]);
180 WideString romaji = utf8_mbstowcs(seq);
181 if (romaji.find (matching_str) == 0) {
182 if (romaji.length () == matching_str.length ()) {
184 exact_match = rules[i];
187 has_partial_match = true;
195 if (has_partial_match) {
196 m_exact_match = exact_match;
198 m_pending += widestr;
201 } else if (!exact_match.is_empty()) {
202 if (!exact_match.get_result(1).empty())
203 m_exact_match = exact_match;
205 m_exact_match.clear ();
206 m_pending = utf8_mbstowcs (exact_match.get_result (1));
207 result = utf8_mbstowcs (exact_match.get_result (0));
211 if (!m_exact_match.is_empty()) {
212 if (!m_exact_match.get_result(0).empty() &&
213 m_exact_match.get_result(1).empty())
215 result = utf8_mbstowcs (m_exact_match.get_result(0));
217 retval = true; /* commit prev pending */
220 m_exact_match.clear ();
222 WideString tmp_result;
223 append(str, tmp_result, pending);
224 result += tmp_result;
227 if (m_pending.length () > 0) {
228 retval = true; /* commit prev pending */
244 Key2KanaConvertor::clear (void)
247 m_exact_match.clear ();
248 m_last_key = KeyEvent ();
249 reset_pseudo_ascii_mode();
253 Key2KanaConvertor::is_pending (void)
255 if (m_pending.length () > 0)
262 Key2KanaConvertor::get_pending (void)
268 Key2KanaConvertor::flush_pending (void)
271 if (!m_exact_match.is_empty ()) {
272 if (!m_exact_match.get_result(0).empty() &&
273 m_exact_match.get_result(1).empty())
275 result = utf8_mbstowcs (m_exact_match.get_result(0));
276 } else if (!m_exact_match.get_result(1).empty()) {
277 result += utf8_mbstowcs (m_exact_match.get_result(1));
278 } else if (m_pending.length () > 0) {
287 Key2KanaConvertor::reset_pending (const WideString &result, const String &raw)
289 m_last_key = KeyEvent ();
291 for (unsigned int i = 0; i < raw.length (); i++) {
292 WideString res, pend;
293 append (raw.substr(i, 1), res, pend);
298 Key2KanaConvertor::process_pseudo_ascii_mode (const WideString & wstr)
300 for (unsigned int i = 0; i < wstr.length (); i++) {
301 if ((wstr[i] >= 'A' && wstr[i] <= 'Z') ||
304 m_is_in_pseudo_ascii_mode = true;
305 } else if (wstr[i] >= 0x80) {
306 m_is_in_pseudo_ascii_mode = false;
310 return m_is_in_pseudo_ascii_mode;
314 Key2KanaConvertor::reset_pseudo_ascii_mode (void)
316 if (m_is_in_pseudo_ascii_mode)
318 m_is_in_pseudo_ascii_mode = false;
322 vi:ts=4:nowrap:ai:expandtab