1
/***************************************************************************
2
* Copyright (C) 2010~2010 by CSSlayer *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
25
#include <ime-core/imi_view.h>
26
#include <ime-core/imi_options.h>
27
#include <ime-core/utils.h>
28
#include <fcitx/ime.h>
29
#include <fcitx-config/hotkey.h>
30
#include <fcitx-config/xdg.h>
31
#include <fcitx-utils/log.h>
32
#include <fcitx-config/fcitx-config.h>
33
#include <fcitx-utils/utils.h>
34
#include <fcitx/instance.h>
35
#include <fcitx/keys.h>
36
#include <fcitx/module.h>
43
#define FCITX_SUNPINYIN_MAX(x, y) ((x) > (y)? (x) : (y))
55
int ABI_VERSION = FCITX_ABI_VERSION;
60
CONFIG_DESC_DEFINE(GetSunpinyinConfigDesc, "fcitx-sunpinyin.desc")
62
boolean LoadSunpinyinConfig(FcitxSunpinyinConfig* fs);
63
static void SaveSunpinyinConfig(FcitxSunpinyinConfig* fs);
64
static void ConfigSunpinyin(FcitxSunpinyin* sunpinyin);
65
static void* SunpinyinGetFullPinyin(void* arg, FcitxModuleFunctionArg args);
66
static INPUT_RETURN_VALUE FcitxSunpinyinDeleteCandidate (FcitxSunpinyin* sunpinyin, CandidateWord* candWord);
69
static const char* fuzzyPairs[][2] = {
86
static const char *correctionPairs[][2] = {
96
* @brief Reset the status.
100
void FcitxSunpinyinReset (void* arg)
102
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) arg;
103
FcitxUIStatus* puncStatus = GetUIStatus(sunpinyin->owner, "punc");
104
FcitxUIStatus* fullwidthStatus = GetUIStatus(sunpinyin->owner, "fullwidth");
105
sunpinyin->view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, fullwidthStatus->getCurrentStatus(fullwidthStatus->arg));
106
sunpinyin->view->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, puncStatus->getCurrentStatus(puncStatus->arg));
107
sunpinyin->view->clearIC();
111
* @brief Process Key Input and return the status
113
* @param keycode keycode from XKeyEvent
114
* @param state state from XKeyEvent
115
* @param count count from XKeyEvent
116
* @return INPUT_RETURN_VALUE
119
INPUT_RETURN_VALUE FcitxSunpinyinDoInput(void* arg, FcitxKeySym sym, unsigned int state)
121
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) arg;
122
FcitxInputState* input = FcitxInstanceGetInputState(sunpinyin->owner);
123
CIMIView* view = sunpinyin->view;
124
FcitxWindowHandler* windowHandler = sunpinyin->windowHandler;
125
FcitxSunpinyinConfig* fs = &sunpinyin->fs;
126
FcitxConfig* config = FcitxInstanceGetConfig(sunpinyin->owner);
127
CandidateWordSetChoose(FcitxInputStateGetCandidateList(input), DIGIT_STR_CHOOSE);
129
int chooseKey = CheckChooseKey(sym, KEY_NONE, DIGIT_STR_CHOOSE);
130
if (state == KEY_CTRL_ALT_COMP && chooseKey >= 0)
132
CandidateWord* candidateWord = CandidateWordGetByIndex(FcitxInputStateGetCandidateList(input), chooseKey);
133
return FcitxSunpinyinDeleteCandidate(sunpinyin, candidateWord);
136
if ( (!IsHotKeySimple(sym, state) || IsHotKey(sym, state, FCITX_SPACE)) && view->getIC()->isEmpty())
137
return IRV_TO_PROCESS;
139
/* there is some special case that ';' is used */
140
if (IsHotKey(sym, state, FCITX_SEMICOLON) &&
141
!(!view->getIC()->isEmpty() && fs->bUseShuangpin && (fs->SPScheme == MS2003 || fs->SPScheme == ZIGUANG)))
142
return IRV_TO_PROCESS;
144
if (IsHotKey(sym, state, FCITX_SEPARATOR) &&
145
view->getIC()->isEmpty())
146
return IRV_TO_PROCESS;
148
if (sym == Key_KP_Enter)
151
if (IsHotKeyDigit(sym, state))
152
return IRV_TO_PROCESS;
154
if (IsHotKey(sym, state, FCITX_SPACE))
155
return CandidateWordChooseByIndex(FcitxInputStateGetCandidateList(input), 0);
157
if (!IsHotKeyUAZ(sym, state)
158
&& !IsHotKeyLAZ(sym, state)
159
&& !IsHotKey(sym, state, FCITX_SEMICOLON)
160
&& !IsHotKey(sym, state, FCITX_BACKSPACE)
161
&& !IsHotKey(sym, state, FCITX_DELETE)
162
&& !IsHotKey(sym, state, FCITX_ENTER)
163
&& !IsHotKey(sym, state, FCITX_LEFT)
164
&& !IsHotKey(sym, state, FCITX_RIGHT)
165
&& !IsHotKey(sym, state, FCITX_HOME)
166
&& !IsHotKey(sym, state, FCITX_END)
167
&& !IsHotKey(sym, state, FCITX_SEPARATOR)
169
return IRV_TO_PROCESS;
171
if (IsHotKey(sym, state, config->hkPrevPage) || IsHotKey(sym, state, config->hkNextPage))
172
return IRV_TO_PROCESS;
174
windowHandler->commit_flag = false;
175
windowHandler->candidate_flag = false;
176
unsigned int changeMasks = view->onKeyEvent(CKeyEvent(sym, sym, state));
178
if (windowHandler->commit_flag)
179
return IRV_COMMIT_STRING;
180
if (!(changeMasks & CIMIView::KEYEVENT_USED))
181
return IRV_TO_PROCESS;
183
if (view->getIC()->isEmpty())
186
if (windowHandler->candidate_flag)
188
return IRV_DISPLAY_CANDWORDS;
191
return IRV_DO_NOTHING;
194
boolean FcitxSunpinyinInit(void* arg)
201
* @brief function DoInput has done everything for us.
204
* @return INPUT_RETURN_VALUE
207
INPUT_RETURN_VALUE FcitxSunpinyinGetCandWords(void* arg)
209
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin* )arg;
210
FcitxInstance* instance = sunpinyin->owner;
211
FcitxInputState* input = FcitxInstanceGetInputState(instance);
214
sunpinyin->view->getPreeditString(ppd);
215
TIConvSrcPtr src = (TIConvSrcPtr) (ppd.string());
218
while (hzlen < ppd.charTypeSize())
220
if (! (ppd.charTypeAt(hzlen) & IPreeditString::USER_CHOICE))
225
CleanInputWindowUp(instance);
227
memcpy(sunpinyin->front_src, src, ppd.caret() * sizeof(TWCHAR));
228
memcpy(sunpinyin->end_src, src + ppd.caret() * sizeof(TWCHAR),
229
(ppd.size() - ppd.caret() + 1) * sizeof(TWCHAR));
230
memcpy(sunpinyin->input_src, src, hzlen * sizeof(TWCHAR));
232
FcitxLog(INFO, "%d", ppd.candi_start());
234
sunpinyin->front_src[ppd.caret()] = 0;
235
sunpinyin->end_src[ppd.size() - ppd.caret() + 1] = 0;
236
sunpinyin->input_src[hzlen] = 0;
238
memset(sunpinyin->clientpreedit, 0, FCITX_SUNPINYIN_MAX(hzlen * UTF8_MAX_LENGTH + 1, MAX_USER_INPUT + 1));
239
WCSTOMBS(sunpinyin->clientpreedit, sunpinyin->input_src, MAX_USER_INPUT);
240
AddMessageAtLast(FcitxInputStateGetClientPreedit(input), MSG_INPUT, "%s", sunpinyin->clientpreedit);
241
FcitxInputStateSetClientCursorPos(input, 0);
243
memset(sunpinyin->preedit, 0, FCITX_SUNPINYIN_MAX(ppd.size() * UTF8_MAX_LENGTH + 1, MAX_USER_INPUT + 1));
244
WCSTOMBS(sunpinyin->preedit, sunpinyin->front_src, MAX_USER_INPUT);
245
FcitxInputStateSetCursorPos(input, strlen(sunpinyin->preedit));
246
WCSTOMBS(&sunpinyin->preedit[strlen(sunpinyin->preedit)], sunpinyin->end_src, MAX_USER_INPUT);
248
FcitxInputStateSetShowCursor(input, true);
250
AddMessageAtLast(FcitxInputStateGetPreedit(input), MSG_INPUT, "%s", sunpinyin->preedit);
253
sunpinyin->view->getCandidateList(pcl, 0, sunpinyin->candNum);
254
for (int i = 0; i < pcl.size(); i ++ )
256
const TWCHAR* pcand = pcl.candiString(i);
260
int *index = (int*) fcitx_malloc0(sizeof(int));
262
CandidateWord candWord;
263
candWord.callback = FcitxSunpinyinGetCandWord;
264
candWord.owner = sunpinyin;
265
candWord.priv = index;
266
candWord.strExtra = NULL;
268
wstring cand_str = pcand;
269
TIConvSrcPtr src = (TIConvSrcPtr)(cand_str.c_str());
270
WCSTOMBS(sunpinyin->ubuf, (const TWCHAR*) src, MAX_CAND_LEN);
272
candWord.strWord = strdup(sunpinyin->ubuf);
274
CandidateWordAppend(FcitxInputStateGetCandidateList(input), &candWord);
278
AddMessageAtLast(FcitxInputStateGetClientPreedit(input), MSG_INPUT, "%s", candWord.strWord);
282
return IRV_DISPLAY_CANDWORDS;
286
* @brief get the candidate word by index
288
* @param iIndex index of candidate word
289
* @return the string of canidate word
292
INPUT_RETURN_VALUE FcitxSunpinyinGetCandWord (void* arg, CandidateWord* candWord)
294
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin* )arg;
295
sunpinyin->windowHandler->commit_flag = false;
296
sunpinyin->windowHandler->candidate_flag = false;
297
int* index = (int*) candWord->priv;
298
sunpinyin->view->onCandidateSelectRequest(*index);
300
if (sunpinyin->windowHandler->commit_flag)
301
return IRV_COMMIT_STRING;
303
if (sunpinyin->windowHandler->candidate_flag)
304
return IRV_DISPLAY_CANDWORDS;
306
return IRV_DO_NOTHING;
310
* @brief initialize the extra input method
313
* @return successful or not
316
void* FcitxSunpinyinCreate (FcitxInstance* instance)
318
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) fcitx_malloc0(sizeof(FcitxSunpinyin));
319
FcitxAddon* addon = GetAddonByName(FcitxInstanceGetAddons(instance), "fcitx-sunpinyin");
320
bindtextdomain("fcitx-sunpinyin", LOCALEDIR);
321
sunpinyin->owner = instance;
322
FcitxSunpinyinConfig* fs = &sunpinyin->fs;
324
if (!LoadSunpinyinConfig(&sunpinyin->fs))
329
CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
331
if (fs->bUseShuangpin)
332
fac.setPinyinScheme(CSunpinyinSessionFactory::SHUANGPIN);
334
fac.setPinyinScheme(CSunpinyinSessionFactory::QUANPIN);
336
ConfigSunpinyin(sunpinyin);
337
sunpinyin->bShuangpin = fs->bUseShuangpin;
339
sunpinyin->view = fac.createSession();
341
if (sunpinyin->view == NULL)
347
FcitxWindowHandler* windowHandler = new FcitxWindowHandler();
348
sunpinyin->windowHandler = windowHandler;
349
sunpinyin->view->getIC()->setCharsetLevel(3);
351
sunpinyin->view->attachWinHandler(windowHandler);
352
sunpinyin->windowHandler->SetOwner(sunpinyin);
353
ConfigSunpinyin(sunpinyin);
355
FcitxRegisterIMv2(instance,
362
FcitxSunpinyinDoInput,
363
FcitxSunpinyinGetCandWords,
366
ReloadConfigFcitxSunpinyin,
368
fs->iSunpinyinPriority,
372
AddFunction(addon, (void*) SunpinyinGetFullPinyin);
378
* @brief Destroy the input method while unload it.
383
void FcitxSunpinyinDestroy (void* arg)
385
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) arg;
386
CSunpinyinSessionFactory& fac = CSunpinyinSessionFactory::getFactory();
387
fac.destroySession(sunpinyin->view);
388
if (sunpinyin->shuangpin_data)
389
delete sunpinyin->shuangpin_data;
391
if (sunpinyin->windowHandler)
392
delete sunpinyin->windowHandler;
397
INPUT_RETURN_VALUE FcitxSunpinyinDeleteCandidate (FcitxSunpinyin* sunpinyin, CandidateWord* candWord)
400
if (candWord->owner == sunpinyin)
403
sunpinyin->view->getCandidateList(pcl, 0, sunpinyin->candNum);
404
int* index = (int*) candWord->priv;
405
CIMIClassicView* classicView = (CIMIClassicView*) sunpinyin->view;
407
classicView->deleteCandidate(*index, mask);
408
return IRV_DISPLAY_CANDWORDS;
411
return IRV_TO_PROCESS;
415
* @brief Load the config file for fcitx-sunpinyin
417
* @param Bool is reload or not
419
boolean LoadSunpinyinConfig(FcitxSunpinyinConfig* fs)
421
ConfigFileDesc *configDesc = GetSunpinyinConfigDesc();
425
FILE *fp = GetXDGFileUserWithPrefix("conf", "fcitx-sunpinyin.config", "rt", NULL);
430
SaveSunpinyinConfig(fs);
432
ConfigFile *cfile = ParseConfigFileFp(fp, configDesc);
434
FcitxSunpinyinConfigConfigBind(fs, cfile, configDesc);
435
ConfigBindSync(&fs->gconfig);
442
void ConfigSunpinyin(FcitxSunpinyin* sunpinyin)
444
FcitxInstance* instance = sunpinyin->owner;
445
FcitxConfig* config = FcitxInstanceGetConfig(instance);
446
FcitxSunpinyinConfig *fs = &sunpinyin->fs;
451
sunpinyin->view->setCandiWindowSize(2048);
453
CHotkeyProfile* prof = sunpinyin->view->getHotkeyProfile();
456
for (i = 0 ; i < 2; i++)
458
if (config->hkPrevPage[i].sym)
459
prof->addPageUpKey(CKeyEvent(config->hkPrevPage[i].sym, 0, config->hkPrevPage[i].state));
460
if (config->hkNextPage[i].sym)
461
prof->addPageDownKey(CKeyEvent(config->hkNextPage[i].sym, 0, config->hkNextPage[i].state));
463
sunpinyin->view->setCancelOnBackspace(1);
466
string_pairs fuzzy, correction;
467
for (i = 0; i < FUZZY_SIZE; i++)
469
fuzzy.push_back(std::make_pair<std::string, std::string>(fuzzyPairs[i][0], fuzzyPairs[i][1]));
471
for (i = 0; i < CORRECT_SIZE; i++)
472
if (fs->bAutoCorrecting[i])
473
correction.push_back(std::make_pair<std::string, std::string>(correctionPairs[i][0], correctionPairs[i][1]));
475
if (fuzzy.size() != 0)
477
AQuanpinSchemePolicy::instance().setFuzzyForwarding(true);
478
AQuanpinSchemePolicy::instance().setFuzzyPinyinPairs(fuzzy);
482
AQuanpinSchemePolicy::instance().setFuzzyForwarding(false);
483
AQuanpinSchemePolicy::instance().clearFuzzyPinyinPairs();
486
if (correction.size() != 0)
488
AQuanpinSchemePolicy::instance().setAutoCorrecting(true);
489
AQuanpinSchemePolicy::instance().setAutoCorrectionPairs(correction);
492
AQuanpinSchemePolicy::instance().setAutoCorrecting(false);
494
if (sunpinyin->shuangpin_data == NULL)
495
sunpinyin->shuangpin_data = new CShuangpinData(fs->SPScheme);
496
AShuangpinSchemePolicy::instance().setShuangpinType(fs->SPScheme);
497
AQuanpinSchemePolicy::instance().setFuzzySegmentation(fs->bFuzzySegmentation);
498
AQuanpinSchemePolicy::instance().setInnerFuzzySegmentation(fs->bFuzzyInnerSegmentation);
501
__EXPORT_API void ReloadConfigFcitxSunpinyin(void* arg)
503
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) arg;
504
LoadSunpinyinConfig(&sunpinyin->fs);
505
ConfigSunpinyin(sunpinyin);
509
* @brief Save the config
513
void SaveSunpinyinConfig(FcitxSunpinyinConfig* fs)
515
ConfigFileDesc *configDesc = GetSunpinyinConfigDesc();
516
FILE *fp = GetXDGFileUserWithPrefix("conf", "fcitx-sunpinyin.config", "wt", NULL);
517
SaveConfigFileFp(fp, &fs->gconfig, configDesc);
522
void* SunpinyinGetFullPinyin(void* arg, FcitxModuleFunctionArg args)
524
FcitxSunpinyin* sunpinyin = (FcitxSunpinyin*) arg;
525
char* pinyin = (char*) args.args[0];
526
boolean *issp = (boolean*) args.args[1];
527
*issp = sunpinyin->bShuangpin;
529
if (sunpinyin->bShuangpin)
531
sunpinyin->shuangpin_data->getMapString(pinyin, syls);
532
if (syls.size() == 0)
535
return strdup(syls[0].c_str());
541
// kate: indent-mode cstyle; space-indent on; indent-width 0;