From 42dfd711977353e892aadbea6f531e59b0d92179 Mon Sep 17 00:00:00 2001 From: Stephan Witt Date: Thu, 12 Jan 2012 07:03:24 +0000 Subject: [PATCH] #7789 unify and fix buffer statistics git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40602 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 87 +++++++++++++++++++++++++++++++++++++++++ src/Buffer.h | 10 +++++ src/BufferView.cpp | 7 ++-- src/buffer_funcs.cpp | 93 -------------------------------------------- src/buffer_funcs.h | 7 ---- 5 files changed, 101 insertions(+), 103 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 8c1ea58e4a..b5756c9116 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -309,11 +309,27 @@ public: CloneList * clone_list_; /// are we in the process of exporting this buffer? mutable bool doing_export; + + /// compute statistics + /// \p from initial position + /// \p to points to the end position + void updateStatistics(DocIterator & from, DocIterator & to, + bool skipNoOutput = true); + /// statistics accessor functions + int wordCount() const { return word_count_; } + int charCount(bool with_blanks) const { + return char_count_ + + (with_blanks ? blank_count_ : 0); + } private: /// So we can force access via the accessors. mutable Buffer const * parent_buffer; + int word_count_; + int char_count_; + int blank_count_; + }; @@ -4427,6 +4443,77 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, } +void Buffer::Impl::updateStatistics(DocIterator & from, DocIterator & to, bool skipNoOutput) +{ + bool inword = false; + word_count_ = 0; + char_count_ = 0; + blank_count_ = 0; + + for (DocIterator dit = from ; dit != to && !dit.atEnd(); ) { + if (!dit.inTexted()) { + dit.forwardPos(); + continue; + } + + Paragraph const & par = dit.paragraph(); + pos_type const pos = dit.pos(); + + // Copied and adapted from isWordSeparator() in Paragraph + if (pos == dit.lastpos()) { + inword = false; + } else { + Inset const * ins = par.getInset(pos); + if (ins && skipNoOutput && !ins->producesOutput()) { + // skip this inset + ++dit.top().pos(); + // stop if end of range was skipped + if (!to.atEnd() && dit >= to) + break; + continue; + } else if (!par.isDeleted(pos)) { + if (par.isWordSeparator(pos)) + inword = false; + else if (!inword) { + ++word_count_; + inword = true; + } + if (ins && ins->isLetter()) + ++char_count_; + else if (ins && ins->isSpace()) + ++blank_count_; + else { + char_type const c = par.getChar(pos); + if (isPrintableNonspace(c)) + ++char_count_; + else if (isSpace(c)) + ++blank_count_; + } + } + } + dit.forwardPos(); + } +} + + +void Buffer::updateStatistics(DocIterator & from, DocIterator & to, bool skipNoOutput) const +{ + d->updateStatistics(from, to, skipNoOutput); +} + + +int Buffer::wordCount() const +{ + return d->wordCount(); +} + + +int Buffer::charCount(bool with_blanks) const +{ + return d->charCount(with_blanks); +} + + Buffer::ReadStatus Buffer::reload() { setBusy(true); diff --git a/src/Buffer.h b/src/Buffer.h index 9a2d4844ad..f740a37b92 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -689,6 +689,16 @@ public: /// void checkChildBuffers(); + /// compute statistics between \p from and \p to + /// \p from initial position + /// \p to points to the end position + /// \p skipNoOutput if notes etc. should be ignored + void updateStatistics(DocIterator & from, DocIterator & to, + bool skipNoOutput = true) const; + /// statistics accessor functions + int wordCount() const; + int charCount(bool with_blanks) const; + private: class MarkAsExporting; friend class MarkAsExporting; diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 2820b7e46f..9a4e5d326a 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1655,9 +1655,10 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) from = doc_iterator_begin(&buffer_); to = doc_iterator_end(&buffer_); } - int const words = countWords(from, to); - int const chars = countChars(from, to, false); - int const chars_blanks = countChars(from, to, true); + buffer_.updateStatistics(from, to); + int const words = buffer_.wordCount(); + int const chars = buffer_.charCount(false); + int const chars_blanks = buffer_.charCount(true); docstring message; if (cur.selection()) message = _("Statistics for the selection:"); diff --git a/src/buffer_funcs.cpp b/src/buffer_funcs.cpp index ff4512b5c6..073ddcb6f4 100644 --- a/src/buffer_funcs.cpp +++ b/src/buffer_funcs.cpp @@ -174,99 +174,6 @@ Buffer * newUnnamedFile(FileName const & path, string const & prefix, } -/* - * FIXME : merge with countChars. The structures of the two functions - * are similar but, unfortunately, they seem to have a different - * notion of what to count. Since nobody ever complained about that, - * this proves (again) that any number beats no number ! (JMarc) - * We have two use cases: - * 1. Count the words of the given range for document statistics - * - ignore inset content without output. (skipNoOutput == true) - * 2. Count the words to present a progress bar for the spell checker - * - has to count whole content. (skipNoOutput == false) - */ -int countWords(DocIterator const & from, DocIterator const & to, - bool skipNoOutput) -{ - int count = 0; - bool inword = false; - - for (DocIterator dit = from ; dit != to && !dit.atEnd(); ) { - if (!dit.inTexted()) { - dit.forwardPos(); - continue; - } - - Paragraph const & par = dit.paragraph(); - pos_type const pos = dit.pos(); - - // Copied and adapted from isWordSeparator() in Paragraph - if (pos == dit.lastpos()) { - inword = false; - } else if (!par.isDeleted(pos)) { - Inset const * ins = par.getInset(pos); - if (ins && skipNoOutput && !ins->producesOutput()) { - // skip this inset - ++dit.top().pos(); - // stop if end of range was skipped - if (!to.atEnd() && dit >= to) - break; - continue; - } - if (par.isWordSeparator(pos)) - inword = false; - else if (!inword) { - ++count; - inword = true; - } - } - dit.forwardPos(); - } - - return count; -} - - -int countChars(DocIterator const & from, DocIterator const & to, - bool with_blanks) -{ - int chars = 0; - int blanks = 0; - for (DocIterator dit = from ; dit != to ; ) { - if (!dit.inTexted()) { - dit.forwardPos(); - continue; - } - - Paragraph const & par = dit.paragraph(); - pos_type const pos = dit.pos(); - - if (pos != dit.lastpos() && !par.isDeleted(pos)) { - if (Inset const * ins = par.getInset(pos)) { - if (!ins->producesOutput()) { - //skip this inset - ++dit.top().pos(); - continue; - } - if (ins->isLetter()) - ++chars; - else if (with_blanks && ins->isSpace()) - ++blanks; - } else { - char_type const c = par.getChar(pos); - if (isPrintableNonspace(c)) - ++chars; - else if (isSpace(c) && with_blanks) - ++blanks; - } - } - dit.forwardPos(); - } - - return chars + blanks; -} - - Buffer * loadIfNeeded(FileName const & fname) { Buffer * buffer = theBufferList().getBuffer(fname); diff --git a/src/buffer_funcs.h b/src/buffer_funcs.h index 97449cc4b1..12aa84123e 100644 --- a/src/buffer_funcs.h +++ b/src/buffer_funcs.h @@ -46,13 +46,6 @@ Buffer * newUnnamedFile(support::FileName const & path, /// file was already loaded it just returns the associated buffer. Buffer * loadIfNeeded(support::FileName const & fname); -/// Count the number of words in the text between these two iterators -int countWords(DocIterator const & from, DocIterator const & to, - bool skipNoOutput = true); - -/// Count the number of chars in the text between these two iterators -int countChars(DocIterator const & from, DocIterator const & to, bool with_blanks); - } // namespace lyx #endif // BUFFER_FUNCS_H