diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 8105d5261b..04ec31b035 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -3039,4 +3039,45 @@ void Buffer::updateLabels(ParIterator & parit) const } } + +bool Buffer::nextWord(DocIterator & from, DocIterator & to, + docstring & word) const +{ + bool inword = false; + bool ignoreword = false; + string lang_code; + to = from; + + while (to.depth()) { + if (isLetter(to)) { + if (!inword) { + inword = true; + ignoreword = false; + from = to; + word.clear(); + lang_code = to.paragraph().getFontSettings(params(), + to.pos()).language()->code(); + } + // Insets like optional hyphens and ligature + // break are part of a word. + if (!to.paragraph().isInset(to.pos())) { + char_type const c = to.paragraph().getChar(to.pos()); + word += c; + if (isDigit(c)) + ignoreword = true; + } + } else { // !isLetter(cur) + if (inword) + if (!word.empty() && !ignoreword) { + return true; + } + inword = false; + } + + to.forwardPos(); + } + + return false; +} + } // namespace lyx diff --git a/src/Buffer.h b/src/Buffer.h index 6b983177cd..5d7b0d94e2 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -492,6 +492,15 @@ public: /// void updateLabels(ParIterator & parit) const; + /// Find next word starting from \p from. + /// \p from initial position to search, will then points to the next + /// word. + /// \p to will points to the end of the next word. + /// \p word will contain the found word if any. + /// \return true if a new word was found. + bool nextWord(DocIterator & from, DocIterator & to, + docstring & word) const; + private: /// search for macro in local (buffer) table or in children MacroData const * getBufferMacro(docstring const & name, diff --git a/src/DocIterator.cpp b/src/DocIterator.cpp index 40c4ae4adc..51433d4781 100644 --- a/src/DocIterator.cpp +++ b/src/DocIterator.cpp @@ -17,6 +17,7 @@ #include "Buffer.h" #include "InsetList.h" #include "Paragraph.h" +#include "LyXRC.h" #include "Text.h" #include "mathed/MathData.h" @@ -27,10 +28,12 @@ #include "support/debug.h" #include "support/lassert.h" +#include "support/lstrings.h" #include using namespace std; +using namespace lyx::support; namespace lyx { @@ -607,4 +610,16 @@ bool operator==(StableDocIterator const & dit1, StableDocIterator const & dit2) } +bool isLetter(DocIterator const & dit) +{ + return dit.inTexted() + && dit.inset().allowSpellCheck() + && dit.pos() != dit.lastpos() + && (dit.paragraph().isLetter(dit.pos()) + // We want to pass the ' and escape chars to ispell + || contains(from_utf8(lyxrc.spellchecker_esc_chars + '\''), + dit.paragraph().getChar(dit.pos()))) + && !dit.paragraph().isDeleted(dit.pos()); +} + } // namespace lyx diff --git a/src/DocIterator.h b/src/DocIterator.h index 737cbd3b13..14baf2566f 100644 --- a/src/DocIterator.h +++ b/src/DocIterator.h @@ -355,6 +355,9 @@ private: std::vector data_; }; +/// Indicate if the character pointed by dit is a letter. +/// This function takes care of spellchecker escape chars. +bool isLetter(DocIterator const & dit); } // namespace lyx diff --git a/src/frontends/qt4/GuiSpellchecker.cpp b/src/frontends/qt4/GuiSpellchecker.cpp index ee53817314..41aa782bab 100644 --- a/src/frontends/qt4/GuiSpellchecker.cpp +++ b/src/frontends/qt4/GuiSpellchecker.cpp @@ -241,59 +241,23 @@ void GuiSpellchecker::clearParams() } -static bool isLetter(DocIterator const & dit) -{ - return dit.inTexted() - && dit.inset().allowSpellCheck() - && dit.pos() != dit.lastpos() - && (dit.paragraph().isLetter(dit.pos()) - // We want to pass the ' and escape chars to ispell - || contains(from_utf8(lyxrc.spellchecker_esc_chars + '\''), - dit.paragraph().getChar(dit.pos()))) - && !dit.paragraph().isDeleted(dit.pos()); -} - - static WordLangTuple nextWord(Cursor & cur, ptrdiff_t & progress) { - BufferParams const & bp = cur.bv().buffer().params(); - bool inword = false; - bool ignoreword = false; + Buffer const & buf = cur.bv().buffer(); cur.resetAnchor(); docstring word; - string lang_code; + DocIterator from = cur; + DocIterator to; + if (!buf.nextWord(from, to, word)) + return WordLangTuple(docstring(), string()); - while (cur.depth()) { - if (isLetter(cur)) { - if (!inword) { - inword = true; - ignoreword = false; - cur.resetAnchor(); - word.clear(); - lang_code = cur.paragraph().getFontSettings(bp, cur.pos()).language()->code(); - } - // Insets like optional hyphens and ligature - // break are part of a word. - if (!cur.paragraph().isInset(cur.pos())) { - char_type const c = cur.paragraph().getChar(cur.pos()); - word += c; - if (isDigit(c)) - ignoreword = true; - } - } else { // !isLetter(cur) - if (inword) - if (!word.empty() && !ignoreword) { - cur.setSelection(); - return WordLangTuple(word, lang_code); - } - inword = false; - } - - cur.forwardPos(); - ++progress; - } - - return WordLangTuple(docstring(), string()); + cur.setCursor(from); + cur.resetAnchor(); + cur.setCursor(to); + cur.setSelection(); + string lang_code = from.paragraph().getFontSettings(buf.params(), cur.pos()).language()->code(); + ++progress; + return WordLangTuple(word, lang_code); }