2 * Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
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
15 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
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.
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.
37 #include <sunpinyin.h>
38 #include <ime-core/imi_glibHandler.h>
43 #include "sunpinyin_preedit_ui.h"
47 class WindowHandler : public CIMIGlibHandler
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);
61 virtual ~WindowHandler();
63 PreeditUI* preedit_ui_impl() { return ui_impl_; }
64 void set_preedit_ui_impl(PreeditUI* ui_impl) {
68 void set_xim_handle(XIMHandle* handle) {
76 void update_preedit_ui(const IPreeditString* ppd, const char* utf_str);
77 void update_candidates_ui(const ICandidateList* pcl, const char* utf_str);
80 void move(int x, int y);
96 WindowHandler::WindowHandler()
98 preedit_str_ = new char[BUF_SIZE];
99 candidate_str_ = new char[BUF_SIZE];
107 WindowHandler::~WindowHandler()
109 delete [] preedit_str_;
110 delete [] candidate_str_;
114 WindowHandler::reload_ui()
117 ui_impl_->update_preedit_string(preedit_str_);
118 ui_impl_->update_candidates_string(candidate_str_);
121 ui_impl_->move(x_, y_);
128 WindowHandler::pause()
138 WindowHandler::move(int x, int y)
143 ui_impl_->move(x, y);
148 WindowHandler::go_on()
150 if (!status_ && pause_) {
158 WindowHandler::update_candidates_ui(const ICandidateList* pcl, const char* utf_str)
160 ui_impl_->update_candidates_string(utf_str);
169 WindowHandler::update_preedit_ui(const IPreeditString* ppd, const char* utf_str)
171 ui_impl_->update_preedit_string(utf_str);
172 if (ppd->size() == 0) {
180 WindowHandler::updatePreedit(const IPreeditString* ppd)
182 TIConvSrcPtr src = (TIConvSrcPtr) (ppd->string());
183 TWCHAR* front_src = new TWCHAR[BUF_SIZE];
184 TWCHAR* end_src = new TWCHAR[BUF_SIZE];
186 memset(front_src, 0, BUF_SIZE * sizeof(TWCHAR));
187 memset(end_src, 0, BUF_SIZE * sizeof(TWCHAR));
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));
193 memset(preedit_str_, 0, BUF_SIZE);
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);
199 // update within the ui provider
200 update_preedit_ui(ppd, preedit_str_);
207 WindowHandler::updateCandidates(const ICandidateList* pcl)
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('.');
216 cand_str += TWCHAR(' ');
219 TIConvSrcPtr src = (TIConvSrcPtr)(cand_str.c_str());
220 WCSTOMBS(candidate_str_, (const TWCHAR*) src, BUF_SIZE - 1);
222 // update within the ui provider
223 update_candidates_ui(pcl, candidate_str_);
227 WindowHandler::updateStatus(int key, int value)
231 WindowHandler::commit(const TWCHAR* str)
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);
243 static PreeditUI* ui_impl = NULL;
244 static WindowHandler* instance = NULL;
245 static CIMIView* view = NULL;
250 CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
251 if (settings_get_int(SHUANGPIN)) {
252 fac.setPinyinScheme(CSunpinyinSessionFactory::SHUANGPIN);
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);
270 fac.setPinyinScheme(CSunpinyinSessionFactory::QUANPIN);
272 view = fac.createSession();
275 settings_get(SKIN_NAME, skin_name);
276 ui_impl = create_preedit_ui(skin_name);
278 instance = new WindowHandler();
279 instance->set_preedit_ui_impl(ui_impl);
280 view->getIC()->setCharsetLevel(1);// GBK
281 view->attachWinHandler(instance);
285 preedit_finalize(void)
287 LOG("preedit_finalizing...");
288 CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
289 fac.destroySession(view);
298 // number of candidates
299 view->setCandiWindowSize(settings_get_int(CANDIDATES_SIZE));
302 CHotkeyProfile* prof = view->getHotkeyProfile();
304 if (settings_get_int(PAGE_MINUS_PLUS)) {
305 prof->addPageUpKey(CKeyEvent(IM_VK_MINUS));
306 prof->addPageDownKey(CKeyEvent(IM_VK_EQUALS));
308 if (settings_get_int(PAGE_COMMA_PERIOD)) {
309 prof->addPageUpKey(CKeyEvent(IM_VK_COMMA));
310 prof->addPageDownKey(CKeyEvent(IM_VK_PERIOD));
312 if (settings_get_int(PAGE_PAREN)) {
313 prof->addPageUpKey(CKeyEvent('['));
314 prof->addPageDownKey(CKeyEvent(']'));
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);
323 // cancel last selection on backspace
324 view->setCancelOnBackspace(settings_get_int(CANCEL_ON_BACKSPACE));
326 // do we need to change the skin?
328 settings_get(SKIN_NAME, skin_name);
329 if (ui_impl->name() != skin_name) {
331 ui_impl = create_preedit_ui(skin_name);
332 instance->set_preedit_ui_impl(ui_impl);
335 instance->reload_ui();
339 preedit_set_handle(XIMHandle* handle)
341 instance->set_xim_handle(handle);
345 preedit_move(int x, int y)
347 instance->move(x, y);
363 preedit_on_key(XIMHandle* handle, unsigned int keycode, unsigned int state)
365 if (keycode < 0x20 && keycode > 0x7E)
367 view->onKeyEvent(CKeyEvent(keycode, keycode, state));
373 return instance->status();
377 preedit_set_full(bool full)
379 view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, full);
383 preedit_set_chinese_punc(bool chn_punc)
385 view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, chn_punc);
389 preedit_omit_next_punct()
391 view->getIC()->omitNextPunct();