~ubuntu-branches/ubuntu/raring/sunpinyin/raring

« back to all changes in this revision

Viewing changes to wrapper/ibus/src/sunpinyin_engine.cpp

  • Committer: Package Import Robot
  • Author(s): YunQiang Su
  • Date: 2012-03-30 15:31:55 UTC
  • mfrom: (1.1.3) (1.2.7 sid)
  • Revision ID: package-import@ubuntu.com-20120330153155-qgls77sogzgtg9zp
Tags: 2.0.3+git20120222-1
* Team upload: git snapshot 20120222.
   - fix breaks if LDFLAGS in environment contains
       multiple words (Closese #646001).
   - rm patches merged to upstream:
       append-os-environ-toenv.patch
       fix-ftbfs-on-sh.patch
       remove-10-candidate-words-limitation.patch
   - refresh disable-lm-dict-compile.patch.
* Bump stardard version to 3.9.3: no modify needed.
* add libsunpinyin3-dbg and python-sunpinyin packages.
* debian/compat to 9, multiarch it.
* rewrite debian/rules with dh 7 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009 Kov Chai <tchaikov@gmail.com>
 
3
 *
 
4
 * The contents of this file are subject to the terms of either the GNU Lesser
 
5
 * General Public License Version 2.1 only ("LGPL") or the Common Development and
 
6
 * Distribution License ("CDDL")(collectively, the "License"). You may not use this
 
7
 * file except in compliance with the License. You can obtain a copy of the CDDL at
 
8
 * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
 
9
 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
 
10
 * specific language governing permissions and limitations under the License. When
 
11
 * distributing the software, include this License Header Notice in each file and
 
12
 * include the full text of the License in the License file as well as the
 
13
 * following notice:
 
14
 *
 
15
 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
 
16
 * (CDDL)
 
17
 * For Covered Software in this distribution, this License shall be governed by the
 
18
 * laws of the State of California (excluding conflict-of-law provisions).
 
19
 * Any litigation relating to this License shall be subject to the jurisdiction of
 
20
 * the Federal Courts of the Northern District of California and the state courts
 
21
 * of the State of California, with venue lying in Santa Clara County, California.
 
22
 *
 
23
 * Contributor(s):
 
24
 *
 
25
 * If you wish your version of this file to be governed by only the CDDL or only
 
26
 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
 
27
 * include this software in this distribution under the [CDDL or LGPL Version 2.1]
 
28
 * license." If you don't indicate a single choice of license, a recipient has the
 
29
 * option to distribute your version of this file under either the CDDL or the LGPL
 
30
 * Version 2.1, or to extend the choice of license to its licensees as provided
 
31
 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
 
32
 * Version 2 license, then the option applies only if the new code is made subject
 
33
 * to such option by the copyright holder.
 
34
 */
 
35
 
 
36
#include <cassert>
 
37
#include <algorithm>
 
38
#include <sstream>
 
39
 
 
40
#include <sunpinyin.h>
 
41
 
 
42
#include "sunpinyin_property.h"
 
43
#include "sunpinyin_lookup_table.h"
 
44
#include "sunpinyin_config.h"
 
45
#include "sunpinyin_config_keys.h"
 
46
#include "imi_ibus_win.h"
 
47
#include "ibus_portable.h"
 
48
#include "sunpinyin_engine.h"
 
49
 
 
50
extern ibus::Config config;
 
51
 
 
52
SunPinyinEngine::SunPinyinEngine(IBusEngine *engine)
 
53
    : m_engine(engine),
 
54
      m_status_prop(SunPinyinProperty::create_status_prop(engine)),
 
55
      m_letter_prop(SunPinyinProperty::create_letter_prop(engine)),
 
56
      m_punct_prop(SunPinyinProperty::create_punct_prop(engine)),
 
57
      m_wh(NULL),
 
58
      m_pv(NULL),
 
59
      m_hotkey_profile(NULL)
 
60
{
 
61
    CSunpinyinSessionFactory& factory = CSunpinyinSessionFactory::getFactory();
 
62
 
 
63
    CSunpinyinSessionFactory::EPyScheme pinyin_scheme =
 
64
        m_config.get_py_scheme(CSunpinyinSessionFactory::QUANPIN);
 
65
    factory.setPinyinScheme(pinyin_scheme);
 
66
    if (pinyin_scheme == CSunpinyinSessionFactory::QUANPIN) {
 
67
        update_fuzzy_pinyins();
 
68
        update_correction_pinyins();
 
69
        update_fuzzy_segs();
 
70
    } else {
 
71
        update_shuangpin_type();
 
72
    }
 
73
    update_user_data_dir();
 
74
    update_punct_mappings();
 
75
 
 
76
    factory.setCandiWindowSize(m_config.get(CONFIG_GENERAL_PAGE_SIZE, 10));
 
77
 
 
78
    m_pv = factory.createSession();
 
79
    if (!m_pv)
 
80
        return;
 
81
 
 
82
    m_hotkey_profile = new CHotkeyProfile();
 
83
    m_pv->setHotkeyProfile(m_hotkey_profile);
 
84
 
 
85
    m_wh = new CIBusWinHandler(this);
 
86
    m_pv->attachWinHandler(m_wh);
 
87
 
 
88
    m_prop_list = ibus_prop_list_new();
 
89
 
 
90
    ibus_prop_list_append(m_prop_list, m_status_prop);
 
91
    ibus_prop_list_append(m_prop_list, m_letter_prop);
 
92
    ibus_prop_list_append(m_prop_list, m_punct_prop);
 
93
    ibus_prop_list_append(m_prop_list, m_setup_prop);
 
94
 
 
95
    update_config();
 
96
}
 
97
 
 
98
SunPinyinEngine::~SunPinyinEngine()
 
99
{
 
100
    if (m_pv) {
 
101
        CSunpinyinSessionFactory& factory =
 
102
            CSunpinyinSessionFactory::getFactory();
 
103
        factory.destroySession(m_pv);
 
104
    }
 
105
 
 
106
    delete m_wh;
 
107
    delete m_hotkey_profile;
 
108
}
 
109
 
 
110
static CKeyEvent
 
111
translate_key(guint key_val, guint /*key_code*/, guint modifiers)
 
112
{
 
113
    // XXX: may need to move this logic into CKeyEvent
 
114
    if (key_val > 0x20 && key_val < 0x7f // isprint(key_val) && !isspace(key_val)
 
115
        && !(modifiers & IM_CTRL_MASK)) {
 
116
        // we only care about key_val here
 
117
        return CKeyEvent(key_val, key_val, modifiers);
 
118
    } else {
 
119
        // what matters is key_code, but ibus sents me key_code as key_val
 
120
        return CKeyEvent(key_val, 0, modifiers);
 
121
    }
 
122
}
 
123
 
 
124
gboolean
 
125
SunPinyinEngine::process_key_event (guint key_val,
 
126
                                    guint key_code,
 
127
                                    guint modifiers)
 
128
{
 
129
    CKeyEvent key = translate_key(key_val, key_code, modifiers);
 
130
 
 
131
    if (!m_pv->getStatusAttrValue(CIBusWinHandler::STATUS_ID_CN)) {
 
132
        // we are in English input mode
 
133
        if (!m_hotkey_profile->isModeSwitchKey(key)) {
 
134
            m_hotkey_profile->rememberLastKey(key);
 
135
            return FALSE;
 
136
        }
 
137
    } else if (m_hotkey_profile->isModeSwitchKey(key)) {
 
138
        m_pv->onKeyEvent(CKeyEvent(IM_VK_ENTER, 0, 0));
 
139
        m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, false);
 
140
        return TRUE;
 
141
    }
 
142
 
 
143
    return m_pv->onKeyEvent(key);
 
144
}
 
