1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2003,2004 Dom Lachowicz
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, Dom Lachowicz
21 * gives permission to link the code of this program with
22 * non-LGPL Spelling Provider libraries (eg: a MSFT Office
23 * spell checker backend) and distribute linked combinations including
24 * the two. You must obey the GNU Lesser General Public License in all
25 * respects for all of the code used other than said providers. If you modify
26 * this file, you may extend this exception to your version of the
27 * file, but you are not obligated to do so. If you do not wish to
28 * do so, delete this exception statement from your version.
38 #include <pspell/pspell.h>
42 /* to allow this to build on places that lack pspell.h */
44 #define PspellManager AspellSpeller
45 #define PspellWordList AspellWordList
46 #define PspellStringEmulation AspellStringEnumeration
47 #define PspellCanHaveError AspellCanHaveError
48 #define PspellConfig AspellConfig
50 #define new_pspell_config new_aspell_config
51 #define delete_pspell_config delete_aspell_config
52 #define pspell_config_replace aspell_config_replace
54 #define new_pspell_manager new_aspell_speller
55 #define to_pspell_manager to_aspell_speller
56 #define delete_pspell_manager delete_aspell_speller
57 #define pspell_manager_error_number aspell_speller_error_number
58 #define pspell_manager_error_message aspell_speller_error_message
59 #define pspell_manager_save_all_word_lists aspell_speller_save_all_word_lists
60 #define pspell_manager_check aspell_speller_check
61 #define pspell_manager_add_to_personal aspell_speller_add_to_personal
62 #define pspell_manager_add_to_session aspell_speller_add_to_session
63 #define pspell_manager_suggest aspell_speller_suggest
64 #define pspell_manager_store_replacement aspell_speller_store_replacement
66 #define pspell_word_list_elements aspell_word_list_elements
67 #define pspell_word_list_size aspell_word_list_size
69 #define pspell_string_emulation_next aspell_string_enumeration_next
70 #define delete_pspell_string_emulation delete_aspell_string_enumeration
72 #define pspell_error_message aspell_error_message
73 #define pspell_error_number aspell_error_number
78 #include "enchant-provider.h"
80 ENCHANT_PLUGIN_DECLARE("Aspell")
86 ENCHANT_MODULE_EXPORT(void)
87 configure_enchant_provider(EnchantProvider * me, const char *dir_name);
89 ENCHANT_MODULE_EXPORT (EnchantProvider *)
90 init_enchant_provider (void);
97 aspell_dict_check (EnchantDict * me, const char *const word, size_t len)
99 PspellManager *manager;
101 char *normalizedWord;
103 manager = (PspellManager *) me->user_data;
105 normalizedWord = g_utf8_normalize (word, len, G_NORMALIZE_NFC);
106 val = pspell_manager_check (manager, normalizedWord, strlen(normalizedWord));
107 g_free(normalizedWord);
114 enchant_dict_set_error (me, pspell_manager_error_message (manager));
120 aspell_dict_suggest (EnchantDict * me, const char *const word,
121 size_t len, size_t * out_n_suggs)
123 PspellManager *manager;
125 const PspellWordList *word_list;
126 PspellStringEmulation *suggestions;
127 char *normalizedWord;
129 char **sugg_arr = NULL;
130 size_t n_suggestions, i;
133 manager = (PspellManager *) me->user_data;
135 normalizedWord = g_utf8_normalize (word, len, G_NORMALIZE_NFC);
136 word_list = pspell_manager_suggest (manager, normalizedWord, strlen(normalizedWord));
137 g_free(normalizedWord);
141 suggestions = pspell_word_list_elements (word_list);
144 n_suggestions = pspell_word_list_size (word_list);
145 *out_n_suggs = n_suggestions;
149 sugg_arr = g_new0 (char *, n_suggestions + 1);
151 for (i = 0; i < n_suggestions; i++)
153 sugg = pspell_string_emulation_next (suggestions);
155 sugg_arr[i] = g_strdup (sugg);
158 delete_pspell_string_emulation (suggestions);
166 aspell_dict_add_to_personal (EnchantDict * me,
167 const char *const word, size_t len)
169 PspellManager *manager;
171 manager = (PspellManager *) me->user_data;
172 pspell_manager_add_to_personal (manager, word, len);
173 pspell_manager_save_all_word_lists (manager);
177 aspell_dict_add_to_session (EnchantDict * me,
178 const char *const word, size_t len)
180 PspellManager *manager;
182 manager = (PspellManager *) me->user_data;
183 pspell_manager_add_to_session (manager, word, len);
187 aspell_dict_store_replacement (EnchantDict * me,
188 const char *const mis, size_t mis_len,
189 const char *const cor, size_t cor_len)
191 PspellManager *manager;
193 manager = (PspellManager *) me->user_data;
194 pspell_manager_store_replacement (manager, mis, mis_len,
196 pspell_manager_save_all_word_lists (manager);
200 aspell_provider_request_dict (EnchantProvider * me, const char *const tag)
203 PspellManager *manager;
204 PspellConfig *spell_config;
205 PspellCanHaveError *spell_error;
207 spell_config = new_pspell_config ();
208 pspell_config_replace (spell_config, "language-tag", tag);
209 pspell_config_replace (spell_config, "encoding", "utf-8");
211 spell_error = new_pspell_manager (spell_config);
212 delete_pspell_config (spell_config);
214 if (pspell_error_number (spell_error) != 0)
219 manager = to_pspell_manager (spell_error);
221 dict = g_new0 (EnchantDict, 1);
222 dict->user_data = (void *) manager;
223 dict->check = aspell_dict_check;
224 dict->suggest = aspell_dict_suggest;
225 dict->add_to_personal = aspell_dict_add_to_personal;
226 dict->add_to_session = aspell_dict_add_to_session;
227 dict->store_replacement = aspell_dict_store_replacement;
233 aspell_provider_dispose_dict (EnchantProvider * me, EnchantDict * dict)
235 PspellManager *manager;
237 manager = (PspellManager *) dict->user_data;
238 delete_pspell_manager (manager);
245 aspell_provider_list_dicts (EnchantProvider * me,
246 size_t * out_n_dicts)
248 PspellConfig * spell_config;
249 AspellDictInfoList * dlist;
250 AspellDictInfoEnumeration * dels;
251 const AspellDictInfo * entry;
252 char ** out_list = NULL;
254 spell_config = new_pspell_config ();
256 dlist = get_aspell_dict_info_list (spell_config);
259 dels = aspell_dict_info_list_elements (dlist);
261 /* TODO: Use aspell_dict_info_list_size() once it is implemented and returns non-zero. */
262 while ( (entry = aspell_dict_info_enumeration_next(dels)) != 0)
268 out_list = g_new0 (char *, *out_n_dicts + 1);
269 dels = aspell_dict_info_list_elements (dlist);
271 for (i = 0; i < *out_n_dicts; i++) {
272 entry = aspell_dict_info_enumeration_next (dels);
273 /* XXX: should this be entry->code or entry->name ? */
274 out_list[i] = g_strdup (entry->code);
277 delete_aspell_dict_info_enumeration (dels);
280 delete_pspell_config (spell_config);
287 aspell_provider_free_string_list (EnchantProvider * me, char **str_list)
289 g_strfreev (str_list);
293 aspell_provider_dispose (EnchantProvider * me)
299 aspell_provider_identify (EnchantProvider * me)
305 aspell_provider_describe (EnchantProvider * me)
307 return "Aspell Provider";
315 init_enchant_provider (void)
317 EnchantProvider *provider;
319 provider = g_new0 (EnchantProvider, 1);
320 provider->dispose = aspell_provider_dispose;
321 provider->request_dict = aspell_provider_request_dict;
322 provider->dispose_dict = aspell_provider_dispose_dict;
323 provider->identify = aspell_provider_identify;
324 provider->describe = aspell_provider_describe;
327 provider->list_dicts = aspell_provider_list_dicts;
330 # warning "You're using an ancient version of Aspell. Some things won't work properly."
333 provider->free_string_list = aspell_provider_free_string_list;
341 static WCHAR* GetDirectoryOfThisLibrary(void)
343 WCHAR dll_path[MAX_PATH];
344 gchar* utf8_dll_path;
346 gunichar2* utf16_prefix;
348 if(!GetModuleFileNameW(s_hModule,dll_path,MAX_PATH))
349 { /* unable to determine filename of this library */
352 utf8_dll_path = g_utf16_to_utf8 (dll_path, -1, NULL, NULL, NULL);
353 utf8_prefix = g_path_get_dirname(utf8_dll_path);
354 g_free(utf8_dll_path);
356 utf16_prefix = g_utf8_to_utf16 (utf8_prefix, -1, NULL, NULL, NULL);
362 static HMODULE LoadLibraryFromPath(const WCHAR* path, const WCHAR* libraryName)
365 WCHAR* wszFullLibraryPath;
366 size_t fullLibraryPathLen;
368 fullLibraryPathLen = wcslen(path) + 1 /* '\\' */+ wcslen(libraryName);
369 wszFullLibraryPath = g_new0(WCHAR, fullLibraryPathLen + 1);
371 wcscpy(wszFullLibraryPath, path);
372 wcscat(wszFullLibraryPath, L"\\");
373 wcscat(wszFullLibraryPath, libraryName);
375 h = LoadLibraryW(wszFullLibraryPath);
377 g_free(wszFullLibraryPath);
381 static WCHAR* GetRegistryValue(HKEY baseKey, const WCHAR * uKeyName, const WCHAR * uKey)
386 WCHAR* wszValue = NULL;
388 if(RegOpenKeyExW(baseKey, uKeyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
390 /* Determine size of string */
391 if(RegQueryValueExW( hKey, uKey, NULL, &lType, NULL, &dwSize) == ERROR_SUCCESS)
393 wszValue = g_new0(WCHAR, dwSize + 1);
394 RegQueryValueExW(hKey, uKey, NULL, &lType, (LPBYTE) wszValue, &dwSize);
403 gboolean load_library(EnchantProvider * me, const char *dir_name, const WCHAR *aspell_module_name)
405 HMODULE aspell_module = NULL;
408 /* first try load from registry path */
409 szModule = enchant_get_registry_value ("Aspell", "Module");
414 wszModule = g_utf8_to_utf16 (szModule, -1, NULL, NULL, NULL);
415 aspell_module = LoadLibraryW(wszModule);
419 if (aspell_module == NULL)
421 /* next try load from aspell registry path */
422 WCHAR* wszDirectory = GetRegistryValue (HKEY_LOCAL_MACHINE, L"Software\\Aspell", L"Path");
425 aspell_module = LoadLibraryFromPath(wszDirectory, aspell_module_name);
426 g_free(wszDirectory);
430 if (aspell_module == NULL)
432 /* then try from same directory as provider */
433 WCHAR* wszDirectory = GetDirectoryOfThisLibrary();
436 aspell_module = LoadLibraryFromPath(wszDirectory, aspell_module_name);
437 g_free(wszDirectory);
441 if (aspell_module == NULL)
443 /* then try default lookup */
444 aspell_module = LoadLibraryW(aspell_module_name);
447 if (aspell_module == NULL)
455 void configure_enchant_provider(EnchantProvider * me, const char *dir_name)
458 if(!load_library(me, dir_name, L"aspell-15.dll") &&
459 !load_library(me, dir_name, L"libaspell-15.dll"))
461 /* we can't seem to load aspell. Avoid late binding problems later */
462 g_warning("Unable to load library aspell-15.dll.");
463 me->request_dict = NULL;
464 me->dispose_dict = NULL;
465 me->list_dicts = NULL;