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>
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 "PYDoublePinyinEditor.h"
26
#define DEFINE_DOUBLE_PINYIN_TABLES
27
#include "PYDoublePinyinTable.h"
30
* c in 'a' ... 'z' => id = c - 'a'
35
((c >= IBUS_a && c <= IBUS_z) ? c - IBUS_a : (c == IBUS_semicolon ? 26 : -1))
37
#define ID_TO_SHENG(id) \
38
(double_pinyin_map[m_config.doublePinyinSchema ()].sheng[id])
39
#define ID_TO_YUNS(id) \
40
(double_pinyin_map[m_config.doublePinyinSchema ()].yun[id])
43
((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
45
DoublePinyinEditor::DoublePinyinEditor (PinyinProperties & props, Config & config)
46
: PinyinEditor (props, config)
51
DoublePinyinEditor::insert (gint ch)
55
if (G_UNLIKELY (m_text.length () >= MAX_PINYIN_LEN))
60
/* it is not availidate ch */
64
if (G_UNLIKELY (m_text.empty () &&
65
ID_TO_SHENG (id) == PINYIN_ID_VOID)) {
69
m_text.insert (m_cursor++, ch);
71
if (m_cursor > m_pinyin_len + 2 || updatePinyin (FALSE) == FALSE) {
73
m_text.erase (--m_cursor, 1);
77
if (updateSpecialPhrases ()) {
82
updateAuxiliaryText ();
88
updateSpecialPhrases ();
89
updatePhraseEditor ();
96
DoublePinyinEditor::removeCharBefore (void)
98
if (G_UNLIKELY (m_cursor == 0))
102
m_text.erase (m_cursor, 1);
104
if (updatePinyin (FALSE)) {
105
updateSpecialPhrases ();
106
updatePhraseEditor ();
110
if (updateSpecialPhrases ()) {
114
updatePreeditText ();
115
updateAuxiliaryText ();
122
DoublePinyinEditor::removeCharAfter (void)
124
if (G_UNLIKELY (m_cursor == m_text.length ()))
127
m_text.erase (m_cursor, 1);
128
if (updateSpecialPhrases ()) {
132
updatePreeditText ();
133
updateAuxiliaryText ();
139
DoublePinyinEditor::removeWordBefore (void)
141
if (G_UNLIKELY (m_cursor == 0))
144
if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
145
m_text.erase (m_pinyin_len, m_cursor - m_pinyin_len);
146
m_cursor = m_pinyin_len;
147
if (updateSpecialPhrases ()) {
151
updatePreeditText ();
152
updateAuxiliaryText ();
156
m_pinyin_len = m_pinyin.back ().begin;
157
m_pinyin.pop_back ();
158
m_text.erase (m_pinyin_len, m_cursor - m_pinyin_len);
159
m_cursor = m_pinyin_len;
160
updateSpecialPhrases ();
161
updatePhraseEditor ();
169
DoublePinyinEditor::removeWordAfter (void)
171
if (G_UNLIKELY (m_cursor == m_text.length ()))
174
m_text.erase (m_cursor);
175
if (updateSpecialPhrases ()) {
179
updatePreeditText ();
180
updateAuxiliaryText ();
186
DoublePinyinEditor::moveCursorLeft (void)
188
if (G_UNLIKELY (m_cursor == 0))
193
if (m_cursor >= m_pinyin_len) {
194
if (updateSpecialPhrases ()) {
198
updatePreeditText ();
199
updateAuxiliaryText ();
203
if (updatePinyin (FALSE)) {
204
updateSpecialPhrases ();
205
updatePhraseEditor ();
209
if (updateSpecialPhrases ()) {
213
updatePreeditText ();
214
updateAuxiliaryText ();
223
DoublePinyinEditor::moveCursorRight (void)
225
if (G_UNLIKELY (m_cursor == m_text.length ()))
229
if (updatePinyin (FALSE)) {
230
updateSpecialPhrases ();
231
updatePhraseEditor ();
235
if (updateSpecialPhrases ()) {
239
updatePreeditText ();
240
updateAuxiliaryText ();
247
DoublePinyinEditor::moveCursorLeftByWord (void)
249
if (G_UNLIKELY (m_cursor == 0))
252
if (G_UNLIKELY (m_cursor > m_pinyin_len)) {
253
m_cursor = m_pinyin_len;
254
if (updateSpecialPhrases ()) {
258
updatePreeditText ();
259
updateAuxiliaryText ();
263
m_cursor = m_pinyin_len = m_pinyin.back ().begin;
264
m_pinyin.pop_back ();
265
updateSpecialPhrases ();
266
updatePhraseEditor ();
274
DoublePinyinEditor::moveCursorRightByWord (void)
276
return moveCursorToEnd ();
280
DoublePinyinEditor::moveCursorToBegin (void)
282
if (G_UNLIKELY (m_cursor == 0))
288
updateSpecialPhrases ();
289
updatePhraseEditor ();
296
DoublePinyinEditor::moveCursorToEnd (void)
298
if (G_UNLIKELY (m_cursor == m_text.length ()))
301
m_cursor = m_text.length ();
302
if (updatePinyin (FALSE)) {
303
updateSpecialPhrases ();
304
updatePhraseEditor ();
308
if (updateSpecialPhrases ()) {
312
updatePreeditText ();
313
updateAuxiliaryText ();
320
DoublePinyinEditor::reset (void)
322
PinyinEditor::reset ();
325
inline const Pinyin *
326
DoublePinyinEditor::isPinyin (gint i)
328
if ((m_config.option () & PINYIN_INCOMPLETE_PINYIN) == 0) {
332
gint8 sheng = ID_TO_SHENG (i);
334
if (sheng == PINYIN_ID_VOID) {
338
return PinyinParser::isPinyin (sheng, 0, PINYIN_INCOMPLETE_PINYIN);
341
inline const Pinyin *
342
DoublePinyinEditor::isPinyin (gint i, gint j)
344
const Pinyin *pinyin;
345
gint8 sheng = ID_TO_SHENG (i);
346
const gint8 *yun = ID_TO_YUNS (j);
348
if (sheng == PINYIN_ID_VOID || yun[0] == PINYIN_ID_VOID)
351
if (sheng == PINYIN_ID_ZERO && yun[0] == PINYIN_ID_ZERO)
354
if (yun[1] == PINYIN_ID_VOID) {
355
return PinyinParser::isPinyin (sheng, yun[0],
356
m_config.option () & (PINYIN_FUZZY_ALL | PINYIN_CORRECT_V_TO_U));
359
pinyin = PinyinParser::isPinyin (sheng, yun[0],
360
m_config.option () & (PINYIN_FUZZY_ALL));
362
pinyin = PinyinParser::isPinyin (sheng, yun[1],
363
m_config.option () & (PINYIN_FUZZY_ALL));
367
/* if sheng == j q x y and yun == v, try to correct v to u */
368
if ((m_config.option () & PINYIN_CORRECT_V_TO_U) == 0)
371
if (yun[0] != PINYIN_ID_V && yun[1] != PINYIN_ID_V)
379
return PinyinParser::isPinyin (sheng, PINYIN_ID_V,
380
m_config.option () & (PINYIN_FUZZY_ALL | PINYIN_CORRECT_V_TO_U));
387
DoublePinyinEditor::updatePinyin (gboolean all)
389
gboolean retval = FALSE;
392
(m_pinyin_len != 0 || !m_pinyin.empty ())) {
398
if (m_pinyin_len > m_cursor) {
400
while (m_pinyin_len > m_cursor) {
401
m_pinyin_len = m_pinyin.back ().begin;
402
m_pinyin.pop_back ();
406
if (m_pinyin_len == m_cursor) {
410
if (m_pinyin_len < m_cursor) {
411
guint len = m_pinyin_len;
412
if (m_pinyin.empty () == FALSE &&
413
m_pinyin.back ()->flags & PINYIN_INCOMPLETE_PINYIN) {
414
const Pinyin *pinyin = isPinyin (ID (m_text[m_pinyin_len -1]),ID (m_text[m_pinyin_len]));
416
m_pinyin.pop_back ();
417
m_pinyin.append (pinyin, m_pinyin_len - 1, 2);
421
while (m_pinyin_len < m_cursor && m_pinyin.size () < MAX_PHRASE_LEN) {
422
const Pinyin *pinyin = NULL;
423
if (m_pinyin_len == m_cursor - 1) {
424
pinyin = isPinyin (ID (m_text[m_pinyin_len]));
427
pinyin = isPinyin (ID (m_text[m_pinyin_len]), ID (m_text[m_pinyin_len + 1]));
429
pinyin = isPinyin (ID (m_text[m_pinyin_len]));
433
if (pinyin->flags & PINYIN_INCOMPLETE_PINYIN) {
434
m_pinyin.append (pinyin, m_pinyin_len, 1);
438
m_pinyin.append (pinyin, m_pinyin_len, 2);
442
if (len == m_pinyin_len)
450
DoublePinyinEditor::updateAuxiliaryTextAfter (String &buffer)
452
if (G_LIKELY (!m_config.doublePinyinShowRaw ()))
455
if (G_LIKELY (m_config.orientation () == IBUS_ORIENTATION_HORIZONTAL)) {
462
if (G_LIKELY (m_cursor == m_text.length ())) {
463
m_buffer << m_text << " ]";
466
buffer.append (m_text.c_str (), m_cursor);
468
buffer.append (m_text.c_str () + m_cursor);
474
DoublePinyinEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
477
if (G_UNLIKELY (keyval == IBUS_semicolon)) {
478
if (cmshm_filter (modifiers) == 0) {
484
return PinyinEditor::processKeyEvent (keyval, keycode, modifiers);