* paragraph support for the global word list. To make it buffer

dependent, we need the buffer pointer. In fact we already have a
  pointer to the text inset. So as soon as inset know their buffer we
  can easily switch to a buffer local word list.
* there might be missing some more places to update the words from a
  buffer, like for example after backspace or more important when the
  cursor leaves a paragraph.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23244 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stefan Schimanski 2008-02-26 13:07:59 +00:00
parent 23f76cf934
commit cd5bad62e0
9 changed files with 131 additions and 43 deletions

View File

@ -204,9 +204,6 @@ public:
/// A cache for the bibfiles (including bibfiles of loaded child /// A cache for the bibfiles (including bibfiles of loaded child
/// documents), needed for appropriate update of natbib labels. /// documents), needed for appropriate update of natbib labels.
mutable EmbeddedFileList bibfilesCache_; mutable EmbeddedFileList bibfilesCache_;
///
WordList words_;
}; };
/// Creates the per buffer temporary directory /// Creates the per buffer temporary directory
@ -2668,16 +2665,4 @@ void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
} }
} }
void Buffer::registerWord(docstring const & word)
{
d->words_.insert(word);
}
WordList const & Buffer::registeredWords() const
{
return d->words_;
}
} // namespace lyx } // namespace lyx

View File

@ -50,7 +50,6 @@ class TeXErrors;
class TexRow; class TexRow;
class TocBackend; class TocBackend;
class Undo; class Undo;
class WordList;
namespace frontend { namespace frontend {
class GuiBufferDelegate; class GuiBufferDelegate;
@ -453,11 +452,6 @@ public:
/// ///
std::vector<Format const *> exportableFormats(bool only_viewable) const; std::vector<Format const *> exportableFormats(bool only_viewable) const;
/// Register word for completion word list.
void registerWord(docstring const & word);
///
WordList const & registeredWords() const;
private: private:
/// search for macro in local (buffer) table or in children /// search for macro in local (buffer) table or in children
MacroData const * getBufferMacro(docstring const & name, MacroData const * getBufferMacro(docstring const & name,

View File

@ -39,7 +39,9 @@
#include "sgml.h" #include "sgml.h"
#include "TextClass.h" #include "TextClass.h"
#include "TexRow.h" #include "TexRow.h"
#include "Text.h"
#include "VSpace.h" #include "VSpace.h"
#include "WordList.h"
#include "frontends/alert.h" #include "frontends/alert.h"
@ -196,6 +198,10 @@ public:
typedef docstring TextContainer; typedef docstring TextContainer;
/// ///
TextContainer text_; TextContainer text_;
typedef std::set<docstring> Words;
///
Words words_;
}; };
@ -233,7 +239,8 @@ Paragraph::Private::Private(Paragraph * owner)
Paragraph::Private::Private(Private const & p, Paragraph * owner) Paragraph::Private::Private(Private const & p, Paragraph * owner)
: owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_), : owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_),
params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_), params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_),
layout_(p.layout_), begin_of_body_(p.begin_of_body_), text_(p.text_) layout_(p.layout_), begin_of_body_(p.begin_of_body_), text_(p.text_),
words_(p.words_)
{ {
id_ = paragraph_id++; id_ = paragraph_id++;
} }
@ -1039,6 +1046,7 @@ Paragraph::Paragraph(Paragraph const & par)
: itemdepth(par.itemdepth), : itemdepth(par.itemdepth),
d(new Paragraph::Private(*par.d, this)) d(new Paragraph::Private(*par.d, this))
{ {
registerWords();
} }
@ -1048,8 +1056,10 @@ Paragraph & Paragraph::operator=(Paragraph const & par)
if (&par != this) { if (&par != this) {
itemdepth = par.itemdepth; itemdepth = par.itemdepth;
deregisterWords();
delete d; delete d;
d = new Private(*par.d, this); d = new Private(*par.d, this);
registerWords();
} }
return *this; return *this;
} }
@ -1057,6 +1067,7 @@ Paragraph & Paragraph::operator=(Paragraph const & par)
Paragraph::~Paragraph() Paragraph::~Paragraph()
{ {
deregisterWords();
delete d; delete d;
} }
@ -2678,4 +2689,66 @@ bool Paragraph::isSeparator(pos_type pos) const
} }
void Paragraph::deregisterWords()
{
Private::Words::const_iterator it;
WordList & wl = theWordList();
for (it = d->words_.begin(); it != d->words_.end(); ++it)
wl.remove(*it);
d->words_.clear();
}
void Paragraph::collectWords(Buffer const & buf, CursorSlice const & sl)
{
// find new words
bool inword = false;
//lyxerr << "Words: ";
pos_type n = size();
for (pos_type pos = 0; pos != n; ++pos) {
if (isDeleted(pos))
continue;
if (!isLetter(pos)) {
inword = false;
continue;
}
if (inword)
continue;
inword = true;
CursorSlice from = sl;
CursorSlice to = sl;
from.pos() = pos;
to.pos() = pos;
from.text()->getWord(from, to, WHOLE_WORD);
if (to.pos() - from.pos() < 6)
continue;
docstring word
= asString(buf, from.pos(), to.pos(), false);
d->words_.insert(word);
//lyxerr << word << " ";
}
//lyxerr << std::endl;
}
void Paragraph::registerWords()
{
Private::Words::const_iterator it;
WordList & wl = theWordList();
for (it = d->words_.begin(); it != d->words_.end(); ++it)
wl.insert(*it);
}
void Paragraph::updateWords(Buffer const & buf, CursorSlice const & sl)
{
deregisterWords();
collectWords(buf, sl);
registerWords();
}
} // namespace lyx } // namespace lyx

