28 | 28 |
#include <fcitx-config/xdg.h>
|
29 | 29 |
#include <fcitx/module/pinyin/pydef.h>
|
30 | 30 |
#include <errno.h>
|
31 | |
|
32 | |
#define CHECK_VALID_IM (strcmp(im->strIconName, "pinyin") == 0 || \
|
33 | |
strcmp(im->strIconName, "googlepinyin") == 0 || \
|
34 | |
strcmp(im->strIconName, "sunpinyin") == 0 || \
|
35 | |
strcmp(im->strIconName, "shuangpin") == 0)
|
|
31 |
#include <iconv.h>
|
|
32 |
|
|
33 |
#define CHECK_VALID_IM (im && \
|
|
34 |
(strcmp(im->uniqueName, "pinyin") == 0 || \
|
|
35 |
strcmp(im->uniqueName, "googlepinyin") == 0 || \
|
|
36 |
strcmp(im->uniqueName, "sunpinyin") == 0 || \
|
|
37 |
strcmp(im->uniqueName, "shuangpin") == 0))
|
36 | 38 |
|
37 | 39 |
#define LOGLEVEL DEBUG
|
38 | 40 |
|
|
66 | 68 |
static void SaveCloudPinyinConfig(FcitxCloudPinyinConfig* fs);
|
67 | 69 |
static char *GetCurrentString(FcitxCloudPinyin* cloudpinyin);
|
68 | 70 |
static char* SplitHZAndPY(char* string);
|
69 | |
void CloudPinyinOnTriggerOn(void* arg);
|
|
71 |
void CloudPinyinHookForNewRequest(void* arg);
|
70 | 72 |
|
71 | 73 |
void SogouParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
72 | 74 |
char* SogouParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
73 | 75 |
void QQParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
74 | 76 |
char* QQParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
75 | 77 |
char* GoogleParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
76 | |
|
77 | |
CloudPinyinEngine engine[3] =
|
|
78 |
char* BaiduParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
|
|
79 |
|
|
80 |
CloudPinyinEngine engine[4] =
|
78 | 81 |
{
|
79 | 82 |
{
|
80 | 83 |
"http://web.pinyin.sogou.com/web_ime/patch.php",
|
|
93 | 96 |
"http://www.google.com/inputtools/request?ime=pinyin&text=%s",
|
94 | 97 |
NULL,
|
95 | 98 |
GoogleParsePinyin
|
|
99 |
},
|
|
100 |
{
|
|
101 |
NULL,
|
|
102 |
"http://olime.baidu.com/py?py=%s&rn=0&pn=1&ol=1",
|
|
103 |
NULL,
|
|
104 |
BaiduParsePinyin
|
96 | 105 |
}
|
97 | 106 |
};
|
98 | 107 |
|
|
108 | 117 |
CloudPinyinReloadConfig
|
109 | 118 |
};
|
110 | 119 |
|
|
120 |
FCITX_EXPORT_API
|
|
121 |
int ABI_VERSION = FCITX_ABI_VERSION;
|
|
122 |
|
|
123 |
static inline boolean ishex(char ch)
|
|
124 |
{
|
|
125 |
if ((ch >= '0' && ch <= '9') || (ch >='a' && ch <='f') || (ch >='A' && ch <='F'))
|
|
126 |
return true;
|
|
127 |
return false;
|
|
128 |
}
|
|
129 |
|
|
130 |
static inline unsigned char tohex(char ch)
|
|
131 |
{
|
|
132 |
if (ch >= '0' && ch <= '9')
|
|
133 |
return ch - '0';
|
|
134 |
if (ch >='a' && ch <='f')
|
|
135 |
return ch - 'a' + 10;
|
|
136 |
if (ch >='A' && ch <='F')
|
|
137 |
return ch - 'A' + 10;
|
|
138 |
return 0;
|
|
139 |
}
|
|
140 |
|
111 | 141 |
void* CloudPinyinCreate(FcitxInstance* instance)
|
112 | 142 |
{
|
113 | 143 |
FcitxCloudPinyin* cloudpinyin = fcitx_malloc0(sizeof(FcitxCloudPinyin));
|
|
138 | 168 |
RegisterUpdateCandidateWordHook(instance, hook);
|
139 | 169 |
|
140 | 170 |
hook.arg = cloudpinyin;
|
141 | |
hook.func = CloudPinyinOnTriggerOn;
|
142 | |
|
|
171 |
hook.func = CloudPinyinHookForNewRequest;
|
|
172 |
|
|
173 |
RegisterResetInputHook(instance, hook);
|
|
174 |
RegisterInputFocusHook(instance, hook);
|
|
175 |
RegisterInputUnFocusHook(instance, hook);
|
143 | 176 |
RegisterTriggerOnHook(instance, hook);
|
144 | 177 |
|
145 | 178 |
CloudPinyinRequestKey(cloudpinyin);
|
|
151 | 184 |
{
|
152 | 185 |
FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
|
153 | 186 |
FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
|
154 | |
FcitxInputState* input = &cloudpinyin->owner->input;
|
|
187 |
FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
|
155 | 188 |
|
156 | 189 |
if (cloudpinyin->initialized == false)
|
157 | 190 |
return;
|
|
160 | 193 |
if (CHECK_VALID_IM)
|
161 | 194 |
{
|
162 | 195 |
/* there is something pending input */
|
163 | |
if (strlen(input->strCodeInput) >= cloudpinyin->config.iMinimumPinyinLength)
|
|
196 |
if (FcitxInputStateGetRawInputBufferSize(input) >= cloudpinyin->config.iMinimumPinyinLength)
|
164 | 197 |
{
|
165 | 198 |
char* strToFree = NULL, *inputString;
|
166 | 199 |
strToFree = GetCurrentString(cloudpinyin);
|
|
233 | 266 |
FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
|
234 | 267 |
FcitxInstance* instance = cloudpinyin->owner;
|
235 | 268 |
int maxfd = 0;
|
236 | |
curl_multi_fdset(cloudpinyin->curlm, &instance->rfds, &instance->wfds, &instance->efds, &maxfd);
|
237 | |
if (maxfd > instance->maxfd)
|
238 | |
instance->maxfd = maxfd;
|
|
269 |
curl_multi_fdset(cloudpinyin->curlm,
|
|
270 |
FcitxInstanceGetReadFDSet(instance),
|
|
271 |
FcitxInstanceGetWriteFDSet(instance),
|
|
272 |
FcitxInstanceGetExceptFDSet(instance),
|
|
273 |
&maxfd);
|
|
274 |
if (maxfd > FcitxInstanceGetMaxFD(instance))
|
|
275 |
FcitxInstanceSetMaxFD(instance, maxfd);
|
239 | 276 |
}
|
240 | 277 |
|
241 | 278 |
void CloudPinyinProcessEvent(void* arg)
|
|
463 | 500 |
void _CloudPinyinAddCandidateWord(FcitxCloudPinyin* cloudpinyin, const char* pinyin)
|
464 | 501 |
{
|
465 | 502 |
CloudPinyinCache* cacheEntry = CloudPinyinCacheLookup(cloudpinyin, pinyin);
|
|
503 |
FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
|
466 | 504 |
|
467 | 505 |
CandidateWord candWord;
|
468 | 506 |
CloudCandWord* cloudCand = fcitx_malloc0(sizeof(CloudCandWord));
|
|
489 | 527 |
if (order < 0)
|
490 | 528 |
order = 0;
|
491 | 529 |
|
492 | |
CandidateWordInsert(cloudpinyin->owner->input.candList, &candWord, order);
|
|
530 |
CandidateWordInsert(FcitxInputStateGetCandidateList(input), &candWord, order);
|
493 | 531 |
}
|
494 | 532 |
|
495 | 533 |
void CloudPinyinFillCandidateWord(FcitxCloudPinyin* cloudpinyin, const char* pinyin)
|
496 | 534 |
{
|
497 | 535 |
CloudPinyinCache* cacheEntry = CloudPinyinCacheLookup(cloudpinyin, pinyin);
|
498 | |
FcitxInputState* input = &cloudpinyin->owner->input;
|
|
536 |
FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
|
499 | 537 |
if (cacheEntry)
|
500 | 538 |
{
|
501 | 539 |
CandidateWord* candWord;
|
502 | |
for (candWord = CandidateWordGetFirst(input->candList);
|
|
540 |
for (candWord = CandidateWordGetFirst(FcitxInputStateGetCandidateList(input));
|
503 | 541 |
candWord != NULL;
|
504 | |
candWord = CandidateWordGetNext(input->candList, candWord))
|
|
542 |
candWord = CandidateWordGetNext(FcitxInputStateGetCandidateList(input), candWord))
|
505 | 543 |
{
|
506 | 544 |
if (candWord->owner == cloudpinyin)
|
507 | 545 |
break;
|
|
525 | 563 |
{
|
526 | 564 |
FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
|
527 | 565 |
CloudCandWord* cloudCand = candWord->priv;
|
|
566 |
FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
|
528 | 567 |
if (cloudCand->filled)
|
529 | 568 |
{
|
530 | 569 |
char* string = GetCurrentString(cloudpinyin);
|
|
533 | 572 |
{
|
534 | 573 |
*py = 0;
|
535 | 574 |
|
536 | |
snprintf(GetOutputString(&cloudpinyin->owner->input), MAX_USER_INPUT, "%s%s", string, candWord->strWord);
|
|
575 |
snprintf(GetOutputString(input), MAX_USER_INPUT, "%s%s", string, candWord->strWord);
|
|
576 |
|
|
577 |
FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
|
|
578 |
FcitxModuleFunctionArg args;
|
|
579 |
args.args[0] = GetOutputString(input);
|
|
580 |
if (im)
|
|
581 |
{
|
|
582 |
if (strcmp(im->strIconName, "sunpinyin") == 0)
|
|
583 |
{
|
|
584 |
//InvokeModuleFunctionWithName(cloudpinyin->owner, "fcitx-sunpinyin", 1, args);
|
|
585 |
}
|
|
586 |
else if (strcmp(im->strIconName, "shuangpin") == 0 || strcmp(im->strIconName, "pinyin") == 0)
|
|
587 |
{
|
|
588 |
InvokeModuleFunctionWithName(cloudpinyin->owner, "fcitx-pinyin", 7, args);
|
|
589 |
}
|
|
590 |
}
|
537 | 591 |
}
|
538 | 592 |
if (string)
|
539 | 593 |
free(string);
|
|
589 | 643 |
char *GetCurrentString(FcitxCloudPinyin* cloudpinyin)
|
590 | 644 |
{
|
591 | 645 |
FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
|
592 | |
char* string = MessagesToCString(cloudpinyin->owner->input.msgPreedit);
|
|
646 |
if (!im)
|
|
647 |
return NULL;
|
|
648 |
FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
|
|
649 |
char* string = MessagesToCString(FcitxInputStateGetPreedit(input));
|
593 | 650 |
char p[MAX_USER_INPUT + 1], *pinyin, *lastpos;
|
594 | 651 |
pinyin = SplitHZAndPY(string);
|
595 | 652 |
lastpos = pinyin;
|
|
776 | 833 |
return NULL;
|
777 | 834 |
}
|
778 | 835 |
|
779 | |
|
780 | |
void CloudPinyinOnTriggerOn(void* arg)
|
|
836 |
char* BaiduParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
|
|
837 |
{
|
|
838 |
char *start = NULL, *end = NULL;
|
|
839 |
static iconv_t conv = 0;
|
|
840 |
if (conv == 0)
|
|
841 |
conv = iconv_open("utf-8", "utf-16be");
|
|
842 |
|
|
843 |
if (conv == (iconv_t)(-1))
|
|
844 |
return NULL;
|
|
845 |
if ((start = strstr(queue->str, "[[[\"")) != NULL)
|
|
846 |
{
|
|
847 |
start += strlen( "[[[\"");
|
|
848 |
if ((end = strstr(start, "\",")) != NULL)
|
|
849 |
{
|
|
850 |
size_t length = end - start;
|
|
851 |
if (length % 6 != 0 || length == 0)
|
|
852 |
return NULL;
|
|
853 |
|
|
854 |
size_t i = 0, j = 0;
|
|
855 |
char* buf = fcitx_malloc0((length / 6 + 1) * 2);
|
|
856 |
while (i < length)
|
|
857 |
{
|
|
858 |
if (start[i] == '\\' && start[i+1] == 'u')
|
|
859 |
{
|
|
860 |
if (ishex(start[i+2]) && ishex(start[i+3]) && ishex(start[i+4]) && ishex(start[i+5]))
|
|
861 |
{
|
|
862 |
buf[j++] = (tohex(start[i+2]) << 4) | tohex(start[i+3]);
|
|
863 |
buf[j++] = (tohex(start[i+4]) << 4) | tohex(start[i+5]);
|
|
864 |
}
|
|
865 |
else
|
|
866 |
break;
|
|
867 |
}
|
|
868 |
|
|
869 |
i += 6;
|
|
870 |
}
|
|
871 |
|
|
872 |
if (i != length)
|
|
873 |
{
|
|
874 |
free(buf);
|
|
875 |
return NULL;
|
|
876 |
}
|
|
877 |
buf[j++] = 0;
|
|
878 |
buf[j++] = 0;
|
|
879 |
size_t len = UTF8_MAX_LENGTH * (length / 6) * sizeof(char);
|
|
880 |
char* realstring = fcitx_malloc0(UTF8_MAX_LENGTH * (length / 6) * sizeof(char));
|
|
881 |
char* p = buf, *pp = realstring;
|
|
882 |
iconv(conv, &p, &j, &pp, &len);
|
|
883 |
|
|
884 |
free(buf);
|
|
885 |
if (utf8_check_string(realstring))
|
|
886 |
return realstring;
|
|
887 |
else
|
|
888 |
{
|
|
889 |
free(realstring);
|
|
890 |
return NULL;
|
|
891 |
}
|
|
892 |
}
|
|
893 |
}
|
|
894 |
return NULL;
|
|
895 |
}
|
|
896 |
|
|
897 |
|
|
898 |
|
|
899 |
void CloudPinyinHookForNewRequest(void* arg)
|
781 | 900 |
{
|
782 | 901 |
FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
|
783 | 902 |
if (!cloudpinyin->initialized && !cloudpinyin->isrequestkey)
|