Codebase list fcitx-cloudpinyin / 96c398d
Imported Upstream version 0.2.0 YunQiang Su 12 years ago
12 changed file(s) with 589 addition(s) and 170 deletion(s). Raw diff Collapse all Expand all
00 project(fcitx-cloudpinyin)
11 cmake_minimum_required(VERSION 2.6)
22
3 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
4 find_package(Fcitx 4.1.2 REQUIRED)
3 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
4 find_package(Fcitx 4.2.0 REQUIRED)
55 find_package(PkgConfig REQUIRED)
66 find_package(Gettext REQUIRED)
77 find_package(Libintl REQUIRED)
1313 "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
1414 IMMEDIATE @ONLY)
1515
16 SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
1716 set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-parameter -fvisibility=hidden ${CMAKE_C_FLAGS}")
1817 set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-parameter -fvisibility=hidden ${CMAKE_CXX_FLAGS}")
1918 set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")
2423
2524 pkg_check_modules(CURL "libcurl" REQUIRED)
2625
26 configure_file(config.h.in config.h)
27
2728 add_subdirectory(src)
2829 add_subdirectory(po)
33 # LIBICONV_FOUND - system has Libiconv
44 # LIBICONV_INCLUDE_DIR - Libiconv include directory
55 # LIBICONV_LIBRARIES - Libraries needed to use Libiconv
6 # LIBICONV_SECOND_ARGUMENT_IS_CONST - iconv second argument is const
67 #
78 # TODO: This will enable translations only if Gettext functionality is
89 # present in libc. Must have more robust system for release, where Gettext
1819 if(LIBICONV_INCLUDE_DIR AND LIBICONV_LIB_FOUND)
1920 set(Libiconv_FIND_QUIETLY TRUE)
2021 endif(LIBICONV_INCLUDE_DIR AND LIBICONV_LIB_FOUND)
22
23 include(CheckCCompilerFlag)
24 include(CheckCSourceCompiles)
2125
2226 find_path(LIBICONV_INCLUDE_DIR iconv.h)
2327
3640 set(LIBICONV_LIB_FOUND TRUE)
3741 endif(LIBICONV_LIBRARIES)
3842 endif (LIBICONV_LIBC_HAS_ICONV_OPEN)
43
44 if (LIBICONV_LIB_FOUND)
45 check_c_compiler_flag("-Werror" ICONV_HAVE_WERROR)
46 set (CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}")
47 if(ICONV_HAVE_WERROR)
48 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
49 endif(ICONV_HAVE_WERROR)
50 set(CMAKE_REQUIRED_INCLUDES "${LIBICONV_INCLUDE_DIR}")
51 set(CMAKE_REQUIRED_LIBRARIES "${LIBICONV_LIBRARIES}")
52 check_c_source_compiles("
53 #include <iconv.h>
54 int main(){
55 iconv_t conv = 0;
56 const char* in = 0;
57 size_t ilen = 0;
58 char* out = 0;
59 size_t olen = 0;
60 iconv(conv, &in, &ilen, &out, &olen);
61 return 0;
62 }
63 " LIBICONV_SECOND_ARGUMENT_IS_CONST )
64 set(CMAKE_REQUIRED_INCLUDES)
65 set(CMAKE_REQUIRED_LIBRARIES)
66 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}")
67 endif(LIBICONV_LIB_FOUND)
3968
4069 endif(LIBICONV_INCLUDE_DIR)
4170
4271 include(FindPackageHandleStandardArgs)
4372 find_package_handle_standard_args(Libiconv DEFAULT_MSG LIBICONV_INCLUDE_DIR LIBICONV_LIB_FOUND)
4473
45 mark_as_advanced(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARIES LIBICONV_LIBC_HAS_ICONV_OPEN LIBICONV_LIB_FOUND)
74 mark_as_advanced(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARIES LIBICONV_LIBC_HAS_ICONV_OPEN LIBICONV_LIB_FOUND)
0 #cmakedefine LIBICONV_SECOND_ARGUMENT_IS_CONST
0 set(PO_FILES zh_CN.po)
0 file(GLOB PO_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.po)
11 file(RELATIVE_PATH REL_SOURCE_ROOT ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR})
22 if ("${REL_SOURCE_ROOT}" STREQUAL "")
33 set(REL_SOURCE_ROOT ".")
0 # SOME DESCRIPTIVE TITLE.
01 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
12 # This file is distributed under the same license as the PACKAGE package.
23 #
4 # Translators:
35 # Weng Xuetian <wengxt@gmail.com>, 2011.
46 msgid ""
57 msgstr ""
6 "Project-Id-Version: \n"
8 "Project-Id-Version: fcitx\n"
79 "Report-Msgid-Bugs-To: \n"
8 "POT-Creation-Date: 2011-08-27 10:51+0800\n"
9 "PO-Revision-Date: 2011-08-27 10:52+0800\n"
10 "Last-Translator: Weng Xuetian <wengxt@gmail.com>\n"
11 "Language-Team: Chinese Simplified <kde-i18n-doc@kde.org>\n"
12 "Language: \n"
10 "POT-Creation-Date: 2011-08-27 22:05+0800\n"
11 "PO-Revision-Date: 2011-11-16 06:56+0000\n"
12 "Last-Translator: csslayer <wengxt@gmail.com>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: zh_CN\n"
1315 "MIME-Version: 1.0\n"
1416 "Content-Type: text/plain; charset=UTF-8\n"
1517 "Content-Transfer-Encoding: 8bit\n"
16 "X-Generator: Lokalize 1.2\n"
17 "Plural-Forms: nplurals=2; plural=n != 1;\n"
18 "Plural-Forms: nplurals=1; plural=0\n"
1819
1920 #: /home/saber/Develop/fcitx-cloudpinyin/build/po/../..//src/cloudpinyin.c:487
2021 msgid " (via cloud)"
3637 msgid "Cloud Pinyin Source"
3738 msgstr "云拼音来源"
3839
40 # unknown
3941 msgid "CloudPinyin"
4042 msgstr "云拼音"
4143
6264 #: unknown
6365 msgid "Sogou"
6466 msgstr "搜狗"
65
66 #~ msgid "Priority of GooglePinyin"
67 #~ msgstr "Google 拼音的优先级"
68
69 #~ msgid "Wrapper of Google Pinyin on Android"
70 #~ msgstr "Android 上的 Google 拼音的封装"
0 # SOME DESCRIPTIVE TITLE.
1 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # This file is distributed under the same license as the PACKAGE package.
3 #
4 # Translators:
5 msgid ""
6 msgstr ""
7 "Project-Id-Version: fcitx\n"
8 "Report-Msgid-Bugs-To: \n"
9 "POT-Creation-Date: 2011-08-27 22:05+0800\n"
10 "PO-Revision-Date: 2011-11-16 06:52+0000\n"
11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Language-Team: Chinese (Taiwan) (http://www.transifex.net/projects/p/fcitx/"
13 "team/zh_TW/)\n"
14 "Language: zh_TW\n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=1; plural=0\n"
19
20 #: /home/saber/Develop/fcitx-cloudpinyin/build/po/../..//src/cloudpinyin.c:487
21 msgid " (via cloud)"
22 msgstr ""
23
24 #: /home/saber/Develop/fcitx-cloudpinyin/build/po/tmp/fcitx-cloudpinyin.conf.in.h:1
25 msgid "Add Cloud Pinyin Support to Pinyin Input Method"
26 msgstr ""
27
28 #: /home/saber/Develop/fcitx-cloudpinyin/build/po/tmp/fcitx-cloudpinyin.conf.in.h:2
29 msgid "Cloud Pinyin"
30 msgstr ""
31
32 #: /home/saber/Develop/fcitx-cloudpinyin/src/fcitx-cloudpinyin.desc:4
33 msgid "Cloud Pinyin Candidate Word Order"
34 msgstr ""
35
36 #: /home/saber/Develop/fcitx-cloudpinyin/src/fcitx-cloudpinyin.desc:24
37 msgid "Cloud Pinyin Source"
38 msgstr ""
39
40 # unknown
41 msgid "CloudPinyin"
42 msgstr ""
43
44 #: /home/saber/Develop/fcitx-cloudpinyin/src/fcitx-cloudpinyin.desc:19
45 msgid "Don't Show the 'via cloud' hint"
46 msgstr ""
47
48 #: unknown
49 msgid "Google"
50 msgstr ""
51
52 #: /home/saber/Develop/fcitx-cloudpinyin/src/fcitx-cloudpinyin.desc:9
53 msgid "Minimum Length of Pinyin To Trigger Cloud Pinyin"
54 msgstr ""
55
56 #: /home/saber/Develop/fcitx-cloudpinyin/src/fcitx-cloudpinyin.desc:14
57 msgid "Only use origin Pinyin to query the result"
58 msgstr ""
59
60 #: unknown
61 msgid "QQ"
62 msgstr ""
63
64 #: unknown
65 msgid "Sogou"
66 msgstr ""
00 include_directories(
1 ${PROJECT_BINARY_DIR}
12 ${CMAKE_CURRENT_SOURCE_DIR}
23 ${CURL_INCLUDE_DIRS}
34 ${FCITX4_FCITX_INCLUDE_DIRS}
1314 set(FCITX_CLOUDPINYIN_SRCS
1415 cloudpinyin.c
1516 cloudpinyinconifg.c
17 fetch.c
1618 )
1719
1820 fcitx_add_addon(fcitx-cloudpinyin ${FCITX_CLOUDPINYIN_SRCS})
00 /***************************************************************************
1 * Copyright (C) 2011~2011 by CSSlayer *
1 * Copyright (C) 2011~2012 by CSSlayer *
22 * wengxt@gmail.com *
33 * *
44 * This program is free software; you can redistribute it and/or modify *
1414 * You should have received a copy of the GNU General Public License *
1515 * along with this program; if not, write to the *
1616 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
1818 ***************************************************************************/
19
20 #include <errno.h>
21 #include <iconv.h>
22 #include <unistd.h>
23
24 #include <curl/curl.h>
25 #include <fcntl.h>
1926
2027 #include <fcitx/fcitx.h>
2128 #include <fcitx/module.h>
2229 #include <fcitx/instance.h>
2330 #include <fcitx/hook.h>
24 #include <curl/curl.h>
25 #include "cloudpinyin.h"
2631 #include <fcitx-utils/log.h>
2732 #include <fcitx/candidate.h>
2833 #include <fcitx-config/xdg.h>
2934 #include <fcitx/module/pinyin/pydef.h>
30 #include <errno.h>
31 #include <iconv.h>
35
36 #include "config.h"
37 #include "cloudpinyin.h"
38 #include "fetch.h"
3239
3340 #define CHECK_VALID_IM (im && \
3441 (strcmp(im->uniqueName, "pinyin") == 0 || \
42 strcmp(im->uniqueName, "pinyin-libpinyin") == 0 || \
43 strcmp(im->uniqueName, "shuangpin-libpinyin") == 0 || \
3544 strcmp(im->uniqueName, "googlepinyin") == 0 || \
3645 strcmp(im->uniqueName, "sunpinyin") == 0 || \
3746 strcmp(im->uniqueName, "shuangpin") == 0))
47
48 #define CLOUDPINYIN_CHECK_PAGE_NUMBER 3
3849
3950 #define LOGLEVEL DEBUG
51
52 #ifdef LIBICONV_SECOND_ARGUMENT_IS_CONST
53 typedef const char* IconvStr;
54 #else
55 typedef char* IconvStr;
56 #endif
4057
4158 typedef struct _CloudCandWord {
4259 boolean filled;
5774 static void CloudPinyinAddCandidateWord(void* arg);
5875 static void CloudPinyinRequestKey(FcitxCloudPinyin* cloudpinyin);
5976 static void CloudPinyinAddInputRequest(FcitxCloudPinyin* cloudpinyin, const char* strPinyin);
60 static void CloudPinyinHandleReqest(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
77 static void CloudPinyinHandleRequest(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
6178 static size_t CloudPinyinWriteFunction(char *ptr, size_t size, size_t nmemb, void *userdata);
6279 static CloudPinyinCache* CloudPinyinCacheLookup(FcitxCloudPinyin* cloudpinyin, const char* pinyin);
6380 static CloudPinyinCache* CloudPinyinAddToCache(FcitxCloudPinyin* cloudpinyin, const char* pinyin, char* string);
64 static INPUT_RETURN_VALUE CloudPinyinGetCandWord(void* arg, CandidateWord* candWord);
81 static INPUT_RETURN_VALUE CloudPinyinGetCandWord(void* arg, FcitxCandidateWord* candWord);
6582 static void _CloudPinyinAddCandidateWord(FcitxCloudPinyin* cloudpinyin, const char* pinyin);
6683 static void CloudPinyinFillCandidateWord(FcitxCloudPinyin* cloudpinyin, const char* pinyin);
6784 static boolean LoadCloudPinyinConfig(FcitxCloudPinyinConfig* fs);
6885 static void SaveCloudPinyinConfig(FcitxCloudPinyinConfig* fs);
6986 static char *GetCurrentString(FcitxCloudPinyin* cloudpinyin);
7087 static char* SplitHZAndPY(char* string);
71 void CloudPinyinHookForNewRequest(void* arg);
88 static void CloudPinyinHookForNewRequest(void* arg);
89 static CURL* CloudPinyinGetFreeCurlHandle(FcitxCloudPinyin* cloudpinyin);
90 static void CloudPinyinReleaseCurlHandle(FcitxCloudPinyin* cloudpinyin, CURL* curl);
7291
7392 void SogouParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
7493 char* SogouParsePinyin(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue);
140159
141160 void* CloudPinyinCreate(FcitxInstance* instance)
142161 {
143 FcitxCloudPinyin* cloudpinyin = fcitx_malloc0(sizeof(FcitxCloudPinyin));
162 FcitxCloudPinyin* cloudpinyin = fcitx_utils_malloc0(sizeof(FcitxCloudPinyin));
144163 bindtextdomain("fcitx-cloudpinyin", LOCALEDIR);
145164 cloudpinyin->owner = instance;
165 int pipe1[2];
166 int pipe2[2];
146167
147168 if (!LoadCloudPinyinConfig(&cloudpinyin->config))
148169 {
150171 return NULL;
151172 }
152173
153 cloudpinyin->curlm = curl_multi_init();
154 if (cloudpinyin->curlm == NULL)
174 if (pipe(pipe1) < 0)
155175 {
156176 free(cloudpinyin);
157177 return NULL;
158178 }
159179
160 curl_multi_setopt(cloudpinyin->curlm, CURLMOPT_MAXCONNECTS, 10l);
161
162 cloudpinyin->queue = fcitx_malloc0(sizeof(CurlQueue));
180 if (pipe(pipe2) < 0) {
181 close(pipe1[0]);
182 close(pipe1[1]);
183 free(cloudpinyin);
184 return NULL;
185 }
186
187 cloudpinyin->pipeRecv = pipe1[0];
188 cloudpinyin->pipeNotify = pipe2[1];
189
190 fcntl(pipe1[0], F_SETFL, O_NONBLOCK);
191 fcntl(pipe1[1], F_SETFL, O_NONBLOCK);
192 fcntl(pipe2[0], F_SETFL, O_NONBLOCK);
193 fcntl(pipe2[1], F_SETFL, O_NONBLOCK);
194
195 cloudpinyin->pendingQueue = fcitx_utils_malloc0(sizeof(CurlQueue));
196 cloudpinyin->finishQueue = fcitx_utils_malloc0(sizeof(CurlQueue));
197 pthread_mutex_init(&cloudpinyin->pendingQueueLock, NULL);
198 pthread_mutex_init(&cloudpinyin->finishQueueLock, NULL);
199
200 FcitxFetchThread* fetch = fcitx_utils_malloc0(sizeof(FcitxFetchThread));
201 cloudpinyin->fetch = fetch;
202 fetch->owner = cloudpinyin;
203 fetch->pipeRecv = pipe2[0];
204 fetch->pipeNotify = pipe1[1];
205 fetch->pendingQueueLock = &cloudpinyin->pendingQueueLock;
206 fetch->finishQueueLock = &cloudpinyin->finishQueueLock;
207 fetch->queue = fcitx_utils_malloc0(sizeof(CurlQueue));
163208
164209 FcitxIMEventHook hook;
165210 hook.arg = cloudpinyin;
166211 hook.func = CloudPinyinAddCandidateWord;
167212
168 RegisterUpdateCandidateWordHook(instance, hook);
213 FcitxInstanceRegisterUpdateCandidateWordHook(instance, hook);
169214
170215 hook.arg = cloudpinyin;
171216 hook.func = CloudPinyinHookForNewRequest;
172217
173 RegisterResetInputHook(instance, hook);
174 RegisterInputFocusHook(instance, hook);
175 RegisterInputUnFocusHook(instance, hook);
176 RegisterTriggerOnHook(instance, hook);
218 FcitxInstanceRegisterResetInputHook(instance, hook);
219 FcitxInstanceRegisterInputFocusHook(instance, hook);
220 FcitxInstanceRegisterInputUnFocusHook(instance, hook);
221 FcitxInstanceRegisterTriggerOnHook(instance, hook);
222
223 pthread_create(&cloudpinyin->pid, NULL, FetchThread, fetch);
177224
178225 CloudPinyinRequestKey(cloudpinyin);
179226
180227 return cloudpinyin;
181228 }
182229
230 CURL* CloudPinyinGetFreeCurlHandle(FcitxCloudPinyin* cloudpinyin)
231 {
232 int i = 0;
233 for (i = 0; i < MAX_HANDLE; i ++) {
234 if (!cloudpinyin->freeList[i].used) {
235 cloudpinyin->freeList[i].used = true;
236 if (cloudpinyin->freeList[i].curl == NULL) {
237 cloudpinyin->freeList[i].curl = curl_easy_init();
238 }
239 return cloudpinyin->freeList[i].curl;
240 }
241 }
242 /* return a stalled handle */
243 return curl_easy_init();
244 }
245
246 void CloudPinyinReleaseCurlHandle(FcitxCloudPinyin* cloudpinyin, CURL* curl)
247 {
248 if (curl == NULL)
249 return;
250 int i = 0;
251 for (i = 0; i < MAX_HANDLE; i ++) {
252 if (cloudpinyin->freeList[i].curl == curl) {
253 cloudpinyin->freeList[i].used = false;
254 return;
255 }
256 }
257 /* if handle is stalled, free it */
258 curl_easy_cleanup(curl);
259 }
260
261
183262 void CloudPinyinAddCandidateWord(void* arg)
184263 {
185264 FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
186 FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
265 FcitxIM* im = FcitxInstanceGetCurrentIM(cloudpinyin->owner);
187266 FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
188267
189268 if (cloudpinyin->initialized == false)
217296
218297 void CloudPinyinRequestKey(FcitxCloudPinyin* cloudpinyin)
219298 {
220 int still_running;
221299 if (cloudpinyin->isrequestkey)
222300 return;
223301
230308 return;
231309 }
232310
233 CURL* curl = curl_easy_init();
311 CURL* curl = CloudPinyinGetFreeCurlHandle(cloudpinyin);
234312 if (!curl)
235313 return;
236 CurlQueue* queue = fcitx_malloc0(sizeof(CurlQueue)), *head = cloudpinyin->queue;
314 CurlQueue* queue = fcitx_utils_malloc0(sizeof(CurlQueue)), *head = cloudpinyin->pendingQueue;
237315 queue->curl = curl;
238316 queue->next = NULL;
239
240 while (head->next != NULL)
241 head = head->next;
242 head->next = queue;
243317 queue->type = RequestKey;
244318 queue->source = cloudpinyin->config.source;
245319
247321 curl_easy_setopt(curl, CURLOPT_WRITEDATA, queue);
248322 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CloudPinyinWriteFunction);
249323 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20l);
250 curl_multi_add_handle(cloudpinyin->curlm, curl);
251 CURLMcode mcode;
252 do {
253 mcode = curl_multi_perform(cloudpinyin->curlm, &still_running);
254 } while (mcode == CURLM_CALL_MULTI_PERFORM);
255
256 if (mcode != CURLM_OK)
257 {
258 FcitxLog(ERROR, "curl error");
259 }
324 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1l);
325
326 /* push into pending queue */
327 pthread_mutex_lock(&cloudpinyin->pendingQueueLock);
328 while (head->next != NULL)
329 head = head->next;
330 head->next = queue;
331 pthread_mutex_unlock(&cloudpinyin->pendingQueueLock);
332
333 char c = 0;
334 write(cloudpinyin->pipeNotify, &c, sizeof(char));
260335 }
261336
262337
265340 {
266341 FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
267342 FcitxInstance* instance = cloudpinyin->owner;
268 int maxfd = 0;
269 curl_multi_fdset(cloudpinyin->curlm,
270 FcitxInstanceGetReadFDSet(instance),
271 FcitxInstanceGetWriteFDSet(instance),
272 FcitxInstanceGetExceptFDSet(instance),
273 &maxfd);
343 int maxfd = cloudpinyin->pipeRecv;
344 FD_SET(maxfd, FcitxInstanceGetReadFDSet(instance));
274345 if (maxfd > FcitxInstanceGetMaxFD(instance))
275346 FcitxInstanceSetMaxFD(instance, maxfd);
276347 }
278349 void CloudPinyinProcessEvent(void* arg)
279350 {
280351 FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
281 CURLMcode mcode;
282 int still_running;
283 do {
284 mcode = curl_multi_perform(cloudpinyin->curlm, &still_running);
285 } while (mcode == CURLM_CALL_MULTI_PERFORM);
286
287 int num_messages = 0;
288 CURLMsg* curl_message = curl_multi_info_read(cloudpinyin->curlm, &num_messages);;
289 CurlQueue* queue, *previous;
290
291 while (curl_message != NULL) {
292 if (curl_message->msg == CURLMSG_DONE) {
293 int curl_result = curl_message->data.result;
294 previous = cloudpinyin->queue;
295 queue = cloudpinyin->queue->next;
296 while (queue != NULL &&
297 queue->curl != curl_message->easy_handle)
298 {
299 previous = queue;
300 queue = queue->next;
301 }
302 if (queue != NULL) {
303 curl_multi_remove_handle(cloudpinyin->curlm, queue->curl);
304 previous->next = queue->next;
305 queue->curl_result = curl_result;
306 curl_easy_getinfo(queue->curl, CURLINFO_HTTP_CODE, &queue->http_code);
307 CloudPinyinHandleReqest(cloudpinyin, queue);
308 }
309 } else {
310 FcitxLog(ERROR, "Unknown CURL message received: %d\n",
311 (int)curl_message->msg);
312 }
313 curl_message = curl_multi_info_read(cloudpinyin->curlm, &num_messages);
314 }
352 char c;
353 while (read(cloudpinyin->pipeRecv, &c, sizeof(char)) > 0);
354 pthread_mutex_lock(&cloudpinyin->finishQueueLock);
355 CurlQueue* queue;
356 queue = cloudpinyin->finishQueue;
357 while (queue->next != NULL)
358 {
359 CurlQueue* pivot = queue->next;
360 queue->next = queue->next->next;
361 CloudPinyinHandleRequest(cloudpinyin, pivot);
362 }
363 pthread_mutex_unlock(&cloudpinyin->finishQueueLock);
315364 }
316365
317366 void CloudPinyinDestroy(void* arg)
333382
334383 void CloudPinyinAddInputRequest(FcitxCloudPinyin* cloudpinyin, const char* strPinyin)
335384 {
336 int still_running;
337 CURL* curl = curl_easy_init();
385 CURL* curl = CloudPinyinGetFreeCurlHandle(cloudpinyin);
338386 if (!curl)
339387 return;
340 CurlQueue* queue = fcitx_malloc0(sizeof(CurlQueue)), *head = cloudpinyin->queue;
388 CurlQueue* queue = fcitx_utils_malloc0(sizeof(CurlQueue)), *head = cloudpinyin->pendingQueue;
341389 queue->curl = curl;
342390 queue->next = NULL;
343
344 while (head->next != NULL)
345 head = head->next;
346 head->next = queue;
347391 queue->type = RequestPinyin;
348392 queue->pinyin = strdup(strPinyin);
349393 queue->source = cloudpinyin->config.source;
353397 asprintf(&url, engine[cloudpinyin->config.source].RequestPinyin, cloudpinyin->key, urlstring);
354398 else
355399 asprintf(&url, engine[cloudpinyin->config.source].RequestPinyin, urlstring);
356 free(urlstring);
400 curl_free(urlstring);
357401
358402 curl_easy_setopt(curl, CURLOPT_URL, url);
359403 curl_easy_setopt(curl, CURLOPT_WRITEDATA, queue);
360404 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CloudPinyinWriteFunction);
361 curl_multi_add_handle(cloudpinyin->curlm, curl);
362405
363406 free(url);
364 CURLMcode mcode;
365 do {
366 mcode = curl_multi_perform(cloudpinyin->curlm, &still_running);
367 } while (mcode == CURLM_CALL_MULTI_PERFORM);
368
369 if (mcode != CURLM_OK)
370 {
371 FcitxLog(ERROR, "curl error");
372 }
373 }
374
375 void CloudPinyinHandleReqest(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
407
408 /* push into pending queue */
409 pthread_mutex_lock(&cloudpinyin->pendingQueueLock);
410 while (head->next != NULL)
411 head = head->next;
412 head->next = queue;
413 pthread_mutex_unlock(&cloudpinyin->pendingQueueLock);
414
415 char c = 0;
416 write(cloudpinyin->pipeNotify, &c, sizeof(char));
417 }
418
419 void CloudPinyinHandleRequest(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
376420 {
377421 if (queue->type == RequestKey)
378422 {
397441 if (cacheEntry == NULL)
398442 cacheEntry = CloudPinyinAddToCache(cloudpinyin, queue->pinyin, realstring);
399443
400 FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
444 FcitxIM* im = FcitxInstanceGetCurrentIM(cloudpinyin->owner);
401445
402446 char* strToFree = NULL, *inputString;
403447 strToFree = GetCurrentString(cloudpinyin);
431475 }
432476 }
433477 }
434 curl_easy_cleanup(queue->curl);
478 CloudPinyinReleaseCurlHandle(cloudpinyin, queue->curl);
435479 if (queue->str)
436480 free(queue->str);
437481 if (queue->pinyin)
461505 if (queue->str != NULL)
462506 queue->str = realloc(queue->str, queue->size + realsize + 1);
463507 else
464 queue->str = fcitx_malloc0(realsize + 1);
508 queue->str = fcitx_utils_malloc0(realsize + 1);
465509
466510 if (queue->str != NULL) {
467511 memcpy(&(queue->str[queue->size]), ptr, realsize);
480524
481525 CloudPinyinCache* CloudPinyinAddToCache(FcitxCloudPinyin* cloudpinyin, const char* pinyin, char* string)
482526 {
483 CloudPinyinCache* cacheEntry = fcitx_malloc0(sizeof(CloudPinyinCache));
527 CloudPinyinCache* cacheEntry = fcitx_utils_malloc0(sizeof(CloudPinyinCache));
484528 cacheEntry->pinyin = strdup(pinyin);
485529 cacheEntry->str = strdup(string);
486530 HASH_ADD_KEYPTR(hh, cloudpinyin->cache, cacheEntry->pinyin, strlen(cacheEntry->pinyin), cacheEntry);
501545 {
502546 CloudPinyinCache* cacheEntry = CloudPinyinCacheLookup(cloudpinyin, pinyin);
503547 FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
504
505 CandidateWord candWord;
506 CloudCandWord* cloudCand = fcitx_malloc0(sizeof(CloudCandWord));
548 struct _FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
549
550 if (cacheEntry) {
551 FcitxCandidateWord* cand;
552 /* only check the first three page */
553 int size = FcitxCandidateWordGetPageSize(candList) * CLOUDPINYIN_CHECK_PAGE_NUMBER;
554 int i = 0;
555 for (cand = FcitxCandidateWordGetFirst(FcitxInputStateGetCandidateList(input));
556 cand != NULL;
557 cand = FcitxCandidateWordGetNext(FcitxInputStateGetCandidateList(input), cand))
558 {
559 if (strcmp(cand->strWord, cacheEntry->str) == 0)
560 return;
561 i ++;
562 if (i >= size)
563 break;
564 }
565 }
566
567 FcitxCandidateWord candWord;
568 CloudCandWord* cloudCand = fcitx_utils_malloc0(sizeof(CloudCandWord));
507569 if (cacheEntry)
508570 {
509571 cloudCand->filled = true;
518580 candWord.callback = CloudPinyinGetCandWord;
519581 candWord.owner = cloudpinyin;
520582 candWord.priv = cloudCand;
583 candWord.wordType = MSG_TIPS;
521584 if (cloudpinyin->config.bDontShowSource)
522585 candWord.strExtra = NULL;
523 else
586 else {
524587 candWord.strExtra = strdup(_(" (via cloud)"));
588 candWord.extraType = MSG_TIPS;
589 }
525590
526591 int order = cloudpinyin->config.iCandidateOrder - 1;
527592 if (order < 0)
528593 order = 0;
529594
530 CandidateWordInsert(FcitxInputStateGetCandidateList(input), &candWord, order);
595 FcitxCandidateWordInsert(candList, &candWord, order);
531596 }
532597
533598 void CloudPinyinFillCandidateWord(FcitxCloudPinyin* cloudpinyin, const char* pinyin)
534599 {
535600 CloudPinyinCache* cacheEntry = CloudPinyinCacheLookup(cloudpinyin, pinyin);
536601 FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
602 struct _FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
537603 if (cacheEntry)
538604 {
539 CandidateWord* candWord;
540 for (candWord = CandidateWordGetFirst(FcitxInputStateGetCandidateList(input));
541 candWord != NULL;
542 candWord = CandidateWordGetNext(FcitxInputStateGetCandidateList(input), candWord))
605 FcitxCandidateWord* candWord;
606 for (candWord = FcitxCandidateWordGetFirst(candList);
607 candWord != NULL;
608 candWord = FcitxCandidateWordGetNext(candList, candWord))
543609 {
544610 if (candWord->owner == cloudpinyin)
545611 break;
546612 }
547613
614 if (candWord == NULL)
615 return;
616
617 CloudCandWord* cloudCand = candWord->priv;
618 if (cloudCand->filled)
619 return;
620
621 FcitxCandidateWord* cand;
622 int i = 0;
623 int size = FcitxCandidateWordGetPageSize(candList) * CLOUDPINYIN_CHECK_PAGE_NUMBER;
624 for (cand = FcitxCandidateWordGetFirst(candList);
625 cand != NULL;
626 cand = FcitxCandidateWordGetNext(candList, cand))
627 {
628 if (strcmp(cand->strWord, cacheEntry->str) == 0) {
629 FcitxCandidateWordRemove(candList, candWord);
630 FcitxUIUpdateInputWindow(cloudpinyin->owner);
631 candWord = NULL;
632 break;
633 }
634 i ++;
635 if (i >= size)
636 break;
637 }
638
548639 if (candWord)
549640 {
550 CloudCandWord* cloudCand = candWord->priv;
551641 if (cloudCand->filled == false)
552642 {
553643 cloudCand->filled = true;
554644 free(candWord->strWord);
555645 candWord->strWord = strdup(cacheEntry->str);
556 UpdateInputWindow(cloudpinyin->owner);
646 FcitxUIUpdateInputWindow(cloudpinyin->owner);
557647 }
558648 }
559649 }
560650 }
561651
562 INPUT_RETURN_VALUE CloudPinyinGetCandWord(void* arg, CandidateWord* candWord)
652 INPUT_RETURN_VALUE CloudPinyinGetCandWord(void* arg, FcitxCandidateWord* candWord)
563653 {
564654 FcitxCloudPinyin* cloudpinyin = (FcitxCloudPinyin*) arg;
565655 CloudCandWord* cloudCand = candWord->priv;
572662 {
573663 *py = 0;
574664
575 snprintf(GetOutputString(input), MAX_USER_INPUT, "%s%s", string, candWord->strWord);
576
577 FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
665 snprintf(FcitxInputStateGetOutputString(input), MAX_USER_INPUT, "%s%s", string, candWord->strWord);
666
667 FcitxIM* im = FcitxInstanceGetCurrentIM(cloudpinyin->owner);
578668 FcitxModuleFunctionArg args;
579 args.args[0] = GetOutputString(input);
669 args.args[0] = FcitxInputStateGetOutputString(input);
580670 if (im)
581671 {
582 if (strcmp(im->strIconName, "sunpinyin") == 0)
672 if (strcmp(im->uniqueName, "sunpinyin") == 0)
583673 {
584674 //InvokeModuleFunctionWithName(cloudpinyin->owner, "fcitx-sunpinyin", 1, args);
585675 }
586 else if (strcmp(im->strIconName, "shuangpin") == 0 || strcmp(im->strIconName, "pinyin") == 0)
676 else if (strcmp(im->uniqueName, "shuangpin") == 0 || strcmp(im->uniqueName, "pinyin") == 0)
587677 {
588 InvokeModuleFunctionWithName(cloudpinyin->owner, "fcitx-pinyin", 7, args);
678 FcitxModuleInvokeFunctionByName(cloudpinyin->owner, "fcitx-pinyin", 7, args);
589679 }
590680 }
591681 }
605695 **/
606696 boolean LoadCloudPinyinConfig(FcitxCloudPinyinConfig* fs)
607697 {
608 ConfigFileDesc *configDesc = GetCloudPinyinConfigDesc();
698 FcitxConfigFileDesc *configDesc = GetCloudPinyinConfigDesc();
609699 if (configDesc == NULL)
610700 return false;
611701
612 FILE *fp = GetXDGFileUserWithPrefix("conf", "fcitx-cloudpinyin.config", "rt", NULL);
702 FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-cloudpinyin.config", "rt", NULL);
613703
614704 if (!fp)
615705 {
616706 if (errno == ENOENT)
617707 SaveCloudPinyinConfig(fs);
618708 }
619 ConfigFile *cfile = ParseConfigFileFp(fp, configDesc);
709 FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc);
620710 FcitxCloudPinyinConfigConfigBind(fs, cfile, configDesc);
621 ConfigBindSync(&fs->config);
711 FcitxConfigBindSync(&fs->config);
622712
623713 if (fp)
624714 fclose(fp);
633723 **/
634724 void SaveCloudPinyinConfig(FcitxCloudPinyinConfig* fs)
635725 {
636 ConfigFileDesc *configDesc = GetCloudPinyinConfigDesc();
637 FILE *fp = GetXDGFileUserWithPrefix("conf", "fcitx-cloudpinyin.config", "wt", NULL);
638 SaveConfigFileFp(fp, &fs->config, configDesc);
726 FcitxConfigFileDesc *configDesc = GetCloudPinyinConfigDesc();
727 FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-cloudpinyin.config", "wt", NULL);
728 FcitxConfigSaveConfigFileFp(fp, &fs->config, configDesc);
639729 if (fp)
640730 fclose(fp);
641731 }
642732
643733 char *GetCurrentString(FcitxCloudPinyin* cloudpinyin)
644734 {
645 FcitxIM* im = GetCurrentIM(cloudpinyin->owner);
735 FcitxIM* im = FcitxInstanceGetCurrentIM(cloudpinyin->owner);
646736 if (!im)
647737 return NULL;
648738 FcitxInputState* input = FcitxInstanceGetInputState(cloudpinyin->owner);
649 char* string = MessagesToCString(FcitxInputStateGetPreedit(input));
739 char* string = FcitxUIMessagesToCString(FcitxInputStateGetPreedit(input));
650740 char p[MAX_USER_INPUT + 1], *pinyin, *lastpos;
651741 pinyin = SplitHZAndPY(string);
652742 lastpos = pinyin;
669759 FcitxModuleFunctionArg arg;
670760 arg.args[0] = lastpos;
671761 boolean isshuangpin = false;
672 if (strcmp(im->strIconName, "sunpinyin") == 0)
762 if (strcmp(im->uniqueName, "sunpinyin") == 0)
673763 {
674764 boolean issp = false;
675765 arg.args[1] = &issp;
676 result = InvokeModuleFunctionWithName(cloudpinyin->owner, "fcitx-sunpinyin", 0, arg);
766 result = FcitxModuleInvokeFunctionByName(cloudpinyin->owner, "fcitx-sunpinyin", 0, arg);
677767 isshuangpin = issp;
678768 }
679 else if (strcmp(im->strIconName, "shuangpin") == 0)
769 else if (strcmp(im->uniqueName, "shuangpin") == 0)
680770 {
681771 isshuangpin = true;
682772 result = InvokeFunction(cloudpinyin->owner, FCITX_PINYIN, SP2QP, arg);
737827 char* p;
738828 int chr;
739829
740 p = utf8_get_char(s, &chr);
830 p = fcitx_utf8_get_char(s, &chr);
741831 if (p - s == 1)
742832 break;
743833 s = p;
748838
749839 void SogouParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
750840 {
751 char* str = fcitx_trim(queue->str);
841 char* str = fcitx_utils_trim(queue->str);
752842 const char* ime_patch_key = "ime_patch_key = \"";
753843 size_t len = strlen(str);
754844 if (len == SOGOU_KEY_LENGTH + strlen(ime_patch_key) + 1
774864 {
775865 size_t length = end - start;
776866 int conv_length;
777 char *realstring = curl_easy_unescape(queue->curl, start, length, &conv_length);
867 char *unescapedstring = curl_easy_unescape(queue->curl, start, length, &conv_length);
868 char *realstring = strdup(unescapedstring);
869 curl_free(unescapedstring);
778870 return realstring;
779871 }
780872 }
783875
784876 void QQParseKey(FcitxCloudPinyin* cloudpinyin, CurlQueue* queue)
785877 {
786 char* str = fcitx_trim(queue->str);
878 char* str = fcitx_utils_trim(queue->str);
787879 const char* ime_patch_key = "{\"key\":\"";
788880 if (strncmp(str, ime_patch_key, strlen(ime_patch_key)) == 0)
789881 {
806898 if ((end = strstr(start, "\"")) != NULL)
807899 {
808900 size_t length = end - start;
809 char *realstring = fcitx_malloc0(sizeof(char) * (length + 1));
901 char *realstring = fcitx_utils_malloc0(sizeof(char) * (length + 1));
810902 strncpy(realstring, start, length);
811903 realstring[length] = '\0';
812904 return realstring;
824916 if ((end = strstr(start, "\"")) != NULL)
825917 {
826918 size_t length = end - start;
827 char *realstring = fcitx_malloc0(sizeof(char) * (length + 1));
919 char *realstring = fcitx_utils_malloc0(sizeof(char) * (length + 1));
828920 strncpy(realstring, start, length);
829921 realstring[length] = '\0';
830922 return realstring;
852944 return NULL;
853945
854946 size_t i = 0, j = 0;
855 char* buf = fcitx_malloc0((length / 6 + 1) * 2);
947 char* buf = fcitx_utils_malloc0((length / 6 + 1) * 2);
856948 while (i < length)
857949 {
858950 if (start[i] == '\\' && start[i+1] == 'u')
877969 buf[j++] = 0;
878970 buf[j++] = 0;
879971 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;
972 char* realstring = fcitx_utils_malloc0(UTF8_MAX_LENGTH * (length / 6) * sizeof(char));
973 IconvStr p = buf; char *pp = realstring;
882974 iconv(conv, &p, &j, &pp, &len);
883975
884976 free(buf);
885 if (utf8_check_string(realstring))
977 if (fcitx_utf8_check_string(realstring))
886978 return realstring;
887979 else
888980 {
00 /***************************************************************************
1 * Copyright (C) 2011~2011 by CSSlayer *
1 * Copyright (C) 2011~2012 by CSSlayer *
22 * wengxt@gmail.com *
33 * *
44 * This program is free software; you can redistribute it and/or modify *
1414 * You should have received a copy of the GNU General Public License *
1515 * along with this program; if not, write to the *
1616 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
1818 ***************************************************************************/
1919
2020 #ifndef FCITX_CLOUDPINYIN_H
2727 #define QQ_KEY_LENGTH 32
2828 #define MAX_CACHE_ENTRY 2048
2929 #define MAX_ERROR 10
30 #define MAX_HANDLE 10l
3031
3132 #define _(x) dgettext("fcitx-cloudpinyin", (x))
3233
4546 RequestKey,
4647 RequestPinyin
4748 } CloudPinyinRequestType ;
49
50 typedef struct _CurlFreeListItem
51 {
52 boolean used;
53 CURL* curl;
54 } CurlFreeListItem;
4855
4956 typedef struct _CurlQueue
5057 {
6875
6976 typedef struct _FcitxCloudPinyinConfig
7077 {
71 GenericConfig config;
78 FcitxGenericConfig config;
7279 int iCandidateOrder;
7380 int iMinimumPinyinLength;
7481 boolean bDontShowSource;
7986 {
8087 struct _FcitxInstance* owner;
8188 FcitxCloudPinyinConfig config;
82 CURLM* curlm;
83 CurlQueue* queue;
89 CurlQueue* pendingQueue;
90 CurlQueue* finishQueue;
91
92 pthread_mutex_t pendingQueueLock;
93 pthread_mutex_t finishQueueLock;
94
95 int pipeNotify;
96 int pipeRecv;
8497 int errorcount;
8598 char key[SOGOU_KEY_LENGTH + 1];
8699 boolean initialized;
87100 CloudPinyinCache* cache;
88101 boolean isrequestkey;
102 struct _FcitxFetchThread* fetch;
103
104 CurlFreeListItem freeList[MAX_HANDLE];
105
106 pthread_t pid;
89107 } FcitxCloudPinyin;
90108
91109 CONFIG_BINDING_DECLARE(FcitxCloudPinyinConfig);
00 /***************************************************************************
1 * Copyright (C) 2010~2010 by CSSlayer *
1 * Copyright (C) 2011~2012 by CSSlayer *
22 * wengxt@gmail.com *
33 * *
44 * This program is free software; you can redistribute it and/or modify *
1414 * You should have received a copy of the GNU General Public License *
1515 * along with this program; if not, write to the *
1616 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
1818 ***************************************************************************/
1919
2020 #include "cloudpinyin.h"
0 /***************************************************************************
1 * Copyright (C) 2012~2012 by CSSlayer *
2 * wengxt@gmail.com *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19
20 #include <sys/select.h>
21 #include <time.h>
22 #include <unistd.h>
23 #include <pthread.h>
24
25 #include <curl/curl.h>
26
27 #include <fcitx-config/fcitx-config.h>
28
29 #include "cloudpinyin.h"
30 #include "fetch.h"
31
32 static void FetchProcessEvent(FcitxFetchThread* fetch);
33 static void FetchProcessPendingRequest(FcitxFetchThread* fetch);
34 static void FetchFinish(FcitxFetchThread* fetch, CurlQueue* queue);
35
36 void* FetchThread(void* arg)
37 {
38 FcitxFetchThread* fetch = (FcitxFetchThread*) arg;
39 fetch->curlm = curl_multi_init();
40 if (fetch->curlm == NULL)
41 return NULL;
42 curl_multi_setopt(fetch->curlm, CURLMOPT_MAXCONNECTS, MAX_HANDLE);
43
44 while (true) {
45
46 char c;
47 while (read(fetch->pipeRecv, &c, sizeof(char)) > 0);
48
49 FetchProcessPendingRequest(fetch);
50 FetchProcessEvent(fetch);
51
52 FD_ZERO(&fetch->rfds);
53 FD_ZERO(&fetch->wfds);
54 FD_ZERO(&fetch->efds);
55
56 FD_SET(fetch->pipeRecv, &fetch->rfds);
57 fetch->maxfd = fetch->pipeRecv;
58
59 int maxfd;
60 curl_multi_fdset(fetch->curlm,
61 &fetch->rfds,
62 &fetch->wfds,
63 &fetch->efds,
64 &maxfd);
65
66 if (maxfd > fetch->maxfd)
67 fetch->maxfd = maxfd;
68
69 struct timeval t, *pt;
70 t.tv_sec = 1;
71 t.tv_usec = 0;
72
73 /* if we have something to fetch, but maxfd is -1 then we give select a time out */
74 if (maxfd < 0 && fetch->queue->next != NULL)
75 pt = &t;
76 else
77 pt = NULL;
78
79 select(fetch->maxfd + 1, &fetch->rfds, &fetch->wfds, &fetch->efds, pt);
80 }
81
82 return NULL;
83 }
84
85 void FetchProcessEvent(FcitxFetchThread* fetch)
86 {
87 CURLMcode mcode;
88 int still_running;
89 do {
90 mcode = curl_multi_perform(fetch->curlm, &still_running);
91 } while (mcode == CURLM_CALL_MULTI_PERFORM);
92
93 int num_messages = 0;
94 CURLMsg* curl_message = curl_multi_info_read(fetch->curlm, &num_messages);
95 CurlQueue* queue, *previous;
96
97 while (curl_message != NULL) {
98 if (curl_message->msg == CURLMSG_DONE) {
99 int curl_result = curl_message->data.result;
100 previous = fetch->queue;
101 queue = fetch->queue->next;
102 while (queue != NULL &&
103 queue->curl != curl_message->easy_handle)
104 {
105 previous = queue;
106 queue = queue->next;
107 }
108 if (queue != NULL) {
109 curl_multi_remove_handle(fetch->curlm, queue->curl);
110 previous->next = queue->next;
111 queue->curl_result = curl_result;
112 curl_easy_getinfo(queue->curl, CURLINFO_HTTP_CODE, &queue->http_code);
113 FetchFinish(fetch, queue);
114 }
115 }
116 curl_message = curl_multi_info_read(fetch->curlm, &num_messages);
117 }
118 }
119
120 void FetchProcessPendingRequest(FcitxFetchThread* fetch)
121 {
122 boolean still_running;
123
124 /* pull all item from pending queue and move to fetch queue */
125 pthread_mutex_lock(fetch->pendingQueueLock);
126 FcitxCloudPinyin *cloudpinyin = fetch->owner;
127 CurlQueue* head = cloudpinyin->pendingQueue;
128 CurlQueue* tail = fetch->queue;
129 while(tail->next)
130 tail = tail->next;
131 while(head->next) {
132 CurlQueue* item = head->next;
133 item->next = tail->next;
134 tail->next = item;
135 head->next = head->next->next;
136 }
137 pthread_mutex_unlock(fetch->pendingQueueLock);
138 /* new item start from here */
139 tail = tail->next;
140 boolean flag = false;
141 while(tail) {
142 curl_multi_add_handle(fetch->curlm, tail->curl);
143 tail = tail->next;
144 flag = true;
145 }
146
147 if (flag) {
148 CURLMcode mcode;
149 do {
150 mcode = curl_multi_perform(fetch->curlm, &still_running);
151 } while (mcode == CURLM_CALL_MULTI_PERFORM);
152 }
153 }
154
155 void FetchFinish(FcitxFetchThread* fetch, CurlQueue* queue)
156 {
157 pthread_mutex_lock(fetch->finishQueueLock);
158
159 FcitxCloudPinyin *cloudpinyin = fetch->owner;
160
161 CurlQueue* head = cloudpinyin->finishQueue;
162 while(head->next)
163 head = head->next;
164 head->next = queue;
165 queue->next = NULL;
166 pthread_mutex_unlock(fetch->finishQueueLock);
167
168 char c = 0;
169 write(fetch->pipeNotify, &c, sizeof(char));
170 }
0 /***************************************************************************
1 * Copyright (C) 2012~2012 by CSSlayer *
2 * wengxt@gmail.com *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19
20 #ifndef FCITX_FETCH_H
21 #define FCITX_FETCH_H
22
23 typedef struct _FcitxFetchThread {
24 CURLM* curlm;
25 int pipeRecv;
26 int pipeNotify;
27 fd_set rfds;
28 fd_set wfds;
29 fd_set efds;
30 int maxfd;
31 CurlQueue* queue;
32
33 pthread_mutex_t* pendingQueueLock;
34 pthread_mutex_t* finishQueueLock;
35
36 FcitxCloudPinyin* owner;
37 } FcitxFetchThread;
38
39 void* FetchThread(void* arg);
40
41 #endif