]> git.lyx.org Git - features.git/commitdiff
Do not consider deleted labels in ambiguity check
authorJuergen Spitzmueller <spitz@lyx.org>
Wed, 9 Jan 2019 08:06:53 +0000 (09:06 +0100)
committerJuergen Spitzmueller <spitz@lyx.org>
Wed, 9 Jan 2019 08:06:53 +0000 (09:06 +0100)
This adds a new (boolean) parameter "active" to the label cache, where
we track whether a label is deleted in ct mode (the same could be done,
if wanted, for labels in notes and inactive branches).

Deleted (inactive) labels are neither considered in the uniqueness check
nor added to the outliner. This also means that undeleted references to
deleted labels are now (correctly) marked as BROKEN.

Cherry-picked from:

    [3ae6bff538/lyxgit]
    [a550a613e8/lyxgit]
    [c457ea90e/lyxgit]
    [5cfd25697/lyxgit]
    [5afacb144/lyxgit]
    [54366c38e/lyxgit]

Fixes: #6563
src/Buffer.cpp
src/Buffer.h
src/BufferView.cpp
src/Text.cpp
src/insets/InsetLabel.cpp
src/insets/InsetRef.cpp
status.23x

index 708244e96958d5084e0d4aad20824204c1698a31..460fc910db116c74bda6aae2ca1a219a6994e50f 100644 (file)
@@ -135,7 +135,22 @@ namespace {
 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> LabelCache;
+
+typedef map<docstring, Buffer::References> RefCache;
 
 } // namespace
 
@@ -309,7 +324,11 @@ public:
        /// was missing).
        bool preview_error_;
 
+       /// Cache the references associated to a label and their positions
+       /// in the buffer.
        mutable RefCache ref_cache_;
+       /// Cache the label insets and their activity status.
+       mutable LabelCache label_cache_;
 
        /// our Text that should be wrapped in an InsetText
        InsetText * inset;
@@ -3915,13 +3934,12 @@ Buffer::References & Buffer::getReferenceCache(docstring const & label)
 
        RefCache::iterator it = d->ref_cache_.find(label);
        if (it != d->ref_cache_.end())
-               return it->second.second;
+               return it->second;
 
-       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;
+               make_pair(label, dummy_refs)).first;
+       return it->second;
 }
 
 
@@ -3938,22 +3956,43 @@ void Buffer::addReference(docstring const & label, Inset * inset, ParIterator it
 }
 
 
-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;
+       LabelInfo linfo;
+       linfo.label = label;
+       linfo.inset = il;
+       linfo.active = active;
+       masterBuffer()->d->label_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->label_cache_) {
+               if (rc.label == label && (rc.active || !active))
+                       return rc.inset;
+       }
+       return nullptr;
+}
+
+
+bool Buffer::activeLabel(docstring const & label) const
+{
+       if (!insetLabel(label, true))
+               return false;
+
+       return true;
 }
 
 
 void Buffer::clearReferenceCache() const
 {
-       if (!d->parent())
+       if (!d->parent()) {
                d->ref_cache_.clear();
+               d->label_cache_.clear();
+       }
 }
 
 
index f30b1a3fca61882669035ee88d5b9a8452659403..c81ba46f0dc920ae9180f28ae9fca350f6226b8c 100644 (file)
@@ -707,18 +707,28 @@ public:
        ///
        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
+       /// (see @ref activeLabel)
+       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;
index 6b3a528f483a164fdeaea66e2e3594421a37c189..68d2c83f00bfecc543ea14d8d56f889ca7eecef6 100644 (file)
@@ -2507,6 +2507,8 @@ bool BufferView::setCursorFromInset(Inset const * inset)
 
 void BufferView::gotoLabel(docstring const & label)
 {
+       FuncRequest action;
+       bool have_inactive = false;
        ListOfBuffers bufs = buffer().allRelatives();
        ListOfBuffers::iterator it = bufs.begin();
        for (; it != bufs.end(); ++it) {
@@ -2517,12 +2519,21 @@ void BufferView::gotoLabel(docstring const & label)
                Toc::const_iterator toc_it = toc->begin();
                Toc::const_iterator end = toc->end();
                for (; toc_it != end; ++toc_it) {
-                       if (label == toc_it->str()) {
+                       if (label == toc_it->str() && toc_it->isOutput()) {
                                lyx::dispatch(toc_it->action());
                                return;
                        }
+                       // If we find an inactive label, save it for the case
+                       // that no active one is there
+                       if (label == toc_it->str() && !have_inactive) {
+                               have_inactive = true;
+                               action = toc_it->action();
+                       }
                }
        }
+       // We only found an inactive label. Go there.
+       if (have_inactive)
+               lyx::dispatch(action);
 }
 
 
index bdff46efec99d179821e66a38f16cfd98e990673..2d916c834b3c08265e0d3938866e2d0201eeda33 100644 (file)
@@ -2041,7 +2041,7 @@ docstring Text::getPossibleLabel(Cursor const & cur) 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;
                }
