int const LYX_FORMAT = LYX_FORMAT_LYX;
typedef map<string, bool> DepClean;
-typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
+
+// Information about labels and their associated refs
+struct LabelInfo {
+ /// label string
+ docstring label;
+ /// label inset
+ InsetLabel const * inset;
+ /// associated references cache
+ Buffer::References references;
+ /// whether this label is active (i.e., not deleted)
+ bool active;
+};
+
+typedef vector<LabelInfo> RefCache;
} // namespace
/// was missing).
bool preview_error_;
+ /// Cache the insets, their associated refs (with positions),
+ /// and whether the insets are active.
mutable RefCache ref_cache_;
/// our Text that should be wrapped in an InsetText
if (d->parent())
return const_cast<Buffer *>(masterBuffer())->getReferenceCache(label);
- RefCache::iterator it = d->ref_cache_.find(label);
- if (it != d->ref_cache_.end())
- return it->second.second;
+ // In what follows, we look whether we find an active label
+ // with the given string in the cache. If so, return its
+ // references cache. If we only find an inactive one, return
+ // that (the last we find, coincidentally). If we find noting,
+ // return an empty references cache.
+ static LabelInfo linfo;
+ linfo.inset = nullptr;
+ linfo.references = References();
+ linfo.active = false;
+ bool have_inactive = false;
+ for (auto & rc : d->ref_cache_) {
+ if (rc.label == label) {
+ if (rc.active)
+ return rc.references;
+ else {
+ linfo = rc;
+ have_inactive = true;
+ }
+ }
+ }
+
+ if (!have_inactive)
+ // We found nothing, so insert the empty one to the cache
+ // for further processing
+ d->ref_cache_.push_back(linfo);
- static InsetLabel const * dummy_il = 0;
- static References const dummy_refs = References();
- it = d->ref_cache_.insert(
- make_pair(label, make_pair(dummy_il, dummy_refs))).first;
- return it->second.second;
+ return linfo.references;
}
}
-void Buffer::setInsetLabel(docstring const & label, InsetLabel const * il)
+void Buffer::setInsetLabel(docstring const & label, InsetLabel const * il,
+ bool const active)
{
- masterBuffer()->d->ref_cache_[label].first = il;
+ static LabelInfo linfo;
+ linfo.label = label;
+ linfo.inset = il;
+ linfo.references = References();
+ linfo.active = active;
+ masterBuffer()->d->ref_cache_.push_back(linfo);
}
-InsetLabel const * Buffer::insetLabel(docstring const & label) const
+InsetLabel const * Buffer::insetLabel(docstring const & label,
+ bool const active) const
{
- return masterBuffer()->d->ref_cache_[label].first;
+ for (auto & rc : masterBuffer()->d->ref_cache_) {
+ if (rc.label == label && (rc.active || !active))
+ return rc.inset;
+ }
+ return nullptr;
+}
+
+
+bool Buffer::activeLabel(docstring const & label) const
+{
+ if (!insetLabel(label))
+ return false;
+
+ for (auto & rc : masterBuffer()->d->ref_cache_) {
+ if (rc.label == label && rc.active)
+ return true;
+ }
+ return false;
}
///
bool isExporting() const;
- ///
+ /// A collection of InsetRef insets and their position in the buffer
typedef std::vector<std::pair<Inset *, ParIterator> > References;
- ///
+ /// Get all InsetRef insets and their positions associated with
+ /// the InsetLabel with the label string \p label
References const & references(docstring const & label) const;
- ///
+ /// Add an InsetRef at position \p it to the Insetlabel
+ /// with the label string \p label
void addReference(docstring const & label, Inset * inset, ParIterator it);
- ///
+ /// Clear the whole reference cache
void clearReferenceCache() const;
- ///
- void setInsetLabel(docstring const & label, InsetLabel const * il);
- ///
- InsetLabel const * insetLabel(docstring const & label) const;
+ /// Set the InsetLabel for a given \p label string. \p active
+ /// determines whether this is an active label (see @ref activeLabel)
+ void setInsetLabel(docstring const & label, InsetLabel const * il,
+ bool const active);
+ /// \return the InsetLabel associated with this \p label string
+ /// If \p active is true we only return active labels.
+ InsetLabel const * insetLabel(docstring const & label,
+ bool const active = false) const;
+ /// \return true if this \param label is an active label.
+ /// Inactive labels are currently deleted labels (in ct mode)
+ bool activeLabel(docstring const & label) const;
/// return a list of all used branches (also in children)
void getUsedBranches(std::list<docstring> &, bool const from_master = false) const;
// We need a unique label
docstring label = text;
int i = 1;
- while (cur.buffer()->insetLabel(label)) {
+ while (cur.buffer()->activeLabel(label)) {
label = text + '-' + convert<docstring>(i);
++i;
}
{
docstring const new_label = label;
int i = 1;
- while (buffer().insetLabel(label)) {
+ bool ambiguous = false;
+ while (buffer().activeLabel(label)) {
label = new_label + '-' + convert<docstring>(i);
++i;
+ ambiguous = true;
}
- if (label != new_label) {
+ if (ambiguous) {
// Warn the user that the label has been changed to something else.
frontend::Alert::warning(_("Label names must be unique!"),
bformat(_("The label %1$s already exists,\n"
void InsetLabel::updateBuffer(ParIterator const & par, UpdateType utype)
{
docstring const & label = getParam("name");
- if (buffer().insetLabel(label)) {
- // Problem: We already have an InsetLabel with the same name!
+
+ // Check if this one is deleted (ct)
+ Paragraph const & para = par.paragraph();
+ bool const active = !para.isDeleted(par.pos());
+
+ if (buffer().activeLabel(label) && active) {
+ // Problem: We already have an active InsetLabel with the same name!
screen_label_ = _("DUPLICATE: ") + label;
return;
}
- buffer().setInsetLabel(label, this);
+ buffer().setInsetLabel(label, this, active);
screen_label_ = label;
if (utype == OutputUpdate) {
UpdateType, TocBackend & backend) const
{
docstring const & label = getParam("name");
+ if (!buffer().activeLabel(label))
+ return;
+
shared_ptr<Toc> toc = backend.toc("label");
- if (buffer().insetLabel(label) != this) {
+ if (buffer().insetLabel(label, true) != this) {
toc->push_back(TocItem(cpit, 0, screen_label_, output_active));
} else {
toc->push_back(TocItem(cpit, 0, screen_label_, output_active));
docstring InsetRef::xhtml(XHTMLStream & xs, OutputParams const & op) const
{
docstring const & ref = getParam("reference");
- InsetLabel const * il = buffer().insetLabel(ref);
+ InsetLabel const * il = buffer().insetLabel(ref, true);
string const & cmd = params().getCmdName();
docstring display_string;
UpdateType, TocBackend & backend) const
{
docstring const & label = getParam("reference");
- if (buffer().insetLabel(label))
+ if (buffer().activeLabel(label))
// This InsetRef has already been taken care of in InsetLabel::addToToc().
return;