Hi,

I've prepared the following patch to demonstrate the way to speed up the native 
spell checker on mac. In case of spell error it is as slow as the original 
version. I'd like to improve that next...

Stephan
Index: src/AppleSpellChecker.h
===================================================================
--- src/AppleSpellChecker.h     (Revision 35122)
+++ src/AppleSpellChecker.h     (Arbeitskopie)
@@ -30,6 +30,9 @@
        void remove(WordLangTuple const &);
        void accept(WordLangTuple const &);
        bool hasDictionary(Language const * lang) const;
+       /// if can spell check whole row
+       virtual bool const canCheckRow() {
+               return true; }
        docstring const error();
        //@}
 
Index: src/TextMetrics.cpp
===================================================================
--- src/TextMetrics.cpp (Revision 35122)
+++ src/TextMetrics.cpp (Arbeitskopie)
@@ -2133,15 +2133,7 @@
 
                // Take this opportunity to spellcheck the row contents.
                if (row_has_changed && lyxrc.spellcheck_continuously) {
-                       WordLangTuple wl;
-                       // dummy variable, not used.
-                       static docstring_list suggestions;
-                       pos_type from = row.pos();
-                       pos_type to = row.endpos();
-                       while (from < row.endpos()) {
-                               text_->getPar(pit).spellCheck(from, to, wl, 
suggestions, false);
-                               from = to + 1;
-                       }
+                       text_->getPar(pit).spellCheckRow(row);
                }
 
                // Don't paint the row if a full repaint has not been requested
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp   (Revision 35122)
+++ src/Paragraph.cpp   (Arbeitskopie)
@@ -38,6 +38,7 @@
 #include "output_latex.h"
 #include "output_xhtml.h"
 #include "ParagraphParameters.h"
+#include "Row.h"
 #include "SpellChecker.h"
 #include "sgml.h"
 #include "TextClass.h"
@@ -3161,6 +3162,20 @@
 }
 
 
+Language * Paragraph::getLanguage(pos_type const from) const
+{
+       Language * lang = const_cast<Language 
*>(getFontSettings(d->inset_owner_->buffer().params(), from).language());
+       if (lang == d->inset_owner_->buffer().params().language
+               && !lyxrc.spellchecker_alt_lang.empty()) {
+               string lang_code;
+               string const lang_variety = split(lyxrc.spellchecker_alt_lang, 
lang_code, '-');
+               lang->setCode(lang_code);
+               lang->setVariety(lang_variety);
+       }
+       return lang;
+}
+       
+
 SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to, 
WordLangTuple & wl,
        docstring_list & suggestions, bool do_suggestion) const
 {
@@ -3180,17 +3195,10 @@
        // FIXME: make this customizable
        // (note that hunspell ignores words with digits by default)
        bool const ignored = hasDigit(word);
-       Language * lang = const_cast<Language *>(getFontSettings(
-                   d->inset_owner_->buffer().params(), from).language());
-       if (lang == d->inset_owner_->buffer().params().language
-           && !lyxrc.spellchecker_alt_lang.empty()) {
-               string lang_code;
-               string const lang_variety =
-                       split(lyxrc.spellchecker_alt_lang, lang_code, '-');
-               lang->setCode(lang_code);
-               lang->setVariety(lang_variety);
-       }
+       
+       Language * lang = getLanguage(from);
        wl = WordLangTuple(word, lang);
+       
        SpellChecker::Result res = ignored ?
                SpellChecker::WORD_OK : speller->check(wl);
 
@@ -3208,6 +3216,49 @@
 }
 
 
+void Paragraph::spellCheckRow(Row const & row) const
+{
+       SpellChecker * speller = theSpellChecker();
+       if (!speller)
+               return;
+       WordLangTuple wl;
+       pos_type from = row.pos();
+       pos_type to = row.endpos();
+       bool wordwise = !speller->canCheckRow();
+       if (!wordwise) {
+               locateWord(from, to, WHOLE_WORD);
+               pos_type start = from;
+               Language * lang = getLanguage(from);
+               while (!wordwise && from < row.endpos()) {
+                       locateWord(from, to, WHOLE_WORD);
+                       if (from >= pos_type(d->text_.size()))
+                               break;
+                       if (from != to) {
+                               // switch to wordwise spell checking for 
multiple languages
+                               wordwise = lang != getLanguage(from);
+                       }
+                       from = to + 1;
+               }
+               if (start == to)
+                       return;
+               docstring word = asString(start, to, AS_STR_INSETS);
+               wl = WordLangTuple(word, lang);
+               SpellChecker::Result res = speller->check(wl);
+               wordwise = SpellChecker::misspelled(res);
+               if (!wordwise)
+                       d->fontlist_.setMisspelled(start, to, false);
+       } 
+       if (wordwise) {
+               static docstring_list suggestions;
+               from = row.pos();
+               while (from < row.endpos()) {
+                       spellCheck(from, to, wl, suggestions, false);
+                       from = to + 1;
+               }
+       }
+}
+
+       
 bool Paragraph::isMisspelled(pos_type pos) const
 {
        pos_type from = pos;
Index: src/SpellChecker.h
===================================================================
--- src/SpellChecker.h  (Revision 35122)
+++ src/SpellChecker.h  (Arbeitskopie)
@@ -71,6 +71,10 @@
        /// check if dictionary exists
        virtual bool hasDictionary(Language const *) const = 0;
 
+       /// if can spell check whole row
+       virtual bool const canCheckRow() {
+               return false; }
+
        /// give an error message on messy exit
        virtual docstring const error() = 0;
 };
Index: src/Paragraph.h
===================================================================
--- src/Paragraph.h     (Revision 35122)
+++ src/Paragraph.h     (Arbeitskopie)
@@ -51,6 +51,7 @@
 class OutputParams;
 class PainterInfo;
 class ParagraphParameters;
+class Row;
 class TexRow;
 class Toc;
 class WordLangTuple;
@@ -430,6 +431,9 @@
        /// Spellcheck word at position \p pos.
        /// \return true if pointed word is misspelled.
        bool isMisspelled(pos_type pos) const;
+
+       void spellCheckRow(Row const & row) const;
+       
        /// an automatically generated identifying label for this paragraph.
        /// presently used only in the XHTML output routines.
        std::string magicLabel() const;
@@ -445,6 +449,8 @@
        ///
        void registerWords();
 
+       Language * getLanguage(pos_type const from) const;
+       
        /// Pimpl away stuff
        class Private;
        ///

Reply via email to