index 7f3651f3a382e9fae870ef94a6d58ff9b97e0698..4a1cc453ff8eb120608144161c62b1ae56a3171a 100644 (file)
@@ -67,11 +67,13 @@ void InsetLabel::uniqueLabel(docstring & label) const
 {
        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"
@@ -146,12 +148,27 @@ docstring InsetLabel::screenLabel() const
 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 active = !para.isDeleted(par.pos());
+       // If not, check whether we are in a deleted inset
+       if (active) {
+               for (size_type sl = 0 ; sl < par.depth() ; ++sl) {
+                       Paragraph const & outer_par = par[sl].paragraph();
+                       if (outer_par.isDeleted(par[sl].pos())) {
+                               active = false;
+                               break;
+                       }
+               }
+       }
+
+       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) {
@@ -175,23 +192,25 @@ void InsetLabel::addToToc(DocIterator const & cpit, bool output_active,
                                                  UpdateType, TocBackend & backend) const
 {
        docstring const & label = getParam("name");
+       // inactive labels get a cross mark
+       if (buffer().insetLabel(label, true) != this)
+               output_active = false;
+
+       // We put both  active and inactive labels to the outliner
        shared_ptr<Toc> toc = backend.toc("label");
-       if (buffer().insetLabel(label) != this) {
-               toc->push_back(TocItem(cpit, 0, screen_label_, output_active));
-       } else {
-               toc->push_back(TocItem(cpit, 0, screen_label_, output_active));
-               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) {
-                       DocIterator const ref_pit(it->second);
-                       if (it->first->lyxCode() == MATH_REF_CODE)
+       toc->push_back(TocItem(cpit, 0, screen_label_, output_active));
+       // The refs get assigned only to the active label. If no active one exists,
+       // assign the (BROKEN) refs to the first inactive one.
+       if (buffer().insetLabel(label, true) == this || !buffer().activeLabel(label)) {
+               for (auto const & p : buffer().references(label)) {
+                       DocIterator const ref_pit(p.second);
+                       if (p.first->lyxCode() == MATH_REF_CODE)
                                toc->push_back(TocItem(ref_pit, 1,
-                                               it->first->asInsetMath()->asRefInset()->screenLabel(),
+                                               p.first->asInsetMath()->asRefInset()->screenLabel(),
                                                output_active));
                        else
                                toc->push_back(TocItem(ref_pit, 1,
-                                               static_cast<InsetRef *>(it->first)->getTOCString(),
+                                               static_cast<InsetRef *>(p.first)->getTOCString(),
                                                output_active));
                }
        }
index 92ad754e50bec5981dab101995ae809b7b9364d0..eef6a9751b8aeacf289717898e33a58c9c5dc13c 100644 (file)
@@ -303,7 +303,7 @@ int InsetRef::docbook(odocstream & os, OutputParams const & runparams) const
 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;
 
@@ -423,12 +423,14 @@ void InsetRef::addToToc(DocIterator const & cpit, bool output_active,
                                                UpdateType, TocBackend & backend) const
 {
        docstring const & label = getParam("reference");
-       if (buffer().insetLabel(label))
+       if (buffer().insetLabel(label)) {
+               broken_ = !buffer().activeLabel(label);
                // This InsetRef has already been taken care of in InsetLabel::addToToc().
                return;
-
+       }
+    
        // It seems that this reference does not point to any valid label.
-
+    
        broken_ = true;
        shared_ptr<Toc> toc = backend.toc("label");
        toc->push_back(TocItem(cpit, 0, screenLabel(), output_active));
index 68c3a511517a7e7bde66d3cc46669d26439ac15c..d62a9607b62952bf1ee7fcb058c3688698a0d7d0 100644 (file)
@@ -134,6 +134,8 @@ What's new
 
 - Fix display of gather environment in leqno mode (bug 11324).
 
+- Fix handling of labels with change tracking (bug 6563).
+
 
 
 * INTERNALS