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
41static NJ_INT16 check_search_cursor(NJ_CLASS *iwnn, NJ_CURSOR *cursor);
42static NJ_INT16 search_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_UINT8 comp_flg, NJ_UINT8 *exit_flag);
43static void set_operation_id(NJ_SEARCH_LOCATION *dicinfo, NJ_UINT8 reverse, NJ_RESULT *result);
44static NJ_INT16 get_word_and_search_next_word(NJ_CLASS *iwnn, NJ_CURSOR *cursor, NJ_RESULT *result, NJ_UINT8 comp_flg);
45
46static NJ_INT16 njd_check_dic(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle);
47
48static 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
123static 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
186static 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
372NJ_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
413static 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
456static 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
469static 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
480NJ_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
538NJ_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
580static 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
674NJ_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
817NJ_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
839NJ_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
867NJ_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
885NJ_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