1 /* vim:set et ts=4 sts=4:
3 * ibus-pinyin - The Chinese PinYin engine for IBus
5 * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
6 * Copyright (c) 2010 BYVoid <byvoid1@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "PYPunctEditor.h"
28 #include "PYPunctTable.h"
30 PunctEditor::PunctEditor (PinyinProperties & props, Config & config)
31 : Editor (props, config),
32 m_punct_mode (MODE_DISABLE),
33 m_lookup_table (m_config.pageSize ())
38 PunctEditor::insert (gchar ch)
40 switch (m_punct_mode) {
43 g_assert (ch == IBUS_grave);
44 g_assert (m_cursor == 0);
45 m_text.insert (m_cursor++, ch);
46 m_punct_mode = MODE_INIT;
47 updatePunctCandidates (0);
48 m_selected_puncts.clear ();
49 m_selected_puncts.insert (m_selected_puncts.begin (), m_punct_candidates[0]);
56 m_selected_puncts.clear ();
61 m_text.insert (m_cursor, ch);
62 updatePunctCandidates (ch);
63 m_punct_mode = MODE_NORMAL;
64 if (m_punct_candidates.size () > 0) {
65 m_selected_puncts.insert (m_selected_puncts.begin () + m_cursor, m_punct_candidates[0]);
72 g_assert_not_reached ();
79 PunctEditor::processSpace (guint keyval, guint keycode, guint modifiers)
81 if (m_punct_mode != MODE_INIT && m_punct_mode != MODE_NORMAL)
83 if (cmshm_filter (modifiers) != 0)
90 PunctEditor::processPunct (guint keyval, guint keycode, guint modifiers)
92 if (cmshm_filter (modifiers) != 0)
95 if (m_punct_mode == MODE_DISABLE) {
96 if (keyval == IBUS_grave) {
102 g_assert (m_punct_mode == MODE_INIT || m_punct_mode == MODE_NORMAL);
105 case IBUS_grave: /* ` */
106 case IBUS_asciitilde: /* ~ */
107 case IBUS_exclam: /* ~ */
108 case IBUS_at: /* @ */
109 case IBUS_numbersign: /* # */
110 case IBUS_dollar: /* $ */
111 case IBUS_percent: /* % */
112 case IBUS_asciicircum: /* ^ */
113 case IBUS_ampersand: /* & */
114 case IBUS_asterisk: /* * */
115 case IBUS_parenleft: /* ( */
116 case IBUS_parenright: /* ) */
117 case IBUS_minus: /* - */
118 case IBUS_underscore: /* _ */
119 case IBUS_equal: /* = */
120 case IBUS_plus: /* + */
121 case IBUS_bracketleft: /* [ */
122 case IBUS_bracketright: /* ] */
123 case IBUS_braceleft: /* { */
124 case IBUS_braceright: /* } */
125 case IBUS_backslash: /* \ */
126 case IBUS_bar: /* | */
127 case IBUS_colon: /* : */
128 case IBUS_semicolon: /* ; */
129 case IBUS_apostrophe: /* ' */
130 case IBUS_quotedbl: /* " */
131 case IBUS_comma: /* , */
132 case IBUS_period: /* . */
133 case IBUS_less: /* < */
134 case IBUS_greater: /* > */
135 case IBUS_slash: /* / */
136 case IBUS_question: /* ? */
137 case IBUS_0...IBUS_9:
138 case IBUS_a...IBUS_z:
139 case IBUS_A...IBUS_Z:
140 return insert (keyval);
147 PunctEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
149 modifiers &= (IBUS_SHIFT_MASK |
159 return processSpace (keyval, keycode, modifiers);
191 moveCursorToBegin ();
210 case IBUS_KP_Page_Up:
215 case IBUS_KP_Page_Down:
220 return processPunct(keyval, keycode, modifiers);
225 PunctEditor::pageUp (void)
227 if (G_LIKELY (m_lookup_table.pageUp ())) {
228 m_selected_puncts[m_cursor - 1] = m_punct_candidates[m_lookup_table.cursorPos ()];
229 updateLookupTableFast (m_lookup_table, TRUE);
230 updatePreeditText ();
231 updateAuxiliaryText ();
236 PunctEditor::pageDown (void)
238 if (G_LIKELY (m_lookup_table.pageDown ())) {
239 m_selected_puncts[m_cursor - 1] = m_punct_candidates[m_lookup_table.cursorPos ()];
240 updateLookupTableFast (m_lookup_table, TRUE);
241 updatePreeditText ();
242 updateAuxiliaryText ();
247 PunctEditor::cursorUp (void)
249 if (G_LIKELY (m_lookup_table.cursorUp ())) {
250 m_selected_puncts[m_cursor - 1] = m_punct_candidates[m_lookup_table.cursorPos ()];
251 updateLookupTableFast (m_lookup_table, TRUE);
252 updatePreeditText ();
253 updateAuxiliaryText ();
258 PunctEditor::cursorDown (void)
260 if (G_LIKELY (m_lookup_table.cursorDown ())) {
261 m_selected_puncts[m_cursor - 1] = m_punct_candidates[m_lookup_table.cursorPos ()];
262 updateLookupTableFast (m_lookup_table, TRUE);
263 updatePreeditText ();
264 updateAuxiliaryText ();
269 PunctEditor::moveCursorLeft (void)
271 if (G_UNLIKELY (m_cursor == 0))
275 m_punct_candidates.clear ();
279 updatePunctCandidates (m_text[m_cursor - 1]);
280 /* restore cursor pos */
281 std::vector<const gchar *>::iterator it;
282 it = std::find (m_punct_candidates.begin (),
283 m_punct_candidates.end (),
284 m_selected_puncts[m_cursor - 1]);
285 g_assert (it != m_punct_candidates.end ());
286 m_lookup_table.setCursorPos (it - m_punct_candidates.begin ());
293 PunctEditor::moveCursorRight (void)
295 if (G_UNLIKELY (m_cursor == m_text.length ()))
298 updatePunctCandidates (m_text[m_cursor - 1]);
300 /* restore cursor pos */
301 std::vector<const gchar *>::iterator it;
302 it = std::find (m_punct_candidates.begin (),
303 m_punct_candidates.end (),
304 m_selected_puncts[m_cursor - 1]);
305 g_assert (it != m_punct_candidates.end ());
306 m_lookup_table.setCursorPos (it - m_punct_candidates.begin ());
313 PunctEditor::moveCursorToBegin (void)
315 if (G_UNLIKELY (m_cursor == 0))
318 g_assert (m_punct_mode == MODE_NORMAL);
320 m_punct_candidates.clear ();
328 PunctEditor::moveCursorToEnd (void)
330 if (G_UNLIKELY (m_cursor == m_text.length ()))
333 g_assert (m_punct_mode == MODE_NORMAL);
334 m_cursor = m_text.length ();
335 updatePunctCandidates (m_text[m_cursor - 1]);
337 /* restore cursor pos */
338 std::vector<const gchar *>::iterator it;
339 it = std::find (m_punct_candidates.begin (),
340 m_punct_candidates.end (),
341 m_selected_puncts[m_cursor - 1]);
342 g_assert (it != m_punct_candidates.end ());
343 m_lookup_table.setCursorPos (it - m_punct_candidates.begin ());
350 PunctEditor::removeCharBefore (void)
352 if (G_UNLIKELY (m_cursor == 0))
356 m_selected_puncts.erase (m_selected_puncts.begin () + m_cursor);
357 m_text.erase (m_cursor, 1);
358 if (m_text.empty()) {
364 updatePunctCandidates (m_text[m_cursor - 1]);
365 /* restore cursor pos */
366 std::vector<const gchar *>::iterator it;
367 it = std::find (m_punct_candidates.begin (),
368 m_punct_candidates.end (),
369 m_selected_puncts[m_cursor - 1]);
370 g_assert (it != m_punct_candidates.end ());
371 m_lookup_table.setCursorPos (it - m_punct_candidates.begin ());
374 m_punct_candidates.clear ();
385 PunctEditor::removeCharAfter (void)
387 if (G_UNLIKELY (m_cursor == m_text.length ()))
389 m_selected_puncts.erase (m_selected_puncts.begin () + m_cursor);
390 m_text.erase (m_cursor, 1);
391 if (m_text.empty()) {
401 PunctEditor::reset (void)
403 m_punct_mode = MODE_DISABLE;
404 m_selected_puncts.clear ();
405 m_punct_candidates.clear ();
411 PunctEditor::candidateClicked (guint index, guint button, guint state)
413 selectCandidateInPage(index);
417 PunctEditor::commit (const gchar *str)
419 StaticText text(str);
425 PunctEditor::commit (void)
428 for (std::vector<const gchar *>::iterator it = m_selected_puncts.begin ();
429 it != m_selected_puncts.end (); it++) {
437 PunctEditor::selectCandidate (guint i)
439 switch (m_punct_mode) {
442 g_assert (m_cursor == 1);
443 m_lookup_table.setCursorPos (i);
444 m_selected_puncts[m_cursor - 1] = m_punct_candidates[i];
450 m_lookup_table.setCursorPos (i);
451 m_selected_puncts[m_cursor - 1] = m_punct_candidates[i];
453 /* if it is the last punct, commit the result */
454 if (m_cursor == m_text.length ()) {
463 g_assert_not_reached ();
470 PunctEditor::selectCandidateInPage (guint i)
472 guint page_size = m_lookup_table.pageSize ();
473 guint cursor_pos = m_lookup_table.cursorPos ();
475 if (G_UNLIKELY (i >= page_size))
478 i += (cursor_pos / page_size) * page_size;
480 return selectCandidate (i);
484 PunctEditor::update (void)
486 updateLookupTable ();
487 updatePreeditText ();
488 updateAuxiliaryText ();
492 PunctEditor::fillLookupTable (void)
494 m_lookup_table.clear ();
495 m_lookup_table.setPageSize (m_config.pageSize ());
496 m_lookup_table.setOrientation (m_config.orientation ());
498 for (std::vector<const gchar *>::iterator it = m_punct_candidates.begin ();
499 it != m_punct_candidates.end (); it++) {
500 StaticText text (*it);
501 // text.appendAttribute (IBUS_ATTR_TYPE_FOREGROUND, 0x004466, 0, -1);
502 m_lookup_table.appendCandidate (text);
507 PunctEditor::updateLookupTable (void)
509 if (m_lookup_table.size ()) {
510 Editor::updateLookupTable (m_lookup_table, TRUE);
518 punct_cmp (const void *p1, const void *p2)
520 const gint s1 = (gint)(glong) p1;
521 const gchar *s2 = **(gchar ***) p2;
526 PunctEditor::updatePunctCandidates (gchar ch)
531 m_punct_candidates.clear();
533 brs = (const gchar ***) std::bsearch (reinterpret_cast<void *>(ch),
535 G_N_ELEMENTS (punct_table),
536 sizeof(punct_table[0]),
539 for (res = (*brs) + 1; *res != NULL; ++res) {
540 m_punct_candidates.push_back (*res);
547 PunctEditor::updateAuxiliaryText (void)
549 switch (m_punct_mode) {
551 hideAuxiliaryText ();
556 StaticText aux_text (m_buffer);
557 Editor::updateAuxiliaryText (aux_text, TRUE);
563 hideAuxiliaryText ();
567 for (String::iterator i = m_text.begin (); i != m_text.end (); ++i) {
568 if (i - m_text.begin () == (gint) m_cursor)
572 if (m_text.end () - m_text.begin () == (gint) m_cursor)
575 StaticText aux_text (m_buffer);
576 Editor::updateAuxiliaryText (aux_text, TRUE);
581 g_assert_not_reached ();
586 PunctEditor::updatePreeditText (void)
588 switch (m_punct_mode) {
594 m_buffer = m_punct_candidates[m_lookup_table.cursorPos ()];
595 StaticText preedit_text (m_buffer);
597 preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
598 Editor::updatePreeditText (preedit_text, m_cursor, TRUE);
604 for (std::vector<const gchar *>::iterator it = m_selected_puncts.begin ();
605 it != m_selected_puncts.end (); it++) {
608 StaticText preedit_text (m_buffer);
610 preedit_text.appendAttribute (IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1);
611 Editor::updatePreeditText (preedit_text, m_cursor, TRUE);
615 g_assert_not_reached ();