1 /*
2  * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "nj_lib.h"
18 #include "nj_err.h"
19 #include "nj_ext.h"
20 #include "nj_dic.h"
21 #include "njd.h"
22 
23 #define NJ_DIC_UNCOMP_EXT_HEADER_SIZE   0x002C
24 #define CREATE_DIC_TYPE_USER            0
25 
26 #define GET_HYOKI_INDEX_OFFSET(cnt)                             \
27     (NJ_LEARN_DIC_HEADER_SIZE + NJ_INDEX_SIZE * ((cnt)+1))
28 
29 #define GET_DATA_AREA_OFFSET(cnt)                               \
30     (NJ_LEARN_DIC_HEADER_SIZE + NJ_INDEX_SIZE * ((cnt)+1) * 2)
31 #define GET_EXT_DATA_AREA_OFFSET(cnt)                                   \
32     (NJ_LEARN_DIC_HEADER_SIZE + NJ_INDEX_SIZE * ((cnt)+1) * 2 + LEARN_DIC_QUE_SIZE * (cnt))
33 
34 #define MIN_SIZE_OF_USER_DIC                                            \
35     (NJ_LEARN_DIC_HEADER_SIZE + NJ_USER_QUE_SIZE + 2 * (NJ_INDEX_SIZE * (1+1)) + 4)
36 #define GET_MAX_WORD_NUM_IN_USER_DIC(size)                              \
37     (((size) - NJ_LEARN_DIC_HEADER_SIZE - (2 * NJ_INDEX_SIZE) - 4)      \
38      / (NJ_USER_QUE_SIZE + 2 * NJ_INDEX_SIZE))
39 
40 
41 static NJ_INT16 check_search_cursor(NJ_CLASS *iwnn, NJ_CURSOR *cursor);
42 static NJ_INT16 search_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_UINT8 comp_flg, NJ_UINT8 *exit_flag);
43 static void set_operation_id(NJ_SEARCH_LOCATION *dicinfo, NJ_UINT8 reverse, NJ_RESULT *result);
44 static NJ_INT16 get_word_and_search_next_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_RESULT *result, NJ_UINT8 comp_flg);
45 
46 static NJ_INT16 njd_check_dic(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle);
47 
check_search_cursor(NJ_CLASS * iwnn,NJ_CURSOR * cursor)48 static NJ_INT16 check_search_cursor(NJ_CLASS *iwnn, NJ_CURSOR *cursor) {
49     NJ_UINT16 i;
50     NJ_DIC_INFO *dicinfo;
51     NJ_SEARCH_LOCATION_SET *loctset;
52 
53 
54     if (cursor->cond.ds == NULL) {
55         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_DIC_NULL);
56     }
57 
58 
59     for (i = 0; i < NJ_MAX_DIC; i++) {
60         loctset = &(cursor->loctset[i]);
61         dicinfo = &(cursor->cond.ds->dic[i]);
62 
63 
64         njd_init_search_location_set(loctset);
65 
66         if (dicinfo->handle != NULL) {
67 
68 
69 
70             if (
71                 (dicinfo->dic_freq[NJ_MODE_TYPE_HENKAN].high > DIC_FREQ_HIGH) ) {
72                 return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_DIC_FREQ_INVALID);
73             }
74 
75 
76             loctset->loct.handle        = dicinfo->handle;
77             loctset->loct.type          = dicinfo->type;
78             loctset->loct.current_info  = 0x10;
79             loctset->loct.status        = NJ_ST_SEARCH_NO_INIT;
80             loctset->dic_freq           = dicinfo->dic_freq[NJ_MODE_TYPE_HENKAN];
81         }
82     }
83 
84     if (cursor->cond.yomi == NULL) {
85 
86         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_YOMI_NULL);
87     }
88 
89     if (cursor->cond.ylen > NJ_MAX_LEN) {
90 
91         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_YOMI_TOO_LONG);
92     }
93 
94     if (cursor->cond.operation == NJ_CUR_OP_LINK) {
95 
96     } else if (cursor->cond.kanji != NULL) {
97 
98         if (nj_strlen(cursor->cond.kanji) > NJ_MAX_RESULT_LEN) {
99             return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_CANDIDATE_TOO_LONG);
100         }
101     }
102 
103     switch (cursor->cond.operation) {
104     case NJ_CUR_OP_COMP:
105     case NJ_CUR_OP_FORE:
106     case NJ_CUR_OP_LINK:
107         break;
108     default:
109         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_OPERATION);
110     }
111 
112     switch (cursor->cond.mode) {
113     case NJ_CUR_MODE_FREQ:
114     case NJ_CUR_MODE_YOMI:
115         break;
116     default:
117         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_MODE);
118     }
119 
120     return 0;
121 }
122 
search_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor,NJ_UINT8 comp_flg,NJ_UINT8 * exit_flag)123 static NJ_INT16 search_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_UINT8 comp_flg,
124                             NJ_UINT8 *exit_flag) {
125     NJ_UINT32 dic_type;
126     NJ_INT16 i;
127     NJ_INT16 ret = 0;
128     NJ_INT16 flag = 0;
129     NJ_SEARCH_LOCATION_SET *loctset;
130 
131 
132     *exit_flag = 1;
133     for (i = 0; i < NJ_MAX_DIC; i++) {
134         loctset = &(cursor->loctset[i]);
135 
136         if (loctset->loct.handle == NULL) {
137             continue;
138         }
139 
140         dic_type = NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle);
141 #ifdef IWNN_ERR_CHECK
142         if (iwnn->err_check_flg == 12) {
143             dic_type = 0x11111111;
144         }
145 #endif
146         switch (dic_type) {
147         case NJ_DIC_TYPE_JIRITSU:
148         case NJ_DIC_TYPE_FZK:
149         case NJ_DIC_TYPE_TANKANJI:
150         case NJ_DIC_TYPE_STDFORE:
151         case NJ_DIC_TYPE_CUSTOM_COMPRESS:
152         case NJ_DIC_TYPE_FORECONV:
153             ret = njd_b_search_word(&cursor->cond, loctset);
154             break;
155         case NJ_DIC_TYPE_USER:
156         case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
157             ret = njd_l_search_word(iwnn, &cursor->cond, loctset, comp_flg);
158             break;
159 
160         case NJ_DIC_TYPE_YOMINASHI:
161             ret = njd_f_search_word(&cursor->cond, loctset);
162             break;
163 
164         default:
165             return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_WORD, NJ_ERR_DIC_TYPE_INVALID);
166         }
167         if (ret < 0) {
168             return ret;
169         }
170         if (ret == 0) {
171             if ((GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END)
172                 && (*exit_flag == 1)) {
173                 *exit_flag = 0;
174             }
175 
176             loctset->loct.status = NJ_ST_SEARCH_END;
177 
178         } else {
179             flag = 1;
180             *exit_flag = 0;
181         }
182     }
183     return flag;
184 }
185 
get_word_and_search_next_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor,NJ_RESULT * result,NJ_UINT8 comp_flg)186 static NJ_INT16 get_word_and_search_next_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_RESULT *result,
187                                               NJ_UINT8 comp_flg) {
188     NJ_INT16  ret = -1;
189     NJ_INT32  i, next, first;
190     NJ_WORD   tmp_word;
191     NJ_RESULT tmp_result;
192     NJ_CHAR   tmp_stroke[NJ_MAX_LEN + NJ_TERM_LEN];
193     NJ_CHAR   result_stroke[NJ_MAX_LEN + NJ_TERM_LEN];
194     NJ_INT32  j, max_len = 0;
195     NJ_UINT32 dic_type;
196     NJ_SEARCH_LOCATION_SET *loctset;
197 
198 
199     next = -1;
200     first= 0;
201 
202     njd_init_word(&tmp_word);
203 
204     result->word = tmp_word;
205     tmp_result.word = tmp_word;
206 
207     for (i = 0; i < NJ_MAX_DIC; i++) {
208         loctset = &(cursor->loctset[i]);
209         if ((loctset->loct.handle == NULL) ||
210             (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END) ||
211             (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END_EXT)) {
212             continue;
213         }
214 
215         dic_type = NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle);
216 
217         switch (dic_type) {
218         case NJ_DIC_TYPE_JIRITSU:
219         case NJ_DIC_TYPE_FZK:
220         case NJ_DIC_TYPE_TANKANJI:
221         case NJ_DIC_TYPE_STDFORE:
222         case NJ_DIC_TYPE_CUSTOM_COMPRESS:
223         case NJ_DIC_TYPE_FORECONV:
224             tmp_word.yomi = cursor->cond.yomi;
225             tmp_word.stem.info1 = cursor->cond.ylen;
226             tmp_result.word.yomi = cursor->cond.yomi;
227             tmp_result.word.stem.info1 = cursor->cond.ylen;
228             break;
229         default:
230             break;
231         }
232 
233         loctset->loct.status |= SET_LOCATION_OPERATION(cursor->cond.operation);
234         if (cursor->cond.mode == NJ_CUR_MODE_FREQ) {
235             if ((cursor->cond.ds->mode & (NJ_CACHE_MODE_VALID)) &&
236                 (cursor->cond.ds->dic[i].srhCache != NULL) &&
237                 (NJ_GET_AIMAI_FROM_SCACHE(cursor->cond.ds->dic[i].srhCache)) &&
238                 (cursor->cond.operation == NJ_CUR_OP_FORE)) {
239                 first = 1;
240 
241                 ret = njd_get_word_data(iwnn, cursor->cond.ds, loctset, (NJ_UINT16)i, &tmp_result.word);
242                 if (ret < 0) {
243                     return ret;
244                 }
245 
246                 ret = njd_get_stroke(iwnn, &tmp_result, tmp_stroke, sizeof(tmp_stroke));
247                 if (ret <= 0) {
248                     if ((ret == 0) || (NJ_GET_ERR_CODE(ret) == NJ_ERR_BUFFER_NOT_ENOUGH)) {
249                         return NJ_SET_ERR_VAL(NJ_FUNC_GET_WORD_AND_SEARCH_NEXT_WORD, NJ_ERR_INVALID_RESULT);
250                     } else {
251                         return ret;
252                     }
253                 }
254                 for (j = 0; j < cursor->cond.ylen; j++) {
255                     if (cursor->cond.yomi[j] != tmp_stroke[j]) {
256                         break;
257                     }
258                 }
259 
260                 switch (dic_type) {
261                 case NJ_DIC_TYPE_JIRITSU:
262                 case NJ_DIC_TYPE_FZK:
263                 case NJ_DIC_TYPE_TANKANJI:
264                 case NJ_DIC_TYPE_STDFORE:
265                 case NJ_DIC_TYPE_CUSTOM_COMPRESS:
266                 case NJ_DIC_TYPE_FORECONV:
267                     ret = njd_b_search_word(&cursor->cond, loctset);
268                     break;
269 
270                 case NJ_DIC_TYPE_USER:
271                 case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
272                     ret = njd_l_search_word(iwnn, &cursor->cond, loctset, comp_flg);
273                     break;
274 
275                 default:
276                     return NJ_SET_ERR_VAL(NJ_FUNC_GET_WORD_AND_SEARCH_NEXT_WORD, NJ_ERR_DIC_TYPE_INVALID);
277                 }
278 
279                 if (ret < 0) {
280                     return ret;
281                 }
282             } else {
283                 ret = njd_get_word_data(iwnn, cursor->cond.ds, loctset, (NJ_UINT16)i, &tmp_result.word);
284                 if (ret < 0) {
285                     return ret;
286                 }
287                 j = cursor->cond.ylen;
288             }
289 
290             if ((j > max_len) ||
291                 ((j == max_len) && (loctset->cache_freq > result->word.stem.hindo)) ||
292                 (next == -1)) {
293 
294                 set_operation_id(&(loctset->loct), 0, result);
295 
296                 result->word = tmp_result.word;
297 
298                 next = i;
299                 max_len = j;
300             }
301 
302         } else {
303 
304             ret = njd_get_word_data(iwnn, cursor->cond.ds, loctset, (NJ_UINT16)i, &(tmp_result.word));
305             if (ret < 0) {
306                 return ret;
307             }
308 
309 
310             ret = njd_get_stroke(iwnn, &tmp_result, tmp_stroke, sizeof(tmp_stroke));
311             if (ret <= 0) {
312                 if ((ret == 0) || (NJ_GET_ERR_CODE(ret) == NJ_ERR_BUFFER_NOT_ENOUGH)) {
313                     return NJ_SET_ERR_VAL(NJ_FUNC_GET_WORD_AND_SEARCH_NEXT_WORD, NJ_ERR_INVALID_RESULT);
314                 } else {
315                     return ret;
316                 }
317             }
318             if ((next == -1) || (nj_strcmp(result_stroke, tmp_stroke) > 0)) {
319 
320                 set_operation_id(&(loctset->loct), 0, result);
321 
322                 result->word = tmp_result.word;
323 
324                 next = i;
325                 nj_strcpy(result_stroke, tmp_stroke);
326             }
327         }
328     }
329 
330 
331     if (next == -1) {
332         return 0;
333     }
334 
335     loctset = &(cursor->loctset[next]);
336     if ((!first) ||
337         ((loctset->loct.handle != NULL) &&
338          (cursor->cond.ds->dic[next].srhCache == NULL))) {
339         dic_type = NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle);
340 
341 
342         switch (dic_type) {
343         case NJ_DIC_TYPE_JIRITSU:
344         case NJ_DIC_TYPE_FZK:
345         case NJ_DIC_TYPE_TANKANJI:
346         case NJ_DIC_TYPE_STDFORE:
347         case NJ_DIC_TYPE_CUSTOM_COMPRESS:
348         case NJ_DIC_TYPE_FORECONV:
349             ret = njd_b_search_word(&cursor->cond, loctset);
350             break;
351 
352         case NJ_DIC_TYPE_USER:
353         case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
354             ret = njd_l_search_word(iwnn, &cursor->cond, loctset, comp_flg);
355             break;
356 
357         case NJ_DIC_TYPE_YOMINASHI:
358             ret = njd_f_search_word(&cursor->cond, loctset);
359             break;
360 
361         default:
362             return NJ_SET_ERR_VAL(NJ_FUNC_GET_WORD_AND_SEARCH_NEXT_WORD, NJ_ERR_DIC_TYPE_INVALID);
363         }
364     }
365 
366     if (ret < 0) {
367         return ret;
368     }
369     return 1;
370 }
371 
njd_get_word_data(NJ_CLASS * iwnn,NJ_DIC_SET * dicset,NJ_SEARCH_LOCATION_SET * loctset,NJ_UINT16 dic_idx,NJ_WORD * word)372 NJ_INT16 njd_get_word_data(NJ_CLASS *iwnn, NJ_DIC_SET *dicset, NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT16 dic_idx, NJ_WORD *word) {
373     NJ_INT16 ret = 0;
374     NJ_UINT32 dic_type;
375 
376 
377 
378     if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END) {
379         return 0;
380     }
381 
382     if (loctset->loct.handle == NULL) {
383         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_WORD_DATA, NJ_ERR_DIC_TYPE_INVALID);
384     }
385 
386     dic_type = NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle);
387 
388     switch (dic_type) {
389     case NJ_DIC_TYPE_JIRITSU:
390     case NJ_DIC_TYPE_FZK:
391     case NJ_DIC_TYPE_TANKANJI:
392     case NJ_DIC_TYPE_STDFORE:
393     case NJ_DIC_TYPE_CUSTOM_COMPRESS:
394     case NJ_DIC_TYPE_FORECONV:
395         ret = njd_b_get_word(loctset, word);
396         break;
397 
398     case NJ_DIC_TYPE_USER:
399     case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
400         ret = njd_l_get_word(iwnn, loctset, word);
401         break;
402 
403     case NJ_DIC_TYPE_YOMINASHI:
404         ret = njd_f_get_word(loctset, word);
405         break;
406 
407     default:
408         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_WORD_DATA, NJ_ERR_DIC_TYPE_INVALID);
409     }
410     return ret;
411 }
412 
set_operation_id(NJ_SEARCH_LOCATION * dicinfo,NJ_UINT8 reverse,NJ_RESULT * result)413 static void set_operation_id(NJ_SEARCH_LOCATION *dicinfo, NJ_UINT8 reverse, NJ_RESULT *result) {
414     NJ_UINT16 dictype;
415     NJ_UINT32 type;
416 
417     if (dicinfo->handle == NULL) {
418 
419         dictype = NJ_DIC_STATIC;
420         return;
421     }
422 
423     type = NJ_GET_DIC_TYPE_EX(NJ_GET_DIC_INFO(dicinfo), dicinfo->handle);
424 
425 
426     switch (type) {
427     case NJ_DIC_TYPE_JIRITSU:
428     case NJ_DIC_TYPE_FZK:
429     case NJ_DIC_TYPE_TANKANJI:
430     case NJ_DIC_TYPE_STDFORE:
431     case NJ_DIC_TYPE_YOMINASHI:
432 
433     case NJ_DIC_TYPE_FORECONV:
434         dictype = NJ_DIC_STATIC;
435         break;
436 
437     case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
438     case NJ_DIC_TYPE_CUSTOM_COMPRESS:
439         dictype = NJ_DIC_CUSTOMIZE;
440         break;
441 
442     case NJ_DIC_TYPE_USER:
443         dictype = NJ_DIC_USER;
444         break;
445 
446     default:
447 
448         dictype = NJ_DIC_STATIC;
449     }
450 
451 
452     result->operation_id =
453         (NJ_UINT16)((NJ_UINT16)NJ_OP_SEARCH | (NJ_UINT16)NJ_FUNC_SEARCH | dictype);
454 }
455 
njd_search_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor,NJ_UINT8 comp_flg,NJ_UINT8 * exit_flag)456 static NJ_INT16 njd_search_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_UINT8 comp_flg,
457                          NJ_UINT8 *exit_flag) {
458     NJ_INT16 ret;
459 
460 
461     ret = check_search_cursor(iwnn, cursor);
462     if (ret != 0) {
463         return ret;
464     }
465 
466     return search_word(iwnn, cursor, comp_flg, exit_flag);
467 }
468 
njd_get_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor,NJ_RESULT * result,NJ_UINT8 comp_flg)469 static NJ_INT16 njd_get_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_RESULT *result,
470                       NJ_UINT8 comp_flg) {
471 
472     NJ_INT16    ret;
473 
474 
475     ret = get_word_and_search_next_word(iwnn, cursor, result, comp_flg);
476 
477     return ret;
478 }
479 
njd_get_stroke(NJ_CLASS * iwnn,NJ_RESULT * result,NJ_CHAR * stroke,NJ_UINT16 size)480 NJ_INT16 njd_get_stroke(NJ_CLASS *iwnn, NJ_RESULT *result, NJ_CHAR *stroke, NJ_UINT16 size) {
481     NJ_INT16 ret = 0;
482     NJ_UINT16 len;
483     NJ_UINT32 dictype;
484 
485 
486     if (result->word.stem.loc.handle == NULL) {
487         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_STROKE, NJ_ERR_INVALID_RESULT);
488     }
489 
490     dictype = NJ_GET_DIC_TYPE_EX(result->word.stem.loc.type, result->word.stem.loc.handle);
491 
492     switch (dictype) {
493     case NJ_DIC_TYPE_JIRITSU:
494     case NJ_DIC_TYPE_FZK:
495     case NJ_DIC_TYPE_TANKANJI:
496     case NJ_DIC_TYPE_STDFORE:
497     case NJ_DIC_TYPE_CUSTOM_COMPRESS:
498     case NJ_DIC_TYPE_FORECONV:
499         if (GET_LOCATION_OPERATION(result->word.stem.loc.status) != NJ_CUR_OP_COMP) {
500             ret = njd_b_get_stroke(&result->word, stroke, size);
501         } else {
502             len = NJ_GET_YLEN_FROM_STEM(&result->word);
503 
504             if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) {
505                 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_STROKE,
506                                       NJ_ERR_BUFFER_NOT_ENOUGH);
507             }
508             if (len == 0) {
509                 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_STROKE,
510                                       NJ_ERR_INVALID_RESULT);
511             }
512             nj_strncpy(stroke, result->word.yomi, len);
513             *(stroke + len) = NJ_CHAR_NUL;
514             return len;
515         }
516         break;
517 
518     case NJ_DIC_TYPE_USER:
519     case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
520         ret = njd_l_get_stroke(iwnn, &result->word, stroke, size);
521         break;
522 
523     case NJ_DIC_TYPE_YOMINASHI:
524         ret = njd_f_get_stroke(&result->word, stroke, size);
525         break;
526 
527     default:
528         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_STROKE, NJ_ERR_DIC_TYPE_INVALID);
529     }
530 
531     if (ret == 0) {
532         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_STROKE, NJ_ERR_INVALID_RESULT);
533     }
534     return ret;
535 }
536 
537 
njd_get_candidate(NJ_CLASS * iwnn,NJ_RESULT * result,NJ_CHAR * candidate,NJ_UINT16 size)538 NJ_INT16 njd_get_candidate(NJ_CLASS *iwnn, NJ_RESULT *result,
539                            NJ_CHAR *candidate, NJ_UINT16 size) {
540     NJ_INT16 ret = 0;
541     NJ_UINT32 dictype;
542 
543 
544     if (result->word.stem.loc.handle == NULL) {
545         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_CANDIDATE, NJ_ERR_INVALID_RESULT);
546     }
547 
548     dictype = NJ_GET_DIC_TYPE_EX(result->word.stem.loc.type, result->word.stem.loc.handle);
549 
550     switch (dictype) {
551     case NJ_DIC_TYPE_JIRITSU:
552     case NJ_DIC_TYPE_FZK:
553     case NJ_DIC_TYPE_TANKANJI:
554     case NJ_DIC_TYPE_STDFORE:
555     case NJ_DIC_TYPE_CUSTOM_COMPRESS:
556     case NJ_DIC_TYPE_FORECONV:
557         ret = njd_b_get_candidate(&result->word, candidate, size);
558         break;
559 
560     case NJ_DIC_TYPE_USER:
561     case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
562         ret = njd_l_get_candidate(iwnn, &result->word, candidate, size);
563         break;
564 
565     case NJ_DIC_TYPE_YOMINASHI:
566         ret = njd_f_get_candidate(&result->word, candidate, size);
567         break;
568 
569     default:
570         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_CANDIDATE, NJ_ERR_DIC_TYPE_INVALID);
571     }
572 
573     if (ret == 0) {
574         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_GET_CANDIDATE, NJ_ERR_INVALID_RESULT);
575     }
576     return ret;
577 }
578 
579 
njd_check_dic(NJ_CLASS * iwnn,NJ_DIC_HANDLE handle)580 static NJ_INT16 njd_check_dic(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle) {
581     NJ_UINT8 *addr;
582     NJ_UINT32 datasize, extsize;
583     NJ_UINT32 version;
584     NJ_UINT32 type;
585 
586 
587     addr = handle;
588 
589 
590     if (NJ_INT32_READ(addr) != NJ_DIC_IDENTIFIER) {
591         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
592     }
593     addr += sizeof(NJ_UINT32);
594 
595 
596     version = NJ_INT32_READ(addr);
597     if ((version != NJ_DIC_VERSION1) && (version != NJ_DIC_VERSION2) &&
598         (version != NJ_DIC_VERSION2_1) && (version != NJ_DIC_VERSION3)) {
599         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
600     }
601     addr += sizeof(NJ_UINT32);
602 
603 
604     type = NJ_INT32_READ(addr);
605     addr += sizeof(NJ_UINT32);
606 
607 
608     datasize = NJ_INT32_READ(addr);
609     addr += sizeof(NJ_UINT32);
610 
611 
612     extsize = NJ_INT32_READ(addr);
613     addr += sizeof(NJ_UINT32);
614 
615 
616     if (NJ_INT32_READ(addr) > (NJ_MAX_LEN * sizeof(NJ_CHAR))) {
617         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
618     }
619     addr += sizeof(NJ_UINT32);
620 
621 
622     if (NJ_INT32_READ(addr) > (NJ_MAX_RESULT_LEN * sizeof(NJ_CHAR))) {
623         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
624     }
625 
626 
627     addr += (extsize + datasize);
628     if (NJ_INT32_READ(addr) != NJ_DIC_IDENTIFIER) {
629         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
630     }
631 
632 
633     switch (type) {
634 
635     case NJ_DIC_TYPE_JIRITSU:
636     case NJ_DIC_TYPE_FZK:
637     case NJ_DIC_TYPE_TANKANJI:
638     case NJ_DIC_TYPE_CUSTOM_COMPRESS:
639     case NJ_DIC_TYPE_STDFORE:
640 
641         if (version != (NJ_UINT32)NJ_DIC_VERSION2) {
642             return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
643         }
644         break;
645 
646     case NJ_DIC_TYPE_RULE:
647 
648         if (version != (NJ_UINT32)NJ_DIC_VERSION2_1) {
649             return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
650         }
651         break;
652 
653     case NJ_DIC_TYPE_YOMINASHI:
654 
655         if (version != (NJ_UINT32)NJ_DIC_VERSION1) {
656             return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
657         }
658         break;
659 
660     case NJ_DIC_TYPE_USER:
661 
662         if (version != (NJ_UINT32)NJ_DIC_VERSION2) {
663             return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_FORMAT_INVALID);
664         }
665         return njd_l_check_dic(iwnn, handle);
666 
667     default:
668         return NJ_SET_ERR_VAL(NJ_FUNC_NJD_CHECK_DIC, NJ_ERR_DIC_TYPE_INVALID);
669     }
670     return 0;
671 }
672 
673 
njx_search_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor)674 NJ_EXTERN NJ_INT16 njx_search_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor) {
675 
676     NJ_SEARCH_CACHE     *pCache;
677     NJ_CHAR             *p_yomi, *p_key;
678     NJ_UINT16           initst, inited;
679     NJ_UINT16           clrcnt, diccnt;
680     NJ_UINT16           kw_len;
681     NJ_UINT16           cacheOverKeyPtr;
682 
683     NJ_UINT8 exit_flag;
684     NJ_UINT8 cnt;
685     NJ_DIC_HANDLE dhdl;
686     NJ_PREVIOUS_SELECTION_INFO *prev_info = &(iwnn->previous_selection);
687 
688 
689     if (iwnn == NULL) {
690         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_SEARCH_WORD, NJ_ERR_PARAM_ENV_NULL);
691     }
692     if (cursor == NULL) {
693         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_SEARCH_WORD, NJ_ERR_PARAM_CURSOR_NULL);
694     }
695 
696 
697     cursor->cond.hinsi.fore = NULL;
698     cursor->cond.hinsi.foreSize = 0;
699     cursor->cond.hinsi.foreFlag = 0;
700     cursor->cond.hinsi.rear = NULL;
701     cursor->cond.hinsi.rearSize = 0;
702     cursor->cond.hinsi.rearFlag = 0;
703 
704 
705     if (cursor->cond.yomi == NULL) {
706         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_YOMI_NULL);
707     }
708     cursor->cond.ylen = nj_strlen(cursor->cond.yomi);
709     cursor->cond.yclen = nj_charlen(cursor->cond.yomi);
710 
711 
712     if (cursor->cond.ds == NULL) {
713         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_PARAM_DIC_NULL);
714     }
715 
716 
717     cursor->cond.ds->mode = NJ_CACHE_MODE_VALID;
718 
719     p_yomi = cursor->cond.yomi;
720     p_key  = cursor->cond.ds->keyword;
721 
722     for (clrcnt = 0; clrcnt < cursor->cond.yclen; clrcnt++) {
723         if (nj_charncmp(p_yomi, p_key, 1) != 0) {
724             break;
725         }
726         p_yomi += NJ_CHAR_LEN(p_yomi);
727         p_key  += NJ_CHAR_LEN(p_key);
728     }
729     if (clrcnt != 0) {
730         initst = clrcnt + 1;
731     } else {
732         initst = 0;
733     }
734 
735     kw_len = nj_charlen(cursor->cond.ds->keyword);
736     if (kw_len >= cursor->cond.yclen) {
737       inited = kw_len + 1;
738     } else {
739       inited = cursor->cond.yclen + 1;
740     }
741 
742     for (diccnt = 0; diccnt < NJ_MAX_DIC; diccnt++) {
743         pCache = cursor->cond.ds->dic[diccnt].srhCache;
744         if (pCache != NULL) {
745 
746             if (NJ_GET_CACHEOVER_FROM_SCACHE(pCache)) {
747 
748                 for (cacheOverKeyPtr = 0; cacheOverKeyPtr < kw_len; cacheOverKeyPtr++) {
749                     if (pCache->keyPtr[cacheOverKeyPtr] == pCache->keyPtr[cacheOverKeyPtr + 1] ) {
750                         break;
751                     }
752                 }
753                 cacheOverKeyPtr++;
754 
755 
756                 if (cacheOverKeyPtr < initst) {
757                     clrcnt = cacheOverKeyPtr;
758                 } else {
759                     clrcnt = initst;
760                 }
761                 for (; clrcnt < inited; clrcnt++) {
762                     pCache->keyPtr[clrcnt] = 0x0000;
763                 }
764 
765                 for (clrcnt = 1; clrcnt < inited; clrcnt++ ) {
766                     if ((pCache->keyPtr[clrcnt - 1] > pCache->keyPtr[clrcnt]) &&
767                         (pCache->keyPtr[clrcnt] != 0)) {
768                         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_CACHE_BROKEN);
769                     }
770                 }
771                 NJ_UNSET_CACHEOVER_TO_SCACHE(pCache);
772             } else {
773                 for (clrcnt = initst; clrcnt < inited; clrcnt++) {
774                     pCache->keyPtr[clrcnt] = 0x0000;
775                 }
776 
777                 for (clrcnt = 1; clrcnt < inited; clrcnt++ ) {
778                     if ((pCache->keyPtr[clrcnt - 1] > pCache->keyPtr[clrcnt]) &&
779                         (pCache->keyPtr[clrcnt] != 0)) {
780                         return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_CACHE_BROKEN);
781                     }
782                 }
783             }
784         }
785     }
786 
787 
788     nj_strcpy(cursor->cond.ds->keyword, cursor->cond.yomi);
789 
790     for (cnt = 0; cnt < NJ_MAX_DIC; cnt++) {
791         dhdl = cursor->cond.ds->dic[cnt].handle;
792 
793         if (dhdl != NULL) {
794             if ((cursor->cond.ds->dic[cnt].dic_freq[NJ_MODE_TYPE_HENKAN].base
795                  > cursor->cond.ds->dic[cnt].dic_freq[NJ_MODE_TYPE_HENKAN].high)) {
796                     return NJ_SET_ERR_VAL(NJ_FUNC_CHECK_SEARCH_CURSOR, NJ_ERR_DIC_FREQ_INVALID);
797                 }
798         }
799     }
800 
801     if( prev_info->count == 0 ) {
802         cursor->cond.hinsi.yominasi_fore = NULL;
803     } else {
804         int prev_hinsi = prev_info->selection_data.b_hinsi;
805 
806 
807         njd_r_get_connect(cursor->cond.ds->rHandle[NJ_MODE_TYPE_HENKAN], prev_hinsi,
808                           0, &(cursor->cond.hinsi.yominasi_fore));
809         njd_r_get_count(cursor->cond.ds->rHandle[NJ_MODE_TYPE_HENKAN],
810                         &(cursor->cond.hinsi.foreSize), &(cursor->cond.hinsi.rearSize));
811     }
812 
813     return njd_search_word(iwnn, cursor, 0, &exit_flag);
814 }
815 
816 
njx_get_word(NJ_CLASS * iwnn,NJ_CURSOR * cursor,NJ_RESULT * result)817 NJ_EXTERN NJ_INT16 njx_get_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_RESULT *result) {
818     NJ_INT16  ret;
819 
820 
821 
822     if (iwnn == NULL) {
823         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_GET_WORD, NJ_ERR_PARAM_ENV_NULL);
824     }
825     if (cursor == NULL) {
826         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_GET_WORD, NJ_ERR_PARAM_CURSOR_NULL);
827     }
828     if (result == NULL) {
829         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_GET_WORD, NJ_ERR_PARAM_RESULT_NULL);
830     }
831 
832     ret = njd_get_word(iwnn, cursor, result, 0);
833 
834     return ret;
835 }
836 
837 
838 
njx_check_dic(NJ_CLASS * iwnn,NJ_DIC_HANDLE handle,NJ_UINT8 restore,NJ_UINT32 size)839 NJ_EXTERN NJ_INT16 njx_check_dic(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT8 restore, NJ_UINT32 size) {
840 
841 
842     if (iwnn == NULL) {
843         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_CHECK_DIC, NJ_ERR_PARAM_ENV_NULL);
844     }
845 
846     if (handle == NULL) {
847         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_CHECK_DIC, NJ_ERR_DIC_HANDLE_NULL);
848     }
849 
850 
851 
852     if (size <= NJ_DIC_COMMON_HEADER_SIZE) {
853         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_CHECK_DIC, NJ_ERR_AREASIZE_INVALID);
854     }
855 
856 
857 
858     if (size != (NJ_DIC_COMMON_HEADER_SIZE
859                  + NJ_INT32_READ(handle + NJ_DIC_POS_DATA_SIZE)
860                  + NJ_INT32_READ(handle + NJ_DIC_POS_EXT_SIZE))) {
861         return NJ_SET_ERR_VAL(NJ_FUNC_NJ_CHECK_DIC, NJ_ERR_AREASIZE_INVALID);
862     }
863 
864     return njd_check_dic(iwnn, handle);
865 }
866 
njd_init_search_location_set(NJ_SEARCH_LOCATION_SET * loctset)867 NJ_INT16 njd_init_search_location_set(NJ_SEARCH_LOCATION_SET* loctset)
868 {
869 
870     loctset->cache_freq         = 0;
871     loctset->dic_freq.base      = 0;
872     loctset->dic_freq.high      = 0;
873     loctset->loct.type          = NJ_DIC_H_TYPE_NORMAL;
874     loctset->loct.handle        = NULL;
875     loctset->loct.current_info  = 0x10;
876     loctset->loct.current       = 0;
877     loctset->loct.top           = 0;
878     loctset->loct.bottom        = 0;
879     loctset->loct.current_cache = 0;
880     loctset->loct.status        = NJ_ST_SEARCH_NO_INIT;
881 
882     return 1;
883 }
884 
njd_init_word(NJ_WORD * word)885 NJ_INT16 njd_init_word(NJ_WORD* word)
886 {
887 
888     word->yomi                  = NULL;
889     word->stem.info1            = 0;
890     word->stem.info2            = 0;
891     word->stem.hindo            = 0;
892     word->fzk.info1             = 0;
893     word->fzk.info2             = 0;
894     word->fzk.hindo             = 0;
895 
896     word->stem.loc.handle       = NULL;
897     word->stem.loc.type         = NJ_DIC_H_TYPE_NORMAL;
898     word->stem.loc.current      = 0;
899     word->stem.loc.top          = 0;
900     word->stem.loc.bottom       = 0;
901     word->stem.loc.current_cache= 0;
902     word->stem.loc.current_info = 0x10;
903     word->stem.loc.status       = NJ_ST_SEARCH_NO_INIT;
904 
905     return 1;
906 }
907