1 /* vim:set et ts=4 sts=4:
3 * ibus-pinyin - The Chinese PinYin engine for IBus
5 * Copyright (c) 2011 Peng Wu <alexepico@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "PYPBopomofoEditor.h"
23 #include "PYLibPinyin.h"
24 #include "PYPinyinProperties.h"
25 #include "PYSimpTradConverter.h"
26 #include "PYHalfFullConverter.h"
31 const static gchar * bopomofo_select_keys[] = {
43 LibPinyinBopomofoEditor::LibPinyinBopomofoEditor
44 (PinyinProperties & props, Config & config)
45 : LibPinyinPhoneticEditor (props, config),
48 m_instance = LibPinyinBackEnd::instance ().allocChewingInstance ();
51 LibPinyinBopomofoEditor::~LibPinyinBopomofoEditor (void)
53 LibPinyinBackEnd::instance ().freeChewingInstance (m_instance);
58 LibPinyinBopomofoEditor::reset (void)
60 m_select_mode = FALSE;
61 LibPinyinPhoneticEditor::reset ();
65 LibPinyinBopomofoEditor::insert (gint ch)
68 if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
71 m_text.insert (m_cursor++, ch);
80 LibPinyinBopomofoEditor::processGuideKey (guint keyval, guint keycode,
83 if (!m_config.guideKey ())
86 if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
89 if (G_LIKELY (m_select_mode))
92 if (G_UNLIKELY (keyval == IBUS_space)) {
102 LibPinyinBopomofoEditor::processAuxiliarySelectKey
103 (guint keyval, guint keycode, guint modifiers)
105 if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
113 if (!m_config.auxiliarySelectKeyKP ())
116 case IBUS_KP_1 ... IBUS_KP_9:
117 i = keyval - IBUS_KP_1;
118 if (!m_config.auxiliarySelectKeyKP ())
121 case IBUS_F1 ... IBUS_F10:
122 i = keyval - IBUS_F1;
123 if (!m_config.auxiliarySelectKeyF ())
130 m_select_mode = TRUE;
131 selectCandidateInPage (i);
138 LibPinyinBopomofoEditor::processSelectKey (guint keyval, guint keycode,
141 if (G_UNLIKELY (!m_text))
144 if (G_LIKELY (!m_select_mode && ((modifiers & IBUS_MOD1_MASK) == 0)))
147 const gchar * pos = NULL;
148 const gchar * keys = bopomofo_select_keys[m_config.selectKeys ()];
149 for ( const gchar * p = keys; *p; ++p ) {
157 m_select_mode = TRUE;
159 guint i = pos - keys;
160 selectCandidateInPage (i);
167 LibPinyinBopomofoEditor::processBopomofo (guint keyval, guint keycode,
170 if (G_UNLIKELY (cmshm_filter (modifiers) != 0))
171 return m_text ? TRUE : FALSE;
173 if (!(pinyin_in_chewing_keyboard (m_instance, keyval, NULL)))
176 if (keyval == IBUS_space)
179 m_select_mode = FALSE;
181 return insert (keyval);
185 LibPinyinBopomofoEditor::processKeyEvent (guint keyval, guint keycode,
188 modifiers &= (IBUS_SHIFT_MASK |
196 if (G_UNLIKELY (processGuideKey (keyval, keycode, modifiers)))
198 if (G_UNLIKELY (processSelectKey (keyval, keycode, modifiers)))
200 if (G_UNLIKELY (processAuxiliarySelectKey (keyval, keycode,
203 if (G_LIKELY (processBopomofo (keyval, keycode, modifiers)))
208 m_select_mode = TRUE;
209 return processSpace (keyval, keycode, modifiers);
211 case IBUS_Up: case IBUS_KP_Up:
212 case IBUS_Down: case IBUS_KP_Down:
213 case IBUS_Page_Up: case IBUS_KP_Page_Up:
214 case IBUS_Page_Down: case IBUS_KP_Page_Down:
216 m_select_mode = TRUE;
217 return LibPinyinPhoneticEditor::processFunctionKey
218 (keyval, keycode, modifiers);
221 case IBUS_Delete: case IBUS_KP_Delete:
222 case IBUS_Left: case IBUS_KP_Left:
223 case IBUS_Right: case IBUS_KP_Right:
224 case IBUS_Home: case IBUS_KP_Home:
225 case IBUS_End: case IBUS_KP_End:
226 m_select_mode = FALSE;
227 return LibPinyinPhoneticEditor::processFunctionKey
228 (keyval, keycode, modifiers);
231 return LibPinyinPhoneticEditor::processFunctionKey
232 (keyval, keycode, modifiers);
238 LibPinyinBopomofoEditor::updatePinyin (void)
240 if (G_UNLIKELY (m_text.empty ())) {
242 /* TODO: check whether to replace "" with NULL. */
243 pinyin_parse_more_chewings (m_instance, "");
248 pinyin_parse_more_chewings (m_instance, m_text.c_str ());
249 pinyin_guess_sentence (m_instance);
253 LibPinyinBopomofoEditor::commit ()
255 if (G_UNLIKELY (m_text.empty ()))
260 /* sentence candidate */
262 pinyin_get_sentence(m_instance, &tmp);
264 if (m_props.modeSimp ()) {
267 SimpTradConverter::simpToTrad (tmp, m_buffer);
272 /* text after pinyin */
273 const gchar *p = m_text.c_str() + m_pinyin_len;
275 const char * symbol = NULL;
276 if (pinyin_in_chewing_keyboard(m_instance, *p, &symbol)) {
279 if (G_UNLIKELY (m_props.modeFull ())) {
280 m_buffer.appendUnichar (HalfFullConverter::toFull (*p));
288 pinyin_train(m_instance);
289 LibPinyinBackEnd::instance ().modified();
290 LibPinyinPhoneticEditor::commit ((const gchar *)m_buffer);
295 LibPinyinBopomofoEditor::updatePreeditText ()
297 /* preedit text = guessed sentence + un-parsed pinyin text */
298 if (G_UNLIKELY (m_text.empty ())) {
305 pinyin_get_sentence(m_instance, &tmp);
307 if (m_props.modeSimp ()) {
310 SimpTradConverter::simpToTrad (tmp, m_buffer);
316 /* append rest text */
317 const gchar *p = m_text.c_str () + m_pinyin_len;
320 StaticText preedit_text (m_buffer);
322 preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
324 guint pinyin_cursor = getPinyinCursor ();
325 Editor::updatePreeditText (preedit_text, pinyin_cursor, TRUE);
329 LibPinyinBopomofoEditor::updateAuxiliaryText (void)
331 if (G_UNLIKELY (m_text.empty ())) {
332 hideAuxiliaryText ();
338 // guint pinyin_cursor = getPinyinCursor ();
339 PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
340 PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_key_rests;
341 for (guint i = 0; i < pinyin_keys->len; ++i) {
342 PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
343 PinyinKeyPos *pos = &g_array_index (pinyin_poses, PinyinKeyPos, i);
344 guint cursor = pos->m_raw_begin;
346 if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
347 m_buffer << '|' << key->get_chewing_string ();
348 } else if (G_LIKELY ( cursor < m_cursor &&
349 m_cursor < pos->m_raw_end )) { /* in word */
351 String raw = m_text.substr (cursor,
353 guint offset = m_cursor - cursor;
355 String before = raw.substr (0, offset);
356 String after = raw.substr (offset);
357 String::const_iterator iter;
358 const char * symbol = NULL;
359 for ( iter = before.begin (); iter != before.end (); ++iter) {
360 if ( pinyin_in_chewing_keyboard(m_instance, *iter, &symbol))
366 for ( iter = after.begin (); iter != after.end (); ++iter) {
367 if ( pinyin_in_chewing_keyboard(m_instance, *iter, &symbol))
372 } else { /* other words */
373 m_buffer << ' ' << key->get_chewing_string ();
377 if (m_cursor == m_pinyin_len)
380 /* append rest text */
381 const gchar * p = m_text.c_str() + m_pinyin_len;
384 StaticText aux_text (m_buffer);
385 Editor::updateAuxiliaryText (aux_text, TRUE);