X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBiblioInfo.cpp;h=243f78c59f6595fb7d24ac0cede957e04e2db87c;hb=63e2ac459745c1f5a650edf1b59fa7f9ff7f680c;hp=c85eabd5e75ee5ddc605d41a65655d8222d3b38f;hpb=ba171930670696153b7fcce8e2ba648a294d8425;p=lyx.git diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp index c85eabd5e7..243f78c59f 100644 --- a/src/BiblioInfo.cpp +++ b/src/BiblioInfo.cpp @@ -326,7 +326,7 @@ docstring const BibTeXInfo::getYear() const // Format is [-]YYYY-MM-DD*/[-]YYYY-MM-DD* // We only want the years. static regex const yreg("[-]?([\\d]{4}).*"); - static regex const ereg(".*/([\\d]{4}).*"); + static regex const ereg(".*/[-]?([\\d]{4}).*"); smatch sm; string const date = to_utf8(year); regex_match(date, sm, yreg); @@ -352,14 +352,6 @@ docstring const BibTeXInfo::getYear() const } -docstring const BibTeXInfo::getXRef() const -{ - if (!is_bibtex_) - return docstring(); - return operator[]("crossref"); -} - - namespace { docstring parseOptions(docstring const & format, string & optkey, @@ -485,7 +477,7 @@ I can tell, but it still feels like a hack. Fixing this would require quite a bit of work, however. */ docstring BibTeXInfo::expandFormat(docstring const & format, - BibTeXInfo const * const xref, int & counter, Buffer const & buf, + BibTeXInfoList const xrefs, int & counter, Buffer const & buf, docstring before, docstring after, docstring dialog, bool next) const { // incorrect use of macros could put us in an infinite loop @@ -534,7 +526,7 @@ docstring BibTeXInfo::expandFormat(docstring const & format, ret << trans; } else { docstring const val = - getValueForKey(key, buf, before, after, dialog, xref, max_keysize); + getValueForKey(key, buf, before, after, dialog, xrefs, max_keysize); if (!scanning_rich) ret << from_ascii("{!!}"); ret << val; @@ -565,16 +557,16 @@ docstring BibTeXInfo::expandFormat(docstring const & format, return _("ERROR!"); fmt = newfmt; docstring const val = - getValueForKey(optkey, buf, before, after, dialog, xref); + getValueForKey(optkey, buf, before, after, dialog, xrefs); if (optkey == "next" && next) ret << ifpart; // without expansion else if (!val.empty()) { int newcounter = 0; - ret << expandFormat(ifpart, xref, newcounter, buf, + ret << expandFormat(ifpart, xrefs, newcounter, buf, before, after, dialog, next); } else if (!elsepart.empty()) { int newcounter = 0; - ret << expandFormat(elsepart, xref, newcounter, buf, + ret << expandFormat(elsepart, xrefs, newcounter, buf, before, after, dialog, next); } // fmt will have been shortened for us already @@ -623,7 +615,7 @@ docstring BibTeXInfo::expandFormat(docstring const & format, } -docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref, +docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs, Buffer const & buf, bool richtext) const { if (!richtext && !info_.empty()) @@ -642,7 +634,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref, docstring const & format = from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_))); int counter = 0; - info_ = expandFormat(format, xref, counter, buf, + info_ = expandFormat(format, xrefs, counter, buf, docstring(), docstring(), docstring(), false); if (info_.empty()) { @@ -660,7 +652,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref, } -docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref, +docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs, Buffer const & buf, docstring const & format, bool richtext, docstring const & before, docstring const & after, docstring const & dialog, bool next) const @@ -668,7 +660,7 @@ docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref, docstring loclabel; int counter = 0; - loclabel = expandFormat(format, xref, counter, buf, + loclabel = expandFormat(format, xrefs, counter, buf, before, after, dialog, next); if (!loclabel.empty() && !next) { @@ -698,7 +690,7 @@ docstring const & BibTeXInfo::operator[](string const & field) const docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, docstring const & before, docstring const & after, docstring const & dialog, - BibTeXInfo const * const xref, size_t maxsize) const + BibTeXInfoList const xrefs, size_t maxsize) const { // anything less is pointless LASSERT(maxsize >= 16, maxsize = 16); @@ -710,8 +702,16 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, } docstring ret = operator[](key); - if (ret.empty() && xref) - ret = (*xref)[key]; + if (ret.empty() && !xrefs.empty()) { + vector::const_iterator it = xrefs.begin(); + vector::const_iterator en = xrefs.end(); + for (; it != en; ++it) { + if (*it && !(**it)[key].empty()) { + ret = (**it)[key]; + break; + } + } + } if (ret.empty()) { // some special keys // FIXME: dialog, textbefore and textafter have nothing to do with this @@ -751,7 +751,7 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, docstring const & format = from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_))); int counter = 0; - ret = expandFormat(format, xref, counter, buf, + ret = expandFormat(format, xrefs, counter, buf, docstring(), docstring(), docstring(), false); } else if (key == "textbefore") ret = before; @@ -790,6 +790,46 @@ public: } // namespace anon +vector const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const +{ + vector result; + if (!data.isBibTeX()) + return result; + // Legacy crossref field. This is not nestable. + if (!nested && !data["crossref"].empty()) { + docstring const xrefkey = data["crossref"]; + result.push_back(xrefkey); + // However, check for nested xdatas + BiblioInfo::const_iterator it = find(xrefkey); + if (it != end()) { + BibTeXInfo const & xref = it->second; + vector const nxdata = getXRefs(xref, true); + if (!nxdata.empty()) + result.insert(result.end(), nxdata.begin(), nxdata.end()); + } + } + // Biblatex's xdata field. Infinitely nestable. + // XData field can consist of a comma-separated list of keys + vector const xdatakeys = getVectorFromString(data["xdata"]); + if (!xdatakeys.empty()) { + vector::const_iterator xit = xdatakeys.begin(); + vector::const_iterator xen = xdatakeys.end(); + for (; xit != xen; ++xit) { + docstring const xdatakey = *xit; + result.push_back(xdatakey); + BiblioInfo::const_iterator it = find(xdatakey); + if (it != end()) { + BibTeXInfo const & xdata = it->second; + vector const nxdata = getXRefs(xdata, true); + if (!nxdata.empty()) + result.insert(result.end(), nxdata.begin(), nxdata.end()); + } + } + } + return result; +} + + vector const BiblioInfo::getKeys() const { vector bibkeys; @@ -853,17 +893,23 @@ docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) co BibTeXInfo const & data = it->second; docstring year = data.getYear(); if (year.empty()) { - // let's try the crossref - docstring const xref = data.getXRef(); - if (xref.empty()) + // let's try the crossrefs + vector const xrefs = getXRefs(data); + if (xrefs.empty()) // no luck return docstring(); - BiblioInfo::const_iterator const xrefit = find(xref); - if (xrefit == end()) - // no luck again - return docstring(); - BibTeXInfo const & xref_data = xrefit->second; - year = xref_data.getYear(); + vector::const_iterator it = xrefs.begin(); + vector::const_iterator en = xrefs.end(); + for (; it != en; ++it) { + BiblioInfo::const_iterator const xrefit = find(*it); + if (xrefit == end()) + continue; + BibTeXInfo const & xref_data = xrefit->second; + year = xref_data.getYear(); + if (!year.empty()) + // success! + break; + } } if (use_modifier && data.modifier() != 0) year += data.modifier(); @@ -887,14 +933,18 @@ docstring const BiblioInfo::getInfo(docstring const & key, if (it == end()) return docstring(_("Bibliography entry not found!")); BibTeXInfo const & data = it->second; - BibTeXInfo const * xrefptr = 0; - docstring const xref = data.getXRef(); - if (!xref.empty()) { - BiblioInfo::const_iterator const xrefit = find(xref); - if (xrefit != end()) - xrefptr = &(xrefit->second); + BibTeXInfoList xrefptrs; + vector const xrefs = getXRefs(data); + if (!xrefs.empty()) { + vector::const_iterator it = xrefs.begin(); + vector::const_iterator en = xrefs.end(); + for (; it != en; ++it) { + BiblioInfo::const_iterator const xrefit = find(*it); + if (xrefit != end()) + xrefptrs.push_back(&(xrefit->second)); + } } - return data.getInfo(xrefptr, buf, richtext); + return data.getInfo(xrefptrs, buf, richtext); } @@ -922,17 +972,21 @@ docstring const BiblioInfo::getLabel(vector keys, BibTeXInfo empty_data; empty_data.key(*key); BibTeXInfo & data = empty_data; - BibTeXInfo const * xrefptr = 0; + vector xrefptrs; if (it != end()) { data = it->second; - docstring const xref = data.getXRef(); - if (!xref.empty()) { - BiblioInfo::const_iterator const xrefit = find(xref); - if (xrefit != end()) - xrefptr = &(xrefit->second); + vector const xrefs = getXRefs(data); + if (!xrefs.empty()) { + vector::const_iterator it = xrefs.begin(); + vector::const_iterator en = xrefs.end(); + for (; it != en; ++it) { + BiblioInfo::const_iterator const xrefit = find(*it); + if (xrefit != end()) + xrefptrs.push_back(&(xrefit->second)); + } } } - ret = data.getLabel(xrefptr, buf, ret, for_xhtml, + ret = data.getLabel(xrefptrs, buf, ret, for_xhtml, before, after, dialog, key + 1 != ken); }