Switch to side-by-side view

--- a/src/aspell/rclaspell.cpp
+++ b/src/aspell/rclaspell.cpp
@@ -19,25 +19,7 @@
 #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) {}
-    ~AspellData() {
-	if (m_handle) 
-	    dlclose(m_handle);
-    }
-
-    void  *m_handle;
-    string m_exec;
-};
-
-Aspell::~Aspell()
-{
-    if (m_data)
-	delete m_data;
-}
+#include "debuglog.h"
 
 // Just a place where we keep the Aspell library entry points together
 class AspellApi {
@@ -52,6 +34,7 @@
     struct AspellConfig * (*aspell_speller_config)(struct AspellSpeller *);
     const struct AspellWordList * (*aspell_speller_suggest)
 	(struct AspellSpeller *, const char *, int);
+    int (*aspell_speller_check)(struct AspellSpeller *, const char *, int);
     struct AspellStringEnumeration * (*aspell_word_list_elements)
 	(const struct AspellWordList * ths);
     const char * (*aspell_string_enumeration_next)
@@ -86,10 +69,45 @@
 };
 static const unsigned int nlibsuffs  = sizeof(aspell_lib_suffixes) / sizeof(char *);
 
+// Stuff that we don't wish to see in the .h (possible sysdeps, etc.)
+class AspellData {
+public:
+    AspellData() 
+        : m_handle(0), m_speller(0) 
+    {}
+    ~AspellData() {
+        LOGDEB2(("~AspellData\n"));
+	if (m_handle) {
+	    dlclose(m_handle);
+            m_handle = 0;
+        }
+        if (m_speller) {
+            // Dumps core if I do this?? 
+            //aapi.delete_aspell_speller(m_speller);
+            m_speller = 0;
+            LOGDEB2(("~AspellData: speller done\n"));
+        }
+    }
+
+    void  *m_handle;
+    string m_exec;
+    AspellSpeller *m_speller;    
+};
+
+Aspell::Aspell(RclConfig *cnf)
+    : m_config(cnf), m_data(0) 
+{
+}
+
+Aspell::~Aspell()
+{
+    deleteZ(m_data);
+}
+
 bool Aspell::init(string &reason)
 {
-    delete m_data;
-    m_data = 0;
+    deleteZ(m_data);
+
     // 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
@@ -114,6 +132,7 @@
     }
     if (m_data->m_exec.empty()) {
 	reason = "aspell program not found or not executable";
+        deleteZ(m_data);
 	return false;
     }
 
@@ -151,8 +170,9 @@
     
  found:
     if (m_data->m_handle == 0) {
-      reason += string(" : ") + dlerror();
-      return false;
+        reason += string(" : ") + dlerror();
+        deleteZ(m_data);
+        return false;
     }
 
     string badnames;
@@ -172,6 +192,8 @@
     NMTOPTR(aspell_speller_suggest, 
 	    (const struct AspellWordList *(*)(struct AspellSpeller *, 
 					       const char *, int)));
+    NMTOPTR(aspell_speller_check, 
+	    (int (*)(struct AspellSpeller *, const char *, int)));
     NMTOPTR(aspell_word_list_elements, 
 	    (struct AspellStringEnumeration *(*)
 	     (const struct AspellWordList *)));
@@ -189,6 +211,7 @@
 
     if (!badnames.empty()) {
 	reason = string("Aspell::init: symbols not found:") + badnames;
+        deleteZ(m_data);
 	return false;
     }
 
@@ -279,18 +302,16 @@
 }
 
 
-bool Aspell::suggest(Rcl::Db &db,
-		     string &term, list<string> &suggestions, string &reason)
+bool Aspell::make_speller(string& reason)
 {
     if (!ok())
 	return false;
+    if (m_data->m_speller != 0)
+        return true;
 
     AspellCanHaveError *ret;
-    AspellSpeller *speller;
-    AspellConfig *config;
-
-    config = aapi.new_aspell_config();
-
+
+    AspellConfig *config = aapi.new_aspell_config();
     aapi.aspell_config_replace(config, "lang", m_lang.c_str());
     aapi.aspell_config_replace(config, "encoding", "utf-8");
     aapi.aspell_config_replace(config, "master", dicPath().c_str());
@@ -304,12 +325,48 @@
 	aapi.delete_aspell_can_have_error(ret);
 	return false;
     }
-    speller = aapi.to_aspell_speller(ret);
-    config = aapi.aspell_speller_config(speller);
+    m_data->m_speller = aapi.to_aspell_speller(ret);
+    return true;
+}
+
+bool Aspell::check(Rcl::Db &db, const string &term, string& reason)
+{
+    LOGDEB2(("Aspell::check [%s]\n", term.c_str()));
+
+    if (!ok() || !make_speller(reason))
+	return false;
+    if (term.empty())
+        return true; //??
+
+    int ret = aapi.aspell_speller_check(m_data->m_speller, 
+                                        term.c_str(), term.length());
+    reason.clear();
+    switch (ret) {
+    case 0: return false;
+    case 1: return true;
+    default:
+    case -1:
+        reason.append("Aspell error: ");
+        reason.append(aapi.aspell_speller_error_message(m_data->m_speller));
+        return false;
+    }
+}
+
+bool Aspell::suggest(Rcl::Db &db, const string &term, 
+                     list<string>& suggestions, string& reason)
+{
+    if (!ok() || !make_speller(reason))
+	return false;
+    if (term.empty())
+        return true; //??
+
+    AspellCanHaveError *ret;
+
     const AspellWordList *wl = 
-	aapi.aspell_speller_suggest(speller, term.c_str(), term.length());
+	aapi.aspell_speller_suggest(m_data->m_speller, 
+                                    term.c_str(), term.length());
     if (wl == 0) {
-	reason = aapi.aspell_speller_error_message(speller);
+	reason = aapi.aspell_speller_error_message(m_data->m_speller);
 	return false;
     }
     AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl);
@@ -326,8 +383,6 @@
 	    suggestions.push_back(word);
     }
     aapi.delete_aspell_string_enumeration(els);
-    aapi.delete_aspell_speller(speller);
-    // Config belongs to speller here? aapi.delete_aspell_config(config);
     return true;
 }