return authors;
}
- docstring author = convertLaTeXCommands(operator[]("author"));
+ docstring author = operator[]("author");
if (author.empty()) {
- author = convertLaTeXCommands(operator[]("editor"));
+ author = operator[]("editor");
if (author.empty())
return author;
}
+ "/" + familyName(authors[1]);
if (authors.size() == 3)
shortauthor += "/" + familyName(authors[2]);
- return shortauthor;
+ return convertLaTeXCommands(shortauthor);
}
+ docstring retval = familyName(authors[0]);
+
if (authors.size() == 2 && authors[1] != "others")
- return bformat(from_ascii("%1$s and %2$s"),
+ retval = bformat(from_ascii("%1$s and %2$s"),
familyName(authors[0]), familyName(authors[1]));
if (authors.size() >= 2)
- return bformat(from_ascii("%1$s et al."),
+ retval = bformat(from_ascii("%1$s et al."),
familyName(authors[0]));
- return familyName(authors[0]);
+ return convertLaTeXCommands(retval);
}
} // anon namespace
-
+/* FIXME
+Bug #9131 revealed an oddity in how we are generating citation information
+when more than one key is given. We end up building a longer and longer format
+string as we go, which we then have to re-parse, over and over and over again,
+rather than generating the information for the individual keys and then putting
+all of that together. We do that to deal with the way separators work, from what
+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,
docstring before, docstring after, docstring dialog, bool next) const
{
// incorrect use of macros could put us in an infinite loop
- static int max_passes = 5000;
+ static int const max_passes = 5000;
+ // the use of overly large keys can lead to performance problems, due
+ // to eventual attempts to convert LaTeX macros to unicode. See bug
+ // #8944. This is perhaps not the best solution, but it will have to
+ // do for now.
+ static size_t const max_keysize = 128;
odocstringstream ret; // return value
string key;
bool scanning_key = false;
// we'll remove characters from the front of fmt as we
// deal with them
while (!fmt.empty()) {
- if (counter++ > max_passes) {
+ if (counter > max_passes) {
LYXERR0("Recursion limit reached while parsing `"
<< format << "'.");
return _("ERROR!");
string const val =
buf.params().documentClass().getCiteMacro(engine_type, key);
fmt = from_utf8(val) + fmt.substr(1);
+ counter += 1;
continue;
} else if (key[0] == '_') {
// a translatable bit
ret << trans;
} else {
docstring const val =
- getValueForKey(key, buf, before, after, dialog, xref);
+ getValueForKey(key, buf, before, after, dialog, xref, max_keysize);
if (!scanning_rich)
ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
ret << val;
getValueForKey(optkey, buf, before, after, dialog, xref);
if (optkey == "next" && next)
ret << ifpart; // without expansion
- else if (!val.empty())
- ret << expandFormat(ifpart, xref, counter, buf,
+ else if (!val.empty()) {
+ int newcounter = 0;
+ ret << expandFormat(ifpart, xref, newcounter, buf,
before, after, dialog, next);
- else if (!elsepart.empty())
- ret << expandFormat(elsepart, xref, counter, buf,
+ } else if (!elsepart.empty()) {
+ int newcounter = 0;
+ ret << expandFormat(elsepart, xref, newcounter, buf,
before, after, dialog, next);
+ }
// fmt will have been shortened for us already
continue;
}
info_ = expandFormat(format, xref, counter, buf,
docstring(), docstring(), docstring(), false);
- if (!info_.empty()) {
+ if (info_.empty()) {
+ // this probably shouldn't happen
+ return info_;
+ }
+
+ if (richtext) {
info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
- info_ = convertLaTeXCommands(processRichtext(info_, false));
- if (richtext)
- return info_richtext_;
+ return info_richtext_;
}
+
+ info_ = convertLaTeXCommands(processRichtext(info_, false));
return info_;
}
docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
Buffer const & buf, docstring const & format, bool richtext,
- docstring before, docstring after, docstring dialog, bool next) const
+ docstring const & before, docstring const & after,
+ docstring const & dialog, bool next) const
{
docstring loclabel;
docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
docstring const & before, docstring const & after, docstring const & dialog,
- BibTeXInfo const * const xref) const
+ BibTeXInfo const * const xref, size_t maxsize) const
{
+ // anything less is pointless
+ LASSERT(maxsize >= 16, maxsize = 16);
string key = oldkey;
bool cleanit = false;
if (prefixIs(oldkey, "clean:")) {
else if (key == "year")
ret = getYear();
}
+
if (cleanit)
- return html::cleanAttr(ret);
+ ret = html::cleanAttr(ret);
+ // make sure it is not too big
+ support::truncateWithEllipsis(ret, maxsize);
return ret;
}
}
-docstring const BiblioInfo::getLabel(vector<docstring> const & keys,
- Buffer const & buf, string const & style, bool richtext,
- docstring const & before, docstring const & after, docstring const & dialog) const
+docstring const BiblioInfo::getLabel(vector<docstring> keys,
+ Buffer const & buf, string const & style, bool for_xhtml,
+ size_t max_size, docstring const & before, docstring const & after,
+ docstring const & dialog) const
{
+ // shorter makes no sense
+ LASSERT(max_size >= 16, max_size = 16);
+
+ // we can't display more than 10 of these, anyway
+ bool const too_many_keys = keys.size() > 10;
+ if (too_many_keys)
+ keys.resize(10);
+
CiteEngineType const engine_type = buf.params().citeEngineType();
DocumentClass const & dc = buf.params().documentClass();
docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, "cite"));
xrefptr = &(xrefit->second);
}
}
- ret = data.getLabel(xrefptr, buf, ret, richtext,
- before, after, dialog, key+1 != ken);
+ ret = data.getLabel(xrefptr, buf, ret, for_xhtml,
+ before, after, dialog, key + 1 != ken);
}
+
+ if (too_many_keys)
+ ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
+ support::truncateWithEllipsis(ret, max_size);
return ret;
}
bool BiblioInfo::isBibtex(docstring const & key) const
{
- BiblioInfo::const_iterator it = find(key);
+ docstring key1;
+ split(key, key1, ',');
+ BiblioInfo::const_iterator it = find(key1);
if (it == end())
return false;
return it->second.isBibTeX();
vector<docstring> const BiblioInfo::getCiteStrings(
vector<docstring> const & keys, vector<CitationStyle> const & styles,
- Buffer const & buf, bool richtext, docstring const & before,
- docstring const & after, docstring const & dialog) const
+ Buffer const & buf, docstring const & before,
+ docstring const & after, docstring const & dialog, size_t max_size) const
{
if (empty())
return vector<docstring>();
vector<docstring> vec(styles.size());
for (size_t i = 0; i != vec.size(); ++i) {
style = styles[i].cmd;
- vec[i] = getLabel(keys, buf, style, richtext, before, after, dialog);
+ vec[i] = getLabel(keys, buf, style, false, max_size, before, after, dialog);
}
return vec;
// FIXME We may want to collect these differently, in the first case,
// so that we might have them in order of appearance.
set<docstring> citekeys;
- Toc const & toc = buf.tocBackend().toc("citation");
- Toc::const_iterator it = toc.begin();
- Toc::const_iterator const en = toc.end();
+ shared_ptr<Toc const> 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())
continue;