]> git.lyx.org Git - features.git/blobdiff - src/frontends/controllers/ControlSpellchecker.C
use std::advance and std::distance instead of home-grown versions
[features.git] / src / frontends / controllers / ControlSpellchecker.C
index 4495b87375bf941a20955607992cacbead6779c3..835aa4c1e9fa76230fa57e9cf7dda8cc9ac0beb8 100644 (file)
@@ -5,21 +5,25 @@
  *
  * \author Edwin Leuven
  *
- * Full author contact details are available in file CREDITS
+ * Full author contact details are available in file CREDITS.
  */
 
 #include <config.h>
 
-
 #include "ControlSpellchecker.h"
 #include "ViewBase.h"
+
 #include "buffer.h"
+#include "bufferparams.h"
 #include "BufferView.h"
+#include "bufferview_funcs.h"
+#include "debug.h"
 #include "gettext.h"
 #include "language.h"
 #include "lyxrc.h"
-#include "lyxtext.h"
-#include "debug.h"
+
+#include "PosIterator.h"
+#include "paragraph.h"
 
 #include "ispell.h"
 #ifdef USE_PSPELL
 #endif
 #endif
 
+#include "support/tostr.h"
+
 #include "frontends/Alert.h"
 
-#include "support/BoostFormat.h"
+
+using lyx::support::bformat;
 
 using std::endl;
+using std::string;
+
 
 ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
        : ControlDialogBD(lv, d),
-         newval_(0.0), oldval_(0), newvalue_(0), count_(0)
+         oldval_(0), newvalue_(0), count_(0)
 {}
 
 
@@ -59,8 +68,10 @@ void ControlSpellchecker::clearParams()
        endSession();
 }
 
+
 namespace {
 
+
 SpellBase * getSpeller(BufferParams const & bp)
 {
        string lang = (lyxrc.isp_use_alt_lang)
@@ -84,6 +95,7 @@ SpellBase * getSpeller(BufferParams const & bp)
 
 }
 
+
 void ControlSpellchecker::startSession()
 {
        lyxerr[Debug::GUI] << "spell startSession" << endl;
@@ -94,10 +106,9 @@ void ControlSpellchecker::startSession()
                return;
        }
 
-       speller_.reset(getSpeller(buffer()->params));
+       speller_.reset(getSpeller(buffer()->params()));
 
        // reset values to initial
-       newval_ = 0.0;
        oldval_ = 0;
        newvalue_ = 0;
        count_ = 0;
@@ -124,8 +135,6 @@ void ControlSpellchecker::endSession()
 {
        lyxerr[Debug::GUI] << "spell endSession" << endl;
 
-       bufferview()->endOfSpellCheck();
-
        emergency_exit_ = true;
 
        if (!speller_.get()) {
@@ -137,19 +146,63 @@ void ControlSpellchecker::endSession()
 }
 
 
+namespace {
+
+
+bool isLetter(PosIterator & cur)
+{
+       return !cur.at_end()
+               && cur.pit()->isLetter(cur.pos())
+               && !isDeletedText(*cur.pit(), cur.pos())
+               && (!cur.inset() || cur.inset()->allowSpellCheck());
+}
+
+
+WordLangTuple nextWord(PosIterator & cur, PosIterator const & end,
+                      int & progress, BufferParams & bp)
+{
+       // skip until we have real text (will jump paragraphs)
+       for (; cur != end && !isLetter(cur); ++cur, ++progress);
+
+       if (cur == end)
+               return WordLangTuple(string(), string());
+
+       string lang_code = cur.pit()->getFontSettings(bp, cur.pos()).language()->code();
+       string str;
+       // and find the end of the word (insets like optional hyphens
+       // and ligature break are part of a word)
+       for (; cur != end && isLetter(cur); ++cur, ++progress) {
+               if (!cur.pit()->isInset(cur.pos()))
+                       str += cur.pit()->getChar(cur.pos());
+       }
+
+       return WordLangTuple(str, lang_code);
+}
+
+
+} //namespace anon
+
+
+
+
 void ControlSpellchecker::check()
 {
        lyxerr[Debug::GUI] << "spell check a word" << endl;
 
        SpellBase::Result res = SpellBase::OK;
 
-       // clear any old selection
-       LyXText * text = bufferview()->getLyXText();
-       bufferview()->toggleSelection(true);
-       bufferview()->update(text, BufferView::SELECT);
+       PosIterator cur(*bufferview());
+       PosIterator const beg = buffer()->pos_iterator_begin();
+       PosIterator const end = buffer()->pos_iterator_end();
+
+       int start = std::distance(beg, cur);
+       int const total = start + std::distance(cur, end);
 
-       while ((res == SpellBase::OK || res == SpellBase::IGNORE)) {
-               word_ = bufferview()->nextWord(newval_);
+       if (cur != buffer()->pos_iterator_begin())
+               for (; cur != end && isLetter(cur); ++cur, ++start);
+
+       while (res == SpellBase::OK || res == SpellBase::IGNORE) {
+               word_ = nextWord(cur, end, start, buffer()->params());
 
                // end of document
                if (word_.word().empty())
@@ -158,7 +211,8 @@ void ControlSpellchecker::check()
                ++count_;
 
                // Update slider if and only if value has changed
-               newvalue_ = int(100.0 * newval_);
+               float progress = total ? float(start)/total : 1;
+               newvalue_ = int(100.0 * progress);
                if (newvalue_!= oldval_) {
                        lyxerr[Debug::GUI] << "Updating spell progress." << endl;
                        oldval_ = newvalue_;
@@ -180,7 +234,10 @@ void ControlSpellchecker::check()
        lyxerr[Debug::GUI] << "Found word \"" << word_.word() << "\"" << endl;
 
        if (!word_.word().empty()) {
-               bufferview()->selectLastWord();
+               int const size = word_.word().size();
+               std::advance(cur, -size);
+               bufferview()->putSelectionAt(cur, size, false);
+               std::advance(cur, size);
        } else {
                showSummary();
                endSession();
@@ -221,22 +278,10 @@ void ControlSpellchecker::showSummary()
        }
 
        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 {
+       if (count_ != 1)
+               message = bformat(_("%1$s words checked."), tostr(count_));
+       else
                message = _("One word checked.");
-       }
-#endif
 
        view().hide();
        Alert::information(_("Spell-checking is complete"), message);
@@ -283,5 +328,3 @@ void ControlSpellchecker::ignoreAll()
        speller_->accept(word_);
        check();
 }
-
-