~ubuntu-branches/ubuntu/quantal/sunpinyin/quantal

« back to all changes in this revision

Viewing changes to wrapper/xim/sunpinyin_preedit.cc

  • 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) 2010 Mike Qin <mikeandmore@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
#include <locale.h>
 
36
 
 
37
#include <sunpinyin.h>
 
38
#include <ime-core/imi_glibHandler.h>
 
39
 
 
40
#include "xim.h"
 
41
#include "common.h"
 
42
#include "settings.h"
 
43
#include "sunpinyin_preedit_ui.h"
 
44
 
 
45
#define BUF_SIZE 4096
 
46
 
 
47
class WindowHandler : public CIMIGlibHandler
 
48
{
 
49
protected:
 
50
    virtual void updatePreedit(const IPreeditString* ppd);
 
51
    virtual void updateCandidates(const ICandidateList* pcl);
 
52
    virtual void updateStatus(int key, int value);
 
53
    virtual void commit(const TWCHAR* str);
 
54
 
 
55
private:
 
56
    PreeditUI* ui_impl_;
 
57
 
 
58
public:
 
59
 
 
60
    WindowHandler();
 
61
    virtual ~WindowHandler();
 
62
 
 
63
    PreeditUI* preedit_ui_impl() { return ui_impl_; }
 
64
    void       set_preedit_ui_impl(PreeditUI* ui_impl) {
 
65
        ui_impl_ = ui_impl;
 
66
    }
 
67
 
 
68
    void set_xim_handle(XIMHandle* handle) {
 
69
        handle_ = handle;
 
70
    }
 
71
 
 
72
    bool status() {
 
73
        return status_;
 
74
    }
 
75
 
 
76
    void update_preedit_ui(const IPreeditString* ppd, const char* utf_str);
 
77
    void update_candidates_ui(const ICandidateList* pcl, const char* utf_str);
 
78
 
 
79
    void pause();
 
80
    void move(int x, int y);
 
81
    void go_on();
 
82
    void reload_ui();
 
83
 
 
84
private:
 
85
    XIMHandle* handle_;
 
86
 
 
87
    char* preedit_str_;
 
88
    char* candidate_str_;
 
89
 
 
90
    bool status_;
 
91
    bool pause_;
 
92
 
 
93
    int  x_, y_;
 
94
};
 
95
 
 
96
WindowHandler::WindowHandler()
 
97
{
 
98
    preedit_str_ = new char[BUF_SIZE];
 
99
    candidate_str_ = new char[BUF_SIZE];
 
100
    status_ = false;
 
101
    pause_ = false;
 
102
    ui_impl_ = NULL;
 
103
    handle_ = NULL;
 
104
    x_ = y_ = 0;
 
105
}
 
106
 
 
107
WindowHandler::~WindowHandler()
 
108
{
 
109
    delete [] preedit_str_;
 
110
    delete [] candidate_str_;
 
111
}
 
112
 
 
113
void
 
114
WindowHandler::reload_ui()
 
115
{
 
116
    ui_impl_->reload();
 
117
    ui_impl_->update_preedit_string(preedit_str_);
 
118
    ui_impl_->update_candidates_string(candidate_str_);
 
119
    if (status_) {
 
120
        ui_impl_->show();
 
121
        ui_impl_->move(x_, y_);
 
122
    } else {
 
123
        ui_impl_->hide();
 
124
    }
 
125
}
 
126
 
 
127
void
 
128
WindowHandler::pause()
 
129
{
 
130
    if (status_) {
 
131
        ui_impl_->hide();
 
132
        status_ = false;
 
133
        pause_ = true;
 
134
    }
 
135
}
 
136
 
 
137
void
 
138
WindowHandler::move(int x, int y)
 
139
{
 
140
    x_ = x;
 
141
    y_ = y;
 
142
    if (ui_impl_) {
 
143
        ui_impl_->move(x, y);
 
144
    }
 
145
}
 
146
 
 
147
void
 
148
WindowHandler::go_on()
 
149
{
 
150
    if (!status_ && pause_) {
 
151
        ui_impl_->show();
 
152
        status_ = true;
 
153
        pause_ = false;
 
154
    }
 
155
}
 
156
 
 
157
void
 
158
WindowHandler::update_candidates_ui(const ICandidateList* pcl, const char* utf_str)
 
159
{
 
160
    ui_impl_->update_candidates_string(utf_str);
 
161
    if (status_) {
 
162
        ui_impl_->show();
 
163
    } else {
 
164
        ui_impl_->hide();
 
165
    }
 
166
}
 
167
 
 
168
void
 
169
WindowHandler::update_preedit_ui(const IPreeditString* ppd, const char* utf_str)
 
170
{
 
171
    ui_impl_->update_preedit_string(utf_str);
 
172
    if (ppd->size() == 0) {
 
173
        status_ = false;
 
174
    } else {
 
175
        status_ = true;
 
176
    }
 
177
}
 
