On Sun, Feb 16, 2003 at 03:37:19AM +0000, John Levon wrote:

> I'll post the Qt side of things soon too

Here's Qt and the rest.

> There's still the bug I mentioned wrt completely-error-free document.

Looking deeper it seems that we really need to make some serious
controller changes to make this even possible. Suggestions are welcome
Angus.


Index: SpellBase.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/SpellBase.h,v
retrieving revision 1.4
diff -u -r1.4 SpellBase.h
--- SpellBase.h 1 Dec 2002 22:59:17 -0000       1.4
+++ SpellBase.h 16 Feb 2003 04:47:25 -0000
@@ -36,14 +36,8 @@
        /// return true if the spellchecker instance still exists
        virtual bool alive() = 0;
 
-       /// clean up on messy exit
-       virtual void cleanUp() = 0;
-
        /// check the given word of the given lang code and return the result
        virtual enum Result check(WordLangTuple const &) = 0;
-
-       /// finish this spellchecker instance
-       virtual void close() = 0;
 
        /// insert the given word into the personal dictionary
        virtual void insert(WordLangTuple const &) = 0;
Index: ispell.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ispell.C,v
retrieving revision 1.6
diff -u -r1.6 ispell.C
--- ispell.C    13 Feb 2003 16:52:28 -0000      1.6
+++ ispell.C    16 Feb 2003 04:47:26 -0000
@@ -9,35 +9,6 @@
 
 #include <config.h>
 
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <cstdio>
-
-// FIXME: do we need any of this horrible gook ?
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <ctime>
-#else
-# if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  include <ctime>
-# endif
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-# ifdef HAVE_STRINGS_H
-   // <strings.h> is needed at least on AIX because FD_ZERO uses bzero().
-   // BUT we cannot include both string.h and strings.h on Irix 6.5 :(
-#  ifdef _AIX
-#   include <strings.h>
-#  endif
-# endif
-#include <sys/select.h>
-#endif
-
 #include "LString.h"
 #include "lyxrc.h"
 #include "language.h"
@@ -45,10 +16,13 @@
 #include "encoding.h"
 #include "ispell.h"
 #include "WordLangTuple.h"
+#include "gettext.h"
 
 #include "support/forkedcall.h"
 #include "support/lstrings.h"
 
+#include <sys/select.h>
+
 #ifndef CXX_GLOBAL_CSTD
 using std::strcpy;
 using std::strlen;
