#7789 unify and fix buffer statistics

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40602 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stephan Witt 2012-01-12 07:03:24 +00:00
parent 576e8d0497
commit 42dfd71197
5 changed files with 101 additions and 103 deletions

View File

@ -310,10 +310,26 @@ public:
/// are we in the process of exporting this buffer? /// are we in the process of exporting this buffer?
mutable bool doing_export; 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: private:
/// So we can force access via the accessors. /// So we can force access via the accessors.
mutable Buffer const * parent_buffer; 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() Buffer::ReadStatus Buffer::reload()
{ {
setBusy(true); setBusy(true);

View File

@ -689,6 +689,16 @@ public:
/// ///
void checkChildBuffers(); 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: private:
class MarkAsExporting; class MarkAsExporting;
friend class MarkAsExporting; friend class MarkAsExporting;

View File

@ -1655,9 +1655,10 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
from = doc_iterator_begin(&buffer_); from = doc_iterator_begin(&buffer_);
to = doc_iterator_end(&buffer_); to = doc_iterator_end(&buffer_);
} }
int const words = countWords(from, to); buffer_.updateStatistics(from, to);
int const chars = countChars(from, to, false); int const words = buffer_.wordCount();
int const chars_blanks = countChars(from, to, true); int const chars = buffer_.charCount(false);
int const chars_blanks = buffer_.charCount(true);
docstring message; docstring message;
if (cur.selection()) if (cur.selection())
message = _("Statistics for the selection:"); message = _("Statistics for the selection:");

View File

@ -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 * loadIfNeeded(FileName const & fname)
{ {
Buffer * buffer = theBufferList().getBuffer(fname); Buffer * buffer = theBufferList().getBuffer(fname);

View File

@ -46,13 +46,6 @@ Buffer * newUnnamedFile(support::FileName const & path,
/// file was already loaded it just returns the associated buffer. /// file was already loaded it just returns the associated buffer.
Buffer * loadIfNeeded(support::FileName const & fname); 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 } // namespace lyx
#endif // BUFFER_FUNCS_H #endif // BUFFER_FUNCS_H