Uwe Stöhr wrote:
> Yes. Could you please report this at bugzilla.lyx.org?
There's already a report for this:
http://bugzilla.lyx.org/show_bug.cgi?id=1684
And even more: I have a fix for this in my 1.4 tree for months, but somehow it
got forgotten (see attached).
Jürgen
Index: src/insets/insetlabel.C
===================================================================
--- src/insets/insetlabel.C (Revision 18698)
+++ src/insets/insetlabel.C (Arbeitskopie)
@@ -69,9 +69,14 @@
cur.noUpdate();
break;
}
- if (p.getContents() != params().getContents())
+ if (p.getContents() != params().getContents()) {
+ string newlabel = cur.bv().buffer()->validateLabel(
+ p.getContents(), InsetBase::LABEL_CODE);
+ if (p.getContents() != newlabel)
+ p.setContents(newlabel);
cur.bv().buffer()->changeRefsIfUnique(params().getContents(),
p.getContents(), InsetBase::REF_CODE);
+ }
setParams(p);
break;
}
Index: src/insets/insetbibitem.C
===================================================================
--- src/insets/insetbibitem.C (Revision 18698)
+++ src/insets/insetbibitem.C (Arbeitskopie)
@@ -65,9 +65,14 @@
cur.noUpdate();
break;
}
- if (p.getContents() != params().getContents())
+ if (p.getContents() != params().getContents()) {
+ string newlabel = cur.bv().buffer()->validateLabel(
+ p.getContents(), InsetBase::BIBITEM_CODE);
+ if (p.getContents() != newlabel)
+ p.setContents(newlabel);
cur.bv().buffer()->changeRefsIfUnique(params().getContents(),
p.getContents(), InsetBase::CITE_CODE);
+ }
setParams(p);
break;
}
Index: src/mathed/math_hullinset.C
===================================================================
--- src/mathed/math_hullinset.C (Revision 18698)
+++ src/mathed/math_hullinset.C (Arbeitskopie)
@@ -1079,6 +1079,7 @@
if (!str.empty())
numbered(r, true);
string old = label(r);
+ str = cur.bv().buffer()->validateLabel(str, InsetBase::LABEL_CODE);
if (str != old) {
cur.bv().buffer()->changeRefsIfUnique(old, str, InsetBase::REF_CODE);
label(r, str);
Index: src/factory.C
===================================================================
--- src/factory.C (Revision 18698)
+++ src/factory.C (Arbeitskopie)
@@ -208,6 +208,11 @@
InsetCommandParams icp;
InsetCommandMailer::string2params(name, cmd.argument,
icp);
+ // check for duplicate labels
+ string newlabel = bv->buffer()->validateLabel(
+ icp.getContents(), InsetBase::BIBITEM_CODE);
+ if (icp.getContents() != newlabel)
+ icp.setContents(newlabel);
return new InsetBibitem(icp);
} else if (name == "bibtex") {
@@ -260,6 +265,11 @@
InsetCommandParams icp;
InsetCommandMailer::string2params(name, cmd.argument,
icp);
+ // check for duplicate labels
+ string newlabel = bv->buffer()->validateLabel(
+ icp.getContents(), InsetBase::LABEL_CODE);
+ if (icp.getContents() != newlabel)
+ icp.setContents(newlabel);
return new InsetLabel(icp);
} else if (name == "ref") {
Index: src/buffer.C
===================================================================
--- src/buffer.C (Revision 18698)
+++ src/buffer.C (Arbeitskopie)
@@ -122,6 +122,7 @@
namespace fs = boost::filesystem;
using std::endl;
+using std::find;
using std::for_each;
using std::make_pair;
@@ -1616,23 +1617,54 @@
}
-void Buffer::changeRefsIfUnique(string const & from, string const & to, InsetBase::Code code)
+vector<string> const Buffer::getLabelsOrCitations(InsetBase::Code code) const
{
- BOOST_ASSERT(code == InsetBase::CITE_CODE || code == InsetBase::REF_CODE);
- // Check if the label 'from' appears more than once
vector<string> labels;
- if (code == InsetBase::CITE_CODE) {
+ if (code == InsetBase::BIBITEM_CODE || code == InsetBase::CITE_CODE) {
vector<pair<string, string> > keys;
fillWithBibKeys(keys);
vector<pair<string, string> >::const_iterator bit = keys.begin();
vector<pair<string, string> >::const_iterator bend = keys.end();
-
for (; bit != bend; ++bit)
labels.push_back(bit->first);
} else
getLabelList(labels);
+ return labels;
+}
+
+
+string const Buffer::validateLabel(string const & label, InsetBase::Code code) const
+{
+ BOOST_ASSERT(code == InsetBase::BIBITEM_CODE || code == InsetBase::LABEL_CODE);
+
+ vector<string> labels = getLabelsOrCitations(code);
+
+ if (find(labels.begin(), labels.end(), label) != labels.end()) {
+ // generate unique label
+ int i = 1;
+ string newlabel = label + "-" + convert<string>(i);
+ while (find(labels.begin(), labels.end(), newlabel) != labels.end()) {
+ ++i;
+ newlabel = label + "-" + convert<string>(i);
+ }
+ Alert::warning(_("Label names must be unique"),
+ bformat(_("The label %1$s already exists.\n"
+ "The name has been changed to %2$s."),
+ label, newlabel));
+ return newlabel;
+ }
+ return label;
+}
+
+
+void Buffer::changeRefsIfUnique(string const & from, string const & to, InsetBase::Code code)
+{
+ BOOST_ASSERT(code == InsetBase::CITE_CODE || code == InsetBase::REF_CODE);
+
+ // Check if the label 'from' appears more than once
+ vector<string> labels = getLabelsOrCitations(code);
if (lyx::count(labels.begin(), labels.end(), from) > 1)
return;
Index: src/CutAndPaste.C
===================================================================
--- src/CutAndPaste.C (Revision 18698)
+++ src/CutAndPaste.C (Arbeitskopie)
@@ -37,6 +37,7 @@
#include "undo.h"
#include "insets/insetcharstyle.h"
+#include "insets/insetcommand.h"
#include "insets/insettabular.h"
#include "mathed/math_data.h"
@@ -45,6 +46,7 @@
#include "support/lstrings.h"
+#include <algorithm>
#include <boost/tuple/tuple.hpp>
using lyx::pos_type;
@@ -52,11 +54,15 @@
using lyx::textclass_type;
using lyx::support::bformat;
+using lyx::support::getStringFromVector;
+using lyx::support::getVectorFromString;
+using lyx::support::tokenPos;
using std::endl;
using std::for_each;
using std::make_pair;
using std::pair;
+using std::replace;
using std::vector;
using std::string;
@@ -223,25 +229,59 @@
// A couple of insets store buffer references so need updating.
insertion.swap(in.paragraphs());
- ParIterator fpit = par_iterator_begin(in);
- ParIterator fend = par_iterator_end(in);
+ InsetIterator const i_end = inset_iterator_end(in);
- for (; fpit != fend; ++fpit) {
- InsetList::iterator lit = fpit->insetlist.begin();
- InsetList::iterator eit = fpit->insetlist.end();
+ for (InsetIterator it = inset_iterator_begin(in); it != i_end; ++it) {
- for (; lit != eit; ++lit) {
- switch (lit->inset->lyxCode()) {
- case InsetBase::TABULAR_CODE: {
- InsetTabular * it = static_cast<InsetTabular*>(lit->inset);
- it->buffer(&buffer);
- break;
- }
+ switch (it->lyxCode()) {
- default:
- break; // nothing
+ case InsetBase::TABULAR_CODE: {
+ InsetTabular & tabular = static_cast<InsetTabular &>(*it);
+ tabular.buffer(&buffer);
+ break;
+ }
+ case InsetBase::LABEL_CODE: {
+ // check for duplicates
+ InsetCommand & lab = static_cast<InsetCommand &>(*it);
+ string const oldcontent = lab.getContents();
+ string const newcontent = cur.bv().buffer()->validateLabel(
+ oldcontent, InsetBase::LABEL_CODE);
+ if (newcontent != oldcontent) {
+ // replace with unique label
+ lab.replaceContents(oldcontent, newcontent);
+ // adapt the references
+ for (InsetIterator itt = inset_iterator_begin(in); itt != i_end; ++itt) {
+ if (itt->lyxCode() == InsetBase::REF_CODE) {
+ InsetCommand & ref = dynamic_cast<InsetCommand &>(*itt);
+ ref.replaceContents(oldcontent, newcontent);
+ }
+ }
}
+ break;
}
+ case InsetBase::BIBITEM_CODE: {
+ // check for duplicates
+ InsetCommand & bib = static_cast<InsetCommand &>(*it);
+ string const oldcontent = bib.getContents();
+ string const newcontent = cur.bv().buffer()->validateLabel(
+ oldcontent, InsetBase::BIBITEM_CODE);
+ if (newcontent != oldcontent) {
+ // replace with unique label
+ bib.replaceContents(oldcontent, newcontent);
+ // adapt the references
+ for (InsetIterator itt = inset_iterator_begin(in); itt != i_end; ++itt) {
+ if (itt->lyxCode() == InsetBase::CITE_CODE) {
+ InsetCommand & cite = dynamic_cast<InsetCommand &>(*itt);
+ cite.replaceContents(oldcontent, newcontent);
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ break; // nothing
+ }
}
insertion.swap(in.paragraphs());
Index: src/buffer.h
===================================================================
--- src/buffer.h (Revision 18698)
+++ src/buffer.h (Arbeitskopie)
@@ -342,6 +342,9 @@
StableDocIterator getCursor() const { return cursor_; }
///
StableDocIterator getAnchor() const { return anchor_; }
+ /// check if \param label ist valid (unique) and return
+ /// a valid one, if not.
+ std::string const validateLabel(std::string const & label, InsetBase::Code code) const;
///
void changeRefsIfUnique(std::string const & from, std::string const & to, InsetBase::Code code);
@@ -353,6 +356,9 @@
bool do_writeFile(std::ostream & ofs) const;
+ /// A helper function for validate Label and ChangeRefsIfUnique
+ std::vector<std::string> const getLabelsOrCitations(InsetBase::Code code) const;
+
/// Use the Pimpl idiom to hide the internals.
class Impl;
/// The pointer never changes although *pimpl_'s contents may.