@@ -60,9 +34,6 @@
 
 namespace {
 
-/// pid for the `ispell' process.
-pid_t isp_pid = -1;
-
 class LaunchIspell : public ForkedProcess {
 public:
        ///
@@ -96,7 +67,7 @@
 
 int LaunchIspell::generateChild()
 {
-       isp_pid = fork();
+       pid_t isp_pid = fork();
 
        if (isp_pid != 0) {
                // failed (-1) or parent process (>0)
@@ -202,29 +173,24 @@
 ISpell::ISpell(BufferParams const & params, string const & lang)
        : str(0)
 {
+       lyxerr[Debug::GUI] << "Created ispell" << endl;
+
        static char o_buf[BUFSIZ];  // jc: it could be smaller
        int pipein[2];
        int pipeout[2];
 
-       isp_pid = -1;
-
        if (pipe(pipein) == -1 || pipe(pipeout) == -1) {
-               lyxerr << "LyX: Can't create pipe for spellchecker!" << endl;
-               setError();
+               error_ = _("Can't create pipe for spellchecker.");
                return;
        }
 
        if ((out = fdopen(pipein[1], "w")) == 0) {
-               lyxerr << "LyX: Can't create stream for pipe for spellchecker!"
-                      << endl;
-               setError();
+               error_ = _("Can't create stream for pipe for spellchecker.");
                return;
        }
 
        if ((in = fdopen(pipeout[0], "r")) == 0) {
-               lyxerr <<"LyX: Can't create stream for pipe for spellchecker!"
-                      << endl;
-               setError();
+               error_ = _("Can't create stream for pipe for spellchecker.");
                return;
        }
 
@@ -232,16 +198,15 @@
 
        isp_fd = pipeout[0];
 
-       LaunchIspell childprocess(params, lang, pipein, pipeout);
-       isp_pid = childprocess.start();
-       if (isp_pid == -1) {
-               lyxerr << "LyX: Can't create child process for spellchecker!"
-                      << endl;
-               setError();
+       LaunchIspell * li = new LaunchIspell(params, lang, pipein, pipeout);
+       child_.reset(li);
+       if (li->start() == -1) {
+               error_ = _("Could not create an ispell process.\nYou may not have "
+                       " the right languages installed.");     
+               child_.reset(0);
                return;
        }
 
-       setError();
        /* 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
@@ -255,8 +220,7 @@
        int retval = 0;
        FD_ZERO(&infds);
        FD_SET(pipeout[0], &infds);
-       tv.tv_sec = 15; // fifteen second timeout. Probably too much,
-       // but it can't really hurt.
+       tv.tv_sec = 2;
        tv.tv_usec = 0;
 
        // Configure provides us with macros which are supposed to do
@@ -272,50 +236,45 @@
                // there is only one fd in infds.
                fgets(buf, 2048, in);
 
-               fputs("!\n", out); // Set terse mode (silently accept correct words)
+               // Set terse mode (silently accept correct words)
+               fputs("!\n", out);
 
        } else if (retval == 0) {
                // timeout. Give nice message to user.
-               lyxerr << "Ispell read timed out, what now?" << endl;
-               // This probably works but could need some thought
-               isp_pid = -1;
+               error_ = _("The spell process returned an error.\nPerhaps "
+                               "it has been configured wrongly ?");
                ::close(pipeout[0]);
                ::close(pipeout[1]);
                ::close(pipein[0]);
                ::close(pipein[1]);
-               isp_fd = -1;
+               child_->kill();
+               child_.reset(0);
        } else {
-               // Select returned error
-               lyxerr << "Select on ispell returned error, what now?" << endl;
+               // select returned error
+               error_ = _("The spell process returned an error.\nPerhaps "
+                               "it has been configured wrongly ?");
+               child_->kill();
+               child_.reset(0);
        }
 }
 
 
 ISpell::~ISpell()
 {
-       delete[] str;
-}
+       lyxerr[Debug::GUI] << "Killing ispell" << endl;
+       fputs("#\n", out); // Save personal dictionary
 
+       fflush(out);
+       fclose(out);
 
-void ISpell::setError()
-{
-       if (isp_pid == -1) {
-               error_ =
-                       "\n\n"
-                       "The spellcheck-process has died for some reason.\n"
-                       "*One* possible reason could be that you do not have\n"
-                       "a dictionary file for the language of this document\n"
-                       "installed.\n"
-                       "Check your spellchecker or set another dictionary\n"
-                       "in the Spellchecker Options menu.\n\n";
-       } else {
-               error_ = 0;
-       }
+       delete [] str;
 }
 
 
 string const ISpell::nextMiss()
 {
+       // Well, somebody is a sick fuck.
+
        if (str == 0 || *(e+1) == '\0')
                return "";
        char * b = e + 2;
@@ -329,13 +288,7 @@
 
 bool ISpell::alive()
 {
-       return isp_pid != -1;
-}
-
-
-void ISpell::cleanUp()
-{
-       ::fclose(out);
+       return child_.get() && child_->running();
 }
 
 
@@ -396,20 +349,6 @@
 }
 
 
-void ISpell::close()
-{
-       // Note: If you decide to optimize this out when it is not
-       // needed please note that when Aspell is used this command
-       // is also needed to save the replacement dictionary.
-       // -- Kevin Atkinson ([EMAIL PROTECTED])
-
-       fputs("#\n", out); // Save personal dictionary
-
-       fflush(out);
-       fclose(out);
-}
-
-
 void ISpell::insert(WordLangTuple const & word)
 {
        ::fputc('*', out); // Insert word in personal dictionary
@@ -428,7 +367,5 @@
 
 string const ISpell::error()
 {
-       if (error_)
-               return error_;
-       return "";
+       return error_;
 }
Index: ispell.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ispell.h,v
retrieving revision 1.5
diff -u -r1.5 ispell.h
--- ispell.h    1 Dec 2002 22:59:17 -0000       1.5
+++ ispell.h    16 Feb 2003 04:47:26 -0000
@@ -10,11 +10,14 @@
 #ifndef SP_ISPELL_H
 #define SP_ISPELL_H
 
-#include <cstdio>
-
 #include "SpellBase.h"
 
+#include <boost/scoped_ptr.hpp>
+
+#include <cstdio>
+
 class BufferParams;
+class ForkedProcess;
 
 /// i/a spell process-based spellchecker
 class ISpell : public SpellBase {
@@ -26,15 +29,9 @@
        /// return true if the spellchecker instance still exists
        virtual bool alive();
 
-       /// clean up on messy exit
-       virtual void cleanUp();
-
        /// check the given word and return the result
        virtual enum Result check(WordLangTuple const & word);
 
-       /// finish this spellchecker instance
-       virtual void close();
-
        /// insert the given word into the personal dictionary
        virtual void insert(WordLangTuple const & word);
 
@@ -48,17 +45,16 @@
        virtual string const error();
 
 private:
-       ///
-       void setError();
-
        /// instream to communicate with ispell
        FILE * in;
        /// outstream to communicate with ispell
        FILE * out;
        /// spell error
-       char const * error_;
+       string error_;
        /// the fd of the outgoing pipe
        int isp_fd;
+
+       boost::scoped_ptr<ForkedProcess> child_;
 
        // vileness below ... please FIXME
        /// str ???
Index: pspell.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/pspell.C,v
retrieving revision 1.8
diff -u -r1.8 pspell.C
--- pspell.C    13 Feb 2003 16:52:40 -0000      1.8
+++ pspell.C    16 Feb 2003 04:47:26 -0000
@@ -12,6 +12,7 @@
 #ifdef USE_PSPELL
 
 #include "support/LAssert.h"
+#include "debug.h"
 
 #define USE_ORIGINAL_MANAGER_FUNCS 1
 // new aspell pspell missing extern "C"
@@ -22,38 +23,39 @@
 #include "pspell.h"
 #include "WordLangTuple.h"
 
+using std::endl;
+
 PSpell::PSpell(BufferParams const &, string const & lang)
        : els(0), spell_error_object(0)
 {
        addManager(lang);
+       lyxerr[Debug::GUI] << "created pspell" << endl;
 }
 
 
 PSpell::~PSpell()
 {
-       cleanUp();
-       close();
+       lyxerr[Debug::GUI] << "killed pspell" << endl;
+
+       if (spell_error_object) {
+               delete_pspell_can_have_error(spell_error_object);
+               spell_error_object = 0;
+       }
+
        if (els)
                delete_pspell_string_emulation(els);
+
        Managers::iterator it = managers_.begin();
        Managers::iterator end = managers_.end();
 
        for (; it != end; ++it) {
+               pspell_manager_save_all_word_lists(it->second.manager);
                delete_pspell_manager(it->second.manager);
                delete_pspell_config(it->second.config);
        }
 }
 
 
-void PSpell::cleanUp()
-{
-       if (spell_error_object) {
-               delete_pspell_can_have_error(spell_error_object);
-               spell_error_object = 0;
-       }
-}
-
-
 void PSpell::addManager(string const & lang)
 {
        PspellConfig * config = new_pspell_config();
@@ -105,17 +107,6 @@
                        res = MISSED;
        }
        return res;
-}
-
-
-void PSpell::close()
-{
-       Managers::iterator it = managers_.begin();
-       Managers::iterator end = managers_.end();
-
-       for (; it != end; ++it) {
-               pspell_manager_save_all_word_lists(it->second.manager);
-       }
 }
 
 
Index: pspell.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/pspell.h,v
retrieving revision 1.3
diff -u -r1.3 pspell.h
--- pspell.h    1 Dec 2002 22:59:17 -0000       1.3
+++ pspell.h    16 Feb 2003 04:47:26 -0000
@@ -37,14 +37,8 @@
         */
        virtual bool alive() { return true; }
 
-       /// clean up on messy exit
-       virtual void cleanUp();
-
        /// check the given word and return the result
        virtual enum Result check(WordLangTuple const &);
-
-       /// finish this spellchecker instance
-       virtual void close();
 
        /// insert the given word into the personal dictionary
        virtual void insert(WordLangTuple const &);
Index: frontends/controllers/ControlSpellchecker.C
===================================================================
RCS file: 
/usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/ControlSpellchecker.C,v
retrieving revision 1.37
diff -u -r1.37 ControlSpellchecker.C
--- frontends/controllers/ControlSpellchecker.C 13 Feb 2003 16:52:49 -0000      1.37
+++ frontends/controllers/ControlSpellchecker.C 16 Feb 2003 04:47:27 -0000
@@ -19,6 +19,7 @@
 #include "language.h"
 #include "lyxrc.h"
 #include "lyxtext.h"
+#include "debug.h"
 
 #include "ispell.h"
 #ifdef USE_PSPELL
@@ -29,17 +30,41 @@
 
 #include "BoostFormat.h"
 
+using std::endl;
+
 ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
        : ControlDialogBD(lv, d),
-         newval_(0.0), oldval_(0), newvalue_(0), count_(0),
-         stop_(false), speller_(0)
+         newval_(0.0), oldval_(0), newvalue_(0), count_(0)
+{}
+
+
+ControlSpellchecker::~ControlSpellchecker()
 {}
 
 
 void ControlSpellchecker::setParams()
 {
-       if (speller_)
+       lyxerr[Debug::GUI] << "spell setParams" << endl;
+       startSession();
+}
+
+
+void ControlSpellchecker::clearParams()
+{
+       lyxerr[Debug::GUI] << "spell clearParams" << endl;
+       endSession();
+}
+
+       
+void ControlSpellchecker::startSession()
+{
+       lyxerr[Debug::GUI] << "spell startSession" << endl;
+
+       if (speller_.get()) {
+               lyxerr[Debug::GUI] << "startSession: speller exists" << endl;
+               speller_.reset(0);
                return;
+       }
 
        // create spell object
        string tmp;
@@ -48,70 +73,152 @@
                tmp = (lyxrc.isp_use_alt_lang) ?
                        lyxrc.isp_alt_lang : buffer()->params.language->code();
 
-               speller_ = new PSpell(buffer()->params, tmp);
+               speller_.reset(new PSpell(buffer()->params, tmp));
        } else {
 #endif
                tmp = (lyxrc.isp_use_alt_lang) ?
                        lyxrc.isp_alt_lang : buffer()->params.language->lang();
 
-               speller_ = new ISpell(buffer()->params, tmp);
+               speller_.reset(new ISpell(buffer()->params, tmp));
 #ifdef USE_PSPELL
        }
 #endif
 
-       if (!speller_->error().empty()) {
-               emergency_exit_ = true;
-               Alert::alert("The spellchecker has failed", speller_->error());
-               clearParams();
+       // reset values to initial
+       newval_ = 0.0;
+       oldval_ = 0;
+       newvalue_ = 0;
+       count_ = 0;
+
+       if (speller_->error().empty())
+               return;
+
+       emergency_exit_ = true;
+       string message = speller_->error();
+       if (message.empty())
+               message = _("The spell checker could not be started.\n"
+                        "Maybe it is mis-configured.");
+
+       Alert::alert("The spellchecker has failed", message);
+       speller_.reset(0);
+}
+
+
+void ControlSpellchecker::endSession()
+{
+       lyxerr[Debug::GUI] << "spell endSession" << endl;
+
+       bufferview()->endOfSpellCheck();
+
+       if (!speller_.get()) {
+               lyxerr[Debug::GUI] << "endSession with no speller" << endl;
                return;
        }
+
+       speller_.reset(0);
 }
 
 
 void ControlSpellchecker::check()
 {
+       lyxerr[Debug::GUI] << "spell check a word" << endl;
+
        SpellBase::Result res = SpellBase::OK;
-       stop_ = false;
 
        // clear any old selection
        LyXText * text = bufferview()->getLyXText();
        bufferview()->toggleSelection(true);
        bufferview()->update(text, BufferView::SELECT);
 
-       while ((res == SpellBase::OK || res == SpellBase::IGNORE) && !stop_) {
+       while ((res == SpellBase::OK || res == SpellBase::IGNORE)) {
                word_ = bufferview()->nextWord(newval_);
 
-               if (word_.word().empty()) {
-                       clearParams();
+               // end of document
+               if (word_.word().empty())
                        break;
-               }
 
                ++count_;
 
                // Update slider if and only if value has changed
                newvalue_ = int(100.0 * newval_);
                if (newvalue_!= oldval_) {
+                       lyxerr[Debug::GUI] << "Updating spell progress." << endl;
                        oldval_ = newvalue_;
                        // set progress bar
-                       view().partialUpdate(0);
+                       view().partialUpdate(SPELL_PROGRESSED);
                }
 
-               if (!speller_ || !speller_->alive()) {
-                       clearParams();
-                       stop();
+               if (!checkAlive())
                        return;
-               }
 
                res = speller_->check(word_);
        }
 
-       if (!stop_ && !word_.word().empty())
+       lyxerr << "Found word \"" << word_.word() << "\"" << endl;
+
+       if (!word_.word().empty()) {
                bufferview()->selectLastWord();
+       } else {
+               showSummary();
+               endSession();
+               return;
+       }
 
        // set suggestions
        if (res != SpellBase::OK && res != SpellBase::IGNORE) {
-               view().partialUpdate(1);
+               lyxerr[Debug::GUI] << "Found a word needing checking." << endl;
+               view().partialUpdate(SPELL_FOUND_WORD);
+       }
+}
+
+
+bool ControlSpellchecker::checkAlive()
+{
+       if (speller_->alive())
+               return true;
+
+       string message = speller_->error();
+       if (message.empty())
+               message = _("The spell checker has died for some reason.\n"
+                        "Maybe it has been killed.");
+
+       view().hide();
+       speller_.reset(0);
+
+       Alert::alert("The spellchecker has failed", message);
+       return false;
+}
+
+
+void ControlSpellchecker::showSummary()
+{
+       if (!checkAlive())
+               return;
+
+       if (count_ == 0)
+               return;
+
+       string message;
+
+#if USE_BOOST_FORMAT
+       if (count_ != 1) {
+               boost::format fmter("%1$d words checked.");
+               fmter % count_;
+               message += fmter.str();
+       } else {
+               message += _("One word checked.");
+       }
+#else
+       if (count_ != 1) {
+               message += tostr(count_) + " words checked";
+       } else {
+               message = _("One word checked.");
        }
+#endif
+
+       Alert::alert("Spellchecking is complete", message);
+
+       view().hide();
 }
 
 
@@ -157,64 +264,3 @@
 }
 
 
-void ControlSpellchecker::stop()
-{
-       stop_ = true;
-       bufferview()->endOfSpellCheck();
-}
-
-
-void ControlSpellchecker::clearParams()
-{
-       if (!speller_)
-               return;
-
-       if (speller_->alive()) {
-               speller_->close();
-
-               message_ = string(_("Spellchecking completed!")) + '\n';
-
-#if USE_BOOST_FORMAT
-               if (count_ != 1) {
-               boost::format fmter("%1$d words checked.");
-               fmter % count_;
-               message_ += fmter.str();
-               } else {
-                       message_ += _("One word checked.");
-               }
-#else
-               if (count_ != 1) {
-                       message_ += tostr(count_) + " words checked";
-               } else {
-                       message_ = _("One word checked.");
-               }
-#endif
-       } else {
-               message_ = speller_->error();
-               speller_->cleanUp();
-               if (message_.empty())
-                   message_ = _("The spell checker has died for some reason.\n"
-                                "Maybe it has been killed.");
-
-               // make sure that the dialog is not launched
-               emergency_exit_ = true;
-               Alert::alert("The spellchecker has failed", message_);
-       }
-
-       delete speller_;
-
-       bufferview()->endOfSpellCheck();
-
-       // show closing message if any words were checked.
-       if (count_ > 0)
-               view().partialUpdate(2);
-
-       // reset values to initial
-       newval_ = 0.0;
-       oldval_ = 0;
-       newvalue_ = 0;
-       count_ = 0;
-       message_.erase();
-       stop_ = false;
-       speller_ = 0;
-}
Index: frontends/controllers/ControlSpellchecker.h
===================================================================
RCS file: 
/usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/ControlSpellchecker.h,v
retrieving revision 1.15
diff -u -r1.15 ControlSpellchecker.h
--- frontends/controllers/ControlSpellchecker.h 13 Feb 2003 16:52:49 -0000      1.15
+++ frontends/controllers/ControlSpellchecker.h 16 Feb 2003 04:47:28 -0000
@@ -12,6 +12,7 @@
 #ifndef CONTROLSPELLCHECKER_H
 #define CONTROLSPELLCHECKER_H
 
+#include <boost/scoped_ptr.hpp>
 
 #include "ControlDialog_impl.h"
 #include "LString.h"
@@ -23,9 +24,15 @@
  */
 class ControlSpellchecker : public ControlDialogBD {
 public:
-       ///
+       enum State {
+               SPELL_PROGRESSED, //< update progress bar
+               SPELL_FOUND_WORD //< found a bad word
+       };
+
        ControlSpellchecker(LyXView &, Dialogs &);
 
+       ~ControlSpellchecker();
+
        /// replace word with replacement
        void replace(string const &);
 
@@ -38,10 +45,8 @@
        /// ignore all occurances of word
        void ignoreAll();
 
-       /// stop checking
-       void stop();
-
        /// check text until next misspelled/unknown word
+       /// returns true when finished
        void check();
 
        /// get suggestion
@@ -53,13 +58,22 @@
        /// returns progress value
        int getProgress() const { return oldval_; }
 
-       /// returns exit message
-       string const getMessage()  const { return message_; }
-
        /// returns word count
        int getCount()  const { return count_; }
 
 private:
+       /// give error message is spellchecker dies
+       bool checkAlive();
+
+       /// start a spell-checking session
+       void startSession();
+
+       /// end a spell-checking session
+       void endSession();
+
+       /// show count of checked words at normal exit
+       void showSummary();
+
        /// set the params before show or update
        void setParams();
        /// clean-up on hide.
@@ -79,14 +93,8 @@
        /// word count
        int count_;
 
-       /// exit message
-       string message_;
-
-       /// set to true to stop checking
-       bool stop_;
-
        /// The actual spellchecker object
-       SpellBase * speller_;
+       boost::scoped_ptr<SpellBase> speller_;
 };
 
 #endif // CONTROLSPELLCHECKER_H
Index: frontends/qt2/QSpellchecker.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QSpellchecker.C,v
retrieving revision 1.18
diff -u -r1.18 QSpellchecker.C
--- frontends/qt2/QSpellchecker.C       15 Feb 2003 22:26:26 -0000      1.18
+++ frontends/qt2/QSpellchecker.C       16 Feb 2003 04:47:29 -0000
@@ -49,13 +49,9 @@
        dialog_->replaceCO->clear();
        dialog_->suggestionsLB->clear();
        dialog_->spellcheckPR->setProgress(0);
-       dialog_->spellcheckPB->setEnabled(true);
-       dialog_->wordED->setEnabled(false);
-       dialog_->replaceCO->setEnabled(false);
-       dialog_->replacePB->setEnabled(false);
-       dialog_->ignorePB->setEnabled(false);
-       dialog_->replacePB_3->setEnabled(false);
-       dialog_->addPB->setEnabled(false);
+
+       // can put in controller ??
+       controller().check();
 }
 
 
@@ -83,35 +79,18 @@
 }
 
 
-void QSpellchecker::spellcheck()
-{
-       dialog_->spellcheckPB->setEnabled(false);
-       dialog_->wordED->setEnabled(true);
-       dialog_->replaceCO->setEnabled(true);
-       dialog_->replacePB->setEnabled(true);
-       dialog_->ignorePB->setEnabled(true);
-       dialog_->replacePB_3->setEnabled(true);
-       dialog_->addPB->setEnabled(true);
-       controller().check();
-}
-
-
-void QSpellchecker::stop()
+void QSpellchecker::partialUpdate(int s)
 {
-       controller().stop();
-       dialog_->spellcheckPB->setEnabled(true);
-       hide();
-}
+       ControlSpellchecker::State const state = 
+               static_cast<ControlSpellchecker::State>(s);
 
+       switch (state) {
 
-void QSpellchecker::partialUpdate(int id)
-{
-       switch (id) {
-       case 0:
+       case ControlSpellchecker::SPELL_PROGRESSED:
                dialog_->spellcheckPR->setProgress(controller().getProgress());
                break;
 
-       case 1: {
+       case ControlSpellchecker::SPELL_FOUND_WORD: {
                dialog_->wordED->setText(toqstr(controller().getWord()));
                dialog_->suggestionsLB->clear();
 
@@ -128,12 +107,5 @@
        }
                break;
 
-       case 2:
-               dialog_->spellcheckPB->setEnabled(true);
-               hide();
-               QMessageBox::information(0, qt_("Spellcheck complete"),
-                                        toqstr(controller().getMessage()),
-                                        qt_("OK"));
-               break;
        }
 }
Index: frontends/qt2/QSpellchecker.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QSpellchecker.h,v
retrieving revision 1.8
diff -u -r1.8 QSpellchecker.h
--- frontends/qt2/QSpellchecker.h       13 Feb 2003 16:52:53 -0000      1.8
+++ frontends/qt2/QSpellchecker.h       16 Feb 2003 04:47:29 -0000
@@ -31,12 +31,10 @@
        /// update from controller
        void partialUpdate(int id);
 private:
-       void stop();
        void accept();
        void add();
        void ignore();
        void replace();
-       void spellcheck();
 
        /// Apply changes
        virtual void apply() {}
Index: frontends/qt2/QSpellcheckerDialog.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QSpellcheckerDialog.C,v
retrieving revision 1.10
diff -u -r1.10 QSpellcheckerDialog.C
--- frontends/qt2/QSpellcheckerDialog.C 13 Feb 2003 16:52:53 -0000      1.10
+++ frontends/qt2/QSpellcheckerDialog.C 16 Feb 2003 04:47:29 -0000
@@ -26,13 +26,7 @@
        form_(form)
 {
        connect(closePB, SIGNAL(clicked()),
-               this, SLOT(stop()));
-}
-
-
-void QSpellcheckerDialog::stop()
-{
-       form_->stop();
+               form, SLOT(slotClose()));
 }
 
 
@@ -42,12 +36,6 @@
 }
 
 
-void QSpellcheckerDialog::spellcheckClicked()
-{
-       form_->spellcheck();
-}
-
-
 void QSpellcheckerDialog::addClicked()
 {
        form_->add();
@@ -95,7 +83,6 @@
 
 void QSpellcheckerDialog::closeEvent(QCloseEvent * e)
 {
-       form_->stop();
        form_->slotWMHide();
        e->accept();
 }
Index: frontends/qt2/QSpellcheckerDialog.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QSpellcheckerDialog.h,v
retrieving revision 1.10
diff -u -r1.10 QSpellcheckerDialog.h
--- frontends/qt2/QSpellcheckerDialog.h 13 Feb 2003 16:52:53 -0000      1.10
+++ frontends/qt2/QSpellcheckerDialog.h 16 Feb 2003 04:47:35 -0000
@@ -25,9 +25,7 @@
        virtual void suggestionChanged(const QString &);
  
 protected slots:
-       virtual void stop();
        virtual void acceptClicked();
-       virtual void spellcheckClicked();
        virtual void addClicked();
        virtual void replaceClicked();
        virtual void ignoreClicked();
Index: frontends/qt2/README
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/README,v
retrieving revision 1.15
diff -u -r1.15 README
--- frontends/qt2/README        15 Feb 2003 21:09:29 -0000      1.15
+++ frontends/qt2/README        16 Feb 2003 04:47:35 -0000
@@ -22,6 +22,8 @@
  
 Remember to check sensible resizing behaviour on a dialog.
 
+Remember to use Edit->Check Accelerators
+
 If necessary, you should override Qt2Base::isValid() for determining the validity
 of the current dialog's contents.
  
Index: frontends/qt2/ui/QSpellcheckerDialogBase.ui
===================================================================
RCS file: 
/usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/ui/QSpellcheckerDialogBase.ui,v
retrieving revision 1.3
diff -u -r1.3 QSpellcheckerDialogBase.ui
--- frontends/qt2/ui/QSpellcheckerDialogBase.ui 15 Feb 2003 22:26:27 -0000      1.3
+++ frontends/qt2/ui/QSpellcheckerDialogBase.ui 16 Feb 2003 04:47:39 -0000
@@ -13,8 +13,8 @@
         <rect>
             <x>0</x>
             <y>0</y>
-            <width>294</width>
-            <height>379</height>
+            <width>323</width>
+            <height>389</height>
         </rect>
     </property>
     <property stdset="1">
@@ -218,7 +218,7 @@
             </property>
             <property stdset="1">
                 <name>text</name>
-                <string>Unknown:</string>
+                <string>Unknown word:</string>
             </property>
             <property>
                 <name>buddy</name>
@@ -263,21 +263,6 @@
                 <string>Replace with selected word</string>
             </property>
         </widget>
-        <widget row="1"  column="2" >
-            <class>QPushButton</class>
-            <property stdset="1">
-                <name>name</name>
-                <cstring>spellcheckPB</cstring>
-            </property>
-            <property stdset="1">
-                <name>text</name>
-                <string>&amp;Start...</string>
-            </property>
-            <property>
-                <name>toolTip</name>
-                <string>Start spellcheck</string>
-            </property>
-        </widget>
     </grid>
 </widget>
 <connections>
@@ -312,12 +297,6 @@
         <slot>addClicked()</slot>
     </connection>
     <connection>
-        <sender>spellcheckPB</sender>
-        <signal>clicked()</signal>
-        <receiver>QSpellcheckerDialogBase</receiver>
-        <slot>spellcheckClicked()</slot>
-    </connection>
-    <connection>
         <sender>suggestionsLB</sender>
         <signal>doubleClicked(QListBoxItem*)</signal>
         <receiver>QSpellcheckerDialogBase</receiver>
@@ -335,11 +314,9 @@
     <slot access="public">optionsClicked()</slot>
     <slot access="public">replaceChanged(const QString &amp;)</slot>
     <slot access="public">replaceClicked()</slot>
-    <slot access="public">spellcheckClicked()</slot>
     <slot access="public">suggestionChanged(const QString &amp;)</slot>
 </connections>
 <tabstops>
-    <tabstop>spellcheckPB</tabstop>
     <tabstop>wordED</tabstop>
     <tabstop>replaceCO</tabstop>
     <tabstop>suggestionsLB</tabstop>
Index: frontends/xforms/FormSpellchecker.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/FormSpellchecker.C,v
retrieving revision 1.31
diff -u -r1.31 FormSpellchecker.C
--- frontends/xforms/FormSpellchecker.C 13 Feb 2003 16:52:58 -0000      1.31
+++ frontends/xforms/FormSpellchecker.C 16 Feb 2003 04:47:40 -0000
@@ -12,7 +12,6 @@
 
 
 #include "xformsBC.h"
-#include "ControlSpellchecker.h"
 #include "FormSpellchecker.h"
 #include "forms/form_spellchecker.h"
 
@@ -23,11 +22,12 @@
 
 #include FORMS_H_LOCATION
 
-typedef FormCB<ControlSpellchecker, FormDB<FD_spellchecker> > base_class;
+using std::endl;
 
+typedef FormCB<ControlSpellchecker, FormDB<FD_spellchecker> > base_class;
 
 FormSpellchecker::FormSpellchecker()
-       : base_class(_("Spellchecker")), state_(STOPPED)
+       : base_class(_("Spellchecker"))
 {}
 
 
@@ -61,8 +61,6 @@
        tooltips().init(dialog_->browser_suggestions, str);
        // Work-around xforms' bug; enable tooltips for browser widgets.
        setPrehandler(dialog_->browser_suggestions);
-       str = _("Start the spellingchecker.");
-       tooltips().init(dialog_->button_start, str);
        str = _("Replace unknown word.");
        tooltips().init(dialog_->button_replace, str);
        str = _("Ignore unknown word.");
@@ -76,16 +74,14 @@
 }
 
 
-void FormSpellchecker::updateState(State state)
+void FormSpellchecker::partialUpdate(int s)
 {
+       ControlSpellchecker::State const state =
+               static_cast<ControlSpellchecker::State>(s);
+
        switch (state) {
-       case READY_TO_START:
-               fl_set_slider_value(dialog_->slider_progress, 0.0);
-               fl_set_object_label(dialog_->slider_progress, "0 %");
-               break;
 
-       case CHECKING:
-       {
+       case ControlSpellchecker::SPELL_FOUND_WORD: {
                // Set suggestions.
                string w = controller().getWord();
                fl_set_input(dialog_->input_replacement, w.c_str());
@@ -98,8 +94,7 @@
                // Fall through...
        }
 
-       case STARTED:
-       {
+       case ControlSpellchecker::SPELL_PROGRESSED: {
                int const progress = controller().getProgress();
                if (progress == 0)
                        break;
@@ -111,68 +106,33 @@
                fl_set_slider_bounds(dialog_->slider_progress, 0.0, total);
                fl_set_slider_value(dialog_->slider_progress, wordcount);
                fl_set_object_label(dialog_->slider_progress, label.c_str());
+               fl_redraw_object(dialog_->slider_progress);
                break;
        }
 
-       case STOPPED:
-       {
-               controller().stop();
-
-               double const wordcount = controller().getCount();
-
-               fl_set_slider_bounds(dialog_->slider_progress, 0.0, wordcount);
-               fl_set_slider_value(dialog_->slider_progress, wordcount);
-               fl_set_object_label(dialog_->slider_progress, "100 %");
-               break;
-       }
        }
-
-       bool const state_change = state_ != state;
-       state_ = state;
-
-       if (!state_change)
-               return;
-
-       bool const running = (state == STARTED || state == CHECKING);
-       string const label = running ? _("Stop|#S") : _("Start|#S");
-
-       fl_set_object_label(dialog_->button_start, idex(label).c_str());
-       fl_set_button_shortcut(dialog_->button_start, scex(label).c_str(), 1);
-       fl_redraw_object(dialog_->button_start);
-
-       string const tip = running ?
-               _("Stop the spellingchecker.") :
-               _("Start the spellingchecker.");
-       tooltips().init(dialog_->button_start, tip);
-
-       setEnabled(dialog_->button_replace,      running);
-       setEnabled(dialog_->button_ignore,       running);
-       setEnabled(dialog_->button_accept,       running);
-       setEnabled(dialog_->button_add,          running);
-       setEnabled(dialog_->browser_suggestions, running);
-       setEnabled(dialog_->input_replacement,   running);
 }
 
 
 void FormSpellchecker::update()
 {
+       lyxerr[Debug::GUI] << "Spell update() " << endl;
+
        // clear input fields
        fl_set_input(dialog_->input_replacement, "");
        fl_set_object_label(dialog_->text_unknown, "");
        fl_clear_browser(dialog_->browser_suggestions);
+       fl_set_slider_value(dialog_->slider_progress, 0.0);
+       fl_set_object_label(dialog_->slider_progress, "0 %");
 
-       // reset dialog and buttons into start condition
-       updateState(READY_TO_START);
+       // FIXME: can we do this in the controller ?
+       controller().check();
 }
 
 
 ButtonPolicy::SMInput FormSpellchecker::input(FL_OBJECT * ob, long ob_value)
 {
-       if (ob == dialog_->button_start) {
-               updateState(STARTED);
-               controller().check();
-
-       } else if (ob == dialog_->button_replace) {
+       if (ob == dialog_->button_replace) {
                string const tmp = getString(dialog_->input_replacement);
                controller().replace(tmp);
 
@@ -205,19 +165,4 @@
        }
 
        return ButtonPolicy::SMI_VALID;
-}
-
-
-void FormSpellchecker::partialUpdate(int id)
-{
-       switch (id) {
-       case 1:
-               // Set suggestions.
-               updateState(CHECKING);
-               break;
-       case 2:
-               // End of spell checking.
-               updateState(STOPPED);
-               break;
-       }
 }
Index: frontends/xforms/FormSpellchecker.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/FormSpellchecker.h,v
retrieving revision 1.16
diff -u -r1.16 FormSpellchecker.h
--- frontends/xforms/FormSpellchecker.h 13 Feb 2003 16:52:58 -0000      1.16
+++ frontends/xforms/FormSpellchecker.h 16 Feb 2003 04:47:40 -0000
@@ -14,8 +14,8 @@
 
 
 #include "FormBase.h"
+#include "ControlSpellchecker.h"
 
-class ControlSpellchecker;
 struct FD_spellchecker;
 
 /** This class provides an XForms implementation of the FormSpellchecker Dialog.
@@ -38,18 +38,6 @@
 
        /// Filter the inputs
        virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
-
-       ///
-       enum State {
-               READY_TO_START,
-               STARTED,
-               CHECKING,
-               STOPPED
-       };
-       ///
-       void updateState(State state);
-       ///
-       State state_;
 };
 
 #endif // FORMSPELLCHECKER_H
Index: frontends/xforms/forms/form_spellchecker.fd
===================================================================
RCS file: 
/usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/forms/form_spellchecker.fd,v
retrieving revision 1.10
diff -u -r1.10 form_spellchecker.fd
--- frontends/xforms/forms/form_spellchecker.fd 26 Jan 2003 16:58:37 -0000      1.10
+++ frontends/xforms/forms/form_spellchecker.fd 16 Feb 2003 04:47:40 -0000
@@ -11,7 +11,7 @@
 Name: form_spellchecker
 Width: 385
 Height: 375
-Number of Objects: 13
+Number of Objects: 12
 
 --------------------
 class: FL_BOX
@@ -124,24 +124,6 @@
 --------------------
 class: FL_BUTTON
 type: NORMAL_BUTTON
-box: 280 25 100 25
-boxtype: FL_UP_BOX
-colors: FL_COL1 FL_COL1
-alignment: FL_ALIGN_CENTER
-style: FL_NORMAL_STYLE
-size: FL_NORMAL_SIZE
-lcol: FL_BLACK
-label: Start|#S
-shortcut: 
-resize: FL_RESIZE_NONE
-gravity: FL_NorthEast FL_NorthEast
-name: button_start
-callback: C_FormBaseInputCB
-argument: 0
-
---------------------
-class: FL_BUTTON
-type: NORMAL_BUTTON
 box: 280 195 100 25
 boxtype: FL_UP_BOX
 colors: FL_COL1 FL_COL1
@@ -185,7 +167,7 @@
 style: FL_NORMAL_STYLE
 size: FL_NORMAL_SIZE
 lcol: FL_BLACK
-label: Accept|#A
+label: Ignore All|#g
 shortcut: 
 resize: FL_RESIZE_X
 gravity: FL_NorthEast FL_NorthEast
Index: support/forkedcall.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/forkedcall.C,v
retrieving revision 1.12
diff -u -r1.12 forkedcall.C
--- support/forkedcall.C        13 Feb 2003 16:53:14 -0000      1.12
+++ support/forkedcall.C        16 Feb 2003 04:47:42 -0000
@@ -143,6 +143,24 @@
        return retval_;
 }
 
+
+bool ForkedProcess::running() const
+{
+       if (!pid())
+               return false;
+
+       // Un-UNIX like, but we don't have much use for
+       // knowing if a zombie exists, so just reap it first.
+       int waitstatus;
+       waitpid(pid(), &waitstatus, WNOHANG);
+
+       // Racy of course, but it will do.
+       if (::kill(pid(), 0) && errno == ESRCH)
+               return false;
+       return true;
+}
+
+
 void ForkedProcess::kill(int tol)
 {
        lyxerr << "ForkedProcess::kill(" << tol << ')' << endl;
Index: support/forkedcall.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/forkedcall.h,v
retrieving revision 1.8
diff -u -r1.8 forkedcall.h
--- support/forkedcall.h        13 Feb 2003 16:53:14 -0000      1.8
+++ support/forkedcall.h        16 Feb 2003 04:47:42 -0000
@@ -94,6 +94,9 @@
        /// Returns the identifying command (for display in the GUI perhaps).
        string const & command() const { return command_; }
 
+       /// is the process running ?
+       bool running() const;
+
        /** Kill child prematurely.
         *  First, a SIGHUP is sent to the child.
         *  If that does not end the child process within "tolerance"

Reply via email to