Here is a patch to use Pspell instead of Ispell for the spell checker. 
It is still not very complete and it does not pass any options to pspell
as the current version of pspell won't except any.  Future versions
will, and if necessary I will update my patch to probably pass on the
options.

It will use Pspell if USE_PSPELL is defined.  The Pspell library needs
to be liked in somewhere.  I was not sure the best way to do this so I
will leave that up to you.  You might want to make using pspell a
configure option.....

Obviously once you figure out how best to specify if pspell is to be
used the  "//#define USE_PSPELL 1" line should be removed.  As Pspell is
still very incomplete I do not recommend you enable it by default. 
However, I do recommand some of the LyX develeprs who have Pspell and
Aspell installed try it out to find any bugs.

Now how about creating an ispell module?  What I originally prepossessed
coming up with an interface you said that you would be willing to do the
ispell part.  The only think that has changes is that I made the
interface more generic.  So are you still willing?

For those of you who don't know what I am talking about the following
links may help:
  http://pspell.sourceforge.net/
  http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg08808.html

-- 
Kevin Atkinson
[EMAIL PROTECTED]
http://metalab.unc.edu/kevina/
--- spellchecker.C.orig Tue Jan 25 12:21:47 2000
+++ spellchecker.C      Mon Apr 10 20:16:33 2000
@@ -49,6 +49,14 @@
 #include "debug.h"
 #include "support/lstrings.h"
 
+//#define USE_PSPELL 1
+
+#ifdef USE_PSPELL
+
+#include <pspell/pspell.h>
+
+#endif
+
 extern LyXRC *lyxrc;
 extern BufferView *current_view;
 
@@ -64,6 +72,8 @@
 
 static bool RunSpellChecker(string const &);
 
+#ifndef USE_PSPELL
+
 static FILE *in, *out;  /* streams to communicate with ispell */
 pid_t isp_pid = -1; // pid for the `ispell' process. Also used (RO) in
                     // lyx_cb.C
@@ -74,6 +84,12 @@
 
 static int isp_fd;
 
+#else
+
+PspellManager * sc;
+
+#endif
+
 static FD_form_spell_options *fd_form_spell_options = 0;
 FD_form_spell_check *fd_form_spell_check = 0;
 
@@ -83,22 +99,57 @@
 //extern void sigchldchecker(int sig);
 extern void sigchldchecker(pid_t pid, int *status);
 
+#ifndef USE_PSPELL
+
 struct isp_result {
        int flag;
-       int count;
-       string str;
-       char **misses;
+       char * str;
+       char * b;
+       char * e;
+       const char * next_miss();
        isp_result() {
                flag = ISP_UNKNOWN;
-               count = 0;
-               misses = static_cast<char**>(0);
+               str = 0;
        }
        ~isp_result() {
-               if (misses) // DEL LINE
-                       delete[] misses;
+               if (str)
+                       delete[] str;
        }
 };
 
+const char * isp_result::next_miss() {
+       if (str == 0 || *(e+1) == '\0') return 0;
+       b = e + 2;
+       e = strpbrk(b, ",\n");
+       *e = '\0';
+       return b;
+}
+
+#else
+
+struct isp_result {
+       int flag;
+       PspellStringEmulation * els;
+       
+       const char * next_miss();
+       isp_result() {
+               flag = ISP_UNKNOWN;
+               els = 0;
+       }
+       ~isp_result() {
+               delete_pspell_string_emulation(els);
+       }
+};
+
+const char * isp_result::next_miss() 
+{
+       return pspell_string_emulation_next(els);
+}
+
+#endif
+
+const char * spell_error;
+
 
 /***** Spellchecker options *****/
 
@@ -219,13 +270,14 @@
        }
 }
 
+#ifndef USE_PSPELL
 
 /***** Spellchecker *****/
 
 // Could also use a clean up. (Asger Alstrup)
 
 static