145
 
 
146
void
 
147
SunPinyinEngine::focus_in ()
 
148
{
 
149
    ibus_engine_register_properties(m_engine, m_prop_list);
 
150
    m_pv->updateWindows(CIMIView::PREEDIT_MASK | CIMIView::CANDIDATE_MASK);
 
151
}
 
152
 
 
153
void
 
154
SunPinyinEngine::focus_out ()
 
155
{
 
156
    reset();
 
157
}
 
158
 
 
159
void
 
160
SunPinyinEngine::reset ()
 
161
{
 
162
    m_pv->updateWindows(m_pv->clearIC());
 
163
}
 
164
 
 
165
void
 
166
SunPinyinEngine::enable ()
 
167
{
 
168
    bool is_cn = m_config.is_initial_mode_cn();
 
169
    m_status_prop.update(is_cn);
 
170
    m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, is_cn);
 
171
 
 
172
    bool is_letter_full = m_config.is_initial_letter_full();
 
173
    m_letter_prop.update(is_letter_full);
 
174
    m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, is_letter_full);
 
175
 
 
176
    bool is_punct_full = m_config.is_initial_punct_full();
 
177
    m_punct_prop.update(is_punct_full);
 
178
    m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, is_punct_full);
 
179
}
 
180
 
 
181
void
 