178
 
 
179
void
 
180
WindowHandler::updatePreedit(const IPreeditString* ppd)
 
181
{
 
182
    TIConvSrcPtr src = (TIConvSrcPtr) (ppd->string());
 
183
    TWCHAR* front_src = new TWCHAR[BUF_SIZE];
 
184
    TWCHAR* end_src = new TWCHAR[BUF_SIZE];
 
185
 
 
186
    memset(front_src, 0, BUF_SIZE * sizeof(TWCHAR));
 
187
    memset(end_src, 0, BUF_SIZE * sizeof(TWCHAR));
 
188
 
 
189
    memcpy(front_src, src, ppd->caret() * sizeof(TWCHAR));
 
190
    memcpy(end_src, src + ppd->caret() * sizeof(TWCHAR),
 
191
           (ppd->size() - ppd->caret() + 1) * sizeof(TWCHAR));
 
192
 
 
193
    memset(preedit_str_, 0, BUF_SIZE);
 
194
 
 
195
    WCSTOMBS(preedit_str_, front_src, BUF_SIZE - 1);
 
196
    preedit_str_[strlen(preedit_str_)] = '|';
 
197
    WCSTOMBS(&preedit_str_[strlen(preedit_str_)], end_src, BUF_SIZE - 1);
 
198
 
 
199
    // update within the ui provider
 
200
    update_preedit_ui(ppd, preedit_str_);
 
201
 
 
202
    delete [] front_src;
 
203
    delete [] end_src;
 
204
}
 
205
 
 
206
void
 
207
WindowHandler::updateCandidates(const ICandidateList* pcl)
 
208
{
 
209
    wstring cand_str;
 
210
    for (int i = 0, sz = pcl->size(); i < sz; i++) {
 
211
        const TWCHAR* pcand = pcl->candiString(i);
 
212
        if (pcand == NULL) break;
 
213
        cand_str += (i == 9) ? '0' : TWCHAR('1' + i);
 
214
        cand_str += TWCHAR('.');
 
215
        cand_str += pcand;
 
216
        cand_str += TWCHAR(' ');
 
217
    }
 
218
 
 
219
    TIConvSrcPtr src = (TIConvSrcPtr)(cand_str.c_str());
 
220
    WCSTOMBS(candidate_str_, (const TWCHAR*) src, BUF_SIZE - 1);
 
221
 
 
222
    // update within the ui provider
 
223
    update_candidates_ui(pcl, candidate_str_);
 
224
}
 
225
 
 
226
void
 
227
WindowHandler::updateStatus(int key, int value)
 
228
{}
 
229
 
 
230
void
 
231
WindowHandler::commit(const TWCHAR* str)
 
232
{
 
233
    char* buf = new char[BUF_SIZE];
 
234
    memset(buf, 0, BUF_SIZE);
 
235
    WCSTOMBS(buf, str, BUF_SIZE - 1);
 
236
    if (handle_ != NULL) {
 
237
        xim_commit_preedit(handle_, buf);
 
238
    }
 
239
    delete [] buf;
 
240
}
 
241
 
 
242
 
 
243
static PreeditUI* ui_impl = NULL;
 
244
static WindowHandler* instance = NULL;
 
245
static CIMIView* view = NULL;
 
246
 
 
247
__EXPORT_API void
 
248
preedit_init()
 
249
{
 
250
    CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
 
251
    if (settings_get_int(SHUANGPIN)) {
 
252
        fac.setPinyinScheme(CSunpinyinSessionFactory::SHUANGPIN);
 
253
        // shuangpin schemes
 
254
        varchar scheme;
 
255
        settings_get(SHUANGPIN_SCHEME, scheme);
 
256
        if (strcmp(scheme, "MS2003") == 0) {
 
257
            AShuangpinSchemePolicy::instance().setShuangpinType(MS2003);
 
258
        } else if (strcmp(scheme, "ABC") == 0) {
 
259
            AShuangpinSchemePolicy::instance().setShuangpinType(ABC);
 
260
        } else if (strcmp(scheme, "ZiRanMa") == 0) {
 
261
            AShuangpinSchemePolicy::instance().setShuangpinType(ZIRANMA);
 
262
        } else if (strcmp(scheme, "PinYin++") == 0) {
 
263
            AShuangpinSchemePolicy::instance().setShuangpinType(PINYINJIAJIA);
 
264
        } else if (strcmp(scheme, "ZiGuang") == 0) {
 
265
            AShuangpinSchemePolicy::instance().setShuangpinType(ZIGUANG);
 
266
        } else if (strcmp(scheme, "XiaoHe") == 0) {
 
267
            AShuangpinSchemePolicy::instance().setShuangpinType(XIAOHE);
 
268
        }
 
269
    } else {
 
270
        fac.setPinyinScheme(CSunpinyinSessionFactory::QUANPIN);
 
271
    }
 
272
    view = fac.createSession();
 
273
 
 
274
    varchar skin_name;
 
275
    settings_get(SKIN_NAME, skin_name);
 
276
    ui_impl = create_preedit_ui(skin_name);
 
277
 
 
278
    instance = new WindowHandler();
 
279
    instance->set_preedit_ui_impl(ui_impl);
 
280
    view->getIC()->setCharsetLevel(1);// GBK
 
281
    view->attachWinHandler(instance);
 
282
}
 
