1 /***************************************************************************
2 * Copyright (C) 2011~2012 by CSSlayer *
3 * wengxt@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21 #include "candidate-internal.h"
22
23 static const UT_icd cand_icd = {
24 sizeof(FcitxCandidateWord), NULL, NULL, FcitxCandidateWordFree
25 };
26
27 FCITX_EXPORT_API
FcitxCandidateWordNewList()28 FcitxCandidateWordList* FcitxCandidateWordNewList()
29 {
30 FcitxCandidateWordList* candList = fcitx_utils_new(FcitxCandidateWordList);
31
32 utarray_init(&candList->candWords, &cand_icd);
33 utarray_reserve(&candList->candWords, 128);
34 candList->wordPerPage = 5; /* anyway put a default value for safety */
35 candList->layoutHint = CLH_NotSet;
36 strncpy(candList->strChoose, DIGIT_STR_CHOOSE, MAX_CAND_WORD);
37
38 return candList;
39 }
40
41 FCITX_EXPORT_API
FcitxCandidateWordFreeList(FcitxCandidateWordList * list)42 void FcitxCandidateWordFreeList(FcitxCandidateWordList* list)
43 {
44 utarray_done(&list->candWords);
45 free(list);
46 }
47
48 FCITX_EXPORT_API
FcitxCandidateWordInsert(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord,int position)49 void FcitxCandidateWordInsert(FcitxCandidateWordList* candList,
50 FcitxCandidateWord* candWord, int position)
51 {
52 fcitx_array_insert(&candList->candWords, candWord, position);
53 }
54
55 FCITX_EXPORT_API
56 void
FcitxCandidateWordMerge(FcitxCandidateWordList * candList,FcitxCandidateWordList * newList,int position)57 FcitxCandidateWordMerge(FcitxCandidateWordList* candList,
58 FcitxCandidateWordList* newList, int position)
59 {
60 void *p;
61 if (!newList)
62 return;
63 if (position >= 0) {
64 fcitx_array_inserta(&candList->candWords, &newList->candWords,
65 position);
66 } else {
67 utarray_concat(&candList->candWords, &newList->candWords);
68 }
69 utarray_steal(&newList->candWords, p);
70 newList->currentPage = 0;
71 free(p);
72 }
73
DummyHandler(void * arg,FcitxCandidateWord * candWord)74 INPUT_RETURN_VALUE DummyHandler(void* arg, FcitxCandidateWord* candWord)
75 {
76 FCITX_UNUSED(arg);
77 FCITX_UNUSED(candWord);
78 return IRV_DO_NOTHING;
79 }
80
81 FCITX_EXPORT_API
FcitxCandidateWordInsertPlaceHolder(FcitxCandidateWordList * candList,int position)82 void FcitxCandidateWordInsertPlaceHolder(FcitxCandidateWordList* candList,
83 int position)
84 {
85 FcitxCandidateWord candWord;
86 memset(&candWord, 0, sizeof(FcitxCandidateWord));
87 candWord.callback = DummyHandler;
88 fcitx_array_insert(&candList->candWords, &candWord, position);
89 }
90
91 FCITX_EXPORT_API
FcitxCandidateWordMove(FcitxCandidateWordList * candList,int from,int to)92 void FcitxCandidateWordMove(FcitxCandidateWordList* candList, int from, int to)
93 {
94 fcitx_array_move(&candList->candWords, from, to);
95 }
96
97 FCITX_EXPORT_API void
FcitxCandidateWordMoveByWord(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord,int to)98 FcitxCandidateWordMoveByWord(FcitxCandidateWordList *candList,
99 FcitxCandidateWord *candWord, int to)
100 {
101 int from = utarray_eltidx(&candList->candWords, candWord);
102 FcitxCandidateWordMove(candList, from, to);
103 }
104
105 FCITX_EXPORT_API void
FcitxCandidateWordRemoveByIndex(FcitxCandidateWordList * candList,int idx)106 FcitxCandidateWordRemoveByIndex(FcitxCandidateWordList *candList, int idx)
107 {
108 fcitx_array_erase(&candList->candWords, idx, 1);
109 }
110
111 FCITX_EXPORT_API void
FcitxCandidateWordRemove(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)112 FcitxCandidateWordRemove(FcitxCandidateWordList *candList,
113 FcitxCandidateWord *candWord)
114 {
115 int idx = utarray_eltidx(&candList->candWords, candWord);
116 FcitxCandidateWordRemoveByIndex(candList, idx);
117 }
118
119 FCITX_EXPORT_API void
FcitxCandidateWordSetPage(FcitxCandidateWordList * candList,int index)120 FcitxCandidateWordSetPage(FcitxCandidateWordList *candList, int index)
121 {
122 if (index >= 0 && index < FcitxCandidateWordPageCount(candList)) {
123 candList->currentPage = index;
124 }
125 }
126
127 FCITX_EXPORT_API void
FcitxCandidateWordSetFocus(FcitxCandidateWordList * candList,int index)128 FcitxCandidateWordSetFocus(FcitxCandidateWordList* candList, int index)
129 {
130 FcitxCandidateWordSetPage(candList, index / candList->wordPerPage);
131 }
132
133 FCITX_EXPORT_API
FcitxCandidateWordReset(FcitxCandidateWordList * candList)134 void FcitxCandidateWordReset(FcitxCandidateWordList* candList)
135 {
136 utarray_clear(&candList->candWords);
137 if (candList->override) {
138 candList->override = false;
139 candList->hasPrev = false;
140 candList->hasNext = false;
141 candList->paging = NULL;
142 if (candList->overrideDestroyNotify)
143 candList->overrideDestroyNotify(candList->overrideArg);
144 candList->overrideArg = NULL;
145 candList->overrideDestroyNotify = NULL;
146 }
147 candList->overrideHighlight = false;
148 candList->overrideHighlightValue = false;
149 candList->currentPage = 0;
150 candList->hasGonePrevPage = false;
151 candList->hasGoneNextPage = false;
152 candList->layoutHint = CLH_NotSet;
153 }
154
155 FCITX_EXPORT_API
FcitxCandidateWordGetCurrentIndex(FcitxCandidateWordList * candList)156 int FcitxCandidateWordGetCurrentIndex(FcitxCandidateWordList* candList)
157 {
158 return candList->currentPage * candList->wordPerPage;
159 }
160
161 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetCurrentWindow(FcitxCandidateWordList * candList)162 FcitxCandidateWordGetCurrentWindow(FcitxCandidateWordList* candList)
163 {
164 return FcitxCandidateWordGetByTotalIndex(
165 candList, candList->currentPage * candList->wordPerPage);
166 }
167
168 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetCurrentWindowNext(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)169 FcitxCandidateWordGetCurrentWindowNext(FcitxCandidateWordList* candList,
170 FcitxCandidateWord* candWord)
171 {
172 FcitxCandidateWord *nextCandWord = (FcitxCandidateWord*)utarray_next(&candList->candWords, candWord);
173 if (nextCandWord == NULL)
174 return NULL;
175 FcitxCandidateWord *startCandWord = FcitxCandidateWordGetCurrentWindow(candList);
176 if (nextCandWord < startCandWord ||
177 nextCandWord >= startCandWord + candList->wordPerPage)
178 return NULL;
179 return nextCandWord;
180 }
181
182 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetCurrentWindowPrev(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)183 FcitxCandidateWordGetCurrentWindowPrev(FcitxCandidateWordList* candList,
184 FcitxCandidateWord* candWord)
185 {
186 FcitxCandidateWord *prevWord = utarray_prev(&candList->candWords, candWord);
187 if (prevWord == NULL)
188 return NULL;
189 FcitxCandidateWord *startWord = FcitxCandidateWordGetCurrentWindow(candList);
190 if (prevWord < startWord ||
191 prevWord >= startWord + candList->wordPerPage)
192 return NULL;
193 return prevWord;
194 }
195
196 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetByTotalIndex(FcitxCandidateWordList * candList,int index)197 FcitxCandidateWordGetByTotalIndex(FcitxCandidateWordList* candList, int index)
198 {
199 return fcitx_array_eltptr(&candList->candWords, index);
200 }
201
202 FCITX_EXPORT_API int
FcitxCandidateWordGetIndex(FcitxCandidateWordList * candList,FcitxCandidateWord * word)203 FcitxCandidateWordGetIndex(FcitxCandidateWordList *candList,
204 FcitxCandidateWord *word)
205 {
206 return utarray_eltidx(&candList->candWords, word);
207 }
208
209 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetByIndex(FcitxCandidateWordList * candList,int index)210 FcitxCandidateWordGetByIndex(FcitxCandidateWordList* candList, int index)
211 {
212 if (index < candList->wordPerPage && index >= 0)
213 return FcitxCandidateWordGetByTotalIndex(
214 candList, candList->currentPage * candList->wordPerPage + index);
215 return NULL;
216 }
217
218 FCITX_EXPORT_API INPUT_RETURN_VALUE
FcitxCandidateWordChooseByIndex(FcitxCandidateWordList * candList,int index)219 FcitxCandidateWordChooseByIndex(FcitxCandidateWordList* candList, int index)
220 {
221 FcitxCandidateWord* candWord = FcitxCandidateWordGetByIndex(candList, index);
222 if (candWord == NULL) {
223 if (FcitxCandidateWordGetListSize(candList) > 0)
224 return IRV_DO_NOTHING;
225 else
226 return IRV_TO_PROCESS;
227 } else
228 return candWord->callback(candWord->owner, candWord);
229 }
230
231 FCITX_EXPORT_API
FcitxCandidateWordChooseByTotalIndex(FcitxCandidateWordList * candList,int index)232 INPUT_RETURN_VALUE FcitxCandidateWordChooseByTotalIndex(FcitxCandidateWordList* candList, int index)
233 {
234 FcitxCandidateWord* candWord = FcitxCandidateWordGetByTotalIndex(candList, index);
235 if (candWord == NULL) {
236 if (FcitxCandidateWordGetListSize(candList) > 0)
237 return IRV_DO_NOTHING;
238 else
239 return IRV_TO_PROCESS;
240 } else
241 return candWord->callback(candWord->owner, candWord);
242 }
243
244 FCITX_EXPORT_API
FcitxCandidateWordHasPrev(FcitxCandidateWordList * candList)245 boolean FcitxCandidateWordHasPrev(FcitxCandidateWordList* candList)
246 {
247 if (candList->override)
248 return candList->hasPrev;
249
250 if (candList->currentPage > 0)
251 return true;
252 else
253 return false;
254 }
255
256 FCITX_EXPORT_API
FcitxCandidateWordHasNext(FcitxCandidateWordList * candList)257 boolean FcitxCandidateWordHasNext(FcitxCandidateWordList* candList)
258 {
259 if (candList->override)
260 return candList->hasNext;
261
262 if (candList->currentPage + 1 < FcitxCandidateWordPageCount(candList))
263 return true;
264 else
265 return false;
266 }
267
268 FCITX_EXPORT_API int
FcitxCandidateWordPageCount(FcitxCandidateWordList * candList)269 FcitxCandidateWordPageCount(FcitxCandidateWordList* candList)
270 {
271 return (utarray_len(&candList->candWords) + candList->wordPerPage - 1) / candList->wordPerPage;
272 }
273
274 FCITX_EXPORT_API
FcitxCandidateWordFree(void * arg)275 void FcitxCandidateWordFree(void* arg)
276 {
277 FcitxCandidateWord* candWord = (FcitxCandidateWord*) arg;
278 if (candWord->strWord)
279 free(candWord->strWord);
280 if (candWord->strExtra)
281 free(candWord->strExtra);
282 if (candWord->priv)
283 free(candWord->priv);
284 }
285
286 FCITX_EXPORT_API
FcitxCandidateWordAppend(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)287 void FcitxCandidateWordAppend(FcitxCandidateWordList* candList, FcitxCandidateWord* candWord)
288 {
289 utarray_push_back(&candList->candWords, candWord);
290 }
291
292 FCITX_EXPORT_API
FcitxCandidateWordGoPrevPage(FcitxCandidateWordList * candList)293 boolean FcitxCandidateWordGoPrevPage(FcitxCandidateWordList* candList)
294 {
295 if (candList->override) {
296 if (candList->paging) {
297 return candList->paging(candList->overrideArg, true);
298 } else {
299 return true;
300 }
301 }
302
303 if (!FcitxCandidateWordPageCount(candList))
304 return false;
305 if (FcitxCandidateWordHasPrev(candList)) {
306 candList->currentPage -- ;
307 candList->hasGonePrevPage = true;
308 return true;
309 }
310 return false;
311 }
312
313 FCITX_EXPORT_API
FcitxCandidateWordGoNextPage(FcitxCandidateWordList * candList)314 boolean FcitxCandidateWordGoNextPage(FcitxCandidateWordList* candList)
315 {
316 if (candList->override) {
317 if (candList->paging) {
318 return candList->paging(candList->overrideArg, false);
319 } else {
320 return true;
321 }
322 }
323
324 if (!FcitxCandidateWordPageCount(candList))
325 return false;
326 if (FcitxCandidateWordHasNext(candList)) {
327 candList->currentPage ++ ;
328 candList->hasGoneNextPage = true;
329 return true;
330 }
331 return false;
332 }
333
334 FCITX_EXPORT_API
FcitxCandidateWordSetChoose(FcitxCandidateWordList * candList,const char * strChoose)335 void FcitxCandidateWordSetChoose(FcitxCandidateWordList* candList, const char* strChoose)
336 {
337 FcitxCandidateWordSetChooseAndModifier(candList, strChoose, FcitxKeyState_None);
338 }
339
340 FCITX_EXPORT_API
FcitxCandidateWordSetChooseAndModifier(FcitxCandidateWordList * candList,const char * strChoose,unsigned int state)341 void FcitxCandidateWordSetChooseAndModifier(FcitxCandidateWordList* candList, const char* strChoose, unsigned int state)
342 {
343 strncpy(candList->strChoose, strChoose, MAX_CAND_WORD);
344 candList->candiateModifier = state;
345 }
346
347 FCITX_EXPORT_API
FcitxCandidateWordGetModifier(FcitxCandidateWordList * candList)348 unsigned int FcitxCandidateWordGetModifier(FcitxCandidateWordList* candList)
349 {
350 return candList->candiateModifier;
351 }
352
353 FCITX_EXPORT_API
FcitxCandidateWordGetChoose(FcitxCandidateWordList * candList)354 const char* FcitxCandidateWordGetChoose(FcitxCandidateWordList* candList)
355 {
356 return candList->strChoose;
357 }
358
359 FCITX_EXPORT_API
FcitxCandidateWordGetCurrentPage(FcitxCandidateWordList * candList)360 int FcitxCandidateWordGetCurrentPage(FcitxCandidateWordList* candList)
361 {
362 return candList->currentPage;
363 }
364
365 FCITX_EXPORT_API
FcitxCandidateWordResize(FcitxCandidateWordList * candList,int length)366 void FcitxCandidateWordResize(FcitxCandidateWordList* candList, int length)
367 {
368 fcitx_array_resize(&candList->candWords, length);
369 }
370
371 FCITX_EXPORT_API
FcitxCandidateWordGetPageSize(FcitxCandidateWordList * candList)372 int FcitxCandidateWordGetPageSize(FcitxCandidateWordList* candList)
373 {
374 return candList->wordPerPage;
375 }
376
377 FCITX_EXPORT_API
FcitxCandidateWordSetPageSize(FcitxCandidateWordList * candList,int size)378 void FcitxCandidateWordSetPageSize(FcitxCandidateWordList* candList, int size)
379 {
380 if (size <= 0 || size > 10)
381 size = 5;
382
383 candList->wordPerPage = size;
384 }
385
386 FCITX_EXPORT_API
FcitxCandidateWordGetCurrentWindowSize(FcitxCandidateWordList * candList)387 int FcitxCandidateWordGetCurrentWindowSize(FcitxCandidateWordList* candList)
388 {
389 if (utarray_len(&candList->candWords) == 0)
390 return 0;
391 /* last page */
392 if (candList->currentPage + 1 == FcitxCandidateWordPageCount(candList)) {
393 int size = utarray_len(&candList->candWords) % candList->wordPerPage;
394 if (size != 0)
395 return size;
396 }
397 return candList->wordPerPage;
398 }
399
400 FCITX_EXPORT_API
FcitxCandidateWordGetListSize(FcitxCandidateWordList * candList)401 int FcitxCandidateWordGetListSize(FcitxCandidateWordList* candList)
402 {
403 return utarray_len(&candList->candWords);
404 }
405
406 FCITX_EXPORT_API
FcitxCandidateWordGetHasGoneToPrevPage(FcitxCandidateWordList * candList)407 boolean FcitxCandidateWordGetHasGoneToPrevPage(FcitxCandidateWordList* candList)
408 {
409 return candList->hasGonePrevPage;
410 }
411
412 FCITX_EXPORT_API
FcitxCandidateWordGetHasGoneToNextPage(FcitxCandidateWordList * candList)413 boolean FcitxCandidateWordGetHasGoneToNextPage(FcitxCandidateWordList* candList)
414 {
415 return candList->hasGoneNextPage;
416 }
417
418 FCITX_EXPORT_API
FcitxCandidateWordGetFirst(FcitxCandidateWordList * candList)419 FcitxCandidateWord* FcitxCandidateWordGetFirst(FcitxCandidateWordList* candList)
420 {
421 return (FcitxCandidateWord*)utarray_front(&candList->candWords);
422 }
423
424 FCITX_EXPORT_API
FcitxCandidateWordGetLast(FcitxCandidateWordList * candList)425 FcitxCandidateWord* FcitxCandidateWordGetLast(FcitxCandidateWordList* candList)
426 {
427 return (FcitxCandidateWord*)utarray_back(&candList->candWords);
428 }
429
430 FCITX_EXPORT_API
FcitxCandidateWordGetNext(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)431 FcitxCandidateWord* FcitxCandidateWordGetNext(FcitxCandidateWordList* candList, FcitxCandidateWord* candWord)
432 {
433 return (FcitxCandidateWord*)utarray_next(&candList->candWords, candWord);
434 }
435
436 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetPrev(FcitxCandidateWordList * candList,FcitxCandidateWord * candWord)437 FcitxCandidateWordGetPrev(FcitxCandidateWordList *candList,
438 FcitxCandidateWord *candWord)
439 {
440 return utarray_prev(&candList->candWords, candWord);
441 }
442
443 FCITX_EXPORT_API
444 int
FcitxCandidateWordCheckChooseKey(FcitxCandidateWordList * candList,FcitxKeySym sym,unsigned int state)445 FcitxCandidateWordCheckChooseKey(FcitxCandidateWordList *candList,
446 FcitxKeySym sym, unsigned int state)
447 {
448 return FcitxHotkeyCheckChooseKeyAndModifier(sym, state,
449 candList->strChoose,
450 candList->candiateModifier);
451 }
452
453 FCITX_EXPORT_API
FcitxCandidateWordGetLayoutHint(FcitxCandidateWordList * candList)454 FcitxCandidateLayoutHint FcitxCandidateWordGetLayoutHint(FcitxCandidateWordList* candList)
455 {
456 return candList->layoutHint;
457 }
458
459 FCITX_EXPORT_API
FcitxCandidateWordSetLayoutHint(FcitxCandidateWordList * candList,FcitxCandidateLayoutHint hint)460 void FcitxCandidateWordSetLayoutHint(FcitxCandidateWordList* candList, FcitxCandidateLayoutHint hint)
461 {
462 candList->layoutHint = hint;
463 }
464
465 FCITX_EXPORT_API
FcitxCandidateWordSetOverridePaging(FcitxCandidateWordList * candList,boolean hasPrev,boolean hasNext,FcitxPaging paging,void * arg,FcitxDestroyNotify destroyNotify)466 void FcitxCandidateWordSetOverridePaging(FcitxCandidateWordList* candList, boolean hasPrev, boolean hasNext, FcitxPaging paging, void* arg, FcitxDestroyNotify destroyNotify)
467 {
468 if (candList->override && candList->overrideDestroyNotify) {
469 candList->overrideDestroyNotify(candList->overrideArg);
470 }
471
472 candList->override = true;
473 candList->hasPrev = hasPrev;
474 candList->hasNext = hasNext;
475 candList->paging = paging;
476 candList->overrideArg = arg;
477 candList->overrideDestroyNotify = destroyNotify;
478 }
479
480 FCITX_EXPORT_API
FcitxCandidateWordSetOverrideDefaultHighlight(FcitxCandidateWordList * candList,boolean overrideValue)481 void FcitxCandidateWordSetOverrideDefaultHighlight(FcitxCandidateWordList* candList, boolean overrideValue)
482 {
483 candList->overrideHighlight = true;
484 candList->overrideHighlightValue = overrideValue;
485 }
486
487 FCITX_EXPORT_API FcitxCandidateWord*
FcitxCandidateWordGetFocus(FcitxCandidateWordList * cand_list,boolean clear)488 FcitxCandidateWordGetFocus(FcitxCandidateWordList *cand_list, boolean clear)
489 {
490 FcitxCandidateWord *res = NULL;
491 FcitxCandidateWord *cand_word;
492 for (cand_word = FcitxCandidateWordGetCurrentWindow(cand_list);
493 cand_word;cand_word = FcitxCandidateWordGetCurrentWindowNext(
494 cand_list, cand_word)) {
495 if (FcitxCandidateWordCheckFocus(cand_word, clear)) {
496 res = cand_word;
497 }
498 }
499 if (!res)
500 return FcitxCandidateWordGetCurrentWindow(cand_list);
501 return res;
502 }
503
504 // kate: indent-mode cstyle; space-indent on; indent-width 0;
505