182
SunPinyinEngine::disable ()
 
183
{
 
184
}
 
185
 
 
186
void
 
187
SunPinyinEngine::page_up ()
 
188
{
 
189
    m_pv->onCandidatePageRequest(-1, true /* relative */);
 
190
}
 
191
 
 
192
void
 
193
SunPinyinEngine::page_down ()
 
194
{
 
195
    m_pv->onCandidatePageRequest(1, true /* relative */);
 
196
}
 
197
 
 
198
void
 
199
SunPinyinEngine::property_activate (const std::string& property, unsigned /*state*/)
 
200
{
 
201
    if (m_status_prop.toggle(property)) {
 
202
        m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN,
 
203
                                 m_status_prop.state());
 
204
    } else if (m_letter_prop.toggle(property)) {
 
205
        m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL,
 
206
                                 m_letter_prop.state());
 
207
    } else if (m_punct_prop.toggle(property)) {
 
208
        m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC,
 
209
                                 m_punct_prop.state());
 
210
    } else {
 
211
        // try to launch the setup UI
 
212
        m_setup_prop.launch(property);
 
213
    }
 
214
}
 
215
 
 
216
void
 
217
SunPinyinEngine::candidate_clicked (guint index)
 
218
{
 
219
    m_pv->onCandidateSelectRequest(index);
 
220
}
 
221
 
 
222
void
 
223
SunPinyinEngine::cursor_up ()
 
224
{
 
225
    if (m_lookup_table.cursor_up()) {
 
226
        update_lookup_table();
 
227
    }
 
228
}
 
229
 
 
230
void
 
231
SunPinyinEngine::cursor_down ()
 
232
{
 
233
    if (m_lookup_table.cursor_down()) {
 
234
        update_lookup_table();
 
235
    }
 
236
}
 
237
 
 
238
bool
 
239
SunPinyinEngine::onConfigChanged(const COptionEvent& event)
 
240
{
 
241
    if (event.name == CONFIG_GENERAL_MEMORY_POWER) {
 
242
        update_history_power();
 
243
    } else if (event.name == CONFIG_GENERAL_PAGE_SIZE) {
 
244
        update_cand_window_size();
 
245
    } else if (event.name == CONFIG_GENERAL_CHARSET_LEVEL) {
 
246
        update_charset_level();
 
247
    } else if (event.name == CONFIG_GENERAL_MAX_BEST) {
 
248
        update_max_best();
 
249
    } else if (event.name == CONFIG_GENERAL_MAX_TAIL_CANDIDATE) {
 
250
        update_max_tail_candidate();
 
251
    } else if (event.name == CONFIG_KEYBOARD_MODE_SWITCH) {
 
252
        update_mode_key();
 
253
    } else if (event.name == CONFIG_KEYBOARD_PUNCT_SWITCH) {
 
254
        update_punct_key();
 
255
    } else if (event.name == CONFIG_KEYBOARD_PAGE_COMMA) {
 
256
        update_page_key_comma();
 
257
    } else if (event.name == CONFIG_KEYBOARD_PAGE_MINUS) {
 
258
        update_page_key_minus();
 
259
    } else if (event.name == CONFIG_KEYBOARD_PAGE_BRACKET) {
 
260
        update_page_key_bracket();
 
261
    } else if (event.name == CONFIG_QUANPIN_FUZZYSEGS_ENABLED) {
 
262
        update_fuzzy_segs();
 
263
    } else if (event.name == CONFIG_KEYBOARD_CANCEL_BACKSPACE) {
 
264
        update_cancel_with_backspace();
 
265
    } else if (event.name == CONFIG_KEYBOARD_SMARK_PUNCT) {
 
266
        update_smart_punc();
 
267
    }
 
268
 
 
269
    return false;
 
270
}
 
271
 
 
272
void
 
273
SunPinyinEngine::update_config()
 
