clean db
[platform/upstream/ibus-libpinyin.git] / src / PYPDoublePinyinEditor.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-pinyin - The Chinese PinYin engine 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., 675 Mass Ave, Cambridge, MA 02139, 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             if (insert (keyval))
92                 return TRUE;
93         }
94     }
95
96     return LibPinyinPinyinEditor::processKeyEvent (keyval, keycode, modifiers);
97 }
98
99 void
100 LibPinyinDoublePinyinEditor::updatePinyin (void)
101 {
102     if (G_UNLIKELY (m_text.empty ())) {
103         m_pinyin_len = 0;
104         /* TODO: check whether to replace "" with NULL. */
105         pinyin_parse_more_double_pinyins (m_instance, "");
106         return;
107     }
108
109     m_pinyin_len =
110         pinyin_parse_more_double_pinyins (m_instance, m_text.c_str ());
111     pinyin_guess_sentence (m_instance);
112 }
113
114
115 void
116 LibPinyinDoublePinyinEditor::updateAuxiliaryText (void)
117 {
118     if (G_UNLIKELY (m_text.empty ())) {
119         hideAuxiliaryText ();
120         return;
121     }
122
123     m_buffer.clear ();
124
125     // guint pinyin_cursor = getPinyinCursor ();
126     PinyinKeyVector & pinyin_keys = m_instance->m_pinyin_keys;
127     PinyinKeyPosVector & pinyin_poses = m_instance->m_pinyin_key_rests;
128     for (guint i = 0; i < pinyin_keys->len; ++i) {
129         PinyinKey *key = &g_array_index (pinyin_keys, PinyinKey, i);
130         PinyinKeyPos *pos = &g_array_index (pinyin_poses, PinyinKeyPos, i);
131         guint cursor = pos->m_raw_begin;
132
133         if (G_UNLIKELY (cursor == m_cursor)) { /* at word boundary. */
134             m_buffer << '|' << key->get_pinyin_string ();
135         } else if (G_LIKELY ( cursor < m_cursor &&
136                               m_cursor < pos->m_raw_end )) { /* in word */
137             /* raw text */
138             String raw = m_text.substr (cursor,
139                                         pos->length ());
140             guint offset = m_cursor - cursor;
141             m_buffer << ' ' << raw.substr (0, offset)
142                      << '|' << raw.substr (offset);
143         } else { /* other words */
144             m_buffer << ' ' << key->get_pinyin_string ();
145         }
146     }
147
148     if (m_cursor == m_pinyin_len)
149         m_buffer << '|';
150
151     /* append rest text */
152     const gchar * p = m_text.c_str() + m_pinyin_len;
153     m_buffer << p;
154
155     StaticText aux_text (m_buffer);
156     Editor::updateAuxiliaryText (aux_text, TRUE);
157 }