X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fspellchecker.C;h=04a578affd791a636bf98aca837ba5c9bff223dd;hb=a69e7a45780e94f4330a91facfe35126c678e34e;hp=f97e8e4c942d239e2fdd6f2dd2c5ce08a3949a82;hpb=a040c0bc6f017d0591bbc7ad1aa590589dbc40ff;p=lyx.git diff --git a/src/spellchecker.C b/src/spellchecker.C index f97e8e4c94..04a578affd 100644 --- a/src/spellchecker.C +++ b/src/spellchecker.C @@ -12,6 +12,10 @@ #include +#ifdef __GNUG__ +#pragma implementation +#endif + #include #include #include @@ -34,9 +38,15 @@ #endif #ifdef HAVE_SYS_SELECT_H +# ifdef HAVE_STRINGS_H + // is needed at least on AIX because FD_ZERO uses bzero(). +# include +# endif #include #endif +#include + #include "LString.h" #include "sp_form.h" #include "spellchecker.h" @@ -48,9 +58,10 @@ #include "lyx_gui_misc.h" #include "debug.h" #include "support/lstrings.h" +#include "encoding.h" -extern LyXRC *lyxrc; -extern BufferView *current_view; +using std::reverse; +using std::endl; // Spellchecker status enum { @@ -62,9 +73,9 @@ enum { ISP_IGNORE }; -static bool RunSpellChecker(string const &); +static bool RunSpellChecker(BufferView * bv); -static FILE *in, *out; /* streams to communicate with ispell */ +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 @@ -87,14 +98,14 @@ struct isp_result { int flag; int count; string str; - char **misses; + char ** misses; isp_result() { flag = ISP_UNKNOWN; count = 0; - misses = (char**)0; + misses = static_cast(0); } ~isp_result() { - if (misses) delete[] misses; + delete[] misses; } }; @@ -108,13 +119,13 @@ struct isp_result { void SpellOptionsUpdate() { // Alternate language - if (lyxrc->isp_alt_lang.empty()) { - lyxrc->isp_use_alt_lang = false; + if (lyxrc.isp_alt_lang.empty()) { + lyxrc.isp_use_alt_lang = false; } else { fl_set_input(fd_form_spell_options->altlang_input, - lyxrc->isp_alt_lang.c_str()); + lyxrc.isp_alt_lang.c_str()); } - if (lyxrc->isp_use_alt_lang) { + if (lyxrc.isp_use_alt_lang) { fl_set_button(fd_form_spell_options->buflang, 0); fl_set_button(fd_form_spell_options->altlang, 1); } else { @@ -123,53 +134,53 @@ void SpellOptionsUpdate() } // Personal dictionary - if (lyxrc->isp_pers_dict.empty()) { - lyxrc->isp_use_pers_dict = false; + if (lyxrc.isp_pers_dict.empty()) { + lyxrc.isp_use_pers_dict = false; } else { fl_set_input(fd_form_spell_options->perdict_input, - lyxrc->isp_pers_dict.c_str()); + lyxrc.isp_pers_dict.c_str()); } fl_set_button(fd_form_spell_options->perdict, - lyxrc->isp_use_pers_dict ? 1:0); + lyxrc.isp_use_pers_dict ? 1:0); // Escape chars - if (lyxrc->isp_esc_chars.empty()) { - lyxrc->isp_use_esc_chars = false; + if (lyxrc.isp_esc_chars.empty()) { + lyxrc.isp_use_esc_chars = false; } else { fl_set_input(fd_form_spell_options->esc_chars_input, - lyxrc->isp_esc_chars.c_str()); + lyxrc.isp_esc_chars.c_str()); } fl_set_button(fd_form_spell_options->esc_chars, - lyxrc->isp_use_esc_chars ? 1:0); + lyxrc.isp_use_esc_chars ? 1:0); // Options fl_set_button(fd_form_spell_options->compounds, - lyxrc->isp_accept_compound ? 1 : 0); + lyxrc.isp_accept_compound ? 1 : 0); fl_set_button(fd_form_spell_options->inpenc, - lyxrc->isp_use_input_encoding ? 1 : 0); + lyxrc.isp_use_input_encoding ? 1 : 0); } // Update spellchecker options void SpellOptionsApplyCB(FL_OBJECT *, long) { // Build new status from form data - lyxrc->isp_use_alt_lang = + lyxrc.isp_use_alt_lang = fl_get_button(fd_form_spell_options->altlang); - lyxrc->isp_use_pers_dict = + lyxrc.isp_use_pers_dict = fl_get_button(fd_form_spell_options->perdict); - lyxrc->isp_accept_compound = + lyxrc.isp_accept_compound = fl_get_button(fd_form_spell_options->compounds); - lyxrc->isp_use_esc_chars = + lyxrc.isp_use_esc_chars = fl_get_button(fd_form_spell_options->esc_chars); - lyxrc->isp_use_input_encoding = + lyxrc.isp_use_input_encoding = fl_get_button(fd_form_spell_options->inpenc); // Update strings with data from input fields - lyxrc->isp_alt_lang = + lyxrc.isp_alt_lang = fl_get_input(fd_form_spell_options->altlang_input); - lyxrc->isp_pers_dict = + lyxrc.isp_pers_dict = fl_get_input(fd_form_spell_options->perdict_input); - lyxrc->isp_esc_chars = + lyxrc.isp_esc_chars = fl_get_input(fd_form_spell_options->esc_chars_input); // Update form @@ -224,7 +235,7 @@ void SpellCheckerOptions() // Could also use a clean up. (Asger Alstrup) static -void create_ispell_pipe(string const & lang) +void create_ispell_pipe(BufferParams const & params, string const & lang) { static char o_buf[BUFSIZ]; // jc: it could be smaller int pipein[2], pipeout[2]; @@ -272,9 +283,9 @@ void create_ispell_pipe(string const & lang) close(pipeout[1]); argc = 0; - char * tmp = new char[lyxrc->isp_command.length() + 1]; - lyxrc->isp_command.copy(tmp, lyxrc->isp_command.length()); - tmp[lyxrc->isp_command.length()] = '\0'; + char * tmp = new char[lyxrc.isp_command.length() + 1]; + lyxrc.isp_command.copy(tmp, lyxrc.isp_command.length()); + tmp[lyxrc.isp_command.length()] = '\0'; argv[argc++] = tmp; tmp = new char[3]; string("-a").copy(tmp, 2); tmp[2] = '\0'; // pipe mode @@ -289,7 +300,7 @@ void create_ispell_pipe(string const & lang) argv[argc++] = tmp; } - if (lyxrc->isp_accept_compound) { + if (lyxrc.isp_accept_compound) { // Consider run-together words as legal compounds tmp = new char[3]; string("-C").copy(tmp, 2); tmp[2] = '\0'; @@ -301,47 +312,51 @@ void create_ispell_pipe(string const & lang) string("-B").copy(tmp, 2); tmp[2] = '\0'; argv[argc++] = tmp; } - if (lyxrc->isp_use_esc_chars) { + if (lyxrc.isp_use_esc_chars) { // Specify additional characters that // can be part of a word tmp = new char[3]; string("-w").copy(tmp, 2); tmp[2] = '\0'; argv[argc++] = tmp; // Put the escape chars in ""s - string tms = "\"" + lyxrc->isp_esc_chars + "\""; + string tms = "\"" + lyxrc.isp_esc_chars + "\""; tmp = new char[tms.length() + 1]; tms.copy(tmp, tms.length()); tmp[tms.length()] = '\0'; argv[argc++] = tmp; } - if (lyxrc->isp_use_pers_dict) { + if (lyxrc.isp_use_pers_dict) { // Specify an alternate personal dictionary tmp = new char[3]; string("-p").copy(tmp, 2); tmp[2]= '\0'; argv[argc++] = tmp; - tmp = new char[lyxrc->isp_pers_dict.length() + 1]; - lyxrc->isp_pers_dict.copy(tmp, lyxrc->isp_pers_dict.length()); - tmp[lyxrc->isp_pers_dict.length()] = '\0'; + tmp = new char[lyxrc.isp_pers_dict.length() + 1]; + lyxrc.isp_pers_dict.copy(tmp, lyxrc.isp_pers_dict.length()); + tmp[lyxrc.isp_pers_dict.length()] = '\0'; argv[argc++] = tmp; } - if (lyxrc->isp_use_input_encoding && - current_view->buffer()->params.inputenc != "default") { + if (lyxrc.isp_use_input_encoding && + params.inputenc != "default") { + string enc = (params.inputenc == "auto") + ? params.language_info->encoding()->LatexName() + : params.inputenc; + string::size_type n = enc.length(); tmp = new char[3]; string("-T").copy(tmp, 2); tmp[2] = '\0'; argv[argc++] = tmp; // Input encoding - tmp = new char[current_view->buffer()->params.inputenc.length() + 1]; - current_view->buffer()->params.inputenc.copy(tmp, current_view->buffer()->params.inputenc.length()); - tmp[current_view->buffer()->params.inputenc.length()] = '\0'; + tmp = new char[n + 1]; + enc.copy(tmp, n); + tmp[n] = '\0'; argv[argc++] = tmp; } argv[argc++] = 0; - execvp("ispell", (char * const *) argv); + execvp(argv[0], const_cast(argv)); // free the memory used by string::copy in the // setup of argv - for (int i= 0; i < argc -1; i++) + for (int i= 0; i < argc -1; ++i) delete[] argv[i]; lyxerr << "LyX: Failed to start ispell!" << endl; @@ -412,7 +427,7 @@ isp_result *ispell_check_word(char *word) /* I think we have to check if ispell is still alive here because the signal-handler could have disabled blocking on the fd */ - if (isp_pid == -1) return (isp_result *) 0; + if (isp_pid == -1) return 0; result = new isp_result; @@ -437,6 +452,9 @@ isp_result *ispell_check_word(char *word) { 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'; @@ -446,11 +464,11 @@ isp_result *ispell_check_word(char *word) if (count) result->misses = new char*[count]; p = strpbrk(nb, ":"); p += 2; - for (i = 0; imisses[i] = p; p = strpbrk(p, ",\n"); *p = 0; - p+= 2; + p += 2; } break; } @@ -466,8 +484,8 @@ isp_result *ispell_check_word(char *word) } -static -inline void ispell_terminate() +static inline +void ispell_terminate() { // Note: If you decide to optimize this out when it is not // needed please note that when Aspell is used this command @@ -481,15 +499,15 @@ inline void ispell_terminate() } -static -inline void ispell_terse_mode() +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) +static inline +void ispell_insert_word(char const *word) { fputc('*', out); // Insert word in personal dictionary fputs(word, out); @@ -497,16 +515,16 @@ inline void ispell_insert_word(char const *word) } -static -inline void ispell_accept_word(char const *word) +static inline +void ispell_accept_word(char const *word) { fputc('@', out); // Accept in this session fputs(word, out); fputc('\n', out); } -static -inline void ispell_store_replacement(char const *mis, string const & cor) { +static inline +void ispell_store_replacement(char const *mis, string const & cor) { if(actual_spell_checker == ASC_ASPELL) { fputs("$$ra ", out); fputs(mis, out); @@ -517,19 +535,20 @@ inline void ispell_store_replacement(char const *mis, string const & cor) { } -void ShowSpellChecker() +void ShowSpellChecker(BufferView * bv) { - FL_OBJECT *obj; + FL_OBJECT * obj; int ret; // Exit if we don't have a document open - if (!current_view->getScreen()) + if (!bv->available()) return; if (fd_form_spell_check == 0) { fd_form_spell_check = create_form_form_spell_check(); // Make sure pressing the close box does not kill LyX. (RvdK) - fl_set_form_atclose(fd_form_spell_check->form_spell_check, IgnoreCloseBoxCB, 0); + fl_set_form_atclose(fd_form_spell_check->form_spell_check, + CancelCloseBoxCB, 0); } // Clear form @@ -585,7 +604,7 @@ void ShowSpellChecker() fl_set_object_lcol(fd_form_spell_check->input, FL_BLACK); fl_set_object_lcol(fd_form_spell_check->browser, FL_BLACK); // activate replace only if the file is not read-only - if (!current_view->buffer()->isReadonly()) { + if (!bv->buffer()->isReadonly()) { fl_activate_object(fd_form_spell_check->replace); fl_set_object_lcol(fd_form_spell_check->replace, FL_BLACK); } @@ -596,7 +615,7 @@ void ShowSpellChecker() fl_set_object_lcol(fd_form_spell_check->options, FL_INACTIVE); fl_set_object_lcol(fd_form_spell_check->start, FL_INACTIVE); - ret = RunSpellChecker(current_view->buffer()->GetLanguage()); + ret = RunSpellChecker(bv); // deactivate insert, accept, replace, and stop fl_deactivate_object(fd_form_spell_check->insert); @@ -626,29 +645,27 @@ void ShowSpellChecker() if (obj == fd_form_spell_check->done) break; } fl_hide_form(fd_form_spell_check->form_spell_check); - EndOfSpellCheck(); + bv->endOfSpellCheck(); return; } // Perform an ispell session static -bool RunSpellChecker(string const & lang) +bool RunSpellChecker(BufferView * bv) { - isp_result *result; - char *word; - int i, oldval, clickline, newvalue; - float newval; - FL_OBJECT *obj; - unsigned int word_count = 0; + isp_result * result; + int i, newvalue; + FL_OBJECT * obj; - string tmp = (lyxrc->isp_use_alt_lang) ? lyxrc->isp_alt_lang:lang; + string tmp = (lyxrc.isp_use_alt_lang) ? lyxrc.isp_alt_lang : bv->buffer()->GetLanguage(); + bool rtl = tmp == "hebrew" || tmp == "arabic"; - oldval = 0; /* used for updating slider only when needed */ - newval = 0.0; + int oldval = 0; /* used for updating slider only when needed */ + float newval = 0.0; /* create ispell process */ - create_ispell_pipe(tmp); + create_ispell_pipe(bv->buffer()->params, tmp); if (isp_pid == -1) { fl_show_message( @@ -659,56 +676,69 @@ bool RunSpellChecker(string const & lang) "Check /usr/lib/ispell or set another\n" "dictionary in the Spellchecker Options menu."), "", ""); fclose(out); - return true; + return false; } // Put ispell in terse mode to improve speed ispell_terse_mode(); + unsigned int word_count = 0; while (true) { - word = NextWord(newval); + char * word = bv->nextWord(newval); if (word == 0) break; - word_count++; + ++word_count; // Update slider if and only if value has changed newvalue = int(100.0*newval); if(newvalue!= oldval) { oldval = newvalue; fl_set_slider_value(fd_form_spell_check->slider, oldval); + } + + if (word_count%1000 == 0) { + obj = fl_check_forms(); + if (obj == fd_form_spell_check->stop) { + delete[] word; + ispell_terminate(); + return true; + } + if (obj == fd_form_spell_check->done) { + delete[] word; + ispell_terminate(); + return false; + } } result = ispell_check_word(word); if (isp_pid == -1) { + delete result; delete[] word; break; } - obj = fl_check_forms(); - if (obj == fd_form_spell_check->stop) { - delete result; - delete[] word; - ispell_terminate(); - return true; - } - if (obj == fd_form_spell_check->done) { - delete result; - delete[] word; - ispell_terminate(); - return false; - } - switch (result->flag) { case ISP_UNKNOWN: case ISP_MISSED: - SelectLastWord(); - fl_set_object_label(fd_form_spell_check->text, word); + { + bv->selectLastWord(); + if (rtl) { + string tmp = word; + reverse(tmp.begin(),tmp.end()); + fl_set_object_label(fd_form_spell_check->text, tmp.c_str()); + } else + 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; icount; i++) { - fl_add_browser_line(fd_form_spell_check->browser, result->misses[i]); + for (i = 0; i < result->count; ++i) { + if (rtl) { + string tmp = result->misses[i]; + reverse(tmp.begin(),tmp.end()); + fl_add_browser_line(fd_form_spell_check->browser, tmp.c_str()); + } else + fl_add_browser_line(fd_form_spell_check->browser, result->misses[i]); } - clickline = -1; + int clickline = -1; while (true) { obj = fl_do_forms(); if (obj == fd_form_spell_check->insert) { @@ -725,7 +755,7 @@ bool RunSpellChecker(string const & lang) 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)); - ReplaceWord(fl_get_input(fd_form_spell_check->input)); + bv->replaceWord(fl_get_input(fd_form_spell_check->input)); break; } if (obj == fd_form_spell_check->browser) { @@ -734,14 +764,21 @@ bool RunSpellChecker(string const & lang) if (clickline == fl_get_browser(fd_form_spell_check->browser)) { ispell_store_replacement(word, fl_get_input(fd_form_spell_check->input)); - ReplaceWord(fl_get_input(fd_form_spell_check->input)); + bv->replaceWord(fl_get_input(fd_form_spell_check->input)); break; } clickline = fl_get_browser(fd_form_spell_check->browser); - fl_set_input(fd_form_spell_check->input, - fl_get_browser_line(fd_form_spell_check->browser, - fl_get_browser(fd_form_spell_check->browser))); - + /// Why not use + /// fl_set_input(fd_form_spell_check->input, result->misses[clickline-1]); ? + if (rtl) { + string tmp = fl_get_browser_line(fd_form_spell_check->browser, + clickline); + reverse(tmp.begin(),tmp.end()); + fl_set_input(fd_form_spell_check->input, tmp.c_str()); + } else + fl_set_input(fd_form_spell_check->input, + fl_get_browser_line(fd_form_spell_check->browser, + clickline)); } if (obj == fd_form_spell_check->stop) { delete result; @@ -757,6 +794,7 @@ bool RunSpellChecker(string const & lang) return false; } } + } default: delete result; delete[] word; @@ -765,8 +803,7 @@ bool RunSpellChecker(string const & lang) if(isp_pid!= -1) { ispell_terminate(); - string word_msg; - word_msg += tostr(word_count); + string word_msg(tostr(word_count)); if (word_count != 1) { word_msg += _(" words checked."); } else { @@ -784,19 +821,14 @@ bool RunSpellChecker(string const & lang) } -//void sigchldhandler(int sig) -void sigchldhandler(pid_t pid, int *status) +void sigchldhandler(pid_t pid, int * status) { - //int status ; - - if (isp_pid>0) - //if (waitpid(isp_pid, &status, WNOHANG) == isp_pid) { + if (isp_pid > 0) if (pid == isp_pid) { isp_pid= -1; fcntl(isp_fd, F_SETFL, O_NONBLOCK); /* set the file descriptor to nonblocking so we can continue */ } - //sigchldchecker(sig); sigchldchecker(pid, status); }