274
{
 
275
    update_history_power();
 
276
    update_cand_window_size();
 
277
    update_max_best();
 
278
    update_max_tail_candidate();
 
279
    update_charset_level();
 
280
    update_page_key_minus();
 
281
    update_page_key_comma();
 
282
    update_page_key_bracket();
 
283
    update_mode_key();
 
284
    update_punct_key();
 
285
    update_cancel_with_backspace();
 
286
    update_smart_punc();
 
287
    update_punct_mappings();
 
288
    update_candi_delete_key();
 
289
    // update_quanpin_config();
 
290
    // update_shuangpin_config();
 
291
}
 
292
 
 
293
void
 
294
SunPinyinEngine::commit_string (const std::wstring& str)
 
295
{
 
296
    IBusText *text;
 
297
    text = ibus_text_new_from_ucs4((const gunichar*) str.c_str());
 
298
    ibus_engine_commit_text(m_engine, text);
 
299
}
 
300
 
 
301
void
 
302
SunPinyinEngine::update_candidates(const ICandidateList& cl)
 
303
{
 
304
    if (m_lookup_table.update_candidates(cl) > 0)
 
305
        update_lookup_table();
 
306
    else
 
307
        ibus_engine_hide_lookup_table (m_engine);
 
308
}
 
309
 
 
310
void
 
311
SunPinyinEngine::update_lookup_table()
 
312
{
 
313
    ibus_engine_update_lookup_table(m_engine, m_lookup_table, TRUE);
 
314
}
 
315
 
 
316
bool
 
317
SunPinyinEngine::is_valid() const
 
318
{
 
319
    return m_pv != NULL;
 
320
}
 
321
 
 
322
static int
 
323
find_embed_preedit_pos(const IPreeditString& preedit)
 
324
{
 
325
    int mask = IPreeditString::USER_CHOICE & IPreeditString::HANZI_CHAR;
 
326
    for (size_t i = 0; i < preedit.charTypeSize(); i++) {
 
327
        if ((preedit.charTypeAt(i) & mask) == 0) {
 
328
            return i;
 
329
        }
 
330
    }
 
331
    return preedit.charTypeSize();
 
332
}
 
333
 
 
334
enum {ORANGE = 0xE76F00, GRAY_BLUE = 0x35556B, WHITE = 0xFFFFFF,
 
335
      BLACK = 0x000000};
 
336
 
 
337
void
 
338
SunPinyinEngine::update_preedit_string(const IPreeditString& preedit)
 
339
{
 
340
    if (preedit.size() > 0) {
 
341
        wstring wstr(preedit.string());
 
342
        int embed_pos = find_embed_preedit_pos(preedit);
 
343
        wstring embed_wstr = wstr.substr(0, embed_pos);
 
344
        wstring preedit_wstr = wstr.substr(embed_pos);
 
345
        const gunichar* embed_cstr = (const gunichar*) embed_wstr.c_str();
 
346
        const gunichar* preedit_cstr = (const gunichar*) preedit_wstr.c_str();
 
347
        IBusText* preedit_text = ibus_text_new_from_ucs4(preedit_cstr);
 
348
        int caret = preedit.caret() - embed_pos;
 
349
 
 
350
        if (preedit.caret() < preedit.size()) {
 
351
            ibus_text_append_attribute(preedit_text, IBUS_ATTR_TYPE_FOREGROUND,
 
352
                                       WHITE, caret, preedit_wstr.size());
 
353
            ibus_text_append_attribute(preedit_text, IBUS_ATTR_TYPE_BACKGROUND,
 
354
                                       GRAY_BLUE, caret, preedit_wstr.size());
 
355
        }
 
356
        ibus_engine_update_auxiliary_text(m_engine, preedit_text, TRUE);
 
357
 
 
358
        ibus_engine_update_preedit_text(m_engine,
 
359
                                        ibus_text_new_from_ucs4(embed_cstr),
 
360
                                        preedit.caret(), TRUE);
 
361
 
 
362
    } else {
 
363
        ibus_engine_hide_auxiliary_text(m_engine);
 
364
        ibus_engine_hide_preedit_text(m_engine);
 
365
    }
 
366
}
 
367
 
 
368
void
 
369
SunPinyinEngine::update_status_property(bool cn)
 
370
{
 
371
    m_status_prop.update(cn);
 
372
}
 
373
 
 
374
void
 
375
SunPinyinEngine::update_punct_property(bool full)
 
376
{
 
377
    m_punct_prop.update(full);
 
378
}
 
379
 
 
380
void
 
