3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
11 * Full author contact details are available in file CREDITS.
16 #include "BiblioInfo.h"
18 #include "BufferParams.h"
19 #include "buffer_funcs.h"
22 #include "InsetIterator.h"
24 #include "output_xhtml.h"
25 #include "Paragraph.h"
26 #include "TextClass.h"
27 #include "TocBackend.h"
29 #include "support/convert.h"
30 #include "support/debug.h"
31 #include "support/docstream.h"
32 #include "support/gettext.h"
33 #include "support/lassert.h"
34 #include "support/lstrings.h"
35 #include "support/regex.h"
36 #include "support/textutils.h"
41 using namespace lyx::support;
48 // gets the "family name" from an author-type string
49 docstring familyName(docstring const & name)
54 // first we look for a comma, and take the last name to be everything
55 // preceding the right-most one, so that we also get the "jr" part.
56 docstring::size_type idx = name.rfind(',');
57 if (idx != docstring::npos)
58 return ltrim(name.substr(0, idx));
60 // OK, so now we want to look for the last name. We're going to
61 // include the "von" part. This isn't perfect.
62 // Split on spaces, to get various tokens.
63 vector<docstring> pieces = getVectorFromString(name, from_ascii(" "));
64 // If we only get two, assume the last one is the last name
65 if (pieces.size() <= 2)
68 // Now we look for the first token that begins with a lower case letter.
69 vector<docstring>::const_iterator it = pieces.begin();
70 vector<docstring>::const_iterator en = pieces.end();
71 for (; it != en; ++it) {
74 char_type const c = (*it)[0];
79 if (it == en) // we never found a "von"
82 // reconstruct what we need to return
85 for (; it != en; ++it) {
96 // converts a string containing LaTeX commands into unicode
98 docstring convertLaTeXCommands(docstring const & str)
103 bool scanning_cmd = false;
104 bool scanning_math = false;
105 bool escaped = false; // used to catch \$, etc.
106 while (!val.empty()) {
107 char_type const ch = val[0];
109 // if we're scanning math, we output everything until we
110 // find an unescaped $, at which point we break out.
117 scanning_math = false;
123 // if we're scanning a command name, then we just
124 // discard characters until we hit something that
127 if (isAlphaASCII(ch)) {
132 // so we're done with this command.
133 // now we fall through and check this character.
134 scanning_cmd = false;
137 // was the last character a \? If so, then this is something like:
138 // \\ or \$, so we'll just output it. That's probably not always right...
140 // exception: output \, as THIN SPACE
142 ret.push_back(0x2009);
153 scanning_math = true;
157 // we just ignore braces
158 if (ch == '{' || ch == '}') {
163 // we're going to check things that look like commands, so if
164 // this doesn't, just output it.
171 // ok, could be a command of some sort
172 // let's see if it corresponds to some unicode
173 // unicodesymbols has things in the form: \"{u},
174 // whereas we may see things like: \"u. So we'll
175 // look for that and change it, if necessary.
176 // FIXME: This is a sort of mini-tex2lyx.
177 // Use the real tex2lyx instead!
178 static lyx::regex const reg("^\\\\\\W\\w");
179 if (lyx::regex_search(to_utf8(val), reg)) {
180 val.insert(3, from_ascii("}"));
181 val.insert(2, from_ascii("{"));
185 docstring const cnvtd = Encodings::fromLaTeXCommand(val,
186 Encodings::TEXT_CMD, termination, rem);
187 if (!cnvtd.empty()) {
188 // it did, so we'll take that bit and proceed with what's left
193 // it's a command of some sort
202 // Escape '<' and '>' and remove richtext markers (e.g. {!this is richtext!}) from a string.
203 docstring processRichtext(docstring const & str, bool richtext)
208 bool scanning_rich = false;
209 while (!val.empty()) {
210 char_type const ch = val[0];
211 if (ch == '{' && val.size() > 1 && val[1] == '!') {
212 // beginning of rich text
213 scanning_rich = true;
217 if (scanning_rich && ch == '!' && val.size() > 1 && val[1] == '}') {
219 scanning_rich = false;
227 // we need to escape '<' and '>'
235 } else if (!scanning_rich /* && !richtext */)
237 // else the character is discarded, which will happen only if
238 // richtext == false and we are scanning rich text
247 //////////////////////////////////////////////////////////////////////
251 //////////////////////////////////////////////////////////////////////
253 BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
254 : is_bibtex_(true), bib_key_(key), entry_type_(type), info_(),
259 docstring const BibTeXInfo::getAuthorList(
260 Buffer const * buf, bool full, bool forceshort) const
262 // Maxnames treshold depend on engine
263 size_t maxnames = buf ?
264 buf->params().documentClass().max_citenames() : 2;
267 docstring const opt = label();
272 docstring const remainder = trim(split(opt, authors, '('));
273 if (remainder.empty())
274 // in this case, we didn't find a "(",
275 // so we don't have author (year)
280 docstring author = operator[]("author");
281 if (author.empty()) {
282 author = operator[]("editor");
287 // FIXME Move this to a separate routine that can
288 // be called from elsewhere.
290 // OK, we've got some names. Let's format them.
291 // Try to split the author list on " and "
292 vector<docstring> const authors =
293 getVectorFromString(author, from_ascii(" and "));
297 CiteEngineType const engine_type = buf ? buf->params().citeEngineType()
298 : ENGINE_TYPE_DEFAULT;
300 // These are defined in the styles
302 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_etal")
304 string const namesep =
305 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_namesep")
307 string const lastnamesep =
308 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_lastnamesep")
310 string const pairnamesep =
311 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_pairnamesep")
314 // Shorten the list (with et al.) if forceshort is set
315 // and the list can actually be shorten, else if maxcitenames
316 // is passed and full is not set.
317 bool shorten = forceshort && authors.size() > 1;
318 vector<docstring>::const_iterator it = authors.begin();
319 vector<docstring>::const_iterator en = authors.end();
320 for (size_t i = 0; it != en; ++it, ++i) {
321 if (i >= maxnames && !full) {
325 if (*it == "others") {
326 retval += buf ? buf->B_(etal) : from_ascii(etal);
329 if (i > 0 && i == authors.size() - 1) {
330 if (authors.size() == 2)
331 retval += buf ? buf->B_(pairnamesep) : from_ascii(pairnamesep);
333 retval += buf ? buf->B_(lastnamesep) : from_ascii(lastnamesep);
335 retval += buf ? buf->B_(namesep) : from_ascii(namesep);
336 retval += familyName(*it);
339 retval = familyName(authors[0]) + (buf ? buf->B_(etal) : from_ascii(etal));
341 return convertLaTeXCommands(retval);
345 docstring const BibTeXInfo::getYear() const
348 // first try legacy year field
349 docstring year = operator[]("year");
352 // now try biblatex's date field
353 year = operator[]("date");
354 // Format is [-]YYYY-MM-DD*/[-]YYYY-MM-DD*
355 // We only want the years.
356 static regex const yreg("[-]?([\\d]{4}).*");
357 static regex const ereg(".*/[-]?([\\d]{4}).*");
359 string const date = to_utf8(year);
360 regex_match(date, sm, yreg);
361 year = from_ascii(sm[1]);
362 // check for an endyear
363 if (regex_match(date, sm, ereg))
364 year += char_type(0x2013) + from_ascii(sm[1]);
368 docstring const opt = label();
373 docstring tmp = split(opt, authors, '(');
375 // we don't have author (year)
378 tmp = split(tmp, year, ')');
385 docstring parseOptions(docstring const & format, string & optkey,
386 docstring & ifpart, docstring & elsepart);
388 // Calls parseOptions to deal with an embedded option, such as:
389 // {%number%[[, no.~%number%]]}
390 // which must appear at the start of format. ifelsepart gets the
391 // whole of the option, and we return what's left after the option.
392 // we return format if there is an error.
393 docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
395 LASSERT(format[0] == '{' && format[1] == '%', return format);
399 docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
400 if (format == rest) { // parse error
401 LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
404 LASSERT(rest.size() <= format.size(),
405 { ifelsepart = docstring(); return format; });
406 ifelsepart = format.substr(0, format.size() - rest.size());
411 // Gets a "clause" from a format string, where the clause is
412 // delimited by '[[' and ']]'. Returns what is left after the
413 // clause is removed, and returns format if there is an error.
414 docstring getClause(docstring const & format, docstring & clause)
416 docstring fmt = format;
419 // we'll remove characters from the front of fmt as we
421 while (!fmt.empty()) {
422 if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
427 // check for an embedded option
428 if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
430 docstring const rest = parseEmbeddedOption(fmt, part);
432 LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
437 } else { // it's just a normal character
446 // parse an options string, which must appear at the start of the
447 // format parameter. puts the parsed bits in optkey, ifpart, and
448 // elsepart and returns what's left after the option is removed.
449 // if there's an error, it returns format itself.
450 docstring parseOptions(docstring const & format, string & optkey,
451 docstring & ifpart, docstring & elsepart)
453 LASSERT(format[0] == '{' && format[1] == '%', return format);
455 docstring fmt = format.substr(2);
456 size_t pos = fmt.find('%'); // end of key
457 if (pos == string::npos) {
458 LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
461 optkey = to_utf8(fmt.substr(0, pos));
462 fmt = fmt.substr(pos + 1);
463 // [[format]] should be next
464 if (fmt[0] != '[' || fmt[1] != '[') {
465 LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
469 docstring curfmt = fmt;
470 fmt = getClause(curfmt, ifpart);
472 LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
476 if (fmt[0] == '}') // we're done, no else clause
477 return fmt.substr(1);
479 // else part should follow
480 if (fmt[0] != '[' || fmt[1] != '[') {
481 LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
486 fmt = getClause(curfmt, elsepart);
488 if (fmt == curfmt || fmt[0] != '}') {
489 LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
492 return fmt.substr(1);
499 Bug #9131 revealed an oddity in how we are generating citation information
500 when more than one key is given. We end up building a longer and longer format
501 string as we go, which we then have to re-parse, over and over and over again,
502 rather than generating the information for the individual keys and then putting
503 all of that together. We do that to deal with the way separators work, from what
504 I can tell, but it still feels like a hack. Fixing this would require quite a
505 bit of work, however.
507 docstring BibTeXInfo::expandFormat(docstring const & format,
508 BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
509 CiteItem const & ci, bool next, bool second) const
511 // incorrect use of macros could put us in an infinite loop
512 static int const max_passes = 5000;
513 // the use of overly large keys can lead to performance problems, due
514 // to eventual attempts to convert LaTeX macros to unicode. See bug
515 // #8944. By default, the size is limited to 128 (in CiteItem), but
516 // for specific purposes (such as XHTML export), it needs to be enlarged
517 // This is perhaps not the best solution, but it will have to do for now.
518 size_t const max_keysize = ci.max_key_size;
519 odocstringstream ret; // return value
521 bool scanning_key = false;
522 bool scanning_rich = false;
524 CiteEngineType const engine_type = buf.params().citeEngineType();
525 docstring fmt = format;
526 // we'll remove characters from the front of fmt as we
528 while (!fmt.empty()) {
529 if (counter > max_passes) {
530 LYXERR0("Recursion limit reached while parsing `"
535 char_type thischar = fmt[0];
536 if (thischar == '%') {
537 // beginning or end of key
540 scanning_key = false;
541 // so we replace the key with its value, which may be empty
545 buf.params().documentClass().getCiteMacro(engine_type, key);
546 fmt = from_utf8(val) + fmt.substr(1);
549 } else if (key[0] == '_') {
550 // a translatable bit
552 buf.params().documentClass().getCiteMacro(engine_type, key);
553 docstring const trans =
554 translateIfPossible(from_utf8(val), buf.params().language->code());
557 docstring const val =
558 getValueForKey(key, buf, ci, xrefs, max_keysize);
560 ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
563 ret << from_ascii("{!</span>!}");
571 else if (thischar == '{') {
572 // beginning of option?
574 LYXERR0("ERROR: Found `{' when scanning key in `" << format << "'.");
577 if (fmt.size() > 1) {
579 // it is the beginning of an optional format
583 docstring const newfmt =
584 parseOptions(fmt, optkey, ifpart, elsepart);
585 if (newfmt == fmt) // parse error
588 docstring const val =
589 getValueForKey(optkey, buf, ci, xrefs);
590 if (optkey == "next" && next)
591 ret << ifpart; // without expansion
592 else if (optkey == "second" && second) {
594 ret << expandFormat(ifpart, xrefs, newcounter, buf,
596 } else if (!val.empty()) {
598 ret << expandFormat(ifpart, xrefs, newcounter, buf,
600 } else if (!elsepart.empty()) {
602 ret << expandFormat(elsepart, xrefs, newcounter, buf,
605 // fmt will have been shortened for us already
609 // beginning of rich text
610 scanning_rich = true;
612 ret << from_ascii("{!");
616 // we are here if '{' was not followed by % or !.
617 // So it's just a character.
620 else if (scanning_rich && thischar == '!'
621 && fmt.size() > 1 && fmt[1] == '}') {
623 scanning_rich = false;
625 ret << from_ascii("!}");
628 else if (scanning_key)
629 key += char(thischar);
633 } catch (EncodingException & /* e */) {
634 LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
640 LYXERR0("Never found end of key in `" << format << "'!");
644 LYXERR0("Never found end of rich text in `" << format << "'!");
651 docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
652 Buffer const & buf, CiteItem const & ci) const
654 bool const richtext = ci.richtext;
656 if (!richtext && !info_.empty())
658 if (richtext && !info_richtext_.empty())
659 return info_richtext_;
662 BibTeXInfo::const_iterator it = find(from_ascii("ref"));
667 CiteEngineType const engine_type = buf.params().citeEngineType();
668 DocumentClass const & dc = buf.params().documentClass();
669 docstring const & format =
670 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
672 info_ = expandFormat(format, xrefs, counter, buf,
676 // this probably shouldn't happen
681 info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
682 return info_richtext_;
685 info_ = convertLaTeXCommands(processRichtext(info_, false));
690 docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
691 Buffer const & buf, docstring const & format,
692 CiteItem const & ci, bool next, bool second) const
697 loclabel = expandFormat(format, xrefs, counter, buf, ci, next, second);
699 if (!loclabel.empty() && !next) {
700 loclabel = processRichtext(loclabel, ci.richtext);
701 loclabel = convertLaTeXCommands(loclabel);
708 docstring const & BibTeXInfo::operator[](docstring const & field) const
710 BibTeXInfo::const_iterator it = find(field);
713 static docstring const empty_value = docstring();
718 docstring const & BibTeXInfo::operator[](string const & field) const
720 return operator[](from_ascii(field));
724 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
725 CiteItem const & ci, BibTeXInfoList const xrefs, size_t maxsize) const
727 // anything less is pointless
728 LASSERT(maxsize >= 16, maxsize = 16);
730 bool cleanit = false;
731 if (prefixIs(oldkey, "clean:")) {
732 key = oldkey.substr(6);
736 docstring ret = operator[](key);
737 if (ret.empty() && !xrefs.empty()) {
738 vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
739 vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
740 for (; it != en; ++it) {
741 if (*it && !(**it)[key].empty()) {
749 // FIXME: dialog, textbefore and textafter have nothing to do with this
750 if (key == "dialog" && ci.context == CiteItem::Dialog)
751 ret = from_ascii("x"); // any non-empty string will do
752 else if (key == "export" && ci.context == CiteItem::Export)
753 ret = from_ascii("x"); // any non-empty string will do
754 else if (key == "ifstar" && ci.Starred)
755 ret = from_ascii("x"); // any non-empty string will do
756 else if (key == "entrytype")
758 else if (prefixIs(key, "ifentrytype:")
759 && from_ascii(key.substr(12)) == entry_type_)
760 ret = from_ascii("x"); // any non-empty string will do
761 else if (key == "key")
763 else if (key == "label")
765 else if (key == "modifier" && modifier_ != 0)
767 else if (key == "numericallabel")
769 else if (key == "abbrvauthor") {
770 // Special key to provide abbreviated author names,
771 // with respect to maxcitenames.
772 ret = getAuthorList(&buf, false, false);
773 if (ci.forceUpperCase && isLowerCase(ret[0]))
774 ret[0] = uppercase(ret[0]);
775 } else if (key == "fullauthor") {
776 // Return a full author list
777 ret = getAuthorList(&buf, true, false);
778 if (ci.forceUpperCase && isLowerCase(ret[0]))
779 ret[0] = uppercase(ret[0]);
780 } else if (key == "forceabbrvauthor") {
781 // Special key to provide abbreviated author names,
782 // irrespective of maxcitenames.
783 ret = getAuthorList(&buf, false, true);
784 if (ci.forceUpperCase && isLowerCase(ret[0]))
785 ret[0] = uppercase(ret[0]);
786 } else if (key == "bibentry") {
787 // Special key to provide the full bibliography entry: see getInfo()
788 CiteEngineType const engine_type = buf.params().citeEngineType();
789 DocumentClass const & dc = buf.params().documentClass();
790 docstring const & format =
791 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_), false));
793 ret = expandFormat(format, xrefs, counter, buf, ci, false, false);
794 } else if (key == "textbefore")
796 else if (key == "textafter")
798 else if (key == "year")
803 ret = html::cleanAttr(ret);
805 // make sure it is not too big
806 support::truncateWithEllipsis(ret, maxsize);
811 //////////////////////////////////////////////////////////////////////
815 //////////////////////////////////////////////////////////////////////
819 // A functor for use with sort, leading to case insensitive sorting
820 class compareNoCase: public binary_function<docstring, docstring, bool>
823 bool operator()(docstring const & s1, docstring const & s2) const {
824 return compare_no_case(s1, s2) < 0;
831 vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
833 vector<docstring> result;
834 if (!data.isBibTeX())
836 // Legacy crossref field. This is not nestable.
837 if (!nested && !data["crossref"].empty()) {
838 docstring const xrefkey = data["crossref"];
839 result.push_back(xrefkey);
840 // However, check for nested xdatas
841 BiblioInfo::const_iterator it = find(xrefkey);
843 BibTeXInfo const & xref = it->second;
844 vector<docstring> const nxdata = getXRefs(xref, true);
846 result.insert(result.end(), nxdata.begin(), nxdata.end());
849 // Biblatex's xdata field. Infinitely nestable.
850 // XData field can consist of a comma-separated list of keys
851 vector<docstring> const xdatakeys = getVectorFromString(data["xdata"]);
852 if (!xdatakeys.empty()) {
853 vector<docstring>::const_iterator xit = xdatakeys.begin();
854 vector<docstring>::const_iterator xen = xdatakeys.end();
855 for (; xit != xen; ++xit) {
856 docstring const xdatakey = *xit;
857 result.push_back(xdatakey);
858 BiblioInfo::const_iterator it = find(xdatakey);
860 BibTeXInfo const & xdata = it->second;
861 vector<docstring> const nxdata = getXRefs(xdata, true);
863 result.insert(result.end(), nxdata.begin(), nxdata.end());
871 vector<docstring> const BiblioInfo::getKeys() const
873 vector<docstring> bibkeys;
874 BiblioInfo::const_iterator it = begin();
875 for (; it != end(); ++it)
876 bibkeys.push_back(it->first);
877 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
882 vector<docstring> const BiblioInfo::getFields() const
884 vector<docstring> bibfields;
885 set<docstring>::const_iterator it = field_names_.begin();
886 set<docstring>::const_iterator end = field_names_.end();
887 for (; it != end; ++it)
888 bibfields.push_back(*it);
889 sort(bibfields.begin(), bibfields.end());
894 vector<docstring> const BiblioInfo::getEntries() const
896 vector<docstring> bibentries;
897 set<docstring>::const_iterator it = entry_types_.begin();
898 set<docstring>::const_iterator end = entry_types_.end();
899 for (; it != end; ++it)
900 bibentries.push_back(*it);
901 sort(bibentries.begin(), bibentries.end());
906 docstring const BiblioInfo::getAuthorList(docstring const & key, Buffer const & buf) const
908 BiblioInfo::const_iterator it = find(key);
911 BibTeXInfo const & data = it->second;
912 return data.getAuthorList(&buf, false);
916 docstring const BiblioInfo::getCiteNumber(docstring const & key) const
918 BiblioInfo::const_iterator it = find(key);
921 BibTeXInfo const & data = it->second;
922 return data.citeNumber();
926 docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
928 BiblioInfo::const_iterator it = find(key);
931 BibTeXInfo const & data = it->second;
932 docstring year = data.getYear();
934 // let's try the crossrefs
935 vector<docstring> const xrefs = getXRefs(data);
939 vector<docstring>::const_iterator it = xrefs.begin();
940 vector<docstring>::const_iterator en = xrefs.end();
941 for (; it != en; ++it) {
942 BiblioInfo::const_iterator const xrefit = find(*it);
945 BibTeXInfo const & xref_data = xrefit->second;
946 year = xref_data.getYear();
952 if (use_modifier && data.modifier() != 0)
953 year += data.modifier();
958 docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
960 docstring const year = getYear(key, use_modifier);
962 return buf.B_("No year");
967 docstring const BiblioInfo::getInfo(docstring const & key,
968 Buffer const & buf, CiteItem const & ci) const
970 BiblioInfo::const_iterator it = find(key);
972 return docstring(_("Bibliography entry not found!"));
973 BibTeXInfo const & data = it->second;
974 BibTeXInfoList xrefptrs;
975 vector<docstring> const xrefs = getXRefs(data);
976 if (!xrefs.empty()) {
977 vector<docstring>::const_iterator it = xrefs.begin();
978 vector<docstring>::const_iterator en = xrefs.end();
979 for (; it != en; ++it) {
980 BiblioInfo::const_iterator const xrefit = find(*it);
982 xrefptrs.push_back(&(xrefit->second));
985 return data.getInfo(xrefptrs, buf, ci);
989 docstring const BiblioInfo::getLabel(vector<docstring> keys,
990 Buffer const & buf, string const & style, CiteItem const & ci) const
992 size_t max_size = ci.max_size;
993 // shorter makes no sense
994 LASSERT(max_size >= 16, max_size = 16);
996 // we can't display more than 10 of these, anyway
997 bool const too_many_keys = keys.size() > 10;
1001 CiteEngineType const engine_type = buf.params().citeEngineType();
1002 DocumentClass const & dc = buf.params().documentClass();
1003 docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, false, "cite"));
1004 docstring ret = format;
1005 vector<docstring>::const_iterator key = keys.begin();
1006 vector<docstring>::const_iterator ken = keys.end();
1007 for (int i = 0; key != ken; ++key, ++i) {
1008 BiblioInfo::const_iterator it = find(*key);
1009 BibTeXInfo empty_data;
1010 empty_data.key(*key);
1011 BibTeXInfo & data = empty_data;
1012 vector<BibTeXInfo const *> xrefptrs;
1015 vector<docstring> const xrefs = getXRefs(data);
1016 if (!xrefs.empty()) {
1017 vector<docstring>::const_iterator it = xrefs.begin();
1018 vector<docstring>::const_iterator en = xrefs.end();
1019 for (; it != en; ++it) {
1020 BiblioInfo::const_iterator const xrefit = find(*it);
1021 if (xrefit != end())
1022 xrefptrs.push_back(&(xrefit->second));
1026 ret = data.getLabel(xrefptrs, buf, ret, ci, key + 1 != ken, i == 1);
1030 ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
1031 support::truncateWithEllipsis(ret, max_size);
1036 bool BiblioInfo::isBibtex(docstring const & key) const
1039 split(key, key1, ',');
1040 BiblioInfo::const_iterator it = find(key1);
1043 return it->second.isBibTeX();
1047 vector<docstring> const BiblioInfo::getCiteStrings(
1048 vector<docstring> const & keys, vector<CitationStyle> const & styles,
1049 Buffer const & buf, CiteItem const & ci) const
1052 return vector<docstring>();
1055 vector<docstring> vec(styles.size());
1056 for (size_t i = 0; i != vec.size(); ++i) {
1057 style = styles[i].name;
1058 vec[i] = getLabel(keys, buf, style, ci);
1065 void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
1067 bimap_.insert(info.begin(), info.end());
1068 field_names_.insert(info.field_names_.begin(), info.field_names_.end());
1069 entry_types_.insert(info.entry_types_.begin(), info.entry_types_.end());
1075 // used in xhtml to sort a list of BibTeXInfo objects
1076 bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
1078 docstring const lauth = lhs->getAuthorList();
1079 docstring const rauth = rhs->getAuthorList();
1080 docstring const lyear = lhs->getYear();
1081 docstring const ryear = rhs->getYear();
1082 docstring const ltitl = lhs->operator[]("title");
1083 docstring const rtitl = rhs->operator[]("title");
1084 return (lauth < rauth)
1085 || (lauth == rauth && lyear < ryear)
1086 || (lauth == rauth && lyear == ryear && ltitl < rtitl);
1092 void BiblioInfo::collectCitedEntries(Buffer const & buf)
1094 cited_entries_.clear();
1095 // We are going to collect all the citation keys used in the document,
1096 // getting them from the TOC.
1097 // FIXME We may want to collect these differently, in the first case,
1098 // so that we might have them in order of appearance.
1099 set<docstring> citekeys;
1100 shared_ptr<Toc const> toc = buf.tocBackend().toc("citation");
1101 Toc::const_iterator it = toc->begin();
1102 Toc::const_iterator const en = toc->end();
1103 for (; it != en; ++it) {
1104 if (it->str().empty())
1106 vector<docstring> const keys = getVectorFromString(it->str());
1107 citekeys.insert(keys.begin(), keys.end());
1109 if (citekeys.empty())
1112 // We have a set of the keys used in this document.
1113 // We will now convert it to a list of the BibTeXInfo objects used in
1115 vector<BibTeXInfo const *> bi;
1116 set<docstring>::const_iterator cit = citekeys.begin();
1117 set<docstring>::const_iterator const cen = citekeys.end();
1118 for (; cit != cen; ++cit) {
1119 BiblioInfo::const_iterator const bt = find(*cit);
1120 if (bt == end() || !bt->second.isBibTeX())
1122 bi.push_back(&(bt->second));
1125 sort(bi.begin(), bi.end(), lSorter);
1127 // Now we can write the sorted keys
1128 vector<BibTeXInfo const *>::const_iterator bit = bi.begin();
1129 vector<BibTeXInfo const *>::const_iterator ben = bi.end();
1130 for (; bit != ben; ++bit)
1131 cited_entries_.push_back((*bit)->key());
1135 void BiblioInfo::makeCitationLabels(Buffer const & buf)
1137 collectCitedEntries(buf);
1138 CiteEngineType const engine_type = buf.params().citeEngineType();
1139 bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
1143 // used to remember the last one we saw
1144 // we'll be comparing entries to see if we need to add
1145 // modifiers, like "1984a"
1146 map<docstring, BibTeXInfo>::iterator last;
1148 vector<docstring>::const_iterator it = cited_entries_.begin();
1149 vector<docstring>::const_iterator const en = cited_entries_.end();
1150 for (; it != en; ++it) {
1151 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1152 // this shouldn't happen, but...
1153 if (biit == bimap_.end())
1154 // ...fail gracefully, anyway.
1156 BibTeXInfo & entry = biit->second;
1158 docstring const num = convert<docstring>(++keynumber);
1159 entry.setCiteNumber(num);
1161 // coverity complains about our derefercing the iterator last,
1162 // which was not initialized above. but it does get initialized
1163 // after the first time through the loop, which is the point of
1165 // coverity[FORWARD_NULL]
1166 if (it != cited_entries_.begin()
1167 && entry.getAuthorList() == last->second.getAuthorList()
1168 // we access the year via getYear() so as to get it from the xref,
1169 // if we need to do so
1170 && getYear(entry.key()) == getYear(last->second.key())) {
1171 if (modifier == 0) {
1172 // so the last one should have been 'a'
1173 last->second.setModifier('a');
1175 } else if (modifier == 'z')
1182 entry.setModifier(modifier);
1183 // remember the last one
1188 it = cited_entries_.begin();
1189 for (; it != en; ++it) {
1190 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1191 // this shouldn't happen, but...
1192 if (biit == bimap_.end())
1193 // ...fail gracefully, anyway.
1195 BibTeXInfo & entry = biit->second;
1197 entry.label(entry.citeNumber());
1199 docstring const auth = entry.getAuthorList(&buf, false);
1200 // we do it this way so as to access the xref, if necessary
1201 // note that this also gives us the modifier
1202 docstring const year = getYear(*it, buf, true);
1203 if (!auth.empty() && !year.empty())
1204 entry.label(auth + ' ' + year);
1206 entry.label(entry.key());
1212 //////////////////////////////////////////////////////////////////////
1216 //////////////////////////////////////////////////////////////////////
1219 CitationStyle citationStyleFromString(string const & command,
1220 BufferParams const & params)
1223 if (command.empty())
1226 string const alias = params.getCiteAlias(command);
1227 string cmd = alias.empty() ? command : alias;
1228 if (isUpperCase(command[0])) {
1229 cs.forceUpperCase = true;
1230 cmd[0] = lowercase(cmd[0]);
1233 size_t const n = command.size() - 1;
1234 if (command[n] == '*') {
1235 cs.hasStarredVersion = true;
1236 if (suffixIs(cmd, '*'))
1237 cmd = cmd.substr(0, cmd.size() - 1);
1245 string citationStyleToString(const CitationStyle & cs, bool const latex)
1247 string cmd = latex ? cs.cmd : cs.name;
1248 if (cs.forceUpperCase)
1249 cmd[0] = uppercase(cmd[0]);
1250 if (cs.hasStarredVersion)