Files
tdesktop/Telegram/lib_spellcheck/spellcheck/platform/linux/linux_enchant.cpp
allhaileris afb81b8278
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
init
2026-02-16 15:50:16 +03:00

252 lines
8.3 KiB
C++

/* enchant
* Copyright (C) 2003 Dom Lachowicz
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, Dom Lachowicz
* gives permission to link the code of this program with
* non-LGPL Spelling Provider libraries (eg: a MSFT Office
* spell checker backend) and distribute linked combinations including
* the two. You must obey the GNU Lesser General Public License in all
* respects for all of the code used other than said providers. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Nicholas Guriev (email: guriev-ns@ya.ru) split the full <enchant++.h> header
* into two files, linux_enchant.h and linux_enchant.cpp, to use within Desktop
* App Toolkit. He also implemented explicit linking with dlopen/dlsym to avoid
* rigid dependency on the Enchant library at runtime.
*/
#include <enchant.h>
#include "base/platform/linux/base_linux_library.h"
#include "spellcheck/platform/linux/linux_enchant.h"
namespace {
struct {
//decltype (enchant_broker_describe) * broker_describe;
//decltype (enchant_broker_dict_exists) * broker_dict_exists;
decltype (enchant_broker_free) * broker_free;
decltype (enchant_broker_free_dict) * broker_free_dict;
decltype (enchant_broker_get_error) * broker_get_error;
decltype (enchant_broker_init) * broker_init;
decltype (enchant_broker_list_dicts) * broker_list_dicts;
decltype (enchant_broker_request_dict) * broker_request_dict;
//decltype (enchant_broker_request_pwl_dict) * broker_request_pwl_dict;
decltype (enchant_broker_set_ordering) * broker_set_ordering;
decltype (enchant_dict_add) * dict_add;
decltype (enchant_dict_add_to_session) * dict_add_to_session;
decltype (enchant_dict_check) * dict_check;
decltype (enchant_dict_describe) * dict_describe;
decltype (enchant_dict_free_string_list) * dict_free_string_list;
decltype (enchant_dict_get_error) * dict_get_error;
decltype (enchant_dict_is_added) * dict_is_added;
//decltype (enchant_dict_is_removed) * dict_is_removed;
decltype (enchant_dict_remove) * dict_remove;
decltype (enchant_dict_remove_from_session) * dict_remove_from_session;
//decltype (enchant_dict_store_replacement) * dict_store_replacement;
decltype (enchant_dict_suggest) * dict_suggest;
} f_enchant;
} // anonymous namespace
enchant::Exception::Exception (const char * ex)
: std::exception (), m_ex ("") {
if (ex)
m_ex = ex;
}
enchant::Exception::~Exception () = default;
const char * enchant::Exception::what () const noexcept {
return m_ex.c_str();
}
enchant::Dict::Dict (EnchantDict * dict, EnchantBroker * broker)
: m_dict (dict), m_broker (broker) {
f_enchant.dict_describe (m_dict, s_describe_fn, this);
}
enchant::Dict::~Dict () {
f_enchant.broker_free_dict (m_broker, m_dict);
}
bool enchant::Dict::check (const std::string & utf8word) {
int val;
val = f_enchant.dict_check (m_dict, utf8word.c_str(), utf8word.size());
if (val == 0)
return true;
else if (val > 0)
return false;
else {
throw enchant::Exception (f_enchant.dict_get_error (m_dict));
}
return false; // never reached
}
void enchant::Dict::suggest (const std::string & utf8word,
std::vector<std::string> & out_suggestions) {
size_t n_suggs;
char ** suggs;
out_suggestions.clear ();
suggs = f_enchant.dict_suggest (m_dict, utf8word.c_str(),
utf8word.size(), &n_suggs);
if (suggs && n_suggs) {
out_suggestions.reserve(n_suggs);
for (size_t i = 0; i < n_suggs; i++) {
out_suggestions.push_back (suggs[i]);
}
f_enchant.dict_free_string_list (m_dict, suggs);
}
}
void enchant::Dict::add (const std::string & utf8word) {
f_enchant.dict_add (m_dict, utf8word.c_str(), utf8word.size());
}
void enchant::Dict::add_to_session (const std::string & utf8word) {
f_enchant.dict_add_to_session (m_dict, utf8word.c_str(), utf8word.size());
}
bool enchant::Dict::is_added (const std::string & utf8word) {
return f_enchant.dict_is_added (m_dict, utf8word.c_str(),
utf8word.size());
}
void enchant::Dict::remove (const std::string & utf8word) {
f_enchant.dict_remove (m_dict, utf8word.c_str(), utf8word.size());
}
void enchant::Dict::remove_from_session (const std::string & utf8word) {
f_enchant.dict_remove_from_session (m_dict, utf8word.c_str(),
utf8word.size());
}
//bool enchant::Dict::is_removed (const std::string & utf8word) {
// return f_enchant.dict_is_removed (m_dict, utf8word.c_str(),
// utf8word.size());
//}
//void enchant::Dict::store_replacement (const std::string & utf8bad,
// const std::string & utf8good) {
// f_enchant.dict_store_replacement (m_dict,
// utf8bad.c_str(), utf8bad.size(),
// utf8good.c_str(), utf8good.size());
//}
enchant::Broker::Broker ()
: m_broker (f_enchant.broker_init ())
{
}
enchant::Broker::~Broker () {
f_enchant.broker_free (m_broker);
}
enchant::Dict * enchant::Broker::request_dict (const std::string & lang) {
EnchantDict * dict = f_enchant.broker_request_dict (m_broker, lang.c_str());
if (!dict) {
throw enchant::Exception (f_enchant.broker_get_error (m_broker));
return 0; // never reached
}
return new Dict (dict, m_broker);
}
//enchant::Dict * enchant::Broker::request_pwl_dict (const std::string & pwl) {
// EnchantDict * dict = f_enchant.broker_request_pwl_dict (m_broker, pwl.c_str());
//
// if (!dict) {
// throw enchant::Exception (f_enchant.broker_get_error (m_broker));
// return 0; // never reached
// }
//
// return new Dict (dict, m_broker);
//}
//bool enchant::Broker::dict_exists (const std::string & lang) {
// if (f_enchant.broker_dict_exists (m_broker, lang.c_str()))
// return true;
// return false;
//}
void enchant::Broker::set_ordering (const std::string & tag, const std::string & ordering) {
f_enchant.broker_set_ordering (m_broker, tag.c_str(), ordering.c_str());
}
//void enchant::Broker::describe (EnchantBrokerDescribeFn fn, void * user_data) {
// f_enchant.broker_describe (m_broker, fn, user_data);
//}
void enchant::Broker::list_dicts (EnchantDictDescribeFn fn, void * user_data) {
f_enchant.broker_list_dicts (m_broker, fn, user_data);
}
#define GET_SYMBOL_enchant(func_name) \
if (!base::Platform::LoadSymbol (handle, "enchant_" # func_name, f_enchant.func_name)) { \
return false; \
}
bool enchant::loader::do_explicit_linking () {
static enum { NotLoadedYet, LoadSuccessful, LoadFailed = -1 } load_status;
if (load_status == NotLoadedYet) {
load_status = LoadFailed;
const auto handle = base::Platform::LoadLibrary ("libenchant.so.1", RTLD_NODELETE)
?: base::Platform::LoadLibrary ("libenchant-2.so.2", RTLD_NODELETE)
?: base::Platform::LoadLibrary ("libenchant.so.2", RTLD_NODELETE);
if (!handle) {
// logs ?
return false;
}
//GET_SYMBOL_enchant (broker_describe);
//GET_SYMBOL_enchant (broker_dict_exists);
GET_SYMBOL_enchant (broker_free);
GET_SYMBOL_enchant (broker_free_dict);
GET_SYMBOL_enchant (broker_get_error);
GET_SYMBOL_enchant (broker_init);
GET_SYMBOL_enchant (broker_list_dicts);
GET_SYMBOL_enchant (broker_request_dict);
//GET_SYMBOL_enchant (broker_request_pwl_dict);
GET_SYMBOL_enchant (broker_set_ordering);
GET_SYMBOL_enchant (dict_add);
GET_SYMBOL_enchant (dict_add_to_session);
GET_SYMBOL_enchant (dict_check);
GET_SYMBOL_enchant (dict_describe);
GET_SYMBOL_enchant (dict_free_string_list);
GET_SYMBOL_enchant (dict_get_error);
GET_SYMBOL_enchant (dict_is_added);
//GET_SYMBOL_enchant (dict_is_removed);
GET_SYMBOL_enchant (dict_remove);
GET_SYMBOL_enchant (dict_remove_from_session);
//GET_SYMBOL_enchant (dict_store_replacement);
GET_SYMBOL_enchant (dict_suggest);
load_status = LoadSuccessful;
}
return load_status == LoadSuccessful;
}
// vi: ts=8 sw=8