381
SunPinyinEngine::update_letter_property(bool full)
 
382
{
 
383
    m_letter_prop.update(full);
 
384
}
 
385
 
 
386
void
 
387
SunPinyinEngine::update_history_power()
 
388
{
 
389
    unsigned power = m_config.get(CONFIG_GENERAL_MEMORY_POWER, 3);
 
390
    CIMIContext* ic = m_pv->getIC();
 
391
    assert(ic);
 
392
    ic->setHistoryPower(power);
 
393
}
 
394
 
 
395
void
 
396
SunPinyinEngine::update_charset_level()
 
397
{
 
398
    unsigned charset = m_config.get(CONFIG_GENERAL_CHARSET_LEVEL, GBK);
 
399
    CIMIContext* ic = m_pv->getIC();
 
400
    assert(ic);
 
401
    charset &= 3;               // charset can only be 0,1,2 or 3
 
402
    ic->setCharsetLevel(charset);
 
403
}
 
404
 
 
405
void
 
406
SunPinyinEngine::update_cand_window_size()
 
407
{
 
408
    unsigned size = m_config.get(CONFIG_GENERAL_PAGE_SIZE, 10);
 
409
    m_pv->setCandiWindowSize(size);
 
410
}
 
411
 
 
412
void
 
413
SunPinyinEngine::update_mode_key()
 
414
{
 
415
    std::string mode_switch("Shift");
 
416
    mode_switch = m_config.get(CONFIG_KEYBOARD_MODE_SWITCH, mode_switch);
 
417
 
 
418
    CKeyEvent shift_l  (IM_VK_SHIFT_L, 0, IM_SHIFT_MASK|IM_RELEASE_MASK);
 
419
    CKeyEvent shift_r  (IM_VK_SHIFT_R, 0, IM_SHIFT_MASK|IM_RELEASE_MASK);
 
420
    CKeyEvent control_l(IM_VK_CONTROL_L, 0, IM_CTRL_MASK|IM_RELEASE_MASK);
 
421
    CKeyEvent control_r(IM_VK_CONTROL_R, 0, IM_CTRL_MASK|IM_RELEASE_MASK);
 
422
 
 
423
    if (mode_switch == "Shift") {
 
424
        m_hotkey_profile->removeModeSwitchKey(control_l);
 
425
        m_hotkey_profile->removeModeSwitchKey(control_r);
 
426
        m_hotkey_profile->addModeSwitchKey(shift_l);
 
427
        m_hotkey_profile->addModeSwitchKey(shift_r);
 
428
    } else if (mode_switch == "Control") {
 
429
        m_hotkey_profile->removeModeSwitchKey(shift_l);
 
430
        m_hotkey_profile->removeModeSwitchKey(shift_r);
 
431
        m_hotkey_profile->addModeSwitchKey(control_l);
 
432
        m_hotkey_profile->addModeSwitchKey(control_r);
 
433
    }
 
434
}
 
435
 
 
436
void
 
437
SunPinyinEngine::update_punct_key()
 
438
{
 
439
    std::string punct_switch("ControlComma");
 
440
    punct_switch = m_config.get(CONFIG_KEYBOARD_PUNCT_SWITCH, punct_switch);
 
441
    if (punct_switch == "ControlComma") {
 
442
        m_hotkey_profile->setPunctSwitchKey(CKeyEvent(IM_VK_COMMA, 0, IM_CTRL_MASK));
 
443
    } else if (punct_switch == "ControlPeriod") {
 
444
        m_hotkey_profile->setPunctSwitchKey(CKeyEvent(IM_VK_PERIOD, 0, IM_CTRL_MASK));
 
445
    }
 
446
}
 
447
 
 
448
void
 
449
SunPinyinEngine::update_page_key_minus()
 
450
{
 
451
    update_page_key(CONFIG_KEYBOARD_PAGE_MINUS, false,
 
452
                    IM_VK_MINUS, IM_VK_EQUALS);
 
453
}
 
454
 
 
455
void
 
456
SunPinyinEngine::update_page_key_comma()
 
457
{
 
458
    update_page_key(CONFIG_KEYBOARD_PAGE_COMMA, false,
 
459
                    IM_VK_COMMA, IM_VK_PERIOD);
 
460
}
 
461
 
 
462
void
 
463
SunPinyinEngine::update_page_key_bracket()
 
