bool scanning_cmd = false;
bool scanning_math = false;
+ bool is_section = false;
bool escaped = false; // used to catch \$, etc.
while (!val.empty()) {
char_type const ch = val[0];
// discard characters until we hit something that
// isn't alpha.
if (scanning_cmd) {
+ if (!is_section && ch == 'S') {
+ is_section = true;
+ val = val.substr(1);
+ continue;
+ }
if (isAlphaASCII(ch)) {
+ is_section = false;
val = val.substr(1);
escaped = false;
continue;
+ } else if (is_section) {
+ ret.push_back(0x00a7);
+ is_section = false;
+ continue;
}
// so we're done with this command.
// now we fall through and check this character.
+ is_section = false;
scanning_cmd = false;
}
}
if (ch == '~') {
- ret += 0x00a0;
+ ret += char_type(0x00a0);
val = val.substr(1);
continue;
}
// get "file" entry from citation record
file = operator[]("file");
- // Jabref case, field has a format:
+ // Jabref case, "file" field has a format (depending on exporter):
// Description:Location:Filetype;Description:Location:Filetype...
- // We will grab only first pdf
+ // or simply:
+ // Location;Location;...
+ // We will strip out the locations and return an \n-separated list
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;
+ docstring filelist;
+ vector<docstring> files = getVectorFromString(file, from_ascii(";"));
+ for (auto const & f : files) {
+ // first try if we have Description:Location:Filetype
+ docstring ret, filedest, tmp;
+ ret = split(f, tmp, ':');
+ tmp = split(ret, filedest, ':');
+ if (filedest.empty())
+ // we haven't, so use the whole string
+ filedest = f;
+ // TODO howto deal with relative directories?
+ FileName fn(to_utf8(filedest));
+ if (fn.exists()) {
+ if (!filelist.empty())
+ filelist += '\n';
+ filelist += "file:///" + filedest;
+ }
+ }
+ if (!filelist.empty())
+ file = filelist;
}
- // kbibtex case, format:
+ // kbibtex case, "localfile" field with format:
// file1.pdf;file2.pdf
- // We will grab only first pdf
+ // We will strip out the locations and return an \n-separated list
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;
+ docstring filelist;
+ vector<docstring> files = getVectorFromString(kfile, from_ascii(";"));
+ for (auto const & f : files) {
+ // TODO howto deal with relative directories?
+ FileName fn(to_utf8(f));
+ if (fn.exists()) {
+ if (!filelist.empty())
+ filelist += '\n';
+ filelist = "file:///" + f;
+ }
+ }
+ if (!filelist.empty())
+ file = filelist;
}
if (!url.empty())
}
docstring ret = operator[](key);
- if (ret.empty() && !xrefs.empty()) {
- // xr is a (reference to a) BibTeXInfo const *
- for (auto const & xr : xrefs) {
- if (xr && !(*xr)[key].empty()) {
- ret = (*xr)[key];
- break;
- }
- }
- }
if (ret.empty()) {
+ docstring subtype;
+ if (contains(key, ':'))
+ subtype = from_ascii(token(key, ':', 1));
// some special keys
// FIXME: dialog, textbefore and textafter have nothing to do with this
if (key == "dialog" && ci.context == CiteItem::Dialog)
ret = cite_number_;
else if (prefixIs(key, "ifmultiple:")) {
// Return whether we have multiple authors
- docstring const kind = operator[](from_ascii(key.substr(11)));
+ docstring const kind = operator[](subtype);
if (multipleAuthors(kind))
ret = from_ascii("x"); // any non-empty string will do
}
// Special key to provide abbreviated name list,
// with respect to maxcitenames. Suitable for Bibliography
// beginnings.
- docstring const kind = operator[](from_ascii(key.substr(11)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, false, false, true);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
} else if (prefixIs(key, "fullnames:")) {
// Return a full name list. Suitable for Bibliography
// beginnings.
- docstring const kind = operator[](from_ascii(key.substr(10)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, true, false, true);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
// Special key to provide abbreviated name lists,
// irrespective of maxcitenames. Suitable for Bibliography
// beginnings.
- docstring const kind = operator[](from_ascii(key.substr(15)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, false, true, true);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
// Special key to provide abbreviated name list,
// with respect to maxcitenames. Suitable for further names inside a
// bibliography item // (such as "ed. by ...")
- docstring const kind = operator[](from_ascii(key.substr(11)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, false, false, true, false);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
} else if (prefixIs(key, "fullbynames:")) {
// Return a full name list. Suitable for further names inside a
// bibliography item // (such as "ed. by ...")
- docstring const kind = operator[](from_ascii(key.substr(10)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, true, false, true, false);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
// Special key to provide abbreviated name lists,
// irrespective of maxcitenames. Suitable for further names inside a
// bibliography item // (such as "ed. by ...")
- docstring const kind = operator[](from_ascii(key.substr(15)));
+ docstring const kind = operator[](subtype);
ret = getAuthorList(&buf, kind, false, true, true, false);
if (ci.forceUpperCase && isLowerCase(ret[0]))
ret[0] = uppercase(ret[0]);
ret = getYear();
}
+ // If we have no result, check in the cross-ref'ed entries
+ if (ret.empty() && !xrefs.empty()) {
+ bool const biblatex =
+ buf.params().documentClass().citeFramework() == "biblatex";
+ // xr is a (reference to a) BibTeXInfo const *
+ for (auto const & xr : xrefs) {
+ if (!xr)
+ continue;
+ // use empty BibTeXInfoList to avoid loops
+ BibTeXInfoList xr_dummy;
+ ret = xr->getValueForKey(oldkey, buf, ci, xr_dummy, maxsize);
+ if (!ret.empty())
+ // success!
+ break;
+ // in biblatex, cross-ref'ed titles are mapped
+ // to booktitle. Same for subtitle etc.
+ if (biblatex && prefixIs(key, "book"))
+ ret = (*xr)[key.substr(4)];
+ // likewise, author is maped onto bookauthor
+ else if (biblatex && contains(key, ":bookauthor"))
+ ret = xr->getValueForKey(subst(key, "bookauthor", "author"),
+ buf, ci, xr_dummy, maxsize);
+ if (!ret.empty())
+ // success!
+ break;
+ }
+ }
+
if (cleanit)
ret = xml::cleanAttr(ret);
}
-docstring authorsToDocBookAuthorGroup(docstring const & authorsString, XMLStream & xs, Buffer const & buf)
+void authorsToDocBookAuthorGroup(docstring const & authorsString, XMLStream & xs, Buffer const & buf,
+ const std::string type)
{
// 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 (! type.empty() && (type != "author" && type != "book")) {
+ LYXERR0("ERROR! Unexpected author contribution `" << type <<"'.");
+ return;
+ }
+
if (authorsString.empty()) {
- return docstring();
+ return;
}
// Split the input list of authors into individual authors.
auto it = authors.cbegin();
auto en = authors.cend();
for (size_t i = 0; it != en; ++it, ++i) {
- xs << xml::StartTag("author");
+ const std::string tag = (type.empty() || type == "author") ? "author" : "othercredit";
+ const std::string attr = (type == "book") ? R"(class="other" otherclass="bookauthor")" : "";
+
+ xs << xml::StartTag(tag, attr);
xs << xml::CR();
xs << xml::StartTag("personname");
xs << xml::CR();
- docstring name = *it;
+ const docstring name = *it;
- // All authors go in a <personname>. If more structure is known, use it; otherwise (just "et al."), print it as such.
+ // All authors go in a <personname>. If more structure is known, use it; otherwise (just "et al."),
+ // print it as such.
if (name == "others") {
xs << buf.B_(etal);
} else {
xs << xml::EndTag("personname");
xs << xml::CR();
- xs << xml::EndTag("author");
+ xs << xml::EndTag(tag);
xs << xml::CR();
// Could add an affiliation after <personname>, but not stored in BibTeX.
}
xs << xml::EndTag("authorgroup");
xs << xml::CR();
-
- return docstring();
}
} // namespace lyx