On Mon, 7 Aug 2000, Juergen Vigna wrote: > This said I'll wait for your move and will give you any information > I can give you (I really am not so familiar with signals) and will > do inquiries on the other developers for knowledge, also I will test > the stuff you send me and see if it works. Well as soon as someone tells me how to properly handle the signals I will modify my original patch (attached) I sent Lyx-Devel to use take advantage of the new features in Pspell .11. The original patch will only use PSPELL if USE_PSPELL is defined. --- Kevin Atkinson kevina at users sourceforge net 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