-void create_ispell_pipe(string const & lang)
+void init_spell_checker(string const & lang)
 {
        static char o_buf[BUFSIZ];  // jc: it could be smaller
        int pipein[2], pipeout[2];
@@ -236,19 +288,19 @@
 
        if(pipe(pipein) == -1 || pipe(pipeout) == -1) {
                lyxerr << "LyX: Can't create pipe for spellchecker!" << endl;
-               return;
+               goto END;
        }
 
        if ((out = fdopen(pipein[1], "w")) == 0) {
                lyxerr << "LyX: Can't create stream for pipe for spellchecker!"
                       << endl;
-               return;
+               goto END;
        }
 
        if ((in = fdopen(pipeout[0], "r")) == 0) {
                lyxerr <<"LyX: Can't create stream for pipe for spellchecker!"
                       << endl;
-               return;
+               goto END;
        }
 
        setvbuf(out, o_buf, _IOLBF, BUFSIZ);
@@ -260,9 +312,9 @@
        if(isp_pid == -1) {
                lyxerr << "LyX: Can't create child process for spellchecker!"
                       << endl;
-               return;
+               goto END;
        }
-
+       
        if(isp_pid == 0) {        
                /* child process */
                dup2(pipein[0], STDIN_FILENO);
@@ -348,7 +400,7 @@
                lyxerr << "LyX: Failed to start ispell!" << endl;
                _exit(0);
        }
-
+       {
        /* Parent process: Read ispells identification message */
        // Hmm...what are we using this id msg for? Nothing? (Lgb)
        // Actually I used it to tell if it's truly Ispell or if it's
@@ -381,6 +433,9 @@
                  actual_spell_checker = ASC_ASPELL;
                else
                  actual_spell_checker = ASC_ISPELL;
+
+               fputs("!\n", out); // Set terse mode (silently accept correct words)
+
                
        } else if (retval == 0) {
                // timeout. Give nice message to user.
@@ -394,12 +449,35 @@
                // Select returned error
                lyxerr << "Select on ispell returned error, what now?" << endl;
        }
+       }
+ END:
+       if (isp_pid == -1) {
+               spell_error = 
+                       "\n\n"
+                       "The ispell-process has died for some reason. *One* possible 
+reason\n"
+                       "could be that you do not have a dictionary file\n"
+                       "for the language of this document installed.\n"
+                       "Check /usr/lib/ispell or set another\n"
+                       "dictionary in the Spellchecker Options menu.";
+       } else {
+               spell_error = 0;
+       }
+}
+
+static
+bool sc_still_alive() {
+       return isp_pid != -1;
 }
 
+static
+void sc_clean_up_after_error() 
+{
+       fclose(out);
+}
 
 // Send word to ispell and get reply
 static