View File

@ -31,6 +31,8 @@ class Buffer;
class BufferParams; class BufferParams;
class Change; class Change;
class Counters; class Counters;
class Cursor;
class CursorSlice;
class Inset; class Inset;
class InsetBibitem; class InsetBibitem;
class LaTeXFeatures; class LaTeXFeatures;
@ -368,7 +370,17 @@ public:
pos_type pos, ///< start from here. pos_type pos, ///< start from here.
bool del = true) const; bool del = true) const;
///
void updateWords(Buffer const & buf, CursorSlice const & sl);
private: private:
///
void deregisterWords();
///
void collectWords(Buffer const & buf, CursorSlice const & sl);
///
void registerWords();
/// Pimpl away stuff /// Pimpl away stuff
class Private; class Private;
/// ///

View File

@ -581,19 +581,7 @@ void Text::charInserted(Cursor & cur)
&& !par.isLetter(cur.pos() - 1)) { && !par.isLetter(cur.pos() - 1)) {
// get the word in front of cursor // get the word in front of cursor
BOOST_ASSERT(this == cur.text()); BOOST_ASSERT(this == cur.text());
CursorSlice focus = cur.top(); cur.paragraph().updateWords(cur.buffer(), cur.top());
focus.backwardPos();
CursorSlice from = focus;
CursorSlice to = focus;
getWord(from, to, PREVIOUS_WORD);
if (focus == from || to == from)
return;
docstring word
= par.asString(cur.buffer(), from.pos(), to.pos(), false);
// register words longer than 5 characters
if (word.length() > 5)
cur.buffer().registerWord(word);
} }
} }
@ -1218,6 +1206,10 @@ bool Text::read(Buffer const & buf, Lexer & lex,
// not BufferParams // not BufferParams
lyx::readParagraph(buf, pars_.back(), lex, errorList); lyx::readParagraph(buf, pars_.back(), lex, errorList);
// register the words in the global word list
CursorSlice sl = CursorSlice(*insetPtr);
sl.pit() = pars_.size() - 1;
pars_.back().updateWords(buf, sl);
} else if (token == "\\begin_deeper") { } else if (token == "\\begin_deeper") {
++depth; ++depth;
} else if (token == "\\end_deeper") { } else if (token == "\\end_deeper") {

View File

@ -21,12 +21,20 @@
namespace lyx { namespace lyx {
///
WordList theGlobalWordList;
WordList & theWordList()
{
return theGlobalWordList;
}
/// ///
struct WordList::Impl { struct WordList::Impl {
/// ///
size_t c_; size_t c_;
/// ///
typedef stx::weighted_btree<docstring, size_t> Words; typedef stx::weighted_btree<docstring, size_t, int> Words;
/// ///
Words words_; Words words_;
}; };
@ -61,14 +69,34 @@ docstring const & WordList::word(size_t idx) const
size_t WordList::size() const size_t WordList::size() const
{ {
return d->words_.size(); return d->words_.summed_weight();
} }
void WordList::insert(docstring const & w) void WordList::insert(docstring const & w)
{ {
d->words_.insert(w, size_t(1), stx::Void()); Impl::Words::iterator it = d->words_.find(w);
if (it == d->words_.end())
d->words_.insert(w, size_t(1), 1);
else {
it.data()++;
d->words_.change_weight(it, 1);
}
} }
void WordList::remove(docstring const & w)
{
Impl::Words::iterator it = d->words_.find(w);
if (it != d->words_.end()) {
it.data()--;
d->words_.change_weight(it, 0);
// We will not erase here, but instead we just leave it
// in the btree with weight 0. This avoid too much
// reorganisation of the tree all the time.
//if (it.data() == 0)
// d->words_.erase(w);
}
}
} // namespace lyx } // namespace lyx

View File

@ -29,12 +29,16 @@ public:
size_t size() const; size_t size() const;
/// ///
void insert(docstring const & w); void insert(docstring const & w);
///
void remove(docstring const & w);
private: private:
struct Impl; struct Impl;
Impl * d; Impl * d;
}; };
WordList & theWordList();
} // namespace lyx } // namespace lyx
#endif // WORDLIST_H #endif // WORDLIST_H

View File

@ -112,7 +112,7 @@ private:
int updateLock_; int updateLock_;
/// the BufferView::inlineCursorPos might be reset by destructive /// the BufferView::inlineCursorPos might be reset by destructive
/// operations like backspace. Hence, we have to keep this flag /// operations like backspace. Hence, we have to keep this flag
/// in addition to know whether the popup is to be kept visible. /// in addition to know whether the completion is to be kept visible.
bool inlineVisible_; bool inlineVisible_;
/// ///
RtlItemDelegate * rtlItemDelegate_; RtlItemDelegate * rtlItemDelegate_;

View File

@ -80,12 +80,12 @@ public:
/// ///
virtual size_t size() const virtual size_t size() const
{ {
return buf_.registeredWords().size(); return theWordList().size();
} }
/// ///
virtual docstring const & data(size_t idx) const virtual docstring const & data(size_t idx) const
{ {
return buf_.registeredWords().word(idx); return theWordList().word(idx);
} }
private: private: