2 * ========================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * ========================================================================
14 #include "mswin_aspell.h"
19 typedef struct AspellConfig AspellConfig
;
20 typedef struct AspellSpeller AspellSpeller
;
21 typedef struct AspellCanHaveError AspellCanHaveError
;
22 typedef struct AspellStringEnumeration AspellStringEnumeration
;
23 typedef struct AspellWordList AspellWordList
;
24 typedef struct AspellError AspellError
;
27 * Aspell function prototypes
29 typedef AspellCanHaveError
* (__cdecl NEW_ASPELL_SPELLER
)(AspellConfig
* config
);
30 typedef AspellConfig
* (__cdecl NEW_ASPELL_CONFIG
)();
31 typedef AspellSpeller
* (__cdecl TO_ASPELL_SPELLER
)(AspellCanHaveError
* obj
);
32 typedef int (__cdecl ASPELL_CONFIG_REPLACE
)(AspellConfig
* ths
, const char * key
, const char * value
);
33 typedef void (__cdecl DELETE_ASPELL_CONFIG
)(AspellConfig
* ths
);
34 typedef const char * (__cdecl ASPELL_CONFIG_RETRIEVE
)(AspellConfig
* ths
, const char * key
);
35 typedef int (__cdecl ASPELL_SPELLER_ADD_TO_PERSONAL
)(AspellSpeller
* ths
, const char * word
, int word_size
);
36 typedef int (__cdecl ASPELL_SPELLER_ADD_TO_SESSION
)(AspellSpeller
* ths
, const char * word
, int word_size
);
37 typedef int (__cdecl ASPELL_SPELLER_CHECK
)(AspellSpeller
* ths
, const char * word
, int word_size
);
38 typedef const AspellWordList
* (__cdecl ASPELL_SPELLER_SUGGEST
)(AspellSpeller
* ths
, const char * word
, int word_size
);
39 typedef int (__cdecl ASPELL_SPELLER_SAVE_ALL_WORD_LISTS
)(AspellSpeller
* ths
);
40 typedef int (__cdecl ASPELL_SPELLER_STORE_REPLACEMENT
)(AspellSpeller
* ths
, const char * mis
, int mis_size
, const char * cor
, int cor_size
);
41 typedef const char * (__cdecl ASPELL_STRING_ENUMERATION_NEXT
)(AspellStringEnumeration
* ths
);
42 typedef AspellStringEnumeration
*(__cdecl ASPELL_WORD_LIST_ELEMENTS
)(const AspellWordList
* ths
);
43 typedef void (__cdecl DELETE_ASPELL_SPELLER
)(AspellSpeller
* ths
);
44 typedef void (__cdecl DELETE_ASPELL_STRING_ENUMERATION
)(AspellStringEnumeration
* ths
);
45 typedef void (__cdecl DELETE_ASPELL_CAN_HAVE_ERROR
)(AspellCanHaveError
* ths
);
46 typedef const char * (__cdecl ASPELL_ERROR_MESSAGE
)(const AspellCanHaveError
* ths
);
47 typedef unsigned int (__cdecl ASPELL_ERROR_NUMBER
)(const AspellCanHaveError
* ths
);
48 typedef const AspellError
* (__cdecl ASPELL_SPELLER_ERROR
)(const AspellSpeller
* ths
);
49 typedef const char * (__cdecl ASPELL_SPELLER_ERROR_MESSAGE
)(const struct AspellSpeller
* ths
);
50 typedef AspellConfig
* (__cdecl ASPELL_SPELLER_CONFIG
)(AspellSpeller
* ths
);
53 * MsWin speller information structure
55 typedef struct ASPELLINFO
57 AspellSpeller
*speller
;
58 AspellStringEnumeration
*suggestion_elements
;
59 const char *error_message
;
61 AspellCanHaveError
*err
;
65 NEW_ASPELL_SPELLER
*new_aspell_speller
;
66 NEW_ASPELL_CONFIG
*new_aspell_config
;
67 TO_ASPELL_SPELLER
*to_aspell_speller
;
68 ASPELL_CONFIG_REPLACE
*aspell_config_replace
;
69 DELETE_ASPELL_CONFIG
*delete_aspell_config
;
70 ASPELL_CONFIG_RETRIEVE
*aspell_config_retrieve
;
71 ASPELL_SPELLER_ADD_TO_PERSONAL
*aspell_speller_add_to_personal
;
72 ASPELL_SPELLER_ADD_TO_SESSION
*aspell_speller_add_to_session
;
73 ASPELL_SPELLER_CHECK
*aspell_speller_check
;
74 ASPELL_SPELLER_SUGGEST
*aspell_speller_suggest
;
75 ASPELL_SPELLER_SAVE_ALL_WORD_LISTS
*aspell_speller_save_all_word_lists
;
76 ASPELL_SPELLER_STORE_REPLACEMENT
*aspell_speller_store_replacement
;
77 ASPELL_STRING_ENUMERATION_NEXT
*aspell_string_enumeration_next
;
78 ASPELL_WORD_LIST_ELEMENTS
*aspell_word_list_elements
;
79 DELETE_ASPELL_SPELLER
*delete_aspell_speller
;
80 DELETE_ASPELL_STRING_ENUMERATION
*delete_aspell_string_enumeration
;
81 DELETE_ASPELL_CAN_HAVE_ERROR
*delete_aspell_can_have_error
;
82 ASPELL_ERROR_MESSAGE
*aspell_error_message
;
83 ASPELL_ERROR_NUMBER
*aspell_error_number
;
84 ASPELL_SPELLER_ERROR
*aspell_speller_error
;
85 ASPELL_SPELLER_ERROR_MESSAGE
*aspell_speller_error_message
;
86 ASPELL_SPELLER_CONFIG
*aspell_speller_config
;
90 * Find, aspell-15.dll, load it, and attempt to initialize our func pointers.
94 speller_load_aspell_library(ASPELLINFO
*aspellinfo
)
98 HMODULE mod_aspell
= NULL
;
99 TCHAR aspell_fullname
[MAX_PATH
+ 1];
100 static const TCHAR aspell_name
[] = TEXT("aspell-15.dll");
102 aspell_fullname
[0] = '\0';
104 // Try to open the Aspell Registry key.
105 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE
, TEXT("SOFTWARE\\Aspell"),
106 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
109 TCHAR aspell_path
[MAX_PATH
+ 1];
110 DWORD aspell_path_len
= sizeof(aspell_path
);
113 if(RegQueryValueEx(hKey
, TEXT("Path"), NULL
, &dtype
,
114 (LPBYTE
)aspell_path
, &aspell_path_len
) == ERROR_SUCCESS
)
116 _sntprintf(aspell_fullname
, ARRAYSIZE(aspell_fullname
),
117 TEXT("%s\\%s"), aspell_path
, aspell_name
);
118 aspell_fullname
[ARRAYSIZE(aspell_fullname
) - 1] = 0;
124 // If the registry thing didn't work, then just try doing a Loadlibrary
125 // using the standard Windows LoadLibrary search gunk.
126 if(!aspell_fullname
[0])
128 _tcsncpy(aspell_fullname
, aspell_name
, ARRAYSIZE(aspell_fullname
));
129 aspell_fullname
[ARRAYSIZE(aspell_fullname
) - 1] = 0;
133 mod_aspell
= LoadLibrary(aspell_fullname
);
141 // Found the library - now try to initialize our function pointers.
143 #define GET_ASPELL_PROC_ADDR(_functype, _func) \
144 aspellinfo->_func = (_functype *)GetProcAddress(mod_aspell, #_func); \
145 if(!aspellinfo->_func) \
148 GET_ASPELL_PROC_ADDR(NEW_ASPELL_SPELLER
, new_aspell_speller
);
149 GET_ASPELL_PROC_ADDR(NEW_ASPELL_CONFIG
, new_aspell_config
);
150 GET_ASPELL_PROC_ADDR(TO_ASPELL_SPELLER
, to_aspell_speller
);
151 GET_ASPELL_PROC_ADDR(ASPELL_CONFIG_REPLACE
, aspell_config_replace
);
152 GET_ASPELL_PROC_ADDR(DELETE_ASPELL_CONFIG
, delete_aspell_config
);
153 GET_ASPELL_PROC_ADDR(ASPELL_CONFIG_RETRIEVE
, aspell_config_retrieve
);
154 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_ADD_TO_PERSONAL
, aspell_speller_add_to_personal
);
155 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_ADD_TO_SESSION
, aspell_speller_add_to_session
);
156 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_CHECK
, aspell_speller_check
);
157 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_SUGGEST
, aspell_speller_suggest
);
158 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_SAVE_ALL_WORD_LISTS
, aspell_speller_save_all_word_lists
);
159 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_STORE_REPLACEMENT
, aspell_speller_store_replacement
);
160 GET_ASPELL_PROC_ADDR(ASPELL_STRING_ENUMERATION_NEXT
, aspell_string_enumeration_next
);
161 GET_ASPELL_PROC_ADDR(ASPELL_WORD_LIST_ELEMENTS
, aspell_word_list_elements
);
162 GET_ASPELL_PROC_ADDR(DELETE_ASPELL_SPELLER
, delete_aspell_speller
);
163 GET_ASPELL_PROC_ADDR(DELETE_ASPELL_STRING_ENUMERATION
, delete_aspell_string_enumeration
);
164 GET_ASPELL_PROC_ADDR(DELETE_ASPELL_CAN_HAVE_ERROR
, delete_aspell_can_have_error
);
165 GET_ASPELL_PROC_ADDR(ASPELL_ERROR_MESSAGE
, aspell_error_message
);
166 GET_ASPELL_PROC_ADDR(ASPELL_ERROR_NUMBER
, aspell_error_number
);
167 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_ERROR
, aspell_speller_error
);
168 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_ERROR_MESSAGE
, aspell_speller_error_message
);
169 GET_ASPELL_PROC_ADDR(ASPELL_SPELLER_CONFIG
, aspell_speller_config
);
171 #undef GET_ASPELL_PROC_ADDR
175 FreeLibrary(mod_aspell
);
180 aspellinfo
->mod_aspell
= mod_aspell
;
185 * Find, load, and initialize the aspell library.
186 * NULL on failure, otherwise an ASPELLINFO pointer.
189 speller_init(char *lang
)
191 ASPELLINFO
*aspellinfo
;
193 aspellinfo
= (ASPELLINFO
*)malloc(sizeof(ASPELLINFO
));
196 AspellConfig
*config
;
197 AspellSpeller
*speller
;
199 memset(aspellinfo
, 0, sizeof(ASPELLINFO
));
201 // Load the aspell library and set up our function pointers, etc.
202 if(!speller_load_aspell_library(aspellinfo
))
204 speller_close(aspellinfo
);
208 config
= aspellinfo
->new_aspell_config();
212 aspellinfo
->aspell_config_replace(config
, "lang", lang
);
215 aspellinfo
->aspell_config_replace(config
, "encoding", "utf-8");
217 aspellinfo
->err
= aspellinfo
->new_aspell_speller(config
);
218 aspellinfo
->delete_aspell_config(config
);
220 if(aspellinfo
->aspell_error_number(aspellinfo
->err
))
222 aspellinfo
->error_message
=
223 aspellinfo
->aspell_error_message(aspellinfo
->err
);
227 aspellinfo
->speller
= aspellinfo
->to_aspell_speller(aspellinfo
->err
);
228 aspellinfo
->err
= NULL
;
231 TODO: Log the current speller config somewhere?
233 config = aspell_speller_config(speller);
235 fputs("Using: ", stdout);
236 fputs(aspell_config_retrieve(config, "lang"), stdout);
238 fputs(aspell_config_retrieve(config, "jargon"), stdout);
240 fputs(aspell_config_retrieve(config, "size"), stdout);
242 fputs(aspell_config_retrieve(config, "module"), stdout);
243 fputs("\n\n", stdout);
252 * Get the last aspell error message.
255 speller_get_error_message(ASPELLINFO
*aspellinfo
)
257 return aspellinfo
? aspellinfo
->error_message
: NULL
;
264 speller_close(ASPELLINFO
*aspellinfo
)
268 // Make sure someone hasn't missed a speller_suggestion_close
269 assert(!aspellinfo
->suggestion_elements
);
273 aspellinfo
->delete_aspell_can_have_error(aspellinfo
->err
);
274 aspellinfo
->err
= NULL
;
277 if(aspellinfo
->speller
)
279 aspellinfo
->delete_aspell_speller(aspellinfo
->speller
);
280 aspellinfo
->speller
= NULL
;
283 if(aspellinfo
->mod_aspell
)
285 FreeLibrary(aspellinfo
->mod_aspell
);
286 aspellinfo
->mod_aspell
= NULL
;
294 * Check the dictionary for a word.
295 * 1:found, 0:not found, -1:error
298 speller_check_word(ASPELLINFO
*aspellinfo
, const char *word
, int word_size
)
304 have
= aspellinfo
->aspell_speller_check(aspellinfo
->speller
, word
, word_size
);
307 aspellinfo
->error_message
=
308 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
317 * Add word to dictionary.
318 * 1:success, 0:failed
321 speller_add_to_dictionary(ASPELLINFO
*aspellinfo
, const char *word
, int word_size
)
323 aspellinfo
->aspell_speller_add_to_personal(aspellinfo
->speller
,
325 if(aspellinfo
->aspell_speller_error(aspellinfo
->speller
))
327 aspellinfo
->error_message
=
328 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
332 aspellinfo
->aspell_speller_save_all_word_lists(aspellinfo
->speller
);
333 if(aspellinfo
->aspell_speller_error(aspellinfo
->speller
))
335 aspellinfo
->error_message
=
336 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
344 * Add this word to the current spelling session.
345 * 1:success, 0:failed
348 speller_ignore_all(ASPELLINFO
*aspellinfo
, const char *word
, int word_size
)
350 aspellinfo
->aspell_speller_add_to_session(aspellinfo
->speller
, word
, word_size
);
351 if(aspellinfo
->aspell_speller_error(aspellinfo
->speller
))
353 aspellinfo
->error_message
=
354 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
363 * 1:success, 0:failed
366 speller_replace_word(ASPELLINFO
*aspellinfo
,
367 const char * mis
, int mis_size
, const char * cor
, int cor_size
)
371 ret
= aspellinfo
->aspell_speller_store_replacement(aspellinfo
->speller
,
372 mis
, mis_size
, cor
, cor_size
);
375 aspellinfo
->error_message
=
376 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
384 * Init the suggestions element array for a specific word.
385 * 1:success, 0:failed
388 speller_suggestion_init(ASPELLINFO
*aspellinfo
, const char *word
, int word_size
)
390 const AspellWordList
*suggestions
;
392 // Make sure someone hasn't missed a speller_suggestion_close
393 assert(!aspellinfo
->suggestion_elements
);
395 suggestions
= aspellinfo
->aspell_speller_suggest(aspellinfo
->speller
,
399 aspellinfo
->error_message
=
400 aspellinfo
->aspell_speller_error_message(aspellinfo
->speller
);
404 aspellinfo
->suggestion_elements
=
405 aspellinfo
->aspell_word_list_elements(suggestions
);
410 * Find next suggestion. Returns NULL when no more are left.
413 speller_suggestion_getnext(ASPELLINFO
*aspellinfo
)
415 return aspellinfo
->aspell_string_enumeration_next(
416 aspellinfo
->suggestion_elements
);
420 * Close the suggestion element array.
423 speller_suggestion_close(ASPELLINFO
*aspellinfo
)
425 aspellinfo
->delete_aspell_string_enumeration(aspellinfo
->suggestion_elements
);
426 aspellinfo
->suggestion_elements
= NULL
;