/**************************************************************************** ** ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "xt9ime.h" #include "xt9callbacks.h" #include "xt9languagemap.h" #include "xt9dbfile.h" #include #include #include #include QT_BEGIN_NAMESPACE namespace QtVirtualKeyboard { Q_LOGGING_CATEGORY(lcXT9, "qt.virtualkeyboard.xt9") Xt9Ime::Xt9Ime(Xt9RequestCallback *requestCallback, Xt9KeyboardGenerator::CodeConverter *codeConverter) : _requestCallback(requestCallback), codeConverter(codeConverter) { } void Xt9Ime::sysInit() { if (!ldbManager) ldbManager.reset(new Xt9LdbManager()); memset(&sWordSymbInfo, 0, sizeof(sWordSymbInfo)); memset(&sKdbInfo, 0, sizeof(sKdbInfo)); memset(&sSearchEngine, 0, sizeof(sSearchEngine)); XT9_API(ET9WordSymbInit, &sWordSymbInfo, 1, ET9Request, this); XT9_API(ET9NAV_Init, &sSearchEngine, &sWordSymbInfo); } bool Xt9Ime::kdbInit(const QVariantMap &vkbLayout) { ET9STATUS eStatus; keyboardGenerator.reset(new Xt9KeyboardGenerator(vkbLayout, codeConverter)); const ET9U32 dwFirstKdbNum = static_cast(vkbLayout[Xt9KeyboardGenerator::PRIMARY_ID].toInt()); eStatus = XT9_API(ET9KDB_Init, &sKdbInfo, &sWordSymbInfo, dwFirstKdbNum, 0, &ET9KDBLoad, &ET9KDBRequest, this); return !eStatus; } void Xt9Ime::uninit() { clearInput(); keyboardGenerator.reset(); ldbManager->closeAll(); sysInit(); } QString Xt9Ime::exactWord(int *wordCompLen) { ET9SimpleWord simpleWord; ET9STATUS eStatus; eStatus = XT9_API(ET9GetExactWord, &sWordSymbInfo, &simpleWord); if (eStatus) { if (wordCompLen) *wordCompLen = 0; return QString(); } if (wordCompLen) *wordCompLen = simpleWord.wCompLen; return QString::fromUtf16(reinterpret_cast(simpleWord.sString), simpleWord.wLen); } bool Xt9Ime::hasActiveInput() const { return ET9HasActiveInput(&sWordSymbInfo); } QStringList Xt9Ime::buildSelectionList(int *defaultListIndex, unsigned short *gestureValue) { ET9STATUS eStatus = ET9STATUS_NONE; return buildSelectionList(defaultListIndex, gestureValue, eStatus); } void Xt9Ime::cursorMoved() { XT9_API(ET9CursorMoved, &sWordSymbInfo, 1); } void Xt9Ime::clearInput() { XT9_API(ET9ClearAllSymbs, &sWordSymbInfo); } void Xt9Ime::setCapsLock() { XT9_API(ET9SetCapsLock, &sWordSymbInfo); } void Xt9Ime::setShift() { XT9_API(ET9SetShift, &sWordSymbInfo); } void Xt9Ime::setUnShift() { XT9_API(ET9SetUnShift, &sWordSymbInfo); } void Xt9Ime::setWorkingDirectory(const QString &workingDirectory) { QString dir = workingDirectory; if (!workingDirectory.isEmpty() && !dir.endsWith(QLatin1Char('/'))) dir.append(QLatin1Char('/')); dir = QDir::toNativeSeparators(dir); XT9_API(ET9NAVCore_SetWorkingDirectory, &sSearchEngine, dir.toUtf8().constData()); } bool Xt9Ime::indexExists(quint16 id) { ET9BOOL exists = 0; XT9_API(ET9NAVCore_IndexExists, &sSearchEngine, id, &exists); return exists != 0; } bool Xt9Ime::createIndex(quint16 id, quint32 contentInfo) { ET9STATUS eStatus; ET9NAVTypeInfo sTypeInfo; if (indexExists(id)) { removeIndex(id); } eStatus = XT9_API(ET9NAVTypeInfo_Init, &sTypeInfo, id, ET9NAVNO_RECORD_KEY_LENGTH, 0, ET9NAVSTORE_DISPLAY_STR_IN_INDEX); if (!eStatus) { eStatus = XT9_API(ET9NAVCore_CreateIndex, &sSearchEngine, id, &sTypeInfo, 1, contentInfo, 0); } return !eStatus; } bool Xt9Ime::insertRecord(quint16 id, const QString &phrase, const QString &tokens) { ET9STATUS eStatus; ET9NAVRecord sRecord; eStatus = XT9_API(ET9NAVRecord_Init_NoKey, &sSearchEngine, &sRecord, id); if (!eStatus) { if (tokens.length() > 0) { eStatus = XT9_API(ET9NAVRecord_AddField_Conversion, &sRecord, static_cast(tokens.utf16()), static_cast(tokens.length()), static_cast(phrase.utf16()), static_cast(phrase.length()), ET9NAVMATCHLOGIC_ANY); } else { eStatus = XT9_API(ET9NAVRecord_AddField_16BIT, &sRecord, static_cast(phrase.utf16()), static_cast(phrase.length()), ET9NAVMATCHLOGIC_ANY); } if (!eStatus) { eStatus = XT9_API(ET9NAVCore_InsertRecord, &sSearchEngine, &sRecord); } } return !eStatus; } void Xt9Ime::finalizeIndex(quint16 id) { XT9_API(ET9NAVCore_FinalizeIndex, &sSearchEngine, id); } void Xt9Ime::updateIndex(quint16 id, const QStringList &wordList) { createIndex(id); for (const QString &word : wordList) { insertRecord(id, word); } finalizeIndex(id); } void Xt9Ime::removeIndex(quint16 id) { XT9_API(ET9NAVCore_RemoveIndex, &sSearchEngine, id); } void Xt9Ime::removeAllIndexes() { XT9_API(ET9NAVCore_RemoveAllIndexes, &sSearchEngine); } void Xt9Ime::mountIndex(quint16 id) { XT9_API(ET9NAVCore_MountIndex, &sSearchEngine, id, ET9NAVMountProperty_ReadOnlyNoValidation); } void Xt9Ime::unmountIndex(quint16 id) { XT9_API(ET9NAVCore_UnmountIndex, &sSearchEngine, id); } ET9STATUS Xt9Ime::ldbReadData(ET9U32 dwLdbNum, ET9U8 *ET9FARDATA *ppbSrc, ET9U32 *pdwSizeInBytes) { const QLocale locale = Xt9LanguageMap::locale(dwLdbNum); if (locale.language() == QLocale::AnyLanguage) { return ET9STATUS_READ_DB_FAIL; } const void *data; qint64 size; if (!ldbManager->loadDictionary(locale, data, size)) { return ET9STATUS_READ_DB_FAIL; } *ppbSrc = static_cast(const_cast(data)); *pdwSizeInBytes = static_cast(size); return ET9STATUS_NONE; } ET9STATUS Xt9Ime::ET9Request(ET9WordSymbInfo *const pWordSymbInfo, ET9_Request *const pRequest) { return reinterpret_cast(pWordSymbInfo->pPublicExtension)->request(pRequest); } ET9STATUS Xt9Ime::request(ET9_Request *const pRequest) { #ifdef XT9_DEBUG qCDebug(lcXT9) << "ET9Request, type =" << pRequest->eType; #endif return _requestCallback->request(pRequest); } ET9STATUS Xt9Ime::ET9KDBLoad(ET9KDBInfo *const pKdbInfo, const ET9U32 dwKdbNum, const ET9U16 wPageNum) { return reinterpret_cast(pKdbInfo->pPublicExtension)->kdbLoad(dwKdbNum, wPageNum); } ET9STATUS Xt9Ime::kdbLoad(const ET9U32 dwKdbNum, const ET9U16 wPageNum) { Q_UNUSED(dwKdbNum) ET9STATUS eStatus; ET9UINT nErrorLine = 0; if (keyboardGenerator->vkbLayout.isEmpty()) { qCWarning(lcXT9) << "Keyboard layout is not set."; return ET9STATUS_READ_DB_FAIL; } QByteArray xmlData = keyboardGenerator->createXmlLayout(); if (xmlData.isEmpty()) { qCWarning(lcXT9) << "Failed to create xml layout."; return ET9STATUS_READ_DB_FAIL; } eStatus = XT9_API(ET9KDB_Load_XmlKDB, &sKdbInfo, static_cast(qRound(keyboardGenerator->layoutWidth)), static_cast(qRound(keyboardGenerator->layoutHeight)), wPageNum, reinterpret_cast(xmlData.constData()), static_cast(xmlData.size()), nullptr, nullptr, &nErrorLine); if (eStatus) { qCWarning(lcXT9).nospace() << "Failed to load xml layout, status: " << eStatus << ", line: " << nErrorLine; qCWarning(lcXT9).nospace().noquote() << xmlData.constData(); } return eStatus; } ET9STATUS Xt9Ime::ET9KDBRequest(ET9KDBInfo *const pKDBInfo, ET9WordSymbInfo *const pWordSymbInfo, ET9KDB_Request *const pET9KDB_Request) { Q_UNUSED(pWordSymbInfo) return reinterpret_cast(pKDBInfo->pPublicExtension)->kdbRequest(pET9KDB_Request); } ET9STATUS Xt9Ime::kdbRequest(ET9KDB_Request *const pET9KDB_Request) { #ifdef XT9_DEBUG qCDebug(lcXT9) << "ET9KDB_Request, type =" << pET9KDB_Request->eType; #endif return ET9STATUS_NONE; } } // namespace QtVirtualKeyboard QT_END_NAMESPACE