-isp_result *ispell_check_word(char *word)
+isp_result * sc_check_word(char *word)
 {
        //Please rewrite to use string.
        isp_result *result;
@@ -437,25 +515,10 @@
        case '&': // Not found, but we have near misses
        {
                result->flag = ISP_MISSED;
-               result->str = buf;
-               // nb is leaked! where should it be freed? I have to
-               // admit I do not understand the intent of the code :(
-               // (JMarc) 
-               char * nb = new char[result->str.length() + 1];
-               result->str.copy(nb, result->str.length());
-               nb[result->str.length()]= '\0';
-               p = strpbrk(nb+2, " ");
-               sscanf(p, "%d", &count); // Get near misses count
-               result->count = count;
-               if (count) result->misses = new char*[count];
-               p = strpbrk(nb, ":");
-               p += 2;
-               for (i = 0; i < count; ++i) {
-                       result->misses[i] = p;
-                       p = strpbrk(p, ",\n");
-                       *p = 0;
-                       p += 2;
-               }
+               char * p = strpbrk(buf, ":");
+               result->str = new char[strlen(p) + 1];
+               result->e   = result->str;
+               strcpy(result->str, p);
                break;
        }
        default: // This shouldn't happend, but you know Murphy
@@ -471,7 +534,7 @@
 
 
 static
-inline void ispell_terminate()
+inline void close_spell_checker()
 {
         // Note: If you decide to optimize this out when it is not 
         // needed please note that when Aspell is used this command 
@@ -486,14 +549,7 @@
 
 
 static
-inline void ispell_terse_mode()
-{
-       fputs("!\n", out); // Set terse mode (silently accept correct words)
-}
-
-
-static
-inline void ispell_insert_word(char const *word)
+inline void sc_insert_word(char const *word)
 {
        fputc('*', out); // Insert word in personal dictionary
        fputs(word, out);
@@ -502,7 +558,7 @@
 
 
 static
-inline void ispell_accept_word(char const *word) 
+inline void sc_accept_word(char const *word) 
 {
        fputc('@', out); // Accept in this session
        fputs(word, out);
@@ -510,7 +566,7 @@
 }
 
 static
-inline void ispell_store_replacement(char const *mis, string const & cor) {
+inline void sc_store_replacement(char const *mis, string const & cor) {
         if(actual_spell_checker == ASC_ASPELL) {
                 fputs("$$ra ", out);
                 fputs(mis, out);
@@ -520,6 +576,90 @@
         }
 }
 
+#else
+
+PspellCanHaveError * spell_error_object;
+
+static
+void init_spell_checker(string const & lang)
+{
+       PspellConfig * config = new_pspell_config();
+       spell_error_object = new_pspell_manager(config);
+       if (pspell_error_number(spell_error_object) != 0) {
+               spell_error = pspell_error_message(spell_error_object);
+       } else {
+               spell_error = 0;
+               sc = to_pspell_manager(spell_error_object);
+               spell_error_object = 0;
+       }
+}
+
+static 
+bool sc_still_alive() {
+       return true;
+}
+
+static
+void sc_clean_up_after_error() 
+{
+       delete_pspell_can_have_error(spell_error_object);
+}
+
+
+
+// Send word to ispell and get reply
+static
+isp_result * sc_check_word(char *word)
+{
+       isp_result * result = new isp_result;
+       int word_ok = pspell_manager_check(sc, word);
+       assert(word_ok != -1);
+
+       if (word_ok) {
+
+               result->flag = ISP_OK;
+
+       } else {
+
+               const PspellWordList * sugs = pspell_manager_suggest(sc, word);
+               assert(sugs != 0);
+               result->els = pspell_word_list_elements(sugs);
+               if (pspell_word_list_empty(sugs)) 
+                       result->flag = ISP_UNKNOWN;
+               else 
+                       result->flag = ISP_MISSED;
+               
+       }
+       return result;
+}
+
+
+static
+inline void close_spell_checker()
+{
+       pspell_manager_save_all_word_lists(sc);
+}
+
+
+static
+inline void sc_insert_word(char const *word)
+{
+       pspell_manager_add_to_personal(sc, word);
+}
+
+
+static
+inline void sc_accept_word(char const *word) 
+{
+       pspell_manager_add_to_personal(sc, word);
+}
+
+static
+inline void sc_store_replacement(char const *mis, string const & cor) {
+       pspell_manager_store_replacement(sc, mis, cor.c_str());
+}
+
+#endif
 
 void ShowSpellChecker()
 {
@@ -652,23 +792,14 @@
        newval = 0.0;
    
        /* create ispell process */
-       create_ispell_pipe(tmp);
+       init_spell_checker(tmp);
 
-       if (isp_pid == -1) {
-               fl_show_message(
-                       _("\n\n"
-                         "The ispell-process has died for some reason. *One* possible 
reason\n"
-                         "could be that you do not have a dictionary file\n"
-                         "for the language of this document installed.\n"
-                         "Check /usr/lib/ispell or set another\n"
-                         "dictionary in the Spellchecker Options menu."), "", "");
-               fclose(out);
+       if (spell_error != 0) {
+               fl_show_message(_(spell_error), "", "");
+               sc_clean_up_after_error();
                return true;
        }
 
-       // Put ispell in terse mode to improve speed
-       ispell_terse_mode();
-
        while (true) {
                word = current_view->nextWord(newval);
                if (word == 0) break;
@@ -681,8 +812,8 @@
                        fl_set_slider_value(fd_form_spell_check->slider, oldval);
                }
 
-               result = ispell_check_word(word);
-               if (isp_pid == -1) {
+               result = sc_check_word(word);
+               if (!sc_still_alive()) {
                        delete[] word;
                        break;
                }
@@ -691,13 +822,13 @@
                if (obj == fd_form_spell_check->stop) {
                        delete result;
                        delete[] word;
-                       ispell_terminate();
+                       close_spell_checker();
                        return true;
                }
                if (obj == fd_form_spell_check->done) {
                        delete result;
                        delete[] word;
-                       ispell_terminate(); 
+                       close_spell_checker(); 
                        return false;
                }
     
@@ -708,19 +839,20 @@
                        fl_set_object_label(fd_form_spell_check->text, word);
                        fl_set_input(fd_form_spell_check->input, word);
                        fl_clear_browser(fd_form_spell_check->browser);
-                       for (i = 0; i < result->count; ++i) {
-                               fl_add_browser_line(fd_form_spell_check->browser, 
result->misses[i]);
+                       const char * w;
+                       while ((w = result->next_miss()) != 0) {
+                               fl_add_browser_line(fd_form_spell_check->browser, w);
                        }
 
                        clickline = -1;
                        while (true) {
                                obj = fl_do_forms();
                                if (obj == fd_form_spell_check->insert) {
-                                       ispell_insert_word(word);
+                                       sc_insert_word(word);
                                        break;
                                }
                                if (obj == fd_form_spell_check->accept) {
-                                       ispell_accept_word(word);
+                                       sc_accept_word(word);
                                        break;
                                }
                                if (obj == fd_form_spell_check->ignore) {
@@ -728,7 +860,7 @@
                                }
                                if (obj == fd_form_spell_check->replace || 
                                    obj == fd_form_spell_check->input) {
-                                       ispell_store_replacement(word, 
fl_get_input(fd_form_spell_check->input));
+                                       sc_store_replacement(word, 
+fl_get_input(fd_form_spell_check->input));
                                        
current_view->replaceWord(fl_get_input(fd_form_spell_check->input));
                                        break;
                                }
@@ -737,7 +869,7 @@
                                        // sent to lyx@via by Mark Burton 
<[EMAIL PROTECTED]>
                                        if (clickline == 
                                            
fl_get_browser(fd_form_spell_check->browser)) {
-                                               ispell_store_replacement(word, 
fl_get_input(fd_form_spell_check->input));
+                                               sc_store_replacement(word, 
+fl_get_input(fd_form_spell_check->input));
                                                
current_view->replaceWord(fl_get_input(fd_form_spell_check->input));
                                                break;
                                        }
@@ -750,14 +882,14 @@
                                if (obj == fd_form_spell_check->stop) {
                                        delete result;
                                        delete[] word;
-                                       ispell_terminate();
+                                       close_spell_checker();
                                        return true;
                                }
            
                                if (obj == fd_form_spell_check->done) {
                                        delete result;
                                        delete[] word;
-                                       ispell_terminate();
+                                       close_spell_checker();
                                        return false;
                                }
                        }
@@ -767,8 +899,8 @@
                }
        }
    
-       if(isp_pid!= -1) {
-               ispell_terminate();
+       if(sc_still_alive()) {
+               close_spell_checker();
                string word_msg;
                word_msg += tostr(word_count);
                if (word_count != 1) {
@@ -780,14 +912,16 @@
                                word_msg.c_str());
                return false;
        } else {
-               fl_show_message(_("The ispell-process has died for some reason.\n"
+               fl_show_message(_("The spell checker has died for some reason.\n"
                                "Maybe it has been killed."), "", "");
-               fclose(out);
+               sc_clean_up_after_error();
                return true;
        }
 }
 
 
+#ifndef USE_PSPELL
+
 //void sigchldhandler(int sig)
 void sigchldhandler(pid_t pid, int *status)
 { 
@@ -804,3 +938,12 @@
        //sigchldchecker(sig);
        sigchldchecker(pid, status);
 }
+
+#else
+
+void sigchldhandler(pid_t pid, int *status)
+{ 
+       // do nothing
+}
+
+#endif

Reply via email to