--- a/src/aspell/rclaspell.cpp
+++ b/src/aspell/rclaspell.cpp
@@ -1,17 +1,24 @@
#ifndef TEST_RCLASPELL
#ifndef lint
-static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.2 2006-10-09 16:37:08 dockes Exp $ (C) 2006 J.F.Dockes";
+static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.3 2006-10-11 14:16:25 dockes Exp $ (C) 2006 J.F.Dockes";
#endif
+#ifdef HAVE_CONFIG_H
+#include "autoconfig.h"
+#endif
+
+#ifdef RCL_USE_ASPELL
+
#include <unistd.h>
#include <dlfcn.h>
#include <iostream>
-#include "aspell.h"
+#include ASPELL_INCLUDE
#include "pathut.h"
#include "execmd.h"
#include "rclaspell.h"
+// Stuff that we don't wish to see in the .h (possible sysdeps, etc.)
class AspellData {
public:
AspellData() : m_handle(0) {}
@@ -62,22 +69,54 @@
badnames += #NM + string(" "); \
}
-bool Aspell::init(const string &basedir, string &reason)
-{
- if (m_data == 0)
- m_data = new AspellData;
- if (m_data->m_handle) {
- dlclose(m_data->m_handle);
- m_data->m_handle = 0;
- }
-
- m_data->m_exec = path_cat(basedir, "bin");
- m_data->m_exec = path_cat(m_data->m_exec, "aspell");
- if (access(m_data->m_exec.c_str(), X_OK) != 0) {
- reason = m_data->m_exec + " not found or not executable";
- return false;
- }
- string lib = path_cat(basedir, "lib");
+const char *aspell_progs[] = {
+#ifdef ASPELL_PROG
+ ASPELL_PROG ,
+#endif
+ "/usr/local/bin/aspell",
+ "/usr/bin/aspell"
+};
+
+bool Aspell::init(string &reason)
+{
+ delete m_data;
+ m_data = 0;
+ // Language: we get this from the configuration, else from the NLS
+ // environment. The aspell language names used for selecting language
+ // definition files (used to create dictionaries) are like en, fr
+ if (!m_config->getConfParam("aspellLanguage", m_lang)) {
+ string lang = "en";
+ const char *cp;
+ if (cp = getenv("LC_ALL"))
+ lang = cp;
+ else if (cp = getenv("LANG"))
+ lang = cp;
+ if (!lang.compare("C"))
+ lang = "en";
+ m_lang = lang.substr(0, lang.find_first_of("_"));
+ } else {
+ if (!m_lang.compare("disable")) {
+ reason = "Aspell disabled in recoll configuration file";
+ return false;
+ }
+ }
+
+ m_data = new AspellData;
+ for (unsigned int i = 0; i < sizeof(aspell_progs) / sizeof(char*); i++) {
+ if (access(aspell_progs[i], X_OK) == 0) {
+ m_data->m_exec = aspell_progs[i];
+ break;
+ }
+ }
+ if (m_data->m_exec.empty()) {
+ reason = "aspell program not found or not executable";
+ return false;
+ }
+
+ // For now, the aspell library has to live under the same prefix as the
+ // aspell program.
+ string aspellPrefix = path_getfather(path_getfather(m_data->m_exec));
+ string lib = path_cat(aspellPrefix, "lib");
lib = path_cat(lib, "libaspell.so");
if ((m_data->m_handle = dlopen(lib.c_str(), RTLD_LAZY)) == 0) {
reason = "Could not open shared library [";
@@ -120,6 +159,7 @@
reason = string("Aspell::init: symbols not found:") + badnames;
return false;
}
+
return true;
}
@@ -130,51 +170,58 @@
string Aspell::dicPath()
{
- return path_cat(m_conf->getConfDir(),
+ return path_cat(m_config->getConfDir(),
string("aspdict.") + m_lang + string(".rws"));
}
bool Aspell::buildDict(Rcl::Db &db, string &reason)
{
- string term;
-
- // Il faut nettoyer la liste, peut-etre faire un tri unique (verifier),
- // puis construire le dico
- Rcl::TermIter *tit = db.termWalkOpen();
- if (tit == 0) {
- reason = "termWalkOpen failed\n";
- return false;
- }
- ExecCmd aspell;
- list<string> args;
- // aspell --lang=[lang] create master [dictApath]
- args.push_back(string("--lang=")+ m_lang);
- args.push_back("create");
- args.push_back("master");
- args.push_back(dicPath());
- // aspell.setStderr("/dev/null");
- string allterms;
- while (db.termWalkNext(tit, term)) {
- // Filter out terms beginning with upper case (special stuff) and
- // containing numbers
- if (term.empty())
- continue;
- if ('A' <= term.at(0) && term.at(0) <= 'Z')
- continue;
- if (term.find_first_of("0123456789+-._@") != string::npos)
- continue;
- allterms += term + "\n";
- // std::cout << "[" << term << "]" << std::endl;
- }
- db.termWalkClose(tit);
- aspell.doexec(m_data->m_exec, args, &allterms);
- return true;
+ if (!ok())
+ return false;
+
+ // We create the dictionary by executing the aspell command:
+ // aspell --lang=[lang] create master [dictApath]
+ ExecCmd aspell;
+ list<string> args;
+ args.push_back(string("--lang=")+ m_lang);
+ args.push_back("create");
+ args.push_back("master");
+ args.push_back(dicPath());
+ aspell.setStderr("/dev/null");
+
+ Rcl::TermIter *tit = db.termWalkOpen();
+ if (tit == 0) {
+ reason = "termWalkOpen failed\n";
+ return false;
+ }
+ string allterms, term;
+ while (db.termWalkNext(tit, term)) {
+ // Filter out terms beginning with upper case (special stuff) and
+ // containing numbers
+ if (term.empty())
+ continue;
+ if ('A' <= term.at(0) && term.at(0) <= 'Z')
+ continue;
+ if (term.find_first_of("0123456789+-._@") != string::npos)
+ continue;
+ allterms += term + "\n";
+ // std::cout << "[" << term << "]" << std::endl;
+ }
+ db.termWalkClose(tit);
+ if (aspell.doexec(m_data->m_exec, args, &allterms)) {
+ reason = string("aspell dictionary creation command failed. Check the language data files for lang = ") + m_lang;
+ return false;
+ }
+ return true;
}
bool Aspell::suggest(Rcl::Db &db,
string &term, list<string> &suggestions, string &reason)
{
+ if (!ok())
+ return false;
+
AspellCanHaveError *ret;
AspellSpeller *speller;
AspellConfig *config;
@@ -221,8 +268,15 @@
return true;
}
+#endif // RCL_USE_ASPELL
#else // TEST_RCLASPELL test driver ->
+
+#ifdef HAVE_CONFIG_H
+#include "autoconfig.h"
+#endif
+
+#ifdef RCL_USE_ASPELL
#include <stdio.h>
#include <stdlib.h>
@@ -304,11 +358,9 @@
exit(1);
}
- string lang = "en";
-
- Aspell aspell(rclconfig, lang);
-
- if (!aspell.init("/usr/local", reason)) {
+ Aspell aspell(rclconfig);
+
+ if (!aspell.init(reason)) {
cerr << "Init failed: " << reason << endl;
exit(1);
}
@@ -331,5 +383,9 @@
}
exit(0);
}
+#else
+int main(int argc, char **argv)
+{return 1;}
+#endif // RCL_USE_ASPELL
#endif // TEST_RCLASPELL test driver