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"
43 using namespace lyx::support;
50 // gets the "prename" and "family name" from an author-type string
51 pair<docstring, docstring> nameParts(docstring const & name)
54 return make_pair(docstring(), docstring());
56 // first we look for a comma, and take the last name to be everything
57 // preceding the right-most one, so that we also get the "jr" part.
58 vector<docstring> pieces = getVectorFromString(name);
59 if (pieces.size() > 1)
60 // whether we have a jr. part or not, it's always
61 // the first and last item (reversed)
62 return make_pair(pieces.back(), pieces.front());
64 // OK, so now we want to look for the last name. We're going to
65 // include the "von" part. This isn't perfect.
66 // Split on spaces, to get various tokens.
67 pieces = getVectorFromString(name, from_ascii(" "));
68 // If we only get two, assume the last one is the last name
69 if (pieces.size() <= 2)
70 return make_pair(pieces.front(), pieces.back());
72 // Now we look for the first token that begins with
73 // a lower case letter or an opening group {.
75 vector<docstring>::const_iterator it = pieces.begin();
76 vector<docstring>::const_iterator en = pieces.end();
78 for (; it != en; ++it) {
81 char_type const c = (*it)[0];
82 if (isLower(c) || c == '{')
91 if (it == en) // we never found a "von" or group
92 return make_pair(prename, pieces.back());
94 // reconstruct the family name
97 for (; it != en; ++it) {
104 return make_pair(prename, surname);
108 docstring constructName(docstring const & name, string const scheme)
110 // re-constructs a name from name parts according
112 docstring const prename = nameParts(name).first;
113 docstring const surname = nameParts(name).second;
114 docstring result = from_ascii(scheme);
115 result = subst(result, from_ascii("%prename%"), prename);
116 result = subst(result, from_ascii("%surname%"), surname);
121 bool multipleAuthors(docstring const author)
123 vector<docstring> const authors =
124 getVectorFromString(author, from_ascii(" and "));
125 return authors.size() > 1;
129 // converts a string containing LaTeX commands into unicode
131 docstring convertLaTeXCommands(docstring const & str)
136 bool scanning_cmd = false;
137 bool scanning_math = false;
138 bool escaped = false; // used to catch \$, etc.
139 while (!val.empty()) {
140 char_type const ch = val[0];
142 // if we're scanning math, we output everything until we
143 // find an unescaped $, at which point we break out.
150 scanning_math = false;
156 // if we're scanning a command name, then we just
157 // discard characters until we hit something that
160 if (isAlphaASCII(ch)) {
165 // so we're done with this command.
166 // now we fall through and check this character.
167 scanning_cmd = false;
170 // was the last character a \? If so, then this is something like:
171 // \\ or \$, so we'll just output it. That's probably not always right...
173 // exception: output \, as THIN SPACE
175 ret.push_back(0x2009);
186 scanning_math = true;
190 // we just ignore braces
191 if (ch == '{' || ch == '}') {
196 // we're going to check things that look like commands, so if
197 // this doesn't, just output it.
204 // ok, could be a command of some sort
205 // let's see if it corresponds to some unicode
206 // unicodesymbols has things in the form: \"{u},
207 // whereas we may see things like: \"u. So we'll
208 // look for that and change it, if necessary.
209 // FIXME: This is a sort of mini-tex2lyx.
210 // Use the real tex2lyx instead!
211 static lyx::regex const reg("^\\\\\\W\\w");
212 if (lyx::regex_search(to_utf8(val), reg)) {
213 val.insert(3, from_ascii("}"));
214 val.insert(2, from_ascii("{"));
218 docstring const cnvtd = Encodings::fromLaTeXCommand(val,
219 Encodings::TEXT_CMD, termination, rem);
220 if (!cnvtd.empty()) {
221 // it did, so we'll take that bit and proceed with what's left
226 // it's a command of some sort
235 // Escape '<' and '>' and remove richtext markers (e.g. {!this is richtext!}) from a string.
236 docstring processRichtext(docstring const & str, bool richtext)
241 bool scanning_rich = false;
242 while (!val.empty()) {
243 char_type const ch = val[0];
244 if (ch == '{' && val.size() > 1 && val[1] == '!') {
245 // beginning of rich text
246 scanning_rich = true;
250 if (scanning_rich && ch == '!' && val.size() > 1 && val[1] == '}') {
252 scanning_rich = false;
260 // we need to escape '<' and '>'
268 } else if (!scanning_rich /* && !richtext */)
270 // else the character is discarded, which will happen only if
271 // richtext == false and we are scanning rich text
280 //////////////////////////////////////////////////////////////////////
284 //////////////////////////////////////////////////////////////////////
286 BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
287 : is_bibtex_(true), bib_key_(key), entry_type_(type), info_(),
292 docstring const BibTeXInfo::getAuthorOrEditorList(Buffer const * buf,
293 bool full, bool forceshort) const
295 docstring author = operator[]("author");
297 author = operator[]("editor");
299 return getAuthorList(buf, author, full, forceshort);
303 docstring const BibTeXInfo::getAuthorList(Buffer const * buf, docstring author,
304 bool full, bool forceshort, bool allnames,
305 bool beginning) const
307 // Maxnames treshold depend on engine
308 size_t maxnames = buf ?
309 buf->params().documentClass().max_citenames() : 2;
312 docstring const opt = label();
317 docstring const remainder = trim(split(opt, authors, '('));
318 if (remainder.empty())
319 // in this case, we didn't find a "(",
320 // so we don't have author (year)
328 // FIXME Move this to a separate routine that can
329 // be called from elsewhere.
331 // OK, we've got some names. Let's format them.
332 // Try to split the author list on " and "
333 vector<docstring> const authors =
334 getVectorFromString(author, from_ascii(" and "));
338 CiteEngineType const engine_type = buf ? buf->params().citeEngineType()
339 : ENGINE_TYPE_DEFAULT;
341 // These are defined in the styles
343 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_etal")
345 string const namesep =
346 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_namesep")
348 string const lastnamesep =
349 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_lastnamesep")
351 string const pairnamesep =
352 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_pairnamesep")
354 string firstnameform =
355 buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstnameform")
356 : "%surname%, %prename%";
358 firstnameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstbynameform")
359 : "%prename% %surname%";
360 string othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!othernameform")
361 : "%surname%, %prename%";
363 othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!otherbynameform")
364 : "%prename% %surname%";
366 // Shorten the list (with et al.) if forceshort is set
367 // and the list can actually be shorten, else if maxcitenames
368 // is passed and full is not set.
369 bool shorten = forceshort && authors.size() > 1;
370 vector<docstring>::const_iterator it = authors.begin();
371 vector<docstring>::const_iterator en = authors.end();
372 for (size_t i = 0; it != en; ++it, ++i) {
373 if (i >= maxnames && !full) {
377 if (*it == "others") {
378 retval += buf ? buf->B_(etal) : from_ascii(etal);
381 if (i > 0 && i == authors.size() - 1) {
382 if (authors.size() == 2)
383 retval += buf ? buf->B_(pairnamesep) : from_ascii(pairnamesep);
385 retval += buf ? buf->B_(lastnamesep) : from_ascii(lastnamesep);
387 retval += buf ? buf->B_(namesep) : from_ascii(namesep);
389 retval += (i == 0) ? constructName(*it, firstnameform)
390 : constructName(*it, othernameform);
392 retval += nameParts(*it).second;
396 retval = constructName(authors[0], firstnameform) + (buf ? buf->B_(etal) : from_ascii(etal));
398 retval = nameParts(authors[0]).second + (buf ? buf->B_(etal) : from_ascii(etal));
401 return convertLaTeXCommands(retval);
405 docstring const BibTeXInfo::getYear() const
408 // first try legacy year field
409 docstring year = operator[]("year");
412 // now try biblatex's date field
413 year = operator[]("date");
414 // Format is [-]YYYY-MM-DD*/[-]YYYY-MM-DD*
415 // We only want the years.
416 static regex const yreg("[-]?([\\d]{4}).*");
417 static regex const ereg(".*/[-]?([\\d]{4}).*");
419 string const date = to_utf8(year);
420 regex_match(date, sm, yreg);
421 year = from_ascii(sm[1]);
422 // check for an endyear
423 if (regex_match(date, sm, ereg))
424 year += char_type(0x2013) + from_ascii(sm[1]);
428 docstring const opt = label();
433 docstring tmp = split(opt, authors, '(');
435 // we don't have author (year)
438 tmp = split(tmp, year, ')');
445 docstring parseOptions(docstring const & format, string & optkey,
446 docstring & ifpart, docstring & elsepart);
448 // Calls parseOptions to deal with an embedded option, such as:
449 // {%number%[[, no.~%number%]]}
450 // which must appear at the start of format. ifelsepart gets the
451 // whole of the option, and we return what's left after the option.
452 // we return format if there is an error.
453 docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
455 LASSERT(format[0] == '{' && format[1] == '%', return format);
459 docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
460 if (format == rest) { // parse error
461 LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
464 LASSERT(rest.size() <= format.size(),
465 { ifelsepart = docstring(); return format; });
466 ifelsepart = format.substr(0, format.size() - rest.size());
471 // Gets a "clause" from a format string, where the clause is
472 // delimited by '[[' and ']]'. Returns what is left after the
473 // clause is removed, and returns format if there is an error.
474 docstring getClause(docstring const & format, docstring & clause)
476 docstring fmt = format;
479 // we'll remove characters from the front of fmt as we
481 while (!fmt.empty()) {
482 if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
487 // check for an embedded option
488 if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
490 docstring const rest = parseEmbeddedOption(fmt, part);
492 LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
497 } else { // it's just a normal character
506 // parse an options string, which must appear at the start of the
507 // format parameter. puts the parsed bits in optkey, ifpart, and
508 // elsepart and returns what's left after the option is removed.
509 // if there's an error, it returns format itself.
510 docstring parseOptions(docstring const & format, string & optkey,
511 docstring & ifpart, docstring & elsepart)
513 LASSERT(format[0] == '{' && format[1] == '%', return format);
515 docstring fmt = format.substr(2);
516 size_t pos = fmt.find('%'); // end of key
517 if (pos == string::npos) {
518 LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
521 optkey = to_utf8(fmt.substr(0, pos));
522 fmt = fmt.substr(pos + 1);
523 // [[format]] should be next
524 if (fmt[0] != '[' || fmt[1] != '[') {
525 LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
529 docstring curfmt = fmt;
530 fmt = getClause(curfmt, ifpart);
532 LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
536 if (fmt[0] == '}') // we're done, no else clause
537 return fmt.substr(1);
539 // else part should follow
540 if (fmt[0] != '[' || fmt[1] != '[') {
541 LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
546 fmt = getClause(curfmt, elsepart);
548 if (fmt == curfmt || fmt[0] != '}') {
549 LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
552 return fmt.substr(1);
559 Bug #9131 revealed an oddity in how we are generating citation information
560 when more than one key is given. We end up building a longer and longer format
561 string as we go, which we then have to re-parse, over and over and over again,
562 rather than generating the information for the individual keys and then putting
563 all of that together. We do that to deal with the way separators work, from what
564 I can tell, but it still feels like a hack. Fixing this would require quite a
565 bit of work, however.
567 docstring BibTeXInfo::expandFormat(docstring const & format,
568 BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
569 CiteItem const & ci, bool next, bool second) const
571 // incorrect use of macros could put us in an infinite loop
572 static int const max_passes = 5000;
573 // the use of overly large keys can lead to performance problems, due
574 // to eventual attempts to convert LaTeX macros to unicode. See bug
575 // #8944. By default, the size is limited to 128 (in CiteItem), but
576 // for specific purposes (such as XHTML export), it needs to be enlarged
577 // This is perhaps not the best solution, but it will have to do for now.
578 size_t const max_keysize = ci.max_key_size;
579 odocstringstream ret; // return value
581 bool scanning_key = false;
582 bool scanning_rich = false;
584 CiteEngineType const engine_type = buf.params().citeEngineType();
585 docstring fmt = format;
586 // we'll remove characters from the front of fmt as we
588 while (!fmt.empty()) {
589 if (counter > max_passes) {
590 LYXERR0("Recursion limit reached while parsing `"
595 char_type thischar = fmt[0];
596 if (thischar == '%') {
597 // beginning or end of key
600 scanning_key = false;
601 // so we replace the key with its value, which may be empty
605 buf.params().documentClass().getCiteMacro(engine_type, key);
606 fmt = from_utf8(val) + fmt.substr(1);
609 } else if (key[0] == '_') {
610 // a translatable bit
612 buf.params().documentClass().getCiteMacro(engine_type, key);
613 docstring const trans =
614 translateIfPossible(from_utf8(val), buf.params().language->code());
617 docstring const val =
618 getValueForKey(key, buf, ci, xrefs, max_keysize);
620 ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
623 ret << from_ascii("{!</span>!}");
631 else if (thischar == '{') {
632 // beginning of option?
634 LYXERR0("ERROR: Found `{' when scanning key in `" << format << "'.");
637 if (fmt.size() > 1) {
639 // it is the beginning of an optional format
643 docstring const newfmt =
644 parseOptions(fmt, optkey, ifpart, elsepart);
645 if (newfmt == fmt) // parse error
648 docstring const val =
649 getValueForKey(optkey, buf, ci, xrefs);
650 if (optkey == "next" && next)
651 ret << ifpart; // without expansion
652 else if (optkey == "second" && second) {
654 ret << expandFormat(ifpart, xrefs, newcounter, buf,
656 } else if (!val.empty()) {
658 ret << expandFormat(ifpart, xrefs, newcounter, buf,
660 } else if (!elsepart.empty()) {
662 ret << expandFormat(elsepart, xrefs, newcounter, buf,
665 // fmt will have been shortened for us already
669 // beginning of rich text
670 scanning_rich = true;
672 ret << from_ascii("{!");
676 // we are here if '{' was not followed by % or !.
677 // So it's just a character.
680 else if (scanning_rich && thischar == '!'
681 && fmt.size() > 1 && fmt[1] == '}') {
683 scanning_rich = false;
685 ret << from_ascii("!}");
688 else if (scanning_key)
689 key += char(thischar);
693 } catch (EncodingException & /* e */) {
694 LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
700 LYXERR0("Never found end of key in `" << format << "'!");
704 LYXERR0("Never found end of rich text in `" << format << "'!");
711 docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
712 Buffer const & buf, CiteItem const & ci) const
714 bool const richtext = ci.richtext;
716 if (!richtext && !info_.empty())
718 if (richtext && !info_richtext_.empty())
719 return info_richtext_;
722 BibTeXInfo::const_iterator it = find(from_ascii("ref"));
727 CiteEngineType const engine_type = buf.params().citeEngineType();
728 DocumentClass const & dc = buf.params().documentClass();
729 docstring const & format =
730 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
732 info_ = expandFormat(format, xrefs, counter, buf,
736 // this probably shouldn't happen
741 info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
742 return info_richtext_;
745 info_ = convertLaTeXCommands(processRichtext(info_, false));
750 docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
751 Buffer const & buf, docstring const & format,
752 CiteItem const & ci, bool next, bool second) const
757 loclabel = expandFormat(format, xrefs, counter, buf, ci, next, second);
759 if (!loclabel.empty() && !next) {
760 loclabel = processRichtext(loclabel, ci.richtext);
761 loclabel = convertLaTeXCommands(loclabel);
768 docstring const & BibTeXInfo::operator[](docstring const & field) const
770 BibTeXInfo::const_iterator it = find(field);
773 static docstring const empty_value = docstring();
778 docstring const & BibTeXInfo::operator[](string const & field) const
780 return operator[](from_ascii(field));
784 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
785 CiteItem const & ci, BibTeXInfoList const xrefs, size_t maxsize) const
787 // anything less is pointless
788 LASSERT(maxsize >= 16, maxsize = 16);
790 bool cleanit = false;
791 if (prefixIs(oldkey, "clean:")) {
792 key = oldkey.substr(6);
796 docstring ret = operator[](key);
797 if (ret.empty() && !xrefs.empty()) {
798 vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
799 vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
800 for (; it != en; ++it) {
801 if (*it && !(**it)[key].empty()) {
809 // FIXME: dialog, textbefore and textafter have nothing to do with this
810 if (key == "dialog" && ci.context == CiteItem::Dialog)
811 ret = from_ascii("x"); // any non-empty string will do
812 else if (key == "export" && ci.context == CiteItem::Export)
813 ret = from_ascii("x"); // any non-empty string will do
814 else if (key == "ifstar" && ci.Starred)
815 ret = from_ascii("x"); // any non-empty string will do
816 else if (key == "ifqualified" && ci.isQualified)
817 ret = from_ascii("x"); // any non-empty string will do
818 else if (key == "entrytype")
820 else if (prefixIs(key, "ifentrytype:")
821 && from_ascii(key.substr(12)) == entry_type_)
822 ret = from_ascii("x"); // any non-empty string will do
823 else if (key == "key")
825 else if (key == "label")
827 else if (key == "modifier" && modifier_ != 0)
829 else if (key == "numericallabel")
831 else if (prefixIs(key, "ifmultiple:")) {
832 // Return whether we have multiple authors
833 docstring const kind = operator[](from_ascii(key.substr(11)));
834 if (multipleAuthors(kind))
835 ret = from_ascii("x"); // any non-empty string will do
837 else if (prefixIs(key, "abbrvnames:")) {
838 // Special key to provide abbreviated name list,
839 // with respect to maxcitenames. Suitable for Bibliography
841 docstring const kind = operator[](from_ascii(key.substr(11)));
842 ret = getAuthorList(&buf, kind, false, false, true);
843 if (ci.forceUpperCase && isLowerCase(ret[0]))
844 ret[0] = uppercase(ret[0]);
845 } else if (prefixIs(key, "fullnames:")) {
846 // Return a full name list. Suitable for Bibliography
848 docstring const kind = operator[](from_ascii(key.substr(10)));
849 ret = getAuthorList(&buf, kind, true, false, true);
850 if (ci.forceUpperCase && isLowerCase(ret[0]))
851 ret[0] = uppercase(ret[0]);
852 } else if (prefixIs(key, "forceabbrvnames:")) {
853 // Special key to provide abbreviated name lists,
854 // irrespective of maxcitenames. Suitable for Bibliography
856 docstring const kind = operator[](from_ascii(key.substr(15)));
857 ret = getAuthorList(&buf, kind, false, true, true);
858 if (ci.forceUpperCase && isLowerCase(ret[0]))
859 ret[0] = uppercase(ret[0]);
860 } else if (prefixIs(key, "abbrvbynames:")) {
861 // Special key to provide abbreviated name list,
862 // with respect to maxcitenames. Suitable for further names inside a
863 // bibliography item // (such as "ed. by ...")
864 docstring const kind = operator[](from_ascii(key.substr(11)));
865 ret = getAuthorList(&buf, kind, false, false, true, false);
866 if (ci.forceUpperCase && isLowerCase(ret[0]))
867 ret[0] = uppercase(ret[0]);
868 } else if (prefixIs(key, "fullbynames:")) {
869 // Return a full name list. Suitable for further names inside a
870 // bibliography item // (such as "ed. by ...")
871 docstring const kind = operator[](from_ascii(key.substr(10)));
872 ret = getAuthorList(&buf, kind, true, false, true, false);
873 if (ci.forceUpperCase && isLowerCase(ret[0]))
874 ret[0] = uppercase(ret[0]);
875 } else if (prefixIs(key, "forceabbrvbynames:")) {
876 // Special key to provide abbreviated name lists,
877 // irrespective of maxcitenames. Suitable for further names inside a
878 // bibliography item // (such as "ed. by ...")
879 docstring const kind = operator[](from_ascii(key.substr(15)));
880 ret = getAuthorList(&buf, kind, false, true, true, false);
881 if (ci.forceUpperCase && isLowerCase(ret[0]))
882 ret[0] = uppercase(ret[0]);
883 } else if (key == "abbrvciteauthor") {
884 // Special key to provide abbreviated author or
885 // editor names (suitable for citation labels),
886 // with respect to maxcitenames.
887 ret = getAuthorOrEditorList(&buf, false, false);
888 if (ci.forceUpperCase && isLowerCase(ret[0]))
889 ret[0] = uppercase(ret[0]);
890 } else if (key == "fullciteauthor") {
891 // Return a full author or editor list (for citation labels)
892 ret = getAuthorOrEditorList(&buf, true, false);
893 if (ci.forceUpperCase && isLowerCase(ret[0]))
894 ret[0] = uppercase(ret[0]);
895 } else if (key == "forceabbrvciteauthor") {
896 // Special key to provide abbreviated author or
897 // editor names (suitable for citation labels),
898 // irrespective of maxcitenames.
899 ret = getAuthorOrEditorList(&buf, false, true);
900 if (ci.forceUpperCase && isLowerCase(ret[0]))
901 ret[0] = uppercase(ret[0]);
902 } else if (key == "bibentry") {
903 // Special key to provide the full bibliography entry: see getInfo()
904 CiteEngineType const engine_type = buf.params().citeEngineType();
905 DocumentClass const & dc = buf.params().documentClass();
906 docstring const & format =
907 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_), false));
909 ret = expandFormat(format, xrefs, counter, buf, ci, false, false);
910 } else if (key == "textbefore")
912 else if (key == "textafter")
914 else if (key == "curpretext")
915 ret = ci.getPretexts()[bib_key_];
916 else if (key == "curposttext")
917 ret = ci.getPosttexts()[bib_key_];
918 else if (key == "year")
923 ret = html::cleanAttr(ret);
925 // make sure it is not too big
926 support::truncateWithEllipsis(ret, maxsize);
931 //////////////////////////////////////////////////////////////////////
935 //////////////////////////////////////////////////////////////////////
939 // A functor for use with sort, leading to case insensitive sorting
940 class compareNoCase: public binary_function<docstring, docstring, bool>
943 bool operator()(docstring const & s1, docstring const & s2) const {
944 return compare_no_case(s1, s2) < 0;
951 vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
953 vector<docstring> result;
954 if (!data.isBibTeX())
956 // Legacy crossref field. This is not nestable.
957 if (!nested && !data["crossref"].empty()) {
958 docstring const xrefkey = data["crossref"];
959 result.push_back(xrefkey);
960 // However, check for nested xdatas
961 BiblioInfo::const_iterator it = find(xrefkey);
963 BibTeXInfo const & xref = it->second;
964 vector<docstring> const nxdata = getXRefs(xref, true);
966 result.insert(result.end(), nxdata.begin(), nxdata.end());
969 // Biblatex's xdata field. Infinitely nestable.
970 // XData field can consist of a comma-separated list of keys
971 vector<docstring> const xdatakeys = getVectorFromString(data["xdata"]);
972 if (!xdatakeys.empty()) {
973 vector<docstring>::const_iterator xit = xdatakeys.begin();
974 vector<docstring>::const_iterator xen = xdatakeys.end();
975 for (; xit != xen; ++xit) {
976 docstring const xdatakey = *xit;
977 result.push_back(xdatakey);
978 BiblioInfo::const_iterator it = find(xdatakey);
980 BibTeXInfo const & xdata = it->second;
981 vector<docstring> const nxdata = getXRefs(xdata, true);
983 result.insert(result.end(), nxdata.begin(), nxdata.end());
991 vector<docstring> const BiblioInfo::getKeys() const
993 vector<docstring> bibkeys;
994 BiblioInfo::const_iterator it = begin();
995 for (; it != end(); ++it)
996 bibkeys.push_back(it->first);
997 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
1002 vector<docstring> const BiblioInfo::getFields() const
1004 vector<docstring> bibfields;
1005 set<docstring>::const_iterator it = field_names_.begin();
1006 set<docstring>::const_iterator end = field_names_.end();
1007 for (; it != end; ++it)
1008 bibfields.push_back(*it);
1009 sort(bibfields.begin(), bibfields.end());
1014 vector<docstring> const BiblioInfo::getEntries() const
1016 vector<docstring> bibentries;
1017 set<docstring>::const_iterator it = entry_types_.begin();
1018 set<docstring>::const_iterator end = entry_types_.end();
1019 for (; it != end; ++it)
1020 bibentries.push_back(*it);
1021 sort(bibentries.begin(), bibentries.end());
1026 docstring const BiblioInfo::getAuthorOrEditorList(docstring const & key, Buffer const & buf) const
1028 BiblioInfo::const_iterator it = find(key);
1031 BibTeXInfo const & data = it->second;
1032 return data.getAuthorOrEditorList(&buf, false);
1036 docstring const BiblioInfo::getCiteNumber(docstring const & key) const
1038 BiblioInfo::const_iterator it = find(key);
1041 BibTeXInfo const & data = it->second;
1042 return data.citeNumber();
1046 docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
1048 BiblioInfo::const_iterator it = find(key);
1051 BibTeXInfo const & data = it->second;
1052 docstring year = data.getYear();
1054 // let's try the crossrefs
1055 vector<docstring> const xrefs = getXRefs(data);
1059 vector<docstring>::const_iterator it = xrefs.begin();
1060 vector<docstring>::const_iterator en = xrefs.end();
1061 for (; it != en; ++it) {
1062 BiblioInfo::const_iterator const xrefit = find(*it);
1063 if (xrefit == end())
1065 BibTeXInfo const & xref_data = xrefit->second;
1066 year = xref_data.getYear();
1072 if (use_modifier && data.modifier() != 0)
1073 year += data.modifier();
1078 docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
1080 docstring const year = getYear(key, use_modifier);
1082 return buf.B_("No year");
1087 docstring const BiblioInfo::getInfo(docstring const & key,
1088 Buffer const & buf, CiteItem const & ci) const
1090 BiblioInfo::const_iterator it = find(key);
1092 return docstring(_("Bibliography entry not found!"));
1093 BibTeXInfo const & data = it->second;
1094 BibTeXInfoList xrefptrs;
1095 vector<docstring> const xrefs = getXRefs(data);
1096 if (!xrefs.empty()) {
1097 vector<docstring>::const_iterator it = xrefs.begin();
1098 vector<docstring>::const_iterator en = xrefs.end();
1099 for (; it != en; ++it) {
1100 BiblioInfo::const_iterator const xrefit = find(*it);
1101 if (xrefit != end())
1102 xrefptrs.push_back(&(xrefit->second));
1105 return data.getInfo(xrefptrs, buf, ci);
1109 docstring const BiblioInfo::getLabel(vector<docstring> keys,
1110 Buffer const & buf, string const & style, CiteItem const & ci) const
1112 size_t max_size = ci.max_size;
1113 // shorter makes no sense
1114 LASSERT(max_size >= 16, max_size = 16);
1116 // we can't display more than 10 of these, anyway
1117 bool const too_many_keys = keys.size() > 10;
1121 CiteEngineType const engine_type = buf.params().citeEngineType();
1122 DocumentClass const & dc = buf.params().documentClass();
1123 docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, false, "cite"));
1124 docstring ret = format;
1125 vector<docstring>::const_iterator key = keys.begin();
1126 vector<docstring>::const_iterator ken = keys.end();
1127 for (int i = 0; key != ken; ++key, ++i) {
1128 BiblioInfo::const_iterator it = find(*key);
1129 BibTeXInfo empty_data;
1130 empty_data.key(*key);
1131 BibTeXInfo & data = empty_data;
1132 vector<BibTeXInfo const *> xrefptrs;
1135 vector<docstring> const xrefs = getXRefs(data);
1136 if (!xrefs.empty()) {
1137 vector<docstring>::const_iterator it = xrefs.begin();
1138 vector<docstring>::const_iterator en = xrefs.end();
1139 for (; it != en; ++it) {
1140 BiblioInfo::const_iterator const xrefit = find(*it);
1141 if (xrefit != end())
1142 xrefptrs.push_back(&(xrefit->second));
1146 ret = data.getLabel(xrefptrs, buf, ret, ci, key + 1 != ken, i == 1);
1150 ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
1151 support::truncateWithEllipsis(ret, max_size);
1156 bool BiblioInfo::isBibtex(docstring const & key) const
1159 split(key, key1, ',');
1160 BiblioInfo::const_iterator it = find(key1);
1163 return it->second.isBibTeX();
1167 vector<docstring> const BiblioInfo::getCiteStrings(
1168 vector<docstring> const & keys, vector<CitationStyle> const & styles,
1169 Buffer const & buf, CiteItem const & ci) const
1172 return vector<docstring>();
1175 vector<docstring> vec(styles.size());
1176 for (size_t i = 0; i != vec.size(); ++i) {
1177 style = styles[i].name;
1178 vec[i] = getLabel(keys, buf, style, ci);
1185 void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
1187 bimap_.insert(info.begin(), info.end());
1188 field_names_.insert(info.field_names_.begin(), info.field_names_.end());
1189 entry_types_.insert(info.entry_types_.begin(), info.entry_types_.end());
1195 // used in xhtml to sort a list of BibTeXInfo objects
1196 bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
1198 docstring const lauth = lhs->getAuthorOrEditorList();
1199 docstring const rauth = rhs->getAuthorOrEditorList();
1200 docstring const lyear = lhs->getYear();
1201 docstring const ryear = rhs->getYear();
1202 docstring const ltitl = lhs->operator[]("title");
1203 docstring const rtitl = rhs->operator[]("title");
1204 return (lauth < rauth)
1205 || (lauth == rauth && lyear < ryear)
1206 || (lauth == rauth && lyear == ryear && ltitl < rtitl);
1212 void BiblioInfo::collectCitedEntries(Buffer const & buf)
1214 cited_entries_.clear();
1215 // We are going to collect all the citation keys used in the document,
1216 // getting them from the TOC.
1217 // FIXME We may want to collect these differently, in the first case,
1218 // so that we might have them in order of appearance.
1219 set<docstring> citekeys;
1220 shared_ptr<Toc const> toc = buf.tocBackend().toc("citation");
1221 Toc::const_iterator it = toc->begin();
1222 Toc::const_iterator const en = toc->end();
1223 for (; it != en; ++it) {
1224 if (it->str().empty())
1226 vector<docstring> const keys = getVectorFromString(it->str());
1227 citekeys.insert(keys.begin(), keys.end());
1229 if (citekeys.empty())
1232 // We have a set of the keys used in this document.
1233 // We will now convert it to a list of the BibTeXInfo objects used in
1235 vector<BibTeXInfo const *> bi;
1236 set<docstring>::const_iterator cit = citekeys.begin();
1237 set<docstring>::const_iterator const cen = citekeys.end();
1238 for (; cit != cen; ++cit) {
1239 BiblioInfo::const_iterator const bt = find(*cit);
1240 if (bt == end() || !bt->second.isBibTeX())
1242 bi.push_back(&(bt->second));
1245 sort(bi.begin(), bi.end(), lSorter);
1247 // Now we can write the sorted keys
1248 vector<BibTeXInfo const *>::const_iterator bit = bi.begin();
1249 vector<BibTeXInfo const *>::const_iterator ben = bi.end();
1250 for (; bit != ben; ++bit)
1251 cited_entries_.push_back((*bit)->key());
1255 void BiblioInfo::makeCitationLabels(Buffer const & buf)
1257 collectCitedEntries(buf);
1258 CiteEngineType const engine_type = buf.params().citeEngineType();
1259 bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
1263 // used to remember the last one we saw
1264 // we'll be comparing entries to see if we need to add
1265 // modifiers, like "1984a"
1266 map<docstring, BibTeXInfo>::iterator last;
1268 vector<docstring>::const_iterator it = cited_entries_.begin();
1269 vector<docstring>::const_iterator const en = cited_entries_.end();
1270 for (; it != en; ++it) {
1271 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1272 // this shouldn't happen, but...
1273 if (biit == bimap_.end())
1274 // ...fail gracefully, anyway.
1276 BibTeXInfo & entry = biit->second;
1278 docstring const num = convert<docstring>(++keynumber);
1279 entry.setCiteNumber(num);
1281 // coverity complains about our derefercing the iterator last,
1282 // which was not initialized above. but it does get initialized
1283 // after the first time through the loop, which is the point of
1285 // coverity[FORWARD_NULL]
1286 if (it != cited_entries_.begin()
1287 && entry.getAuthorOrEditorList() == last->second.getAuthorOrEditorList()
1288 // we access the year via getYear() so as to get it from the xref,
1289 // if we need to do so
1290 && getYear(entry.key()) == getYear(last->second.key())) {
1291 if (modifier == 0) {
1292 // so the last one should have been 'a'
1293 last->second.setModifier('a');
1295 } else if (modifier == 'z')
1302 entry.setModifier(modifier);
1303 // remember the last one
1308 it = cited_entries_.begin();
1309 for (; it != en; ++it) {
1310 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1311 // this shouldn't happen, but...
1312 if (biit == bimap_.end())
1313 // ...fail gracefully, anyway.
1315 BibTeXInfo & entry = biit->second;
1317 entry.label(entry.citeNumber());
1319 docstring const auth = entry.getAuthorOrEditorList(&buf, false);
1320 // we do it this way so as to access the xref, if necessary
1321 // note that this also gives us the modifier
1322 docstring const year = getYear(*it, buf, true);
1323 if (!auth.empty() && !year.empty())
1324 entry.label(auth + ' ' + year);
1326 entry.label(entry.key());
1332 //////////////////////////////////////////////////////////////////////
1336 //////////////////////////////////////////////////////////////////////
1339 CitationStyle citationStyleFromString(string const & command,
1340 BufferParams const & params)
1343 if (command.empty())
1346 string const alias = params.getCiteAlias(command);
1347 string cmd = alias.empty() ? command : alias;
1348 if (isUpperCase(command[0])) {
1349 cs.forceUpperCase = true;
1350 cmd[0] = lowercase(cmd[0]);
1353 size_t const n = command.size() - 1;
1354 if (command[n] == '*') {
1355 cs.hasStarredVersion = true;
1356 if (suffixIs(cmd, '*'))
1357 cmd = cmd.substr(0, cmd.size() - 1);
1365 string citationStyleToString(const CitationStyle & cs, bool const latex)
1367 string cmd = latex ? cs.cmd : cs.name;
1368 if (cs.forceUpperCase)
1369 cmd[0] = uppercase(cmd[0]);
1370 if (cs.hasStarredVersion)