464
{
 
465
    update_page_key(CONFIG_KEYBOARD_PAGE_BRACKET, false,
 
466
                    IM_VK_OPEN_BRACKET, IM_VK_CLOSE_BRACKET);
 
467
}
 
468
 
 
469
void
 
470
SunPinyinEngine::update_page_key(const char* conf_key, bool default_val,
 
471
                            unsigned page_up, unsigned page_down)
 
472
{
 
473
    bool enabled = m_config.get(conf_key, default_val);
 
474
 
 
475
    if (enabled) {
 
476
        m_hotkey_profile->addPageUpKey(CKeyEvent(page_up, 0));
 
477
        m_hotkey_profile->addPageDownKey(CKeyEvent(page_down, 0));
 
478
    } else {
 
479
        m_hotkey_profile->removePageUpKey(CKeyEvent(page_up, 0));
 
480
        m_hotkey_profile->removePageDownKey(CKeyEvent(page_down, 0));
 
481
    }
 
482
}
 
483
 
 
484
void
 
485
SunPinyinEngine::update_cancel_with_backspace()
 
486
{
 
487
    bool enabled = m_config.get(CONFIG_KEYBOARD_CANCEL_BACKSPACE, true);
 
488
    m_pv->setCancelOnBackspace(enabled);
 
489
}
 
490
 
 
491
void
 
492
SunPinyinEngine::update_smart_punc()
 
493
{
 
494
    m_pv->setSmartPunct(m_config.get(CONFIG_KEYBOARD_SMARK_PUNCT, true));
 
495
}
 
496
 
 
497
void
 
498
SunPinyinEngine::update_max_best()
 
499
{
 
500
    if (m_pv->getIC() == NULL) {
 
501
        return;
 
502
    }
 
503
    int oldval = (int) m_pv->getIC()->getMaxBest();
 
504
    m_pv->getIC()->setMaxBest(m_config.get(CONFIG_GENERAL_MAX_BEST, oldval));
 
505
}
 
506
 
 
507
void
 
508
SunPinyinEngine::update_max_tail_candidate()
 
509
{
 
510
    if (m_pv->getIC() == NULL) {
 
511
        return;
 
512
    }
 
513
    int oldval = (int) m_pv->getIC()->getMaxTailCandidateNum();
 
514
    m_pv->getIC()->setMaxTailCandidateNum(
 
515
        m_config.get(CONFIG_GENERAL_MAX_TAIL_CANDIDATE, oldval));
 
516
}
 
517
 
 
518
string_pairs parse_pairs(const std::vector<std::string>& strings)
 
519
{
 
520
    string_pairs pairs;
 
521
    for (std::vector<std::string>::const_iterator pair = strings.begin();
 
522
         pair != strings.end(); ++pair) {
 
523
 
 
524
        std::string::size_type found = pair->find(':');
 
525
        if (found == pair->npos || pair->length() < 3)
 
526
            continue;
 
527
        if (found == 0 && (*pair)[0] == ':')
 
528
            found = 1;
 
529
 
 
530
        pairs.push_back(make_pair(pair->substr(0, found),
 
531
                                  pair->substr(found+1)));
 
532
    }
 
533
    return pairs;
 
534
}
 
535
 
 
536
// the mappings in default_pairs will override the ones in user_pairs
 
537
string_pairs merge_pairs(const string_pairs& default_pairs,
 
538
                         const string_pairs& user_pairs)
 
539
{
 
540
    typedef std::map<std::string, int> Indexes;
 
541
    Indexes indexes;
 
542
    int index = 0;
 
543
    for (string_pairs::const_iterator it = default_pairs.begin();
 
544
         it != default_pairs.end(); ++it, ++index) {
 
545
        Indexes::iterator found = indexes.find(it->first);
 
546
        if (found == indexes.end()) {
 
547
            indexes[it->first] = index;
 
548
        } else {
 
549
            // it is a paired punct.
 
550
            indexes[it->first] = -found->second;
 
551
        }
 
552
    }
 
553
    string_pairs result(default_pairs);
 
554
    for (string_pairs::const_iterator it = user_pairs.begin();
 
555
         it != user_pairs.end(); ++it) {
 
556
        Indexes::iterator found = indexes.find(it->first);
 
557
        if (found == indexes.end()) {
 
558
            result.push_back(*it);
 
559
        } else if (found->second >= 0) {
 
560
            result[found->second] = *it;
 
561
        } else {
 
562
            // it is a paired punct,
 
563
            // but we don't support this kind of mapping yet,
 
564
            // so quietly ignore it.
 
565
        }
 
566
    }
 
567
    return result;
 
568
}
 
