fixes compile
[platform/upstream/ibus-libpinyin.git] / src / PYPDoublePinyinEditor.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-libpinyin - Intelligent Pinyin engine based on libpinyin for IBus
4  *
5  * Copyright (c) 2011 Peng Wu <alexepico@gmail.com>
6  *
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)
10  * any later version.
11  *
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.
16  *
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21
22 #include "PYPDoublePinyinEditor.h"
23 #include "PYConfig.h"
24 #include "PYLibPinyin.h"
25
26 using namespace PY;
27
28 /*
29  * c in 'a' ... 'z' => id = c - 'a'
30  * c == ';'         => id = 26
31  * else             => id = -1
32  */
33 #define ID(c) \
34     ((c >= IBUS_a && c <= IBUS_z) ? c - IBUS_a : (c == IBUS_semicolon ? 26 : -1))
35
36 #define IS_ALPHA(c) \
37         ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
38
39
40 LibPinyinDoublePinyinEditor::LibPinyinDoublePinyinEditor
41 ( PinyinProperties & props, Config & config)
42     : LibPinyinPinyinEditor (props, config)
43 {
44     m_instance = LibPinyinBackEnd::instance ().allocPinyinInstance ();
45 }
46
47 LibPinyinDoublePinyinEditor::~LibPinyinDoublePinyinEditor (void)
48 {
49     LibPinyinBackEnd::instance ().freePinyinInstance (m_instance);
50     m_instance = NULL;
51 }
52
53 gboolean
54 LibPinyinDoublePinyinEditor::insert (gint ch)
55 {
56     /* is full */
57     if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
58         return TRUE;
59
60     gint id = ID (ch);
61     if (id == -1) {
62         /* it is not available ch */
63         return FALSE;
64     }
65
66 #if 0
67     if (G_UNLIKELY (m_text.empty () && ID_TO_SHENG (id) == PINYIN_ID_VOID)) {
68         return FALSE;
69     }
70 #endif
71
72     m_text.insert (m_cursor++, ch);
73     updatePinyin ();
74     update ();
75
76     return TRUE;
77 }
78
79 void LibPinyinDoublePinyinEditor::reset (void)
80 {
81     LibPinyinPinyinEditor::reset ();
82 }
83
84 gboolean
85 LibPinyinDoublePinyinEditor::processKeyEvent (guint keyval, guint keycode,
86                                               guint modifiers)
87 {
88     /* handle ';' key */
89     if (G_UNLIKELY (keyval == IBUS_semicolon)) {
90         if (cmshm_filter (modifiers) == 0) {
91
92             if (m_text.empty ())
93                 return FALSE;
94
95             if (insert (keyval))
96                 return TRUE;
97         }
98     }
99
100     return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
101 }
102
103 void
104 LibPinyinDoublePinyinEditor::updatePinyin (void)
105 {
106     if (G_UNLIKELY (m_text.empty ())) {
107         m_pinyin_len = 0;
108         /* TODO: check whether to replace "" with NULL. */
109         pinyin_parse_more_double_pinyins (m_instance, "");
110         pinyin_guess_sentence(m_instance);
111         return;
112     }
113
114     m_pinyin_len =
115         pinyin_parse_more_double_pinyins (m_instance, m_text.c_str ());
116     pinyin_guess_sentence (m_instance);
117 }
118
119
120 void
121 LibPinyinDoublePinyinEditor::updateAuxiliaryText (void)
122 {
123     if (G_UNLIKELY (m_text.empty ())) {
124         hideAuxiliaryText ();
125         return;
126     }
127
128     m_buffer.clear ();
129
130     guint len = 0;
131     pinyin_get_n_pinyin (m_instance, &len);
132
133     for (guint i = 0; i < len; ++i) {
134         PinyinKey *key = NULL;
135         pinyin_get_pinyin_key (m_instance, i, &key);
136
137         PinyinKeyPos *pos = NULL;
138         pinyin_get_pinyin_key_rest (m_instance, i, &pos);
139
140         guint16 cursor = 0, end = 0;
141         pinyin_get_pinyin_key_rest_positions (m_instance, pos, &cursor, &end);
142
143         gchar * str = NULL;
144         if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
145             pinyin_get_pinyin_string (m_instance, key, &str);
146             m_buffer << '|' << str;
147             g_free (str);
148         } else if (G_LIKELY (cursor < m_cursor &&
149                              m_cursor < end)) { /* in word */
150             guint16 length = 0;
151             pinyin_get_pinyin_key_rest_length (m_instance, pos, &length);
152
153             /* raw text */
154             String raw = m_text.substr (cursor, length);
155             guint offset = m_cursor - cursor;
156             m_buffer << ' ' << raw.substr (0, offset)
157                      << '|' << raw.substr (offset);
158         } else { /* other words */
159             pinyin_get_pinyin_string (m_instance, key, &str);
160             m_buffer << ' ' << str;
161             g_free (str);
162         }
163     }
164
165     if (m_cursor == m_pinyin_len)
166         m_buffer << '|';
167
168     /* append rest text */
169     const gchar * p = m_text.c_str() + m_pinyin_len;
170     m_buffer << p;
171
172     StaticText aux_text (m_buffer);
173     Editor::updateAuxiliaryText (aux_text, TRUE);
174 }