diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 31e61455b2..4519737d6b 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -100,10 +100,12 @@ #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include using namespace std; using namespace lyx::support; @@ -117,10 +119,10 @@ namespace { int const LYX_FORMAT = 316; // JSpitzm: subfig support -} // namespace anon - - typedef map DepClean; +typedef map > RefCache; + +} // namespace anon class Buffer::Impl { @@ -205,6 +207,8 @@ public: /// A cache for the bibfiles (including bibfiles of loaded child /// documents), needed for appropriate update of natbib labels. mutable EmbeddedFileList bibfilesCache_; + + mutable RefCache ref_cache_; }; /// Creates the per buffer temporary directory @@ -2064,6 +2068,47 @@ void Buffer::writeParentMacros(odocstream & os) const } +Buffer::References & Buffer::references(docstring const & label) +{ + if (d->parent_buffer) + return const_cast(masterBuffer())->references(label); + + RefCache::iterator it = d->ref_cache_.find(label); + if (it != d->ref_cache_.end()) + return it->second.second; + + static InsetLabel const * dummy_il = 0; + static References const dummy_refs; + it = d->ref_cache_.insert(make_pair(label, make_pair(dummy_il, dummy_refs))).first; + return it->second.second; +} + + +Buffer::References const & Buffer::references(docstring const & label) const +{ + return const_cast(this)->references(label); +} + + +void Buffer::setInsetLabel(docstring const & label, InsetLabel const * il) +{ + masterBuffer()->d->ref_cache_[label].first = il; +} + + +InsetLabel const * Buffer::insetLabel(docstring const & label) const +{ + return masterBuffer()->d->ref_cache_[label].first; +} + + +void Buffer::clearReferenceCache() const +{ + if (!d->parent_buffer) + d->ref_cache_.clear(); +} + + void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to, InsetCode code) { @@ -2327,9 +2372,6 @@ void Buffer::resetChildDocuments(bool close_them) const resetParentBuffer(this, ip, close_them); } - if (use_gui && masterBuffer() == this) - updateLabels(*this); - // clear references to children in macro tables d->children_positions.clear(); d->position_to_children.clear(); diff --git a/src/Buffer.h b/src/Buffer.h index c35a2479c0..4e01081476 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -31,6 +31,8 @@ class ErrorItem; class ErrorList; class FuncRequest; class Inset; +class InsetRef; +class InsetLabel; class Font; class Format; class Lexer; @@ -451,7 +453,15 @@ public: bool isExportable(std::string const & format) const; /// std::vector exportableFormats(bool only_viewable) const; - + + /// + typedef std::vector > References; + References & references(docstring const & label); + References const & references(docstring const & label) const; + void clearReferenceCache() const; + void setInsetLabel(docstring const & label, InsetLabel const * il); + InsetLabel const * insetLabel(docstring const & label) const; + private: /// search for macro in local (buffer) table or in children MacroData const * getBufferMacro(docstring const & name, diff --git a/src/buffer_funcs.cpp b/src/buffer_funcs.cpp index 50356170b2..1d9d651263 100644 --- a/src/buffer_funcs.cpp +++ b/src/buffer_funcs.cpp @@ -491,6 +491,7 @@ void updateLabels(Buffer const & buf, bool childonly) // start over the counters textclass.counters().reset(); + buf.clearReferenceCache(); } Buffer & cbuf = const_cast(buf); diff --git a/src/insets/InsetLabel.cpp b/src/insets/InsetLabel.cpp index 4c87e69591..c23cee2b06 100644 --- a/src/insets/InsetLabel.cpp +++ b/src/insets/InsetLabel.cpp @@ -12,17 +12,23 @@ #include "InsetLabel.h" +#include "InsetRef.h" + #include "Buffer.h" #include "BufferView.h" #include "DispatchResult.h" #include "FuncRequest.h" +#include "InsetIterator.h" #include "ParIterator.h" #include "sgml.h" #include "Text.h" #include "TocBackend.h" -#include "support/lstrings.h" +#include "frontends/alert.h" + #include "support/lyxalgo.h" +#include "support/gettext.h" +#include "support/lstrings.h" using namespace std; using namespace lyx::support; @@ -57,10 +63,32 @@ docstring InsetLabel::screenLabel() const } +void InsetLabel::updateLabels(ParIterator const & it) +{ + docstring const & label = getParam("name"); + if (buffer().insetLabel(label)) + // Problem: We already have an InsetLabel with the same name! + return; + buffer().setInsetLabel(label, this); +} + + void InsetLabel::addToToc(ParConstIterator const & cpit) const { + docstring const & label = getParam("name"); Toc & toc = buffer().tocBackend().toc("label"); - toc.push_back(TocItem(cpit, 0, screenLabel())); + if (buffer().insetLabel(label) != this) { + toc.push_back(TocItem(cpit, 0, _("DUPLICATE: ") + label)); + return; + } + toc.push_back(TocItem(cpit, 0, label)); + Buffer::References const & refs = buffer().references(label); + Buffer::References::const_iterator it = refs.begin(); + Buffer::References::const_iterator end = refs.end(); + for (; it != end; ++it) { + ParConstIterator const ref_pit(it->second); + toc.push_back(TocItem(ref_pit, 1, it->first->screenLabel())); + } } diff --git a/src/insets/InsetLabel.h b/src/insets/InsetLabel.h index 6e97d51100..13284c8db2 100644 --- a/src/insets/InsetLabel.h +++ b/src/insets/InsetLabel.h @@ -43,6 +43,8 @@ public: static bool isCompatibleCommand(std::string const & s) { return s == "label"; } /// + void updateLabels(ParIterator const & it); + /// void addToToc(ParConstIterator const &) const; protected: /// diff --git a/src/insets/InsetRef.cpp b/src/insets/InsetRef.cpp index 02fc0b9355..88c76fa553 100644 --- a/src/insets/InsetRef.cpp +++ b/src/insets/InsetRef.cpp @@ -26,8 +26,8 @@ #include "support/gettext.h" #include "support/lstrings.h" -using namespace std; using namespace lyx::support; +using namespace std; namespace lyx { @@ -152,32 +152,23 @@ void InsetRef::textString(odocstream & os) const } +void InsetRef::updateLabels(ParIterator const & it) +{ + docstring const & label = getParam("reference"); + buffer().references(label).push_back(make_pair(this, it)); +} + + void InsetRef::addToToc(ParConstIterator const & cpit) const { docstring const & label = getParam("reference"); - Toc & toc = buffer().tocBackend().toc("label"); - Toc::iterator it = toc.begin(); - Toc::iterator end = toc.end(); - for (; it != end; ++it) { - if (it->str() == label) - break; - } - - docstring const reflabel = screenLabel(); - if (it == end) { - // This label has not been parsed yet so we just add it temporarily. - // InsetLabel::addTocToc() will fix that later. - toc.push_back(TocItem(cpit, 0, label)); - toc.push_back(TocItem(cpit, 1, reflabel)); + if (buffer().insetLabel(label)) + // This InsetRef has already been taken care of in InsetLabel::addToToc(). return; - } - // The Toc item for this label already exists so let's add - // this inset to this node. - ++it; - while (it != end && it->str() == reflabel) - ++it; - toc.insert(it, TocItem(cpit, 1, reflabel)); + Toc & toc = buffer().tocBackend().toc("label"); + docstring const reflabel = _("BROKEN: ") + screenLabel(); + toc.push_back(TocItem(cpit, 0, reflabel)); } diff --git a/src/insets/InsetRef.h b/src/insets/InsetRef.h index 9bc8d44641..eab494474b 100644 --- a/src/insets/InsetRef.h +++ b/src/insets/InsetRef.h @@ -63,6 +63,8 @@ public: /// static bool isCompatibleCommand(std::string const & s); /// + void updateLabels(ParIterator const & it); + /// void addToToc(ParConstIterator const &) const; protected: ///