|
a/src/aspell/rclaspell.cpp |
|
b/src/aspell/rclaspell.cpp |
|
... |
|
... |
17 |
#include ASPELL_INCLUDE
|
17 |
#include ASPELL_INCLUDE
|
18 |
|
18 |
|
19 |
#include "pathut.h"
|
19 |
#include "pathut.h"
|
20 |
#include "execmd.h"
|
20 |
#include "execmd.h"
|
21 |
#include "rclaspell.h"
|
21 |
#include "rclaspell.h"
|
22 |
|
22 |
#include "debuglog.h"
|
23 |
// Stuff that we don't wish to see in the .h (possible sysdeps, etc.)
|
|
|
24 |
class AspellData {
|
|
|
25 |
public:
|
|
|
26 |
AspellData() : m_handle(0) {}
|
|
|
27 |
~AspellData() {
|
|
|
28 |
if (m_handle)
|
|
|
29 |
dlclose(m_handle);
|
|
|
30 |
}
|
|
|
31 |
|
|
|
32 |
void *m_handle;
|
|
|
33 |
string m_exec;
|
|
|
34 |
};
|
|
|
35 |
|
|
|
36 |
Aspell::~Aspell()
|
|
|
37 |
{
|
|
|
38 |
if (m_data)
|
|
|
39 |
delete m_data;
|
|
|
40 |
}
|
|
|
41 |
|
23 |
|
42 |
// Just a place where we keep the Aspell library entry points together
|
24 |
// Just a place where we keep the Aspell library entry points together
|
43 |
class AspellApi {
|
25 |
class AspellApi {
|
44 |
public:
|
26 |
public:
|
45 |
struct AspellConfig *(*new_aspell_config)();
|
27 |
struct AspellConfig *(*new_aspell_config)();
|
|
... |
|
... |
50 |
void (*delete_aspell_can_have_error)(struct AspellCanHaveError *);
|
32 |
void (*delete_aspell_can_have_error)(struct AspellCanHaveError *);
|
51 |
struct AspellSpeller * (*to_aspell_speller)(struct AspellCanHaveError *);
|
33 |
struct AspellSpeller * (*to_aspell_speller)(struct AspellCanHaveError *);
|
52 |
struct AspellConfig * (*aspell_speller_config)(struct AspellSpeller *);
|
34 |
struct AspellConfig * (*aspell_speller_config)(struct AspellSpeller *);
|
53 |
const struct AspellWordList * (*aspell_speller_suggest)
|
35 |
const struct AspellWordList * (*aspell_speller_suggest)
|
54 |
(struct AspellSpeller *, const char *, int);
|
36 |
(struct AspellSpeller *, const char *, int);
|
|
|
37 |
int (*aspell_speller_check)(struct AspellSpeller *, const char *, int);
|
55 |
struct AspellStringEnumeration * (*aspell_word_list_elements)
|
38 |
struct AspellStringEnumeration * (*aspell_word_list_elements)
|
56 |
(const struct AspellWordList * ths);
|
39 |
(const struct AspellWordList * ths);
|
57 |
const char * (*aspell_string_enumeration_next)
|
40 |
const char * (*aspell_string_enumeration_next)
|
58 |
(struct AspellStringEnumeration * ths);
|
41 |
(struct AspellStringEnumeration * ths);
|
59 |
void (*delete_aspell_string_enumeration)(struct AspellStringEnumeration *);
|
42 |
void (*delete_aspell_string_enumeration)(struct AspellStringEnumeration *);
|
|
... |
|
... |
84 |
".so.15",
|
67 |
".so.15",
|
85 |
".so.16"
|
68 |
".so.16"
|
86 |
};
|
69 |
};
|
87 |
static const unsigned int nlibsuffs = sizeof(aspell_lib_suffixes) / sizeof(char *);
|
70 |
static const unsigned int nlibsuffs = sizeof(aspell_lib_suffixes) / sizeof(char *);
|
88 |
|
71 |
|
|
|
72 |
// Stuff that we don't wish to see in the .h (possible sysdeps, etc.)
|
|
|
73 |
class AspellData {
|
|
|
74 |
public:
|
|
|
75 |
AspellData()
|
|
|
76 |
: m_handle(0), m_speller(0)
|
|
|
77 |
{}
|
|
|
78 |
~AspellData() {
|
|
|
79 |
LOGDEB2(("~AspellData\n"));
|
|
|
80 |
if (m_handle) {
|
|
|
81 |
dlclose(m_handle);
|
|
|
82 |
m_handle = 0;
|
|
|
83 |
}
|
|
|
84 |
if (m_speller) {
|
|
|
85 |
// Dumps core if I do this??
|
|
|
86 |
//aapi.delete_aspell_speller(m_speller);
|
|
|
87 |
m_speller = 0;
|
|
|
88 |
LOGDEB2(("~AspellData: speller done\n"));
|
|
|
89 |
}
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
void *m_handle;
|
|
|
93 |
string m_exec;
|
|
|
94 |
AspellSpeller *m_speller;
|
|
|
95 |
};
|
|
|
96 |
|
|
|
97 |
Aspell::Aspell(RclConfig *cnf)
|
|
|
98 |
: m_config(cnf), m_data(0)
|
|
|
99 |
{
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
Aspell::~Aspell()
|
|
|
103 |
{
|
|
|
104 |
deleteZ(m_data);
|
|
|
105 |
}
|
|
|
106 |
|
89 |
bool Aspell::init(string &reason)
|
107 |
bool Aspell::init(string &reason)
|
90 |
{
|
108 |
{
|
91 |
delete m_data;
|
109 |
deleteZ(m_data);
|
92 |
m_data = 0;
|
110 |
|
93 |
// Language: we get this from the configuration, else from the NLS
|
111 |
// Language: we get this from the configuration, else from the NLS
|
94 |
// environment. The aspell language names used for selecting language
|
112 |
// environment. The aspell language names used for selecting language
|
95 |
// definition files (used to create dictionaries) are like en, fr
|
113 |
// definition files (used to create dictionaries) are like en, fr
|
96 |
if (!m_config->getConfParam("aspellLanguage", m_lang) || m_lang.empty()) {
|
114 |
if (!m_config->getConfParam("aspellLanguage", m_lang) || m_lang.empty()) {
|
97 |
string lang = "en";
|
115 |
string lang = "en";
|
|
... |
|
... |
112 |
break;
|
130 |
break;
|
113 |
}
|
131 |
}
|
114 |
}
|
132 |
}
|
115 |
if (m_data->m_exec.empty()) {
|
133 |
if (m_data->m_exec.empty()) {
|
116 |
reason = "aspell program not found or not executable";
|
134 |
reason = "aspell program not found or not executable";
|
|
|
135 |
deleteZ(m_data);
|
117 |
return false;
|
136 |
return false;
|
118 |
}
|
137 |
}
|
119 |
|
138 |
|
120 |
// We first look for the aspell library in libdir, and also try to
|
139 |
// We first look for the aspell library in libdir, and also try to
|
121 |
// be clever with ASPELL_PROG.
|
140 |
// be clever with ASPELL_PROG.
|
|
... |
|
... |
149 |
}
|
168 |
}
|
150 |
}
|
169 |
}
|
151 |
|
170 |
|
152 |
found:
|
171 |
found:
|
153 |
if (m_data->m_handle == 0) {
|
172 |
if (m_data->m_handle == 0) {
|
154 |
reason += string(" : ") + dlerror();
|
173 |
reason += string(" : ") + dlerror();
|
|
|
174 |
deleteZ(m_data);
|
155 |
return false;
|
175 |
return false;
|
156 |
}
|
176 |
}
|
157 |
|
177 |
|
158 |
string badnames;
|
178 |
string badnames;
|
159 |
NMTOPTR(new_aspell_config, (struct AspellConfig *(*)()));
|
179 |
NMTOPTR(new_aspell_config, (struct AspellConfig *(*)()));
|
160 |
NMTOPTR(aspell_config_replace, (int (*)(struct AspellConfig *,
|
180 |
NMTOPTR(aspell_config_replace, (int (*)(struct AspellConfig *,
|
|
... |
|
... |
170 |
NMTOPTR(aspell_speller_config,
|
190 |
NMTOPTR(aspell_speller_config,
|
171 |
(struct AspellConfig *(*)(struct AspellSpeller *)));
|
191 |
(struct AspellConfig *(*)(struct AspellSpeller *)));
|
172 |
NMTOPTR(aspell_speller_suggest,
|
192 |
NMTOPTR(aspell_speller_suggest,
|
173 |
(const struct AspellWordList *(*)(struct AspellSpeller *,
|
193 |
(const struct AspellWordList *(*)(struct AspellSpeller *,
|
174 |
const char *, int)));
|
194 |
const char *, int)));
|
|
|
195 |
NMTOPTR(aspell_speller_check,
|
|
|
196 |
(int (*)(struct AspellSpeller *, const char *, int)));
|
175 |
NMTOPTR(aspell_word_list_elements,
|
197 |
NMTOPTR(aspell_word_list_elements,
|
176 |
(struct AspellStringEnumeration *(*)
|
198 |
(struct AspellStringEnumeration *(*)
|
177 |
(const struct AspellWordList *)));
|
199 |
(const struct AspellWordList *)));
|
178 |
NMTOPTR(aspell_string_enumeration_next,
|
200 |
NMTOPTR(aspell_string_enumeration_next,
|
179 |
(const char * (*)(struct AspellStringEnumeration *)));
|
201 |
(const char * (*)(struct AspellStringEnumeration *)));
|
|
... |
|
... |
187 |
(const char *(*)(const struct AspellSpeller *)));
|
209 |
(const char *(*)(const struct AspellSpeller *)));
|
188 |
NMTOPTR(delete_aspell_speller, (void (*)(struct AspellSpeller *)));
|
210 |
NMTOPTR(delete_aspell_speller, (void (*)(struct AspellSpeller *)));
|
189 |
|
211 |
|
190 |
if (!badnames.empty()) {
|
212 |
if (!badnames.empty()) {
|
191 |
reason = string("Aspell::init: symbols not found:") + badnames;
|
213 |
reason = string("Aspell::init: symbols not found:") + badnames;
|
|
|
214 |
deleteZ(m_data);
|
192 |
return false;
|
215 |
return false;
|
193 |
}
|
216 |
}
|
194 |
|
217 |
|
195 |
return true;
|
218 |
return true;
|
196 |
}
|
219 |
}
|
|
... |
|
... |
277 |
db.termWalkClose(tit);
|
300 |
db.termWalkClose(tit);
|
278 |
return true;
|
301 |
return true;
|
279 |
}
|
302 |
}
|
280 |
|
303 |
|
281 |
|
304 |
|
282 |
bool Aspell::suggest(Rcl::Db &db,
|
305 |
bool Aspell::make_speller(string& reason)
|
283 |
string &term, list<string> &suggestions, string &reason)
|
|
|
284 |
{
|
306 |
{
|
285 |
if (!ok())
|
307 |
if (!ok())
|
286 |
return false;
|
308 |
return false;
|
|
|
309 |
if (m_data->m_speller != 0)
|
|
|
310 |
return true;
|
287 |
|
311 |
|
288 |
AspellCanHaveError *ret;
|
312 |
AspellCanHaveError *ret;
|
289 |
AspellSpeller *speller;
|
|
|
290 |
AspellConfig *config;
|
|
|
291 |
|
313 |
|
292 |
config = aapi.new_aspell_config();
|
314 |
AspellConfig *config = aapi.new_aspell_config();
|
293 |
|
|
|
294 |
aapi.aspell_config_replace(config, "lang", m_lang.c_str());
|
315 |
aapi.aspell_config_replace(config, "lang", m_lang.c_str());
|
295 |
aapi.aspell_config_replace(config, "encoding", "utf-8");
|
316 |
aapi.aspell_config_replace(config, "encoding", "utf-8");
|
296 |
aapi.aspell_config_replace(config, "master", dicPath().c_str());
|
317 |
aapi.aspell_config_replace(config, "master", dicPath().c_str());
|
297 |
aapi.aspell_config_replace(config, "sug-mode", "fast");
|
318 |
aapi.aspell_config_replace(config, "sug-mode", "fast");
|
298 |
// aapi.aspell_config_replace(config, "sug-edit-dist", "2");
|
319 |
// aapi.aspell_config_replace(config, "sug-edit-dist", "2");
|
|
... |
|
... |
302 |
if (aapi.aspell_error(ret) != 0) {
|
323 |
if (aapi.aspell_error(ret) != 0) {
|
303 |
reason = aapi.aspell_error_message(ret);
|
324 |
reason = aapi.aspell_error_message(ret);
|
304 |
aapi.delete_aspell_can_have_error(ret);
|
325 |
aapi.delete_aspell_can_have_error(ret);
|
305 |
return false;
|
326 |
return false;
|
306 |
}
|
327 |
}
|
307 |
speller = aapi.to_aspell_speller(ret);
|
328 |
m_data->m_speller = aapi.to_aspell_speller(ret);
|
308 |
config = aapi.aspell_speller_config(speller);
|
329 |
return true;
|
|
|
330 |
}
|
|
|
331 |
|
|
|
332 |
bool Aspell::check(Rcl::Db &db, const string &term, string& reason)
|
|
|
333 |
{
|
|
|
334 |
LOGDEB2(("Aspell::check [%s]\n", term.c_str()));
|
|
|
335 |
|
|
|
336 |
if (!ok() || !make_speller(reason))
|
|
|
337 |
return false;
|
|
|
338 |
if (term.empty())
|
|
|
339 |
return true; //??
|
|
|
340 |
|
|
|
341 |
int ret = aapi.aspell_speller_check(m_data->m_speller,
|
|
|
342 |
term.c_str(), term.length());
|
|
|
343 |
reason.clear();
|
|
|
344 |
switch (ret) {
|
|
|
345 |
case 0: return false;
|
|
|
346 |
case 1: return true;
|
|
|
347 |
default:
|
|
|
348 |
case -1:
|
|
|
349 |
reason.append("Aspell error: ");
|
|
|
350 |
reason.append(aapi.aspell_speller_error_message(m_data->m_speller));
|
|
|
351 |
return false;
|
|
|
352 |
}
|
|
|
353 |
}
|
|
|
354 |
|
|
|
355 |
bool Aspell::suggest(Rcl::Db &db, const string &term,
|
|
|
356 |
list<string>& suggestions, string& reason)
|
|
|
357 |
{
|
|
|
358 |
if (!ok() || !make_speller(reason))
|
|
|
359 |
return false;
|
|
|
360 |
if (term.empty())
|
|
|
361 |
return true; //??
|
|
|
362 |
|
|
|
363 |
AspellCanHaveError *ret;
|
|
|
364 |
|
309 |
const AspellWordList *wl =
|
365 |
const AspellWordList *wl =
|
310 |
aapi.aspell_speller_suggest(speller, term.c_str(), term.length());
|
366 |
aapi.aspell_speller_suggest(m_data->m_speller,
|
|
|
367 |
term.c_str(), term.length());
|
311 |
if (wl == 0) {
|
368 |
if (wl == 0) {
|
312 |
reason = aapi.aspell_speller_error_message(speller);
|
369 |
reason = aapi.aspell_speller_error_message(m_data->m_speller);
|
313 |
return false;
|
370 |
return false;
|
314 |
}
|
371 |
}
|
315 |
AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl);
|
372 |
AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl);
|
316 |
const char *word;
|
373 |
const char *word;
|
317 |
while ((word = aapi.aspell_string_enumeration_next(els)) != 0) {
|
374 |
while ((word = aapi.aspell_string_enumeration_next(els)) != 0) {
|
|
... |
|
... |
324 |
string sw(word);
|
381 |
string sw(word);
|
325 |
if (db.termExists(sw) && db.stemDiffers("english", sw, term))
|
382 |
if (db.termExists(sw) && db.stemDiffers("english", sw, term))
|
326 |
suggestions.push_back(word);
|
383 |
suggestions.push_back(word);
|
327 |
}
|
384 |
}
|
328 |
aapi.delete_aspell_string_enumeration(els);
|
385 |
aapi.delete_aspell_string_enumeration(els);
|
329 |
aapi.delete_aspell_speller(speller);
|
|
|
330 |
// Config belongs to speller here? aapi.delete_aspell_config(config);
|
|
|
331 |
return true;
|
386 |
return true;
|
332 |
}
|
387 |
}
|
333 |
|
388 |
|
334 |
#endif // RCL_USE_ASPELL
|
389 |
#endif // RCL_USE_ASPELL
|
335 |
|
390 |
|