569
 
 
570
void
 
571
SunPinyinEngine::update_punct_mappings()
 
572
{
 
573
    CSimplifiedChinesePolicy& policy = ASimplifiedChinesePolicy::instance();
 
574
    if (m_config.get(PINYIN_PUNCTMAPPING_ENABLED, false)) {
 
575
        std::vector<std::string> mappings;
 
576
        mappings = m_config.get(PINYIN_PUNCTMAPPING_MAPPINGS, mappings);
 
577
        string_pairs pairs(merge_pairs(policy.getDefaultPunctMapping(),
 
578
                                       parse_pairs(mappings)));
 
579
        policy.setPunctMapping(pairs);
 
580
    }
 
581
}
 
582
 
 
583
void
 
584
SunPinyinEngine::update_user_data_dir()
 
585
{
 
586
    std::stringstream user_data_dir;
 
587
    user_data_dir << g_get_home_dir()
 
588
                  << G_DIR_SEPARATOR_S << ".sunpinyin";
 
589
    ASimplifiedChinesePolicy::instance().setUserDataDir(user_data_dir.str());
 
590
}
 
591
 
 
592
void
 
593
SunPinyinEngine::update_fuzzy_pinyins()
 
594
{
 
595
    bool enabled = m_config.get(QUANPIN_FUZZY_ENABLED, false);
 
596
    AQuanpinSchemePolicy::instance().setFuzzyForwarding(enabled);
 
597
    AShuangpinSchemePolicy::instance().setFuzzyForwarding(enabled);
 
598
    if (!enabled)
 
599
        return;
 
600
    std::vector<std::string> fuzzy_pinyins;
 
601
    fuzzy_pinyins = m_config.get(QUANPIN_FUZZY_PINYINS, fuzzy_pinyins);
 
602
    AQuanpinSchemePolicy::instance().setFuzzyPinyinPairs(parse_pairs(fuzzy_pinyins));
 
603
    AShuangpinSchemePolicy::instance().setFuzzyPinyinPairs(parse_pairs(fuzzy_pinyins));
 
604
}
 
605
 
 
606
void
 
607
SunPinyinEngine::update_correction_pinyins()
 
608
{
 
609
    bool enabled = m_config.get(QUANPIN_AUTOCORRECTION_ENABLED, false);
 
610
    AQuanpinSchemePolicy::instance().setAutoCorrecting(enabled);
 
611
    if (!enabled)
 
612
        return;
 
613
    std::vector<std::string> correction_pinyins;
 
614
    correction_pinyins = m_config.get(QUANPIN_AUTOCORRECTION_PINYINS, correction_pinyins);
 
615
    AQuanpinSchemePolicy::instance().setAutoCorrectionPairs(parse_pairs(correction_pinyins));
 
616
}
 
617
 
 
618
void
 
619
SunPinyinEngine::update_fuzzy_segs()
 
620
{
 
621
    bool enable_fuzzy_segs = m_config.get(CONFIG_QUANPIN_FUZZYSEGS_ENABLED, false);
 
622
    AQuanpinSchemePolicy::instance().setFuzzySegmentation(enable_fuzzy_segs);
 
623
    bool enable_inner_fuzzy = m_config.get(CONFIG_QUANPIN_INNERFUZZY_ENABLED, false);
 
624
    AQuanpinSchemePolicy::instance().setInnerFuzzySegmentation(CONFIG_QUANPIN_INNERFUZZY_ENABLED);
 
625
}
 
626
 
 
627
void
 
628
SunPinyinEngine::update_shuangpin_type()
 
629
{
 
630
    EShuangpinType shuangpin_type = MS2003;
 
631
    shuangpin_type = (EShuangpinType) m_config.get(SHUANGPIN_TYPE, (int) shuangpin_type);
 
632
    AShuangpinSchemePolicy::instance().setShuangpinType(shuangpin_type);
 
633
}
 
634
 
 
635
void
 
636
SunPinyinEngine::update_candi_delete_key()
 
637
{
 
638
    /* FIXME: need to get candi_delete_key from user's configuration */
 
639
    m_hotkey_profile->setCandiDeleteKey(CKeyEvent(0, 0, IM_ALT_MASK));
 
640
}