X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBiblioInfo.cpp;h=7005519ac3f8978a535e8f4c258a2b7402b71e06;hb=45e8ea4acc557dd54e062750f47ff569b5b98c43;hp=e7ca878a2bd51eaabbe3c3b0dd5b6e7eb5c2db79;hpb=c2f5c850d9c2a74a06dfec64fa57511950d6f64d;p=lyx.git diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp index e7ca878a2b..7005519ac3 100644 --- a/src/BiblioInfo.cpp +++ b/src/BiblioInfo.cpp @@ -22,7 +22,7 @@ #include "Encoding.h" #include "InsetIterator.h" #include "Language.h" -#include "output_xhtml.h" +#include "xml.h" #include "Paragraph.h" #include "TextClass.h" #include "TocBackend.h" @@ -488,8 +488,8 @@ docstring processRichtext(docstring const & str, bool richtext) ////////////////////////////////////////////////////////////////////// BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type) - : is_bibtex_(true), bib_key_(key), num_bib_key_(0), entry_type_(type), info_(), - modifier_(0) + : is_bibtex_(true), bib_key_(key), num_bib_key_(0), entry_type_(type), + info_(), format_(), modifier_(0) {} @@ -651,6 +651,75 @@ docstring const BibTeXInfo::getYear() const } +void BibTeXInfo::getLocators(docstring & doi, docstring & url, docstring & file) const +{ + if (is_bibtex_) { + // get "doi" entry from citation record + doi = operator[]("doi"); + if (!doi.empty() && !prefixIs(doi,from_ascii("http"))) + doi = "https://doi.org/" + doi; + // get "url" entry from citation record + url = operator[]("url"); + // get "file" entry from citation record + file = operator[]("file"); + + // Jabref case, field has a format: + // Description:Location:Filetype;Description:Location:Filetype... + // We will grab only first pdf + if (!file.empty()) { + docstring ret, filedest, tmp; + ret = split(file, tmp, ':'); + tmp = split(ret, filedest, ':'); + //TODO howto deal with relative directories? + FileName f(to_utf8(filedest)); + if (f.exists()) + file = "file:///" + filedest; + } + + // kbibtex case, format: + // file1.pdf;file2.pdf + // We will grab only first pdf + docstring kfile; + if (file.empty()) + kfile = operator[]("localfile"); + if (!kfile.empty()) { + docstring filedest, tmp; + tmp = split(kfile, filedest, ';'); + //TODO howto deal with relative directories? + FileName f(to_utf8(filedest)); + if (f.exists()) + file = "file:///" + filedest; + } + + if (!url.empty()) + return; + + // try biblatex specific fields, see its manual + // 3.13.7 "Electronic Publishing Informationl" + docstring eprinttype = operator[]("eprinttype"); + docstring eprint = operator[]("eprint"); + if (eprint.empty()) + return; + + if (eprinttype == "arxiv") + url = "https://arxiv.org/abs/" + eprint; + if (eprinttype == "jstor") + url = "https://www.jstor.org/stable/" + eprint; + if (eprinttype == "pubmed") + url = "http://www.ncbi.nlm.nih.gov/pubmed/" + eprint; + if (eprinttype == "hdl") + url = "https://hdl.handle.net/" + eprint; + if (eprinttype == "googlebooks") + url = "http://books.google.com/books?id=" + eprint; + + return; + } + + // Here can be handled the bibliography environment. All one could do + // here is let LyX scan the entry for URL or HRef insets. +} + + namespace { docstring parseOptions(docstring const & format, string & optkey, @@ -927,12 +996,27 @@ docstring BibTeXInfo::expandFormat(docstring const & format, docstring const & BibTeXInfo::getInfo(BibTeXInfoList const & xrefs, - Buffer const & buf, CiteItem const & ci) const + Buffer const & buf, CiteItem const & ci, docstring const & format_in) const { bool const richtext = ci.richtext; - if (!richtext && !info_.empty()) + CiteEngineType const engine_type = buf.params().citeEngineType(); + DocumentClass const & dc = buf.params().documentClass(); + docstring const & format = format_in.empty()? + from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_))) + : format_in; + + if (format != format_) { + // clear caches since format changed + info_.clear(); + info_richtext_.clear(); + format_ = format; + } + + if (!richtext && !info_.empty()) { + info_ = convertLaTeXCommands(processRichtext(info_, false)); return info_; + } if (richtext && !info_richtext_.empty()) return info_richtext_; @@ -942,10 +1026,6 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfoList const & xrefs, return info_; } - CiteEngineType const engine_type = buf.params().citeEngineType(); - DocumentClass const & dc = buf.params().documentClass(); - docstring const & format = - from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_))); int counter = 0; info_ = expandFormat(format, xrefs, counter, buf, ci, false, false); @@ -1013,11 +1093,10 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, docstring ret = operator[](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]; + // xr is a (reference to a) BibTeXInfo const * + for (auto const & xr : xrefs) { + if (xr && !(*xr)[key].empty()) { + ret = (*xr)[key]; break; } } @@ -1160,7 +1239,7 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, } if (cleanit) - ret = html::cleanAttr(ret); + ret = xml::cleanAttr(ret); // make sure it is not too big support::truncateWithEllipsis(ret, maxsize); @@ -1177,13 +1256,9 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, namespace { // A functor for use with sort, leading to case insensitive sorting -class compareNoCase: public binary_function -{ -public: - bool operator()(docstring const & s1, docstring const & s2) const { - return compare_no_case(s1, s2) < 0; - } -}; +bool compareNoCase(const docstring & a, const docstring & b) { + return compare_no_case(a, b) < 0; +} } // namespace @@ -1210,10 +1285,7 @@ vector const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const // 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; + for (auto const & xdatakey : xdatakeys) { result.push_back(xdatakey); BiblioInfo::const_iterator it = find(xdatakey); if (it != end()) { @@ -1231,10 +1303,9 @@ vector const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const vector const BiblioInfo::getKeys() const { vector bibkeys; - BiblioInfo::const_iterator it = begin(); - for (; it != end(); ++it) - bibkeys.push_back(it->first); - sort(bibkeys.begin(), bibkeys.end(), compareNoCase()); + for (auto const & bi : *this) + bibkeys.push_back(bi.first); + sort(bibkeys.begin(), bibkeys.end(), &compareNoCase); return bibkeys; } @@ -1242,10 +1313,8 @@ vector const BiblioInfo::getKeys() const vector const BiblioInfo::getFields() const { vector bibfields; - set::const_iterator it = field_names_.begin(); - set::const_iterator end = field_names_.end(); - for (; it != end; ++it) - bibfields.push_back(*it); + for (auto const & fn : field_names_) + bibfields.push_back(fn); sort(bibfields.begin(), bibfields.end()); return bibfields; } @@ -1254,10 +1323,8 @@ vector const BiblioInfo::getFields() const vector const BiblioInfo::getEntries() const { vector bibentries; - set::const_iterator it = entry_types_.begin(); - set::const_iterator end = entry_types_.end(); - for (; it != end; ++it) - bibentries.push_back(*it); + for (auto const & et : entry_types_) + bibentries.push_back(et); sort(bibentries.begin(), bibentries.end()); return bibentries; } @@ -1282,6 +1349,15 @@ docstring const BiblioInfo::getCiteNumber(docstring const & key) const return data.citeNumber(); } +void BiblioInfo::getLocators(docstring const & key, docstring & doi, docstring & url, docstring & file) const +{ + BiblioInfo::const_iterator it = find(key); + if (it == end()) + return; + BibTeXInfo const & data = it->second; + data.getLocators(doi,url,file); +} + docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const { @@ -1323,20 +1399,19 @@ docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, b docstring const BiblioInfo::getInfo(docstring const & key, - Buffer const & buf, CiteItem const & ci) const + Buffer const & buf, CiteItem const & ci, docstring const & format) const { BiblioInfo::const_iterator it = find(key); if (it == end()) return docstring(_("Bibliography entry not found!")); BibTeXInfo const & data = it->second; BibTeXInfoList xrefptrs; - vector const xrefs = getXRefs(data); for (docstring const & xref : getXRefs(data)) { BiblioInfo::const_iterator const xrefit = find(xref); if (xrefit != end()) xrefptrs.push_back(&(xrefit->second)); } - return data.getInfo(xrefptrs, buf, ci); + return data.getInfo(xrefptrs, buf, ci, format); } @@ -1368,7 +1443,7 @@ docstring const BiblioInfo::getLabel(vector keys, for (int i = 0; key != ken; ++key, ++i) { handled_keys.push_back(*key); int n = 0; - for (auto const k : handled_keys) { + for (auto const & k : handled_keys) { if (k == *key) ++n; } @@ -1459,13 +1534,11 @@ void BiblioInfo::collectCitedEntries(Buffer const & buf) // FIXME We may want to collect these differently, in the first case, // so that we might have them in order of appearance. set citekeys; - shared_ptr toc = buf.tocBackend().toc("citation"); - Toc::const_iterator it = toc->begin(); - Toc::const_iterator const en = toc->end(); - for (; it != en; ++it) { - if (it->str().empty()) + Toc const & toc = *buf.tocBackend().toc("citation"); + for (auto const & t : toc) { + if (t.str().empty()) continue; - vector const keys = getVectorFromString(it->str()); + vector const keys = getVectorFromString(t.str()); citekeys.insert(keys.begin(), keys.end()); } if (citekeys.empty()) @@ -1475,10 +1548,8 @@ void BiblioInfo::collectCitedEntries(Buffer const & buf) // We will now convert it to a list of the BibTeXInfo objects used in // this document... vector bi; - set::const_iterator cit = citekeys.begin(); - set::const_iterator const cen = citekeys.end(); - for (; cit != cen; ++cit) { - BiblioInfo::const_iterator const bt = find(*cit); + for (auto const & ck : citekeys) { + BiblioInfo::const_iterator const bt = find(ck); if (bt == end() || !bt->second.isBibTeX()) continue; bi.push_back(&(bt->second)); @@ -1487,10 +1558,9 @@ void BiblioInfo::collectCitedEntries(Buffer const & buf) sort(bi.begin(), bi.end(), lSorter); // Now we can write the sorted keys - vector::const_iterator bit = bi.begin(); - vector::const_iterator ben = bi.end(); - for (; bit != ben; ++bit) - cited_entries_.push_back((*bit)->key()); + // b is a BibTeXInfo const * + for (auto const & b : bi) + cited_entries_.push_back(b->key()); } @@ -1507,10 +1577,9 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf) // modifiers, like "1984a" map::iterator last = bimap_.end(); - vector::const_iterator it = cited_entries_.begin(); - vector::const_iterator const en = cited_entries_.end(); - for (; it != en; ++it) { - map::iterator const biit = bimap_.find(*it); + // add letters to years + for (auto const & ce : cited_entries_) { + map::iterator const biit = bimap_.find(ce); // this shouldn't happen, but... if (biit == bimap_.end()) // ...fail gracefully, anyway. @@ -1545,9 +1614,8 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf) } } // Set the labels - it = cited_entries_.begin(); - for (; it != en; ++it) { - map::iterator const biit = bimap_.find(*it); + for (auto const & ce : cited_entries_) { + map::iterator const biit = bimap_.find(ce); // this shouldn't happen, but... if (biit == bimap_.end()) // ...fail gracefully, anyway. @@ -1559,7 +1627,7 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf) docstring const auth = entry.getAuthorOrEditorList(&buf, false); // we do it this way so as to access the xref, if necessary // note that this also gives us the modifier - docstring const year = getYear(*it, buf, true); + docstring const year = getYear(ce, buf, true); if (!auth.empty() && !year.empty()) entry.label(auth + ' ' + year); else @@ -1612,4 +1680,77 @@ string citationStyleToString(const CitationStyle & cs, bool const latex) return cmd; } + +docstring authorsToDocBookAuthorGroup(docstring const & authorsString, XMLStream & xs, Buffer const & buf) +{ + // This function closely mimics getAuthorList, but produces DocBook instead of text. + // It has been greatly simplified, as the complete list of authors is always produced. No separators are required, + // as the output has a database-like shape. + // constructName has also been merged within, as it becomes really simple and leads to no copy-paste. + + if (authorsString.empty()) { + return docstring(); + } + + // Split the input list of authors into individual authors. + vector const authors = getAuthors(authorsString); + + // Retrieve the "et al." variation. + string const etal = buf.params().documentClass().getCiteMacro(buf.params().citeEngineType(), "_etal"); + + // Output the list of authors. + xs << xml::StartTag("authorgroup"); + auto it = authors.cbegin(); + auto en = authors.cend(); + for (size_t i = 0; it != en; ++it, ++i) { + xs << xml::StartTag("author"); + xs << xml::CR(); + xs << xml::StartTag("personname"); + xs << xml::CR(); + docstring name = *it; + + // All authors go in a . If more structure is known, use it; otherwise (just "et al."), print it as such. + if (name == "others") { + xs << buf.B_(etal); + } else { + name_parts parts = nameParts(name); + if (! parts.prefix.empty()) { + xs << xml::StartTag("honorific"); + xs << parts.prefix; + xs << xml::EndTag("honorific"); + xs << xml::CR(); + } + if (! parts.prename.empty()) { + xs << xml::StartTag("firstname"); + xs << parts.prename; + xs << xml::EndTag("firstname"); + xs << xml::CR(); + } + if (! parts.surname.empty()) { + xs << xml::StartTag("surname"); + xs << parts.surname; + xs << xml::EndTag("surname"); + xs << xml::CR(); + } + if (! parts.suffix.empty()) { + xs << xml::StartTag("othername", "role=\"suffix\""); + xs << parts.suffix; + xs << xml::EndTag("othername"); + xs << xml::CR(); + } + } + + xs << xml::EndTag("personname"); + xs << xml::CR(); + xs << xml::EndTag("author"); + xs << xml::CR(); + + // Could add an affiliation after , but not stored in BibTeX. + } + xs << xml::EndTag("authorgroup"); + xs << xml::CR(); + + return docstring(); +} + } // namespace lyx