3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
10 * \author Jürgen Spitzmüller
12 * Full author contact details are available in file CREDITS.
17 #include "BiblioInfo.h"
19 #include "BufferParams.h"
20 #include "buffer_funcs.h"
23 #include "InsetIterator.h"
25 #include "output_xhtml.h"
26 #include "Paragraph.h"
27 #include "TextClass.h"
28 #include "TocBackend.h"
30 #include "support/convert.h"
31 #include "support/debug.h"
32 #include "support/docstream.h"
33 #include "support/gettext.h"
34 #include "support/lassert.h"
35 #include "support/lstrings.h"
36 #include "support/regex.h"
37 #include "support/textutils.h"
42 using namespace lyx::support;
49 // gets the "prename" and "family name" from an author-type string
50 pair<docstring, docstring> nameParts(docstring const & name)
53 return make_pair(docstring(), docstring());
55 // first we look for a comma, and take the last name to be everything
56 // preceding the right-most one, so that we also get the "jr" part.
57 vector<docstring> pieces = getVectorFromString(name);
58 if (pieces.size() > 1)
59 // whether we have a jr. part or not, it's always
60 // the first and last item (reversed)
61 return make_pair(pieces.back(), pieces.front());
63 // OK, so now we want to look for the last name. We're going to
64 // include the "von" part. This isn't perfect.
65 // Split on spaces, to get various tokens.
66 pieces = getVectorFromString(name, from_ascii(" "));
67 // If we only get two, assume the last one is the last name
68 if (pieces.size() <= 2)
69 return make_pair(pieces.front(), pieces.back());
71 // Now we look for the first token that begins with
72 // a lower case letter or an opening group {.
74 vector<docstring>::const_iterator it = pieces.begin();
75 vector<docstring>::const_iterator en = pieces.end();
77 for (; it != en; ++it) {
80 char_type const c = (*it)[0];
81 if (isLower(c) || c == '{')
90 if (it == en) // we never found a "von" or group
91 return make_pair(prename, pieces.back());
93 // reconstruct the family name
96 for (; it != en; ++it) {
103 return make_pair(prename, surname);
107 docstring constructName(docstring const & name, string const scheme)
109 // re-constructs a name from name parts according
111 docstring const prename = nameParts(name).first;
112 docstring const surname = nameParts(name).second;
113 docstring result = from_ascii(scheme);
114 result = subst(result, from_ascii("%prename%"), prename);
115 result = subst(result, from_ascii("%surname%"), surname);
120 bool multipleAuthors(docstring const author)
122 vector<docstring> const authors =
123 getVectorFromString(author, from_ascii(" and "));
124 return authors.size() > 1;
128 // converts a string containing LaTeX commands into unicode
130 docstring convertLaTeXCommands(docstring const & str)
135 bool scanning_cmd = false;
136 bool scanning_math = false;
137 bool escaped = false; // used to catch \$, etc.
138 while (!val.empty()) {
139 char_type const ch = val[0];
141 // if we're scanning math, we output everything until we
142 // find an unescaped $, at which point we break out.
149 scanning_math = false;
155 // if we're scanning a command name, then we just
156 // discard characters until we hit something that
159 if (isAlphaASCII(ch)) {
164 // so we're done with this command.
165 // now we fall through and check this character.
166 scanning_cmd = false;
169 // was the last character a \? If so, then this is something like:
170 // \\ or \$, so we'll just output it. That's probably not always right...
172 // exception: output \, as THIN SPACE
174 ret.push_back(0x2009);
185 scanning_math = true;
189 // we just ignore braces
190 if (ch == '{' || ch == '}') {
195 // we're going to check things that look like commands, so if
196 // this doesn't, just output it.
203 // ok, could be a command of some sort
204 // let's see if it corresponds to some unicode
205 // unicodesymbols has things in the form: \"{u},
206 // whereas we may see things like: \"u. So we'll
207 // look for that and change it, if necessary.
208 // FIXME: This is a sort of mini-tex2lyx.
209 // Use the real tex2lyx instead!
210 static lyx::regex const reg("^\\\\\\W\\w");
211 if (lyx::regex_search(to_utf8(val), reg)) {
212 val.insert(3, from_ascii("}"));
213 val.insert(2, from_ascii("{"));
217 docstring const cnvtd = Encodings::fromLaTeXCommand(val,
218 Encodings::TEXT_CMD, termination, rem);
219 if (!cnvtd.empty()) {
220 // it did, so we'll take that bit and proceed with what's left
225 // it's a command of some sort
234 // Escape '<' and '>' and remove richtext markers (e.g. {!this is richtext!}) from a string.
235 docstring processRichtext(docstring const & str, bool richtext)
240 bool scanning_rich = false;
241 while (!val.empty()) {
242 char_type const ch = val[0];
243 if (ch == '{' && val.size() > 1 && val[1] == '!') {
244 // beginning of rich text
245 scanning_rich = true;
249 if (scanning_rich && ch == '!' && val.size() > 1 && val[1] == '}') {
251 scanning_rich = false;
259 // we need to escape '<' and '>'
267 } else if (!scanning_rich /* && !richtext */)
269 // else the character is discarded, which will happen only if
270 // richtext == false and we are scanning rich text
279 //////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////
285 BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
286 : is_bibtex_(true), bib_key_(key), entry_type_(type), info_(),
291 docstring const BibTeXInfo::getAuthorOrEditorList(Buffer const * buf,
292 bool full, bool forceshort) const
294 docstring author = operator[]("author");
296 author = operator[]("editor");
298 return getAuthorList(buf, author, full, forceshort);
302 docstring const BibTeXInfo::getAuthorList(Buffer const * buf, docstring author,
303 bool full, bool forceshort, bool allnames,
304 bool beginning) const
306 // Maxnames treshold depend on engine
307 size_t maxnames = buf ?
308 buf->params().documentClass().max_citenames() : 2;
311 docstring const opt = label();
316 docstring const remainder = trim(split(opt, authors, '('));
317 if (remainder.empty())
318 // in this case, we didn't find a "(",
319 // so we don't have author (year)
327 // FIXME Move this to a separate routine that can
328 // be called from elsewhere.
330 // OK, we've got some names. Let's format them.
331 // Try to split the author list on " and "
332 vector<docstring> const authors =
333 getVectorFromString(author, from_ascii(" and "));
337 CiteEngineType const engine_type = buf ? buf->params().citeEngineType()
338 : ENGINE_TYPE_DEFAULT;
340 // These are defined in the styles
342 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_etal")
344 string const namesep =
345 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_namesep")
347 string const lastnamesep =
348 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_lastnamesep")
350 string const pairnamesep =
351 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_pairnamesep")
353 string firstnameform =
354 buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstnameform")
355 : "%surname%, %prename%";
357 firstnameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstbynameform")
358 : "%prename% %surname%";
359 string othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!othernameform")
360 : "%surname%, %prename%";
362 othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!otherbynameform")
363 : "%prename% %surname%";
365 // Shorten the list (with et al.) if forceshort is set
366 // and the list can actually be shorten, else if maxcitenames
367 // is passed and full is not set.
368 bool shorten = forceshort && authors.size() > 1;
369 vector<docstring>::const_iterator it = authors.begin();
370 vector<docstring>::const_iterator en = authors.end();
371 for (size_t i = 0; it != en; ++it, ++i) {
372 if (i >= maxnames && !full) {
376 if (*it == "others") {
377 retval += buf ? buf->B_(etal) : from_ascii(etal);
380 if (i > 0 && i == authors.size() - 1) {
381 if (authors.size() == 2)
382 retval += buf ? buf->B_(pairnamesep) : from_ascii(pairnamesep);
384 retval += buf ? buf->B_(lastnamesep) : from_ascii(lastnamesep);
386 retval += buf ? buf->B_(namesep) : from_ascii(namesep);
388 retval += (i == 0) ? constructName(*it, firstnameform)
389 : constructName(*it, othernameform);
391 retval += nameParts(*it).second;
395 retval = constructName(authors[0], firstnameform) + (buf ? buf->B_(etal) : from_ascii(etal));
397 retval = nameParts(authors[0]).second + (buf ? buf->B_(etal) : from_ascii(etal));
400 return convertLaTeXCommands(retval);
404 docstring const BibTeXInfo::getYear() const
407 // first try legacy year field
408 docstring year = operator[]("year");
411 // now try biblatex's date field
412 year = operator[]("date");
413 // Format is [-]YYYY-MM-DD*/[-]YYYY-MM-DD*
414 // We only want the years.
415 static regex const yreg("[-]?([\\d]{4}).*");
416 static regex const ereg(".*/[-]?([\\d]{4}).*");
418 string const date = to_utf8(year);
419 regex_match(date, sm, yreg);
420 year = from_ascii(sm[1]);
421 // check for an endyear
422 if (regex_match(date, sm, ereg))
423 year += char_type(0x2013) + from_ascii(sm[1]);
427 docstring const opt = label();
432 docstring tmp = split(opt, authors, '(');
434 // we don't have author (year)
437 tmp = split(tmp, year, ')');
444 docstring parseOptions(docstring const & format, string & optkey,
445 docstring & ifpart, docstring & elsepart);
447 // Calls parseOptions to deal with an embedded option, such as:
448 // {%number%[[, no.~%number%]]}
449 // which must appear at the start of format. ifelsepart gets the
450 // whole of the option, and we return what's left after the option.
451 // we return format if there is an error.
452 docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
454 LASSERT(format[0] == '{' && format[1] == '%', return format);
458 docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
459 if (format == rest) { // parse error
460 LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
463 LASSERT(rest.size() <= format.size(),
464 { ifelsepart = docstring(); return format; });
465 ifelsepart = format.substr(0, format.size() - rest.size());
470 // Gets a "clause" from a format string, where the clause is
471 // delimited by '[[' and ']]'. Returns what is left after the
472 // clause is removed, and returns format if there is an error.
473 docstring getClause(docstring const & format, docstring & clause)
475 docstring fmt = format;
478 // we'll remove characters from the front of fmt as we
480 while (!fmt.empty()) {
481 if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
486 // check for an embedded option
487 if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
489 docstring const rest = parseEmbeddedOption(fmt, part);
491 LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
496 } else { // it's just a normal character
505 // parse an options string, which must appear at the start of the
506 // format parameter. puts the parsed bits in optkey, ifpart, and
507 // elsepart and returns what's left after the option is removed.
508 // if there's an error, it returns format itself.
509 docstring parseOptions(docstring const & format, string & optkey,
510 docstring & ifpart, docstring & elsepart)
512 LASSERT(format[0] == '{' && format[1] == '%', return format);
514 docstring fmt = format.substr(2);
515 size_t pos = fmt.find('%'); // end of key
516 if (pos == string::npos) {
517 LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
520 optkey = to_utf8(fmt.substr(0, pos));
521 fmt = fmt.substr(pos + 1);
522 // [[format]] should be next
523 if (fmt[0] != '[' || fmt[1] != '[') {
524 LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
528 docstring curfmt = fmt;
529 fmt = getClause(curfmt, ifpart);
531 LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
535 if (fmt[0] == '}') // we're done, no else clause
536 return fmt.substr(1);
538 // else part should follow
539 if (fmt[0] != '[' || fmt[1] != '[') {
540 LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
545 fmt = getClause(curfmt, elsepart);
547 if (fmt == curfmt || fmt[0] != '}') {
548 LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
551 return fmt.substr(1);
558 Bug #9131 revealed an oddity in how we are generating citation information
559 when more than one key is given. We end up building a longer and longer format
560 string as we go, which we then have to re-parse, over and over and over again,
561 rather than generating the information for the individual keys and then putting
562 all of that together. We do that to deal with the way separators work, from what
563 I can tell, but it still feels like a hack. Fixing this would require quite a
564 bit of work, however.
566 docstring BibTeXInfo::expandFormat(docstring const & format,
567 BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
568 CiteItem const & ci, bool next, bool second) const
570 // incorrect use of macros could put us in an infinite loop
571 static int const max_passes = 5000;
572 // the use of overly large keys can lead to performance problems, due
573 // to eventual attempts to convert LaTeX macros to unicode. See bug
574 // #8944. By default, the size is limited to 128 (in CiteItem), but
575 // for specific purposes (such as XHTML export), it needs to be enlarged
576 // This is perhaps not the best solution, but it will have to do for now.
577 size_t const max_keysize = ci.max_key_size;
578 odocstringstream ret; // return value
580 bool scanning_key = false;
581 bool scanning_rich = false;
583 CiteEngineType const engine_type = buf.params().citeEngineType();
584 docstring fmt = format;
585 // we'll remove characters from the front of fmt as we
587 while (!fmt.empty()) {
588 if (counter > max_passes) {
589 LYXERR0("Recursion limit reached while parsing `"
594 char_type thischar = fmt[0];
595 if (thischar == '%') {
596 // beginning or end of key
599 scanning_key = false;
600 // so we replace the key with its value, which may be empty
604 buf.params().documentClass().getCiteMacro(engine_type, key);
605 fmt = from_utf8(val) + fmt.substr(1);
608 } else if (key[0] == '_') {
609 // a translatable bit
611 buf.params().documentClass().getCiteMacro(engine_type, key);
612 docstring const trans =
613 translateIfPossible(from_utf8(val), buf.params().language->code());
616 docstring const val =
617 getValueForKey(key, buf, ci, xrefs, max_keysize);
619 ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
622 ret << from_ascii("{!</span>!}");
630 else if (thischar == '{') {
631 // beginning of option?
633 LYXERR0("ERROR: Found `{' when scanning key in `" << format << "'.");
636 if (fmt.size() > 1) {
638 // it is the beginning of an optional format
642 docstring const newfmt =
643 parseOptions(fmt, optkey, ifpart, elsepart);
644 if (newfmt == fmt) // parse error
647 docstring const val =
648 getValueForKey(optkey, buf, ci, xrefs);
649 if (optkey == "next" && next)
650 ret << ifpart; // without expansion
651 else if (optkey == "second" && second) {
653 ret << expandFormat(ifpart, xrefs, newcounter, buf,
655 } else if (!val.empty()) {
657 ret << expandFormat(ifpart, xrefs, newcounter, buf,
659 } else if (!elsepart.empty()) {
661 ret << expandFormat(elsepart, xrefs, newcounter, buf,
664 // fmt will have been shortened for us already
668 // beginning of rich text
669 scanning_rich = true;
671 ret << from_ascii("{!");
675 // we are here if '{' was not followed by % or !.
676 // So it's just a character.
679 else if (scanning_rich && thischar == '!'
680 && fmt.size() > 1 && fmt[1] == '}') {
682 scanning_rich = false;
684 ret << from_ascii("!}");
687 else if (scanning_key)
688 key += char(thischar);
692 } catch (EncodingException & /* e */) {
693 LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
699 LYXERR0("Never found end of key in `" << format << "'!");
703 LYXERR0("Never found end of rich text in `" << format << "'!");
710 docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
711 Buffer const & buf, CiteItem const & ci) const
713 bool const richtext = ci.richtext;
715 if (!richtext && !info_.empty())
717 if (richtext && !info_richtext_.empty())
718 return info_richtext_;
721 BibTeXInfo::const_iterator it = find(from_ascii("ref"));
726 CiteEngineType const engine_type = buf.params().citeEngineType();
727 DocumentClass const & dc = buf.params().documentClass();
728 docstring const & format =
729 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
731 info_ = expandFormat(format, xrefs, counter, buf,
735 // this probably shouldn't happen
740 info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
741 return info_richtext_;
744 info_ = convertLaTeXCommands(processRichtext(info_, false));
749 docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
750 Buffer const & buf, docstring const & format,
751 CiteItem const & ci, bool next, bool second) const
756 loclabel = expandFormat(format, xrefs, counter, buf, ci, next, second);
758 if (!loclabel.empty() && !next) {
759 loclabel = processRichtext(loclabel, ci.richtext);
760 loclabel = convertLaTeXCommands(loclabel);
767 docstring const & BibTeXInfo::operator[](docstring const & field) const
769 BibTeXInfo::const_iterator it = find(field);
772 static docstring const empty_value = docstring();
777 docstring const & BibTeXInfo::operator[](string const & field) const
779 return operator[](from_ascii(field));
783 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
784 CiteItem const & ci, BibTeXInfoList const xrefs, size_t maxsize) const
786 // anything less is pointless
787 LASSERT(maxsize >= 16, maxsize = 16);
789 bool cleanit = false;
790 if (prefixIs(oldkey, "clean:")) {
791 key = oldkey.substr(6);
795 docstring ret = operator[](key);
796 if (ret.empty() && !xrefs.empty()) {
797 vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
798 vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
799 for (; it != en; ++it) {
800 if (*it && !(**it)[key].empty()) {
808 // FIXME: dialog, textbefore and textafter have nothing to do with this
809 if (key == "dialog" && ci.context == CiteItem::Dialog)
810 ret = from_ascii("x"); // any non-empty string will do
811 else if (key == "export" && ci.context == CiteItem::Export)
812 ret = from_ascii("x"); // any non-empty string will do
813 else if (key == "ifstar" && ci.Starred)
814 ret = from_ascii("x"); // any non-empty string will do
815 else if (key == "entrytype")
817 else if (prefixIs(key, "ifentrytype:")
818 && from_ascii(key.substr(12)) == entry_type_)
819 ret = from_ascii("x"); // any non-empty string will do
820 else if (key == "key")
822 else if (key == "label")
824 else if (key == "modifier" && modifier_ != 0)
826 else if (key == "numericallabel")
828 else if (prefixIs(key, "ifmultiple:")) {
829 // Return whether we have multiple authors
830 docstring const kind = operator[](from_ascii(key.substr(11)));
831 if (multipleAuthors(kind))
832 ret = from_ascii("x"); // any non-empty string will do
834 else if (prefixIs(key, "abbrvnames:")) {
835 // Special key to provide abbreviated name list,
836 // with respect to maxcitenames. Suitable for Bibliography
838 docstring const kind = operator[](from_ascii(key.substr(11)));
839 ret = getAuthorList(&buf, kind, false, false, true);
840 if (ci.forceUpperCase && isLowerCase(ret[0]))
841 ret[0] = uppercase(ret[0]);
842 } else if (prefixIs(key, "fullnames:")) {
843 // Return a full name list. Suitable for Bibliography
845 docstring const kind = operator[](from_ascii(key.substr(10)));
846 ret = getAuthorList(&buf, kind, true, false, true);
847 if (ci.forceUpperCase && isLowerCase(ret[0]))
848 ret[0] = uppercase(ret[0]);
849 } else if (prefixIs(key, "forceabbrvnames:")) {
850 // Special key to provide abbreviated name lists,
851 // irrespective of maxcitenames. Suitable for Bibliography
853 docstring const kind = operator[](from_ascii(key.substr(15)));
854 ret = getAuthorList(&buf, kind, false, true, true);
855 if (ci.forceUpperCase && isLowerCase(ret[0]))
856 ret[0] = uppercase(ret[0]);
857 } else if (prefixIs(key, "abbrvbynames:")) {
858 // Special key to provide abbreviated name list,
859 // with respect to maxcitenames. Suitable for further names inside a
860 // bibliography item // (such as "ed. by ...")
861 docstring const kind = operator[](from_ascii(key.substr(11)));
862 ret = getAuthorList(&buf, kind, false, false, true, false);
863 if (ci.forceUpperCase && isLowerCase(ret[0]))
864 ret[0] = uppercase(ret[0]);
865 } else if (prefixIs(key, "fullbynames:")) {
866 // Return a full name list. Suitable for further names inside a
867 // bibliography item // (such as "ed. by ...")
868 docstring const kind = operator[](from_ascii(key.substr(10)));
869 ret = getAuthorList(&buf, kind, true, false, true, false);
870 if (ci.forceUpperCase && isLowerCase(ret[0]))
871 ret[0] = uppercase(ret[0]);
872 } else if (prefixIs(key, "forceabbrvbynames:")) {
873 // Special key to provide abbreviated name lists,
874 // irrespective of maxcitenames. Suitable for further names inside a
875 // bibliography item // (such as "ed. by ...")
876 docstring const kind = operator[](from_ascii(key.substr(15)));
877 ret = getAuthorList(&buf, kind, false, true, true, false);
878 if (ci.forceUpperCase && isLowerCase(ret[0]))
879 ret[0] = uppercase(ret[0]);
880 } else if (key == "abbrvciteauthor") {
881 // Special key to provide abbreviated author or
882 // editor names (suitable for citation labels),
883 // with respect to maxcitenames.
884 ret = getAuthorOrEditorList(&buf, false, false);
885 if (ci.forceUpperCase && isLowerCase(ret[0]))
886 ret[0] = uppercase(ret[0]);
887 } else if (key == "fullciteauthor") {
888 // Return a full author or editor list (for citation labels)
889 ret = getAuthorOrEditorList(&buf, true, false);
890 if (ci.forceUpperCase && isLowerCase(ret[0]))
891 ret[0] = uppercase(ret[0]);
892 } else if (key == "forceabbrvciteauthor") {
893 // Special key to provide abbreviated author or
894 // editor names (suitable for citation labels),
895 // irrespective of maxcitenames.
896 ret = getAuthorOrEditorList(&buf, false, true);
897 if (ci.forceUpperCase && isLowerCase(ret[0]))
898 ret[0] = uppercase(ret[0]);
899 } else if (key == "bibentry") {
900 // Special key to provide the full bibliography entry: see getInfo()
901 CiteEngineType const engine_type = buf.params().citeEngineType();
902 DocumentClass const & dc = buf.params().documentClass();
903 docstring const & format =
904 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_), false));
906 ret = expandFormat(format, xrefs, counter, buf, ci, false, false);
907 } else if (key == "textbefore")
909 else if (key == "textafter")
911 else if (key == "year")
916 ret = html::cleanAttr(ret);
918 // make sure it is not too big
919 support::truncateWithEllipsis(ret, maxsize);
924 //////////////////////////////////////////////////////////////////////
928 //////////////////////////////////////////////////////////////////////
932 // A functor for use with sort, leading to case insensitive sorting
933 class compareNoCase: public binary_function<docstring, docstring, bool>
936 bool operator()(docstring const & s1, docstring const & s2) const {
937 return compare_no_case(s1, s2) < 0;
944 vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
946 vector<docstring> result;
947 if (!data.isBibTeX())
949 // Legacy crossref field. This is not nestable.
950 if (!nested && !data["crossref"].empty()) {
951 docstring const xrefkey = data["crossref"];
952 result.push_back(xrefkey);
953 // However, check for nested xdatas
954 BiblioInfo::const_iterator it = find(xrefkey);
956 BibTeXInfo const & xref = it->second;
957 vector<docstring> const nxdata = getXRefs(xref, true);
959 result.insert(result.end(), nxdata.begin(), nxdata.end());
962 // Biblatex's xdata field. Infinitely nestable.
963 // XData field can consist of a comma-separated list of keys
964 vector<docstring> const xdatakeys = getVectorFromString(data["xdata"]);
965 if (!xdatakeys.empty()) {
966 vector<docstring>::const_iterator xit = xdatakeys.begin();
967 vector<docstring>::const_iterator xen = xdatakeys.end();
968 for (; xit != xen; ++xit) {
969 docstring const xdatakey = *xit;
970 result.push_back(xdatakey);
971 BiblioInfo::const_iterator it = find(xdatakey);
973 BibTeXInfo const & xdata = it->second;
974 vector<docstring> const nxdata = getXRefs(xdata, true);
976 result.insert(result.end(), nxdata.begin(), nxdata.end());
984 vector<docstring> const BiblioInfo::getKeys() const
986 vector<docstring> bibkeys;
987 BiblioInfo::const_iterator it = begin();
988 for (; it != end(); ++it)
989 bibkeys.push_back(it->first);
990 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
995 vector<docstring> const BiblioInfo::getFields() const
997 vector<docstring> bibfields;
998 set<docstring>::const_iterator it = field_names_.begin();
999 set<docstring>::const_iterator end = field_names_.end();
1000 for (; it != end; ++it)
1001 bibfields.push_back(*it);
1002 sort(bibfields.begin(), bibfields.end());
1007 vector<docstring> const BiblioInfo::getEntries() const
1009 vector<docstring> bibentries;
1010 set<docstring>::const_iterator it = entry_types_.begin();
1011 set<docstring>::const_iterator end = entry_types_.end();
1012 for (; it != end; ++it)
1013 bibentries.push_back(*it);
1014 sort(bibentries.begin(), bibentries.end());
1019 docstring const BiblioInfo::getAuthorOrEditorList(docstring const & key, Buffer const & buf) const
1021 BiblioInfo::const_iterator it = find(key);
1024 BibTeXInfo const & data = it->second;
1025 return data.getAuthorOrEditorList(&buf, false);
1029 docstring const BiblioInfo::getCiteNumber(docstring const & key) const
1031 BiblioInfo::const_iterator it = find(key);
1034 BibTeXInfo const & data = it->second;
1035 return data.citeNumber();
1039 docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
1041 BiblioInfo::const_iterator it = find(key);
1044 BibTeXInfo const & data = it->second;
1045 docstring year = data.getYear();
1047 // let's try the crossrefs
1048 vector<docstring> const xrefs = getXRefs(data);
1052 vector<docstring>::const_iterator it = xrefs.begin();
1053 vector<docstring>::const_iterator en = xrefs.end();
1054 for (; it != en; ++it) {
1055 BiblioInfo::const_iterator const xrefit = find(*it);
1056 if (xrefit == end())
1058 BibTeXInfo const & xref_data = xrefit->second;
1059 year = xref_data.getYear();
1065 if (use_modifier && data.modifier() != 0)
1066 year += data.modifier();
1071 docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
1073 docstring const year = getYear(key, use_modifier);
1075 return buf.B_("No year");
1080 docstring const BiblioInfo::getInfo(docstring const & key,
1081 Buffer const & buf, CiteItem const & ci) const
1083 BiblioInfo::const_iterator it = find(key);
1085 return docstring(_("Bibliography entry not found!"));
1086 BibTeXInfo const & data = it->second;
1087 BibTeXInfoList xrefptrs;
1088 vector<docstring> const xrefs = getXRefs(data);
1089 if (!xrefs.empty()) {
1090 vector<docstring>::const_iterator it = xrefs.begin();
1091 vector<docstring>::const_iterator en = xrefs.end();
1092 for (; it != en; ++it) {
1093 BiblioInfo::const_iterator const xrefit = find(*it);
1094 if (xrefit != end())
1095 xrefptrs.push_back(&(xrefit->second));
1098 return data.getInfo(xrefptrs, buf, ci);
1102 docstring const BiblioInfo::getLabel(vector<docstring> keys,
1103 Buffer const & buf, string const & style, CiteItem const & ci) const
1105 size_t max_size = ci.max_size;
1106 // shorter makes no sense
1107 LASSERT(max_size >= 16, max_size = 16);
1109 // we can't display more than 10 of these, anyway
1110 bool const too_many_keys = keys.size() > 10;
1114 CiteEngineType const engine_type = buf.params().citeEngineType();
1115 DocumentClass const & dc = buf.params().documentClass();
1116 docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, false, "cite"));
1117 docstring ret = format;
1118 vector<docstring>::const_iterator key = keys.begin();
1119 vector<docstring>::const_iterator ken = keys.end();
1120 for (int i = 0; key != ken; ++key, ++i) {
1121 BiblioInfo::const_iterator it = find(*key);
1122 BibTeXInfo empty_data;
1123 empty_data.key(*key);
1124 BibTeXInfo & data = empty_data;
1125 vector<BibTeXInfo const *> xrefptrs;
1128 vector<docstring> const xrefs = getXRefs(data);
1129 if (!xrefs.empty()) {
1130 vector<docstring>::const_iterator it = xrefs.begin();
1131 vector<docstring>::const_iterator en = xrefs.end();
1132 for (; it != en; ++it) {
1133 BiblioInfo::const_iterator const xrefit = find(*it);
1134 if (xrefit != end())
1135 xrefptrs.push_back(&(xrefit->second));
1139 ret = data.getLabel(xrefptrs, buf, ret, ci, key + 1 != ken, i == 1);
1143 ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
1144 support::truncateWithEllipsis(ret, max_size);
1149 bool BiblioInfo::isBibtex(docstring const & key) const
1152 split(key, key1, ',');
1153 BiblioInfo::const_iterator it = find(key1);
1156 return it->second.isBibTeX();
1160 vector<docstring> const BiblioInfo::getCiteStrings(
1161 vector<docstring> const & keys, vector<CitationStyle> const & styles,
1162 Buffer const & buf, CiteItem const & ci) const
1165 return vector<docstring>();
1168 vector<docstring> vec(styles.size());
1169 for (size_t i = 0; i != vec.size(); ++i) {
1170 style = styles[i].name;
1171 vec[i] = getLabel(keys, buf, style, ci);
1178 void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
1180 bimap_.insert(info.begin(), info.end());
1181 field_names_.insert(info.field_names_.begin(), info.field_names_.end());
1182 entry_types_.insert(info.entry_types_.begin(), info.entry_types_.end());
1188 // used in xhtml to sort a list of BibTeXInfo objects
1189 bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
1191 docstring const lauth = lhs->getAuthorOrEditorList();
1192 docstring const rauth = rhs->getAuthorOrEditorList();
1193 docstring const lyear = lhs->getYear();
1194 docstring const ryear = rhs->getYear();
1195 docstring const ltitl = lhs->operator[]("title");
1196 docstring const rtitl = rhs->operator[]("title");
1197 return (lauth < rauth)
1198 || (lauth == rauth && lyear < ryear)
1199 || (lauth == rauth && lyear == ryear && ltitl < rtitl);
1205 void BiblioInfo::collectCitedEntries(Buffer const & buf)
1207 cited_entries_.clear();
1208 // We are going to collect all the citation keys used in the document,
1209 // getting them from the TOC.
1210 // FIXME We may want to collect these differently, in the first case,
1211 // so that we might have them in order of appearance.
1212 set<docstring> citekeys;
1213 shared_ptr<Toc const> toc = buf.tocBackend().toc("citation");
1214 Toc::const_iterator it = toc->begin();
1215 Toc::const_iterator const en = toc->end();
1216 for (; it != en; ++it) {
1217 if (it->str().empty())
1219 vector<docstring> const keys = getVectorFromString(it->str());
1220 citekeys.insert(keys.begin(), keys.end());
1222 if (citekeys.empty())
1225 // We have a set of the keys used in this document.
1226 // We will now convert it to a list of the BibTeXInfo objects used in
1228 vector<BibTeXInfo const *> bi;
1229 set<docstring>::const_iterator cit = citekeys.begin();
1230 set<docstring>::const_iterator const cen = citekeys.end();
1231 for (; cit != cen; ++cit) {
1232 BiblioInfo::const_iterator const bt = find(*cit);
1233 if (bt == end() || !bt->second.isBibTeX())
1235 bi.push_back(&(bt->second));
1238 sort(bi.begin(), bi.end(), lSorter);
1240 // Now we can write the sorted keys
1241 vector<BibTeXInfo const *>::const_iterator bit = bi.begin();
1242 vector<BibTeXInfo const *>::const_iterator ben = bi.end();
1243 for (; bit != ben; ++bit)
1244 cited_entries_.push_back((*bit)->key());
1248 void BiblioInfo::makeCitationLabels(Buffer const & buf)
1250 collectCitedEntries(buf);
1251 CiteEngineType const engine_type = buf.params().citeEngineType();
1252 bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
1256 // used to remember the last one we saw
1257 // we'll be comparing entries to see if we need to add
1258 // modifiers, like "1984a"
1259 map<docstring, BibTeXInfo>::iterator last;
1261 vector<docstring>::const_iterator it = cited_entries_.begin();
1262 vector<docstring>::const_iterator const en = cited_entries_.end();
1263 for (; it != en; ++it) {
1264 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1265 // this shouldn't happen, but...
1266 if (biit == bimap_.end())
1267 // ...fail gracefully, anyway.
1269 BibTeXInfo & entry = biit->second;
1271 docstring const num = convert<docstring>(++keynumber);
1272 entry.setCiteNumber(num);
1274 // coverity complains about our derefercing the iterator last,
1275 // which was not initialized above. but it does get initialized
1276 // after the first time through the loop, which is the point of
1278 // coverity[FORWARD_NULL]
1279 if (it != cited_entries_.begin()
1280 && entry.getAuthorOrEditorList() == last->second.getAuthorOrEditorList()
1281 // we access the year via getYear() so as to get it from the xref,
1282 // if we need to do so
1283 && getYear(entry.key()) == getYear(last->second.key())) {
1284 if (modifier == 0) {
1285 // so the last one should have been 'a'
1286 last->second.setModifier('a');
1288 } else if (modifier == 'z')
1295 entry.setModifier(modifier);
1296 // remember the last one
1301 it = cited_entries_.begin();
1302 for (; it != en; ++it) {
1303 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1304 // this shouldn't happen, but...
1305 if (biit == bimap_.end())
1306 // ...fail gracefully, anyway.
1308 BibTeXInfo & entry = biit->second;
1310 entry.label(entry.citeNumber());
1312 docstring const auth = entry.getAuthorOrEditorList(&buf, false);
1313 // we do it this way so as to access the xref, if necessary
1314 // note that this also gives us the modifier
1315 docstring const year = getYear(*it, buf, true);
1316 if (!auth.empty() && !year.empty())
1317 entry.label(auth + ' ' + year);
1319 entry.label(entry.key());
1325 //////////////////////////////////////////////////////////////////////
1329 //////////////////////////////////////////////////////////////////////
1332 CitationStyle citationStyleFromString(string const & command,
1333 BufferParams const & params)
1336 if (command.empty())
1339 string const alias = params.getCiteAlias(command);
1340 string cmd = alias.empty() ? command : alias;
1341 if (isUpperCase(command[0])) {
1342 cs.forceUpperCase = true;
1343 cmd[0] = lowercase(cmd[0]);
1346 size_t const n = command.size() - 1;
1347 if (command[n] == '*') {
1348 cs.hasStarredVersion = true;
1349 if (suffixIs(cmd, '*'))
1350 cmd = cmd.substr(0, cmd.size() - 1);
1358 string citationStyleToString(const CitationStyle & cs, bool const latex)
1360 string cmd = latex ? cs.cmd : cs.name;
1361 if (cs.forceUpperCase)
1362 cmd[0] = uppercase(cmd[0]);
1363 if (cs.hasStarredVersion)