linux_enchant.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* enchant
  2. * Copyright (C) 2003 Dom Lachowicz
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. *
  19. * In addition, as a special exception, Dom Lachowicz
  20. * gives permission to link the code of this program with
  21. * non-LGPL Spelling Provider libraries (eg: a MSFT Office
  22. * spell checker backend) and distribute linked combinations including
  23. * the two. You must obey the GNU Lesser General Public License in all
  24. * respects for all of the code used other than said providers. If you modify
  25. * this file, you may extend this exception to your version of the
  26. * file, but you are not obligated to do so. If you do not wish to
  27. * do so, delete this exception statement from your version.
  28. *
  29. * Nicholas Guriev (email: guriev-ns@ya.ru) split the full <enchant++.h> header
  30. * into two files, linux_enchant.h and linux_enchant.cpp, to use within Desktop
  31. * App Toolkit. He also implemented explicit linking with dlopen/dlsym to avoid
  32. * rigid dependency on the Enchant library at runtime.
  33. */
  34. #include <enchant.h>
  35. #include "base/platform/linux/base_linux_library.h"
  36. #include "spellcheck/platform/linux/linux_enchant.h"
  37. namespace {
  38. struct {
  39. //decltype (enchant_broker_describe) * broker_describe;
  40. //decltype (enchant_broker_dict_exists) * broker_dict_exists;
  41. decltype (enchant_broker_free) * broker_free;
  42. decltype (enchant_broker_free_dict) * broker_free_dict;
  43. decltype (enchant_broker_get_error) * broker_get_error;
  44. decltype (enchant_broker_init) * broker_init;
  45. decltype (enchant_broker_list_dicts) * broker_list_dicts;
  46. decltype (enchant_broker_request_dict) * broker_request_dict;
  47. //decltype (enchant_broker_request_pwl_dict) * broker_request_pwl_dict;
  48. decltype (enchant_broker_set_ordering) * broker_set_ordering;
  49. decltype (enchant_dict_add) * dict_add;
  50. decltype (enchant_dict_add_to_session) * dict_add_to_session;
  51. decltype (enchant_dict_check) * dict_check;
  52. decltype (enchant_dict_describe) * dict_describe;
  53. decltype (enchant_dict_free_string_list) * dict_free_string_list;
  54. decltype (enchant_dict_get_error) * dict_get_error;
  55. decltype (enchant_dict_is_added) * dict_is_added;
  56. //decltype (enchant_dict_is_removed) * dict_is_removed;
  57. decltype (enchant_dict_remove) * dict_remove;
  58. decltype (enchant_dict_remove_from_session) * dict_remove_from_session;
  59. //decltype (enchant_dict_store_replacement) * dict_store_replacement;
  60. decltype (enchant_dict_suggest) * dict_suggest;
  61. } f_enchant;
  62. } // anonymous namespace
  63. enchant::Exception::Exception (const char * ex)
  64. : std::exception (), m_ex ("") {
  65. if (ex)
  66. m_ex = ex;
  67. }
  68. enchant::Exception::~Exception () = default;
  69. const char * enchant::Exception::what () const noexcept {
  70. return m_ex.c_str();
  71. }
  72. enchant::Dict::Dict (EnchantDict * dict, EnchantBroker * broker)
  73. : m_dict (dict), m_broker (broker) {
  74. f_enchant.dict_describe (m_dict, s_describe_fn, this);
  75. }
  76. enchant::Dict::~Dict () {
  77. f_enchant.broker_free_dict (m_broker, m_dict);
  78. }
  79. bool enchant::Dict::check (const std::string & utf8word) {
  80. int val;
  81. val = f_enchant.dict_check (m_dict, utf8word.c_str(), utf8word.size());
  82. if (val == 0)
  83. return true;
  84. else if (val > 0)
  85. return false;
  86. else {
  87. throw enchant::Exception (f_enchant.dict_get_error (m_dict));
  88. }
  89. return false; // never reached
  90. }
  91. void enchant::Dict::suggest (const std::string & utf8word,
  92. std::vector<std::string> & out_suggestions) {
  93. size_t n_suggs;
  94. char ** suggs;
  95. out_suggestions.clear ();
  96. suggs = f_enchant.dict_suggest (m_dict, utf8word.c_str(),
  97. utf8word.size(), &n_suggs);
  98. if (suggs && n_suggs) {
  99. out_suggestions.reserve(n_suggs);
  100. for (size_t i = 0; i < n_suggs; i++) {
  101. out_suggestions.push_back (suggs[i]);
  102. }
  103. f_enchant.dict_free_string_list (m_dict, suggs);
  104. }
  105. }
  106. void enchant::Dict::add (const std::string & utf8word) {
  107. f_enchant.dict_add (m_dict, utf8word.c_str(), utf8word.size());
  108. }
  109. void enchant::Dict::add_to_session (const std::string & utf8word) {
  110. f_enchant.dict_add_to_session (m_dict, utf8word.c_str(), utf8word.size());
  111. }
  112. bool enchant::Dict::is_added (const std::string & utf8word) {
  113. return f_enchant.dict_is_added (m_dict, utf8word.c_str(),
  114. utf8word.size());
  115. }
  116. void enchant::Dict::remove (const std::string & utf8word) {
  117. f_enchant.dict_remove (m_dict, utf8word.c_str(), utf8word.size());
  118. }
  119. void enchant::Dict::remove_from_session (const std::string & utf8word) {
  120. f_enchant.dict_remove_from_session (m_dict, utf8word.c_str(),
  121. utf8word.size());
  122. }
  123. //bool enchant::Dict::is_removed (const std::string & utf8word) {
  124. // return f_enchant.dict_is_removed (m_dict, utf8word.c_str(),
  125. // utf8word.size());
  126. //}
  127. //void enchant::Dict::store_replacement (const std::string & utf8bad,
  128. // const std::string & utf8good) {
  129. // f_enchant.dict_store_replacement (m_dict,
  130. // utf8bad.c_str(), utf8bad.size(),
  131. // utf8good.c_str(), utf8good.size());
  132. //}
  133. enchant::Broker::Broker ()
  134. : m_broker (f_enchant.broker_init ())
  135. {
  136. }
  137. enchant::Broker::~Broker () {
  138. f_enchant.broker_free (m_broker);
  139. }
  140. enchant::Dict * enchant::Broker::request_dict (const std::string & lang) {
  141. EnchantDict * dict = f_enchant.broker_request_dict (m_broker, lang.c_str());
  142. if (!dict) {
  143. throw enchant::Exception (f_enchant.broker_get_error (m_broker));
  144. return 0; // never reached
  145. }
  146. return new Dict (dict, m_broker);
  147. }
  148. //enchant::Dict * enchant::Broker::request_pwl_dict (const std::string & pwl) {
  149. // EnchantDict * dict = f_enchant.broker_request_pwl_dict (m_broker, pwl.c_str());
  150. //
  151. // if (!dict) {
  152. // throw enchant::Exception (f_enchant.broker_get_error (m_broker));
  153. // return 0; // never reached
  154. // }
  155. //
  156. // return new Dict (dict, m_broker);
  157. //}
  158. //bool enchant::Broker::dict_exists (const std::string & lang) {
  159. // if (f_enchant.broker_dict_exists (m_broker, lang.c_str()))
  160. // return true;
  161. // return false;
  162. //}
  163. void enchant::Broker::set_ordering (const std::string & tag, const std::string & ordering) {
  164. f_enchant.broker_set_ordering (m_broker, tag.c_str(), ordering.c_str());
  165. }
  166. //void enchant::Broker::describe (EnchantBrokerDescribeFn fn, void * user_data) {
  167. // f_enchant.broker_describe (m_broker, fn, user_data);
  168. //}
  169. void enchant::Broker::list_dicts (EnchantDictDescribeFn fn, void * user_data) {
  170. f_enchant.broker_list_dicts (m_broker, fn, user_data);
  171. }
  172. #define GET_SYMBOL_enchant(func_name) \
  173. if (!base::Platform::LoadSymbol (handle, "enchant_" # func_name, f_enchant.func_name)) { \
  174. return false; \
  175. }
  176. bool enchant::loader::do_explicit_linking () {
  177. static enum { NotLoadedYet, LoadSuccessful, LoadFailed = -1 } load_status;
  178. if (load_status == NotLoadedYet) {
  179. load_status = LoadFailed;
  180. const auto handle = base::Platform::LoadLibrary ("libenchant.so.1", RTLD_NODELETE)
  181. ?: base::Platform::LoadLibrary ("libenchant-2.so.2", RTLD_NODELETE)
  182. ?: base::Platform::LoadLibrary ("libenchant.so.2", RTLD_NODELETE);
  183. if (!handle) {
  184. // logs ?
  185. return false;
  186. }
  187. //GET_SYMBOL_enchant (broker_describe);
  188. //GET_SYMBOL_enchant (broker_dict_exists);
  189. GET_SYMBOL_enchant (broker_free);
  190. GET_SYMBOL_enchant (broker_free_dict);
  191. GET_SYMBOL_enchant (broker_get_error);
  192. GET_SYMBOL_enchant (broker_init);
  193. GET_SYMBOL_enchant (broker_list_dicts);
  194. GET_SYMBOL_enchant (broker_request_dict);
  195. //GET_SYMBOL_enchant (broker_request_pwl_dict);
  196. GET_SYMBOL_enchant (broker_set_ordering);
  197. GET_SYMBOL_enchant (dict_add);
  198. GET_SYMBOL_enchant (dict_add_to_session);
  199. GET_SYMBOL_enchant (dict_check);
  200. GET_SYMBOL_enchant (dict_describe);
  201. GET_SYMBOL_enchant (dict_free_string_list);
  202. GET_SYMBOL_enchant (dict_get_error);
  203. GET_SYMBOL_enchant (dict_is_added);
  204. //GET_SYMBOL_enchant (dict_is_removed);
  205. GET_SYMBOL_enchant (dict_remove);
  206. GET_SYMBOL_enchant (dict_remove_from_session);
  207. //GET_SYMBOL_enchant (dict_store_replacement);
  208. GET_SYMBOL_enchant (dict_suggest);
  209. load_status = LoadSuccessful;
  210. }
  211. return load_status == LoadSuccessful;
  212. }
  213. // vi: ts=8 sw=8