283
 
 
284
__EXPORT_API void
 
285
preedit_finalize(void)
 
286
{
 
287
    LOG("preedit_finalizing...");
 
288
    CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
 
289
    fac.destroySession(view);
 
290
 
 
291
    delete ui_impl;
 
292
    delete instance;
 
293
}
 
294
 
 
295
__EXPORT_API void
 
296
preedit_reload(void)
 
297
{
 
298
    // number of candidates
 
299
    view->setCandiWindowSize(settings_get_int(CANDIDATES_SIZE));
 
300
 
 
301
    // page up/down key
 
302
    CHotkeyProfile* prof = view->getHotkeyProfile();
 
303
    prof->clear();
 
304
    if (settings_get_int(PAGE_MINUS_PLUS)) {
 
305
        prof->addPageUpKey(CKeyEvent(IM_VK_MINUS));
 
306
        prof->addPageDownKey(CKeyEvent(IM_VK_EQUALS));
 
307
    }
 
308
    if (settings_get_int(PAGE_COMMA_PERIOD)) {
 
309
        prof->addPageUpKey(CKeyEvent(IM_VK_COMMA));
 
310
        prof->addPageDownKey(CKeyEvent(IM_VK_PERIOD));
 
311
    }
 
312
    if (settings_get_int(PAGE_PAREN)) {
 
313
        prof->addPageUpKey(CKeyEvent('['));
 
314
        prof->addPageDownKey(CKeyEvent(']'));
 
315
    }
 
316
 
 
317
    // fuzzy segmentation
 
318
    bool enable_fuzzy = settings_get_int(FUZZY_SEGMENTATION);
 
319
    bool enable_inner = settings_get_int(FUZZY_INNER_SEGMENTATION);
 
320
    AQuanpinSchemePolicy::instance().setFuzzySegmentation(enable_fuzzy);
 
321
    AQuanpinSchemePolicy::instance().setInnerFuzzySegmentation(enable_inner);
 
322
 
 
323
    // cancel last selection on backspace
 
324
    view->setCancelOnBackspace(settings_get_int(CANCEL_ON_BACKSPACE));
 
325
 
 
326
    // do we need to change the skin?
 
327
    varchar skin_name;
 
328
    settings_get(SKIN_NAME, skin_name);
 
329
    if (ui_impl->name() != skin_name) {
 
330
        delete ui_impl;
 
331
        ui_impl = create_preedit_ui(skin_name);
 
332
        instance->set_preedit_ui_impl(ui_impl);
 
333
    }
 
334
 
 
335
    instance->reload_ui();
 
336
}
 
337
 
 
338
__EXPORT_API void
 
339
preedit_set_handle(XIMHandle* handle)
 
340
{
 
341
    instance->set_xim_handle(handle);
 
342
}
 
343
 
 
344
__EXPORT_API void
 
345
preedit_move(int x, int y)
 
346
{
 
347
    instance->move(x, y);
 
348
}
 
349
 
 
350
__EXPORT_API void
 
351
preedit_pause(void)
 
352
{
 
353
    instance->pause();
 
354
}
 
355
 
 
356
__EXPORT_API void
 
357
preedit_go_on(void)
 
358
{
 
359
    instance->go_on();
 
360
}
 
361
 
 
362
__EXPORT_API void
 
363
preedit_on_key(XIMHandle* handle, unsigned int keycode, unsigned int state)
 
364
{
 
365
    if (keycode < 0x20 && keycode > 0x7E)
 
366
        keycode = 0;
 
367
    view->onKeyEvent(CKeyEvent(keycode, keycode, state));
 
368
}
 
369
 
 
370
__EXPORT_API bool
 
371
preedit_status(void)
 
372
{
 
373
    return instance->status();
 
374
}
 
375
 
 
376
__EXPORT_API void
 
377
preedit_set_full(bool full)
 
378
{
 
379
    view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, full);
 
380
}
 
381
 
 
382
__EXPORT_API void
 
383
preedit_set_chinese_punc(bool chn_punc)
 
384
{
 
385
    view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, chn_punc);
 
386
}
 
387
 
 
388
__EXPORT_API void
 
389
preedit_omit_next_punct()
 
390
{
 
391
    view->getIC()->omitNextPunct();
 
392
}
 
393