From 7391a872cac48a2d17d353867e4dbd8ddeab8021 Mon Sep 17 00:00:00 2001 From: Stephan Witt Date: Tue, 24 Jan 2012 06:20:25 +0000 Subject: [PATCH] #7789 correct buffer statistics when change tracking is on; LyX incorrectly counts the words in deleted notes git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@40673 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 82 ++++++++++++++++++++++++++++++++++++++ src/Buffer.h | 10 +++++ src/BufferView.cpp | 7 ++-- src/buffer_funcs.cpp | 93 -------------------------------------------- src/buffer_funcs.h | 7 ---- status.20x | 3 ++ 6 files changed, 99 insertions(+), 103 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index cf2646caff..7780fc15ab 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -306,11 +306,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_; + }; @@ -4242,7 +4258,73 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, return progress; } +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 a0ac56b1b5..36834e7753 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -655,6 +655,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: /// Change name of buffer. Updates "read-only" flag. void setFileName(support::FileName const & fname); diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 88cd94d389..1aa3c3b60a 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1642,9 +1642,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 diff --git a/status.20x b/status.20x index 87d09f68b3..75114b2305 100644 --- a/status.20x +++ b/status.20x @@ -208,6 +208,9 @@ What's new - Fix a warning when changing table settings via the dialog (bug 7755). +- Correct buffer statistics when change tracking is on. + LyX did incorrectly count the words in deleted notes (bug 7789). + * DOCUMENTATION AND LOCALIZATION