diff options
Diffstat (limited to 'src/plugins/openwnn/3rdparty/openwnn/wnnEngine/openwnndictionary.cpp')
-rw-r--r-- | src/plugins/openwnn/3rdparty/openwnn/wnnEngine/openwnndictionary.cpp | 913 |
1 files changed, 913 insertions, 0 deletions
diff --git a/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/openwnndictionary.cpp b/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/openwnndictionary.cpp new file mode 100644 index 00000000..1063fd9a --- /dev/null +++ b/src/plugins/openwnn/3rdparty/openwnn/wnnEngine/openwnndictionary.cpp @@ -0,0 +1,913 @@ +/* + * Qt implementation of OpenWnn library + * This file is part of the Qt Virtual Keyboard module. + * Contact: http://www.qt.io/licensing/ + * + * Copyright (C) 2015 The Qt Company + * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nj_lib.h" +#include "nj_err.h" +#include "nj_ext.h" +#include "nj_dic.h" + + +#include <stdlib.h> +#include <string.h> + +#include "openwnndictionary.h" + +#include <QtCore/private/qobject_p.h> + +/** + * Error codes + */ +#define NJ_FUNC_SET_DICTIONARY_PARAMETERS 0x00FA +#define NJ_FUNC_SET_APPROX_PATTERN 0x00F6 +#define NJ_FUNC_GET_LEFT_PART_OF_SPEECH 0x00F5 +#define NJ_FUNC_GET_RIGHT_PART_OF_SPEECH 0x00F4 +#define NJ_FUNC_SET_LEFT_PART_OF_SPEECH 0x00F3 +#define NJ_FUNC_SET_RIGHT_PART_OF_SPEECH 0x00F2 +#define NJ_FUNC_SET_STROKE 0x00F1 +#define NJ_FUNC_SET_CANDIDATE 0x00F0 +#define NJ_FUNC_GET_LEFT_PART_OF_SPEECH_SPECIFIED_TYPE 0x00EE +#define NJ_FUNC_GET_RIGHT_PART_OF_SPEECH_SPECIFIED_TYPE 0x00ED + +#define NJ_ERR_ALLOC_FAILED 0x7D00 +#define NJ_ERR_NOT_ALLOCATED 0x7C00 +#define NJ_ERR_INVALID_PARAM 0x7B00 +#define NJ_ERR_APPROX_PATTERN_IS_FULL 0x7A00 + +/** + * Structure of internal work area + */ +#define NJ_MAX_CHARSET_FROM_LEN 1 +#define NJ_MAX_CHARSET_TO_LEN 3 +#define NJ_APPROXSTORE_SIZE (NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN + NJ_MAX_CHARSET_TO_LEN + NJ_TERM_LEN) + + +#define NJ_JNI_FLAG_NONE (0x00) +#define NJ_JNI_FLAG_ENABLE_CURSOR (0x01) +#define NJ_JNI_FLAG_ENABLE_RESULT (0x02) + +/** + * Predefined approx patterns + */ +typedef struct { + int size; + NJ_UINT8 *from; + NJ_UINT8 *to; +} PREDEF_APPROX_PATTERN; + +#include "predef_table.h" + +typedef struct { + NJ_DIC_HANDLE dicHandle[NJ_MAX_DIC]; + NJ_UINT32 dicSize[NJ_MAX_DIC]; + NJ_UINT8 dicType[NJ_MAX_DIC]; + NJ_CHAR keyString[NJ_MAX_LEN + NJ_TERM_LEN]; + NJ_RESULT result; + NJ_CURSOR cursor; + NJ_SEARCH_CACHE srhCache[NJ_MAX_DIC]; + NJ_DIC_SET dicSet; + NJ_CLASS wnnClass; + NJ_CHARSET approxSet; + NJ_CHAR approxStr[NJ_MAX_CHARSET * NJ_APPROXSTORE_SIZE]; + NJ_CHAR previousStroke[NJ_MAX_LEN + NJ_TERM_LEN]; + NJ_CHAR previousCandidate[NJ_MAX_RESULT_LEN + NJ_TERM_LEN]; + NJ_UINT8 flag; +} NJ_WORK; + +extern "C" { + extern NJ_UINT32 dic_size[]; + extern NJ_UINT8 dic_type[]; + extern NJ_UINT8 *dic_data[]; + extern NJ_UINT8 *con_data[]; +} + +class OpenWnnDictionaryPrivate : public QObjectPrivate +{ +public: + OpenWnnDictionaryPrivate() + { + init(); + } + + ~OpenWnnDictionaryPrivate() + { + } + + void init() + { + /* Initialize the work area */ + memset(&work, 0, sizeof(NJ_WORK)); + + for (int i = 0; i < NJ_MAX_DIC; i++) { + work.dicHandle[i] = dic_data[i]; + work.dicSize[i] = dic_size[i]; + work.dicType[i] = dic_type[i]; + } + + if (con_data != NULL) { + work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] = con_data[0]; + } + + /* Execute the initialize method to initialize the internal work area */ + njx_init(&(work.wnnClass)); + } + + static void clearDictionaryStructure(NJ_DIC_INFO *dicInfo) + { + dicInfo->type = 0; + dicInfo->handle = NULL; + /* dicInfo->srhCache = NULL; */ + + dicInfo->dic_freq[NJ_MODE_TYPE_HENKAN].base = 0; + dicInfo->dic_freq[NJ_MODE_TYPE_HENKAN].high = 0; + } + + static NJ_CHAR convertUTFCharToNjChar(const NJ_UINT8 *src) + { + NJ_CHAR ret; + NJ_UINT8* dst; + + /* convert UTF-16BE character to NJ_CHAR format */ + dst = (NJ_UINT8*)&ret; + dst[0] = src[0]; + dst[1] = src[1]; + + return ret; + } + + static void convertStringToNjChar(NJ_CHAR *dst, const QString &srcString, int maxChars) + { + const QByteArray utf8Data(srcString.toUtf8()); + const unsigned char *src = (const unsigned char *)utf8Data.constData(); + int i, o; + + /* convert UTF-8 to UTF-16BE */ + for (i = o = 0; src[i] != 0x00 && o < maxChars;) { + NJ_UINT8 *dst_tmp; + dst_tmp = (NJ_UINT8 *)&(dst[o]); + + if ((src[i] & 0x80) == 0x00) { + /* U+0000 ... U+007f */ + /* 8[0xxxxxxx] -> 16BE[00000000 0xxxxxxx] */ + dst_tmp[0] = 0x00; + dst_tmp[1] = src[i + 0] & 0x7f; + i++; + o++; + } else if ((src[i] & 0xe0) == 0xc0) { + /* U+0080 ... U+07ff */ + /* 8[110xxxxx 10yyyyyy] -> 16BE[00000xxx xxyyyyyy] */ + if (src[i + 1] == 0x00) { + break; + } + dst_tmp[0] = ((src[i + 0] & 0x1f) >> 2); + dst_tmp[1] = ((src[i + 0] & 0x1f) << 6) | (src[i + 1] & 0x3f); + i += 2; + o++; + } else if ((src[i] & 0xf0) == 0xe0) { + /* U+0800 ... U+ffff */ + /* 8[1110xxxx 10yyyyyy 10zzzzzz] -> 16BE[xxxxyyyy yyzzzzzz] */ + if (src[i + 1] == 0x00 || src[i + 2] == 0x00) { + break; + } + dst_tmp[0] = ((src[i + 0] & 0x0f) << 4) | ((src[i + 1] & 0x3f) >> 2); + dst_tmp[1] = ((src[i + 1] & 0x3f) << 6) | (src[i + 2] & 0x3f); + i += 3; + o++; + } else if ((src[i] & 0xf8) == 0xf0) { + NJ_UINT8 dst1, dst2, dst3; + /* U+10000 ... U+10ffff */ + /* 8[11110www 10xxxxxx 10yyyyyy 10zzzzzz] -> 32BE[00000000 000wwwxx xxxxyyyy yyzzzzzz] */ + /* -> 16BE[110110WW XXxxxxyy 110111yy yyzzzzzz] */ + /* -- --====== == -------- */ + /* dst1 dst2 dst3 */ + /* "wwwxx"(00001-10000) - 1 = "WWXX"(0000-1111) */ + if (!(o < maxChars - 1)) { + /* output buffer is full */ + break; + } + if (src[i + 1] == 0x00 || src[i + 2] == 0x00 || src[i + 3] == 0x00) { + break; + } + dst1 = (((src[i + 0] & 0x07) << 2) | ((src[i + 1] & 0x3f) >> 4)) - 1; + dst2 = ((src[i + 1] & 0x3f) << 4) | ((src[i + 2] & 0x3f) >> 2); + dst3 = ((src[i + 2] & 0x3f) << 6) | (src[i + 3] & 0x3f); + + dst_tmp[0] = 0xd8 | ((dst1 & 0x0c) >> 2); + dst_tmp[1] = ((dst1 & 0x03) << 6) | ((dst2 & 0xfc) >> 2); + dst_tmp[2] = 0xdc | ((dst2 & 0x03)); + dst_tmp[3] = dst3; + i += 4; + o += 2; + } else { /* Broken code */ + break; + } + } + + dst[o] = NJ_CHAR_NUL; + } + + static QString convertNjCharToString(const NJ_CHAR *src, int maxChars) + { + QByteArray dst((NJ_MAX_LEN + NJ_MAX_RESULT_LEN + NJ_TERM_LEN) * 3 + 1, Qt::Uninitialized); + + int i, o; + + /* convert UTF-16BE to a UTF-8 */ + for (i = o = 0; src[i] != 0x0000 && i < maxChars;) { + NJ_UINT8* src_tmp; + src_tmp = (NJ_UINT8*)&(src[i]); + + if (src_tmp[0] == 0x00 && src_tmp[1] <= 0x7f) { + /* U+0000 ... U+007f */ + /* 16BE[00000000 0xxxxxxx] -> 8[0xxxxxxx] */ + dst[o + 0] = src_tmp[1] & 0x007f; + i++; + o++; + } else if (src_tmp[0] <= 0x07) { + /* U+0080 ... U+07ff */ + /* 16BE[00000xxx xxyyyyyy] -> 8[110xxxxx 10yyyyyy] */ + dst[o + 0] = 0xc0 | ((src_tmp[0] & 0x07) << 2) | ((src_tmp[1] & 0xc0) >> 6); + dst[o + 1] = 0x80 | ((src_tmp[1] & 0x3f)); + i++; + o += 2; + } else if (src_tmp[0] >= 0xd8 && src_tmp[0] <= 0xdb) { + NJ_UINT8 src1, src2, src3; + /* U+10000 ... U+10ffff (surrogate pair) */ + /* 32BE[00000000 000wwwxx xxxxyyyy yyzzzzzz] -> 8[11110www 10xxxxxx 10yyyyyy 10zzzzzz] */ + /* 16BE[110110WW XXxxxxyy 110111yy yyzzzzzz] */ + /* -- --====== == -------- */ + /* src1 src2 src3 */ + /* "WWXX"(0000-1111) + 1 = "wwwxx"(0001-10000) */ + if (!(i < maxChars - 1) || src_tmp[2] < 0xdc || src_tmp[2] > 0xdf) { + /* That is broken code */ + break; + } + src1 = (((src_tmp[0] & 0x03) << 2) | ((src_tmp[1] & 0xc0) >> 6)) + 1; + src2 = ((src_tmp[1] & 0x3f) << 2) | ((src_tmp[2] & 0x03)); + src3 = src_tmp[3]; + + dst[o + 0] = 0xf0 | ((src1 & 0x1c) >> 2); + dst[o + 1] = 0x80 | ((src1 & 0x03) << 4) | ((src2 & 0xf0) >> 4); + dst[o + 2] = 0x80 | ((src2 & 0x0f) << 2) | ((src3 & 0xc0) >> 6); + dst[o + 3] = 0x80 | (src3 & 0x3f); + i += 2; + o += 4; + } else { + /* U+0800 ... U+ffff (except range of surrogate pair) */ + /* 16BE[xxxxyyyy yyzzzzzz] -> 8[1110xxxx 10yyyyyy 10zzzzzz] */ + dst[o + 0] = 0xe0 | ((src_tmp[0] & 0xf0) >> 4); + dst[o + 1] = 0x80 | ((src_tmp[0] & 0x0f) << 2) | ((src_tmp[1] & 0xc0) >> 6); + dst[o + 2] = 0x80 | ((src_tmp[1] & 0x3f)); + i++; + o += 3; + } + } + dst.resize(o); + + return QString::fromUtf8(dst.constData(), dst.size()); + } + + void clearDictionaryParameters() + { + int index; + + /* Clear all dictionary set information structure and reset search state */ + for (index = 0; index < NJ_MAX_DIC; index++) { + clearDictionaryStructure(&(work.dicSet.dic[index])); + } + work.flag = NJ_JNI_FLAG_NONE; + + /* Clear the cache information */ + memset(work.dicSet.keyword, 0, sizeof(work.dicSet.keyword)); + } + + int setDictionaryParameter(int index, int base, int high) + { + if ((index < 0 || index > NJ_MAX_DIC-1) || + (base < -1 || base > 1000) || + (high < -1 || high > 1000)) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_DICTIONARY_PARAMETERS, NJ_ERR_INVALID_PARAM); + } + + /* Create the dictionary set information structure */ + if (base < 0 || high < 0 || base > high) { + /* If -1 was specified to base or high, clear that dictionary information structure */ + /* If base is larger than high, clear that dictionary information structure */ + clearDictionaryStructure(&(work.dicSet.dic[index])); + } else { + /* Set the dictionary information structure */ + work.dicSet.dic[index].type = work.dicType[index]; + work.dicSet.dic[index].handle = work.dicHandle[index]; + work.dicSet.dic[index].srhCache = &(work.srhCache[index]); + + work.dicSet.dic[index].dic_freq[NJ_MODE_TYPE_HENKAN].base = base; + work.dicSet.dic[index].dic_freq[NJ_MODE_TYPE_HENKAN].high = high; + } + + /* Reset search state because the dicionary information was changed */ + work.flag = NJ_JNI_FLAG_NONE; + + return 0; + } + + int searchWord(OpenWnnDictionary::SearchOperation operation, OpenWnnDictionary::SearchOrder order, const QString &keyString) + { + if (!(operation == OpenWnnDictionary::SEARCH_EXACT || + operation == OpenWnnDictionary::SEARCH_PREFIX || + operation == OpenWnnDictionary::SEARCH_LINK) || + !(order == OpenWnnDictionary::ORDER_BY_FREQUENCY || + order == OpenWnnDictionary::ORDER_BY_KEY) || + keyString.isEmpty()) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_WORD, NJ_ERR_INVALID_PARAM); + } + + if (keyString.length() > NJ_MAX_LEN) { + /* If too long key string was specified, return "No result is found" */ + work.flag &= ~NJ_JNI_FLAG_ENABLE_CURSOR; + work.flag &= ~NJ_JNI_FLAG_ENABLE_RESULT; + return 0; + } + + convertStringToNjChar(work.keyString, keyString, NJ_MAX_LEN); + + /* Set the structure for search */ + memset(&(work.cursor), 0, sizeof(NJ_CURSOR)); + work.cursor.cond.operation = operation; + work.cursor.cond.mode = order; + work.cursor.cond.ds = &(work.dicSet); + work.cursor.cond.yomi = work.keyString; + work.cursor.cond.charset = &(work.approxSet); + + /* If the link search feature is specified, set the predict search information to structure */ + if (operation == OpenWnnDictionary::SEARCH_LINK) { + work.cursor.cond.yomi = work.previousStroke; + work.cursor.cond.kanji = work.previousCandidate; + } + + /* Search a specified word */ + memcpy(&(work.wnnClass.dic_set), &(work.dicSet), sizeof(NJ_DIC_SET)); + int result = njx_search_word(&(work.wnnClass), &(work.cursor)); + + /* If a result is found, enable getNextWord method */ + if (result == 1) { + work.flag |= NJ_JNI_FLAG_ENABLE_CURSOR; + } else { + work.flag &= ~NJ_JNI_FLAG_ENABLE_CURSOR; + } + work.flag &= ~NJ_JNI_FLAG_ENABLE_RESULT; + + return result; + } + + int getNextWord(int length) + { + if (work.flag & NJ_JNI_FLAG_ENABLE_CURSOR) { + int result; + + /* Get a specified word and search a next word */ + if (length <= 0) { + result = njx_get_word(&(work.wnnClass), &(work.cursor), &(work.result)); + } else { + do { + result = njx_get_word(&(work.wnnClass), &(work.cursor), &(work.result)); + if (length == (NJ_GET_YLEN_FROM_STEM(&(work.result.word)) + NJ_GET_YLEN_FROM_FZK(&(work.result.word)))) { + break; + } + } while(result > 0); + } + + /* If a result is found, enable getStroke, getCandidate, getFrequency methods */ + if (result > 0) { + work.flag |= NJ_JNI_FLAG_ENABLE_RESULT; + } else { + work.flag &= ~NJ_JNI_FLAG_ENABLE_RESULT; + } + return result; + } else { + /* When njx_search_word() was not yet called, return "No result is found" */ + return 0; + } + } + + QString getStroke() + { + if (work.flag & NJ_JNI_FLAG_ENABLE_RESULT) { + NJ_CHAR stroke[NJ_MAX_LEN + NJ_TERM_LEN]; + + if (njx_get_stroke(&(work.wnnClass), &(work.result), stroke, sizeof(NJ_CHAR) * (NJ_MAX_LEN + NJ_TERM_LEN)) >= 0) { + return convertNjCharToString(stroke, NJ_MAX_LEN); + } + } + return QString(); + } + + QString getCandidate() + { + if (work.flag & NJ_JNI_FLAG_ENABLE_RESULT) { + NJ_CHAR candidate[NJ_MAX_LEN + NJ_TERM_LEN]; + + if (njx_get_candidate(&(work.wnnClass), &(work.result), candidate, sizeof(NJ_CHAR) * (NJ_MAX_RESULT_LEN + NJ_TERM_LEN)) >= 0) { + return convertNjCharToString(candidate, NJ_MAX_RESULT_LEN); + } + } + return QString(); + } + + int getFrequency() + { + if (work.flag & NJ_JNI_FLAG_ENABLE_RESULT) { + return work.result.word.stem.hindo; + } + return 0; + } + + int getLeftPartOfSpeech() + { + return NJ_GET_FPOS_FROM_STEM(&(work.result.word)); + } + + int getRightPartOfSpeech() + { + return NJ_GET_BPOS_FROM_STEM(&(work.result.word)); + } + + void clearApproxPatterns() + { + /* Clear state */ + work.flag = NJ_JNI_FLAG_NONE; + + /* Clear approximate patterns */ + work.approxSet.charset_count = 0; + for (int i = 0; i < NJ_MAX_CHARSET; i++) { + work.approxSet.from[i] = NULL; + work.approxSet.to[i] = NULL; + } + + /* Clear the cache information */ + memset(work.dicSet.keyword, 0, sizeof(work.dicSet.keyword)); + } + + int setApproxPattern(const QString &src, const QString &dst) + { + if (src.isEmpty() || src.length() > 1 || + dst.isEmpty() || dst.length() > 3) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_APPROX_PATTERN, NJ_ERR_INVALID_PARAM); + } + + if (work.approxSet.charset_count < NJ_MAX_CHARSET) { + NJ_CHAR* from; + NJ_CHAR* to; + + /* Set pointers of string to store approximate informations */ + from = work.approxStr + NJ_APPROXSTORE_SIZE * work.approxSet.charset_count; + to = work.approxStr + NJ_APPROXSTORE_SIZE * work.approxSet.charset_count + NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN; + work.approxSet.from[work.approxSet.charset_count] = from; + work.approxSet.to[work.approxSet.charset_count] = to; + + /* Convert approximate informations to internal format */ + convertStringToNjChar(from, src, NJ_MAX_CHARSET_FROM_LEN); + convertStringToNjChar(to, dst, NJ_MAX_CHARSET_TO_LEN); + work.approxSet.charset_count++; + + /* Reset search state because the seach condition was changed */ + work.flag = NJ_JNI_FLAG_NONE; + + return 0; + } + + /* If the approx pattern registration area was full, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_APPROX_PATTERN, NJ_ERR_APPROX_PATTERN_IS_FULL); + } + + int setApproxPattern(OpenWnnDictionary::ApproxPattern approxPattern) + { + if (!(approxPattern == OpenWnnDictionary::APPROX_PATTERN_EN_TOUPPER || + approxPattern == OpenWnnDictionary::APPROX_PATTERN_EN_TOLOWER || + approxPattern == OpenWnnDictionary::APPROX_PATTERN_EN_QWERTY_NEAR || + approxPattern == OpenWnnDictionary::APPROX_PATTERN_EN_QWERTY_NEAR_UPPER || + approxPattern == OpenWnnDictionary::APPROX_PATTERN_JAJP_12KEY_NORMAL)) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_APPROX_PATTERN, NJ_ERR_INVALID_PARAM); + } + + const PREDEF_APPROX_PATTERN *pattern = predefinedApproxPatterns[approxPattern]; + if (work.approxSet.charset_count + pattern->size <= NJ_MAX_CHARSET) { + for (int i = 0; i < pattern->size; i++) { + NJ_CHAR *from; + NJ_CHAR *to; + + /* Set pointers of string to store approximate informations */ + from = work.approxStr + NJ_APPROXSTORE_SIZE * (work.approxSet.charset_count + i); + to = work.approxStr + NJ_APPROXSTORE_SIZE * (work.approxSet.charset_count + i) + NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN; + work.approxSet.from[work.approxSet.charset_count + i] = from; + work.approxSet.to[work.approxSet.charset_count + i] = to; + + /* Set approximate pattern */ + from[0] = convertUTFCharToNjChar(pattern->from + i * 2); /* "2" means the size of UTF-16BE */ + from[1] = 0x0000; + + to[0] = convertUTFCharToNjChar(pattern->to + i * 2); /* "2" means the size of UTF-16BE */ + to[1] = 0x0000; + } + work.approxSet.charset_count += pattern->size; + + /* Reset search state because the seach condition was changed */ + work.flag = NJ_JNI_FLAG_NONE; + + return 0; + } + + /* If the approx pattern registration area was full, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_APPROX_PATTERN, NJ_ERR_APPROX_PATTERN_IS_FULL); + } + + QStringList getApproxPattern(const QString &src) + { + if (src.isEmpty() || src.length() > 1) + return QStringList(); + + NJ_CHAR from[NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN]; + convertStringToNjChar(from, src, NJ_MAX_CHARSET_FROM_LEN); + + QStringList result; + for (int i = 0; i < work.approxSet.charset_count; i++) { + if (nj_strcmp(from, work.approxSet.from[i]) == 0) { + result.append(convertNjCharToString(work.approxSet.to[i], NJ_MAX_CHARSET_TO_LEN)); + } + } + + return result; + } + + void clearResult() + { + /* Clear the current word information */ + memset(&(work.result), 0, sizeof(NJ_RESULT)); + memset(&(work.previousStroke), 0, sizeof(work.previousStroke)); + memset(&(work.previousCandidate), 0, sizeof(work.previousCandidate)); + } + + int setLeftPartOfSpeech(int leftPartOfSpeech) + { + NJ_UINT16 lcount = 0, rcount = 0; + + if (work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] == NULL) { + /* No rule dictionary was set */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_LEFT_PART_OF_SPEECH, NJ_ERR_NO_RULEDIC); + } + + njd_r_get_count(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], &lcount, &rcount); + + if (leftPartOfSpeech < 1 || leftPartOfSpeech > lcount) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_LEFT_PART_OF_SPEECH, NJ_ERR_INVALID_PARAM); + } + + NJ_SET_FPOS_TO_STEM(&(work.result.word), leftPartOfSpeech); + return 0; + } + + int setRightPartOfSpeech(int rightPartOfSpeech) + { + NJ_UINT16 lcount = 0, rcount = 0; + + if (work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] == NULL) { + /* No rule dictionary was set */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_RIGHT_PART_OF_SPEECH, NJ_ERR_NO_RULEDIC); + } + + njd_r_get_count(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], &lcount, &rcount); + + if (rightPartOfSpeech < 1 || rightPartOfSpeech > rcount) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_RIGHT_PART_OF_SPEECH, NJ_ERR_INVALID_PARAM); + } + + NJ_SET_BPOS_TO_STEM(&(work.result.word), rightPartOfSpeech); + return 0; + } + + int setStroke(const QString &stroke) + { + if (stroke.isEmpty()) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_STROKE, NJ_ERR_INVALID_PARAM); + } + + if (stroke.length() > NJ_MAX_LEN) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_STROKE, NJ_ERR_YOMI_TOO_LONG); + } + + /* Store stroke string */ + convertStringToNjChar(work.previousStroke, stroke, NJ_MAX_LEN); + + return 0; + } + + int setCandidate(const QString &candidate) + { + if (candidate.isEmpty()) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_CANDIDATE, NJ_ERR_INVALID_PARAM); + } + + if (candidate.length() > NJ_MAX_RESULT_LEN) { + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_SET_CANDIDATE, NJ_ERR_CANDIDATE_TOO_LONG); + } + + /* Store candidate string */ + convertStringToNjChar(work.previousCandidate, candidate, NJ_MAX_RESULT_LEN); + + return 0; + } + + int selectWord() + { + /* Put the previous word information to engine */ + memcpy(&(work.wnnClass.dic_set), &(work.dicSet), sizeof(NJ_DIC_SET)); + return njx_select(&(work.wnnClass), &(work.result)); + } + + QBitArray getConnectArray(int leftPartOfSpeech) + { + NJ_UINT16 lcount = 0, rcount = 0; + + if (work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] == NULL) { + /* No rule dictionary was set */ + return QBitArray(); + } + + njd_r_get_count(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], &lcount, &rcount); + + if (leftPartOfSpeech < 0 || leftPartOfSpeech > lcount) { + /* Invalid POS is specified */ + return QBitArray(); + } + + /* 1-origin */ + QBitArray result(rcount + 1); + int i; + NJ_UINT8* connect; + + if (leftPartOfSpeech > 0) { + /* Get the packed connect array */ + njd_r_get_connect(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], leftPartOfSpeech, NJ_RULE_TYPE_FTOB, &connect); + + /* Extract connect array from bit field */ + for (i = 0; i < rcount; i++) { + if (connect[i / 8] & (0x80 >> (i % 8))) { + result.setBit(i + 1); + } + } + } + return result; + } + + int getNumberOfLeftPOS() + { + if (work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] == NULL) + /* No rule dictionary was set */ + return 0; + + NJ_UINT16 lcount = 0, rcount = 0; + + njd_r_get_count(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], &lcount, &rcount); + return lcount; + } + + int getNumberOfRightPOS() + { + if (work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN] == NULL) + /* No rule dictionary was set */ + return 0; + + NJ_UINT16 lcount = 0, rcount = 0; + + njd_r_get_count(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], &lcount, &rcount); + return rcount; + } + + int getLeftPartOfSpeechSpecifiedType(OpenWnnDictionary::PartOfSpeechType posType) + { + NJ_UINT8 type; + switch(posType) { + case OpenWnnDictionary::POS_TYPE_V1: + type = NJ_HINSI_V1_F; + break; + case OpenWnnDictionary::POS_TYPE_V2: + type = NJ_HINSI_V2_F; + break; + case OpenWnnDictionary::POS_TYPE_V3: + type = NJ_HINSI_V3_F; + break; + case OpenWnnDictionary::POS_TYPE_BUNTOU: + /* No part of speech is defined at this type */ + return 0; + case OpenWnnDictionary::POS_TYPE_TANKANJI: + type = NJ_HINSI_TANKANJI_F; + break; + case OpenWnnDictionary::POS_TYPE_SUUJI: + /* No part of speech is defined at this type */ + return 0; + case OpenWnnDictionary::POS_TYPE_MEISI: + type = NJ_HINSI_MEISI_F; + break; + case OpenWnnDictionary::POS_TYPE_JINMEI: + type = NJ_HINSI_JINMEI_F; + break; + case OpenWnnDictionary::POS_TYPE_CHIMEI: + type = NJ_HINSI_CHIMEI_F; + break; + case OpenWnnDictionary::POS_TYPE_KIGOU: + type = NJ_HINSI_KIGOU_F; + break; + default: + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_GET_LEFT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_INVALID_PARAM); + } + return njd_r_get_hinsi(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], type); + } + + int getRightPartOfSpeechSpecifiedType(OpenWnnDictionary::PartOfSpeechType posType) + { + NJ_UINT8 type; + switch(posType) { + case OpenWnnDictionary::POS_TYPE_V1: + /* No part of speech is defined at this type */ + return 0; + case OpenWnnDictionary::POS_TYPE_V2: + /* No part of speech is defined at this type */ + return 0; + case OpenWnnDictionary::POS_TYPE_V3: + /* No part of speech is defined at this type */ + return 0; + case OpenWnnDictionary::POS_TYPE_BUNTOU: + type = NJ_HINSI_BUNTOU_B; + break; + case OpenWnnDictionary::POS_TYPE_TANKANJI: + type = NJ_HINSI_TANKANJI_B; + break; + case OpenWnnDictionary::POS_TYPE_SUUJI: + type = NJ_HINSI_SUUJI_B; + break; + case OpenWnnDictionary::POS_TYPE_MEISI: + type = NJ_HINSI_MEISI_B; + break; + case OpenWnnDictionary::POS_TYPE_JINMEI: + type = NJ_HINSI_JINMEI_B; + break; + case OpenWnnDictionary::POS_TYPE_CHIMEI: + type = NJ_HINSI_CHIMEI_B; + break; + case OpenWnnDictionary::POS_TYPE_KIGOU: + type = NJ_HINSI_KIGOU_B; + break; + default: + /* If a invalid parameter was specified, return an error code */ + return NJ_SET_ERR_VAL(NJ_FUNC_GET_RIGHT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_INVALID_PARAM); + } + return njd_r_get_hinsi(work.dicSet.rHandle[NJ_MODE_TYPE_HENKAN], type); + } + + NJ_WORK work; +}; + +OpenWnnDictionary::OpenWnnDictionary(QObject *parent) : + QObject(*new OpenWnnDictionaryPrivate(), parent) +{ +} + +OpenWnnDictionary::~OpenWnnDictionary() +{ +} + +void OpenWnnDictionary::setInUseState(bool flag) +{ + Q_UNUSED(flag) + // Not implemented +} + +void OpenWnnDictionary::clearDictionary() +{ + Q_D(OpenWnnDictionary); + d->clearDictionaryParameters(); +} + +int OpenWnnDictionary::setDictionary(int index, int base, int high) +{ + Q_D(OpenWnnDictionary); + switch (index) { + case OpenWnnDictionary::INDEX_USER_DICTIONARY: + // Not implemented + return 0; + case OpenWnnDictionary::INDEX_LEARN_DICTIONARY: + // Not implemented + return 0; + default: + return d->setDictionaryParameter(index, base, high); + } +} + +void OpenWnnDictionary::clearApproxPattern() +{ + Q_D(OpenWnnDictionary); + return d->clearApproxPatterns(); +} + +int OpenWnnDictionary::setApproxPattern(const QString &src, const QString &dst) +{ + Q_D(OpenWnnDictionary); + return d->setApproxPattern(src, dst); +} + +int OpenWnnDictionary::setApproxPattern(ApproxPattern approxPattern) +{ + Q_D(OpenWnnDictionary); + return d->setApproxPattern(approxPattern); +} + +int OpenWnnDictionary::searchWord(SearchOperation operation, SearchOrder order, const QString &keyString) +{ + Q_D(OpenWnnDictionary); + /* Unset the previous word information */ + d->clearResult(); + /* Search to fixed dictionary */ + return d->searchWord(operation, order, keyString); +} + +int OpenWnnDictionary::searchWord(SearchOperation operation, SearchOrder order, const QString &keyString, const WnnWord &wnnWord) +{ + Q_D(OpenWnnDictionary); + + /* Search to fixed dictionary with link information */ + d->clearResult(); + d->setStroke(wnnWord.stroke); + d->setCandidate(wnnWord.candidate); + d->setLeftPartOfSpeech(wnnWord.partOfSpeech.left); + d->setRightPartOfSpeech(wnnWord.partOfSpeech.right); + d->selectWord(); + + return d->searchWord(operation, order, keyString); +} + +QSharedPointer<WnnWord> OpenWnnDictionary::getNextWord(int length) +{ + Q_D(OpenWnnDictionary); + + /* Get the result from fixed dictionary */ + int res = d->getNextWord(length); + if (res > 0) + return QSharedPointer<WnnWord>::create(d->getCandidate(), d->getStroke(), WnnPOS(d->getLeftPartOfSpeech(), d->getRightPartOfSpeech()), d->getFrequency()); + return QSharedPointer<WnnWord>(); +} + +QList<QBitArray> OpenWnnDictionary::getConnectMatrix() +{ + Q_D(OpenWnnDictionary); + QList<QBitArray> result; + + /* 1-origin */ + int lcount = d->getNumberOfLeftPOS(); + result.reserve(lcount + 1); + + for (int i = 0; i < lcount + 1; i++) { + result.append(d->getConnectArray(i)); + } + return result; +} + +WnnPOS OpenWnnDictionary::getPOS(PartOfSpeechType type) +{ + Q_D(OpenWnnDictionary); + return WnnPOS(d->getLeftPartOfSpeechSpecifiedType(type), d->getRightPartOfSpeechSpecifiedType(type)); +} + +int OpenWnnDictionary::learnWord(const WnnWord &word, const WnnWord *previousWord) +{ + Q_UNUSED(word) + Q_UNUSED(previousWord) + // Not implemented + return -1; +} |