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_(),
293 docstring const BibTeXInfo::getAuthorOrEditorList(Buffer const * buf,
294 bool full, bool forceshort) const
296 docstring author = operator[]("author");
298 author = operator[]("editor");
300 return getAuthorList(buf, author, full, forceshort);
304 docstring const BibTeXInfo::getAuthorList(Buffer const * buf,
305 docstring const & author, bool const full, bool const forceshort,
306 bool const allnames, bool const beginning) const
308 // Maxnames treshold depend on engine
309 size_t maxnames = buf ?
310 buf->params().documentClass().max_citenames() : 2;
313 docstring const opt = label();
318 docstring const remainder = trim(split(opt, authors, '('));
319 if (remainder.empty())
320 // in this case, we didn't find a "(",
321 // so we don't have author (year)
329 // FIXME Move this to a separate routine that can
330 // be called from elsewhere.
332 // OK, we've got some names. Let's format them.
333 // Try to split the author list on " and "
334 vector<docstring> const authors =
335 getVectorFromString(author, from_ascii(" and "));
339 CiteEngineType const engine_type = buf ? buf->params().citeEngineType()
340 : ENGINE_TYPE_DEFAULT;
342 // These are defined in the styles
344 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_etal")
346 string const namesep =
347 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_namesep")
349 string const lastnamesep =
350 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_lastnamesep")
352 string const pairnamesep =
353 buf ? buf->params().documentClass().getCiteMacro(engine_type, "_pairnamesep")
355 string firstnameform =
356 buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstnameform")
357 : "%surname%, %prename%";
359 firstnameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!firstbynameform")
360 : "%prename% %surname%";
361 string othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!othernameform")
362 : "%surname%, %prename%";
364 othernameform = buf ? buf->params().documentClass().getCiteMacro(engine_type, "!otherbynameform")
365 : "%prename% %surname%";
367 // Shorten the list (with et al.) if forceshort is set
368 // and the list can actually be shortened, else if maxcitenames
369 // is passed and full is not set.
370 bool shorten = forceshort && authors.size() > 1;
371 vector<docstring>::const_iterator it = authors.begin();
372 vector<docstring>::const_iterator en = authors.end();
373 for (size_t i = 0; it != en; ++it, ++i) {
374 if (i >= maxnames && !full) {
378 if (*it == "others") {
379 retval += buf ? buf->B_(etal) : from_ascii(etal);
382 if (i > 0 && i == authors.size() - 1) {
383 if (authors.size() == 2)
384 retval += buf ? buf->B_(pairnamesep) : from_ascii(pairnamesep);
386 retval += buf ? buf->B_(lastnamesep) : from_ascii(lastnamesep);
388 retval += buf ? buf->B_(namesep) : from_ascii(namesep);
390 retval += (i == 0) ? constructName(*it, firstnameform)
391 : constructName(*it, othernameform);
393 retval += nameParts(*it).second;
397 retval = constructName(authors[0], firstnameform) + (buf ? buf->B_(etal) : from_ascii(etal));
399 retval = nameParts(authors[0]).second + (buf ? buf->B_(etal) : from_ascii(etal));
402 return convertLaTeXCommands(retval);
406 docstring const BibTeXInfo::getYear() const
409 // first try legacy year field
410 docstring year = operator[]("year");
413 // now try biblatex's date field
414 year = operator[]("date");
415 // Format is [-]YYYY-MM-DD*/[-]YYYY-MM-DD*
416 // We only want the years.
417 static regex const yreg("[-]?([\\d]{4}).*");
418 static regex const ereg(".*/[-]?([\\d]{4}).*");
420 string const date = to_utf8(year);
421 if (!regex_match(date, sm, yreg))
422 // cannot parse year.
424 year = from_ascii(sm[1]);
425 // check for an endyear
426 if (regex_match(date, sm, ereg))
427 year += char_type(0x2013) + from_ascii(sm[1]);
431 docstring const opt = label();
436 docstring tmp = split(opt, authors, '(');
438 // we don't have author (year)
441 tmp = split(tmp, year, ')');
448 docstring parseOptions(docstring const & format, string & optkey,
449 docstring & ifpart, docstring & elsepart);
451 // Calls parseOptions to deal with an embedded option, such as:
452 // {%number%[[, no.~%number%]]}
453 // which must appear at the start of format. ifelsepart gets the
454 // whole of the option, and we return what's left after the option.
455 // we return format if there is an error.
456 docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
458 LASSERT(format[0] == '{' && format[1] == '%', return format);
462 docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
463 if (format == rest) { // parse error
464 LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
467 LASSERT(rest.size() <= format.size(),
468 { ifelsepart = docstring(); return format; });
469 ifelsepart = format.substr(0, format.size() - rest.size());
474 // Gets a "clause" from a format string, where the clause is
475 // delimited by '[[' and ']]'. Returns what is left after the
476 // clause is removed, and returns format if there is an error.
477 docstring getClause(docstring const & format, docstring & clause)
479 docstring fmt = format;
482 // we'll remove characters from the front of fmt as we
484 while (!fmt.empty()) {
485 if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
490 // check for an embedded option
491 if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
493 docstring const rest = parseEmbeddedOption(fmt, part);
495 LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
500 } else { // it's just a normal character
509 // parse an options string, which must appear at the start of the
510 // format parameter. puts the parsed bits in optkey, ifpart, and
511 // elsepart and returns what's left after the option is removed.
512 // if there's an error, it returns format itself.
513 docstring parseOptions(docstring const & format, string & optkey,
514 docstring & ifpart, docstring & elsepart)
516 LASSERT(format[0] == '{' && format[1] == '%', return format);
518 docstring fmt = format.substr(2);
519 size_t pos = fmt.find('%'); // end of key
520 if (pos == string::npos) {
521 LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
524 optkey = to_utf8(fmt.substr(0, pos));
525 fmt = fmt.substr(pos + 1);
526 // [[format]] should be next
527 if (fmt[0] != '[' || fmt[1] != '[') {
528 LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
532 docstring curfmt = fmt;
533 fmt = getClause(curfmt, ifpart);
535 LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
539 if (fmt[0] == '}') // we're done, no else clause
540 return fmt.substr(1);
542 // else part should follow
543 if (fmt[0] != '[' || fmt[1] != '[') {
544 LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
549 fmt = getClause(curfmt, elsepart);
551 if (fmt == curfmt || fmt[0] != '}') {
552 LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
555 return fmt.substr(1);
562 Bug #9131 revealed an oddity in how we are generating citation information
563 when more than one key is given. We end up building a longer and longer format
564 string as we go, which we then have to re-parse, over and over and over again,
565 rather than generating the information for the individual keys and then putting
566 all of that together. We do that to deal with the way separators work, from what
567 I can tell, but it still feels like a hack. Fixing this would require quite a
568 bit of work, however.
570 docstring BibTeXInfo::expandFormat(docstring const & format,
571 BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
572 CiteItem const & ci, bool next, bool second) const
574 // incorrect use of macros could put us in an infinite loop
575 static int const max_passes = 5000;
576 // the use of overly large keys can lead to performance problems, due
577 // to eventual attempts to convert LaTeX macros to unicode. See bug
578 // #8944. By default, the size is limited to 128 (in CiteItem), but
579 // for specific purposes (such as XHTML export), it needs to be enlarged
580 // This is perhaps not the best solution, but it will have to do for now.
581 size_t const max_keysize = ci.max_key_size;
582 odocstringstream ret; // return value
584 bool scanning_key = false;
585 bool scanning_rich = false;
587 CiteEngineType const engine_type = buf.params().citeEngineType();
588 docstring fmt = format;
589 // we'll remove characters from the front of fmt as we
591 while (!fmt.empty()) {
592 if (counter > max_passes) {
593 LYXERR0("Recursion limit reached while parsing `"
598 char_type thischar = fmt[0];
599 if (thischar == '%') {
600 // beginning or end of key
603 scanning_key = false;
604 // so we replace the key with its value, which may be empty
608 buf.params().documentClass().getCiteMacro(engine_type, key);
609 fmt = from_utf8(val) + fmt.substr(1);
612 } else if (key[0] == '_') {
613 // a translatable bit
615 buf.params().documentClass().getCiteMacro(engine_type, key);
616 docstring const trans =
617 translateIfPossible(from_utf8(val), buf.params().language->code());
620 docstring const val =
621 getValueForKey(key, buf, ci, xrefs, max_keysize);
623 ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
626 ret << from_ascii("{!</span>!}");
634 else if (thischar == '{') {
635 // beginning of option?
637 LYXERR0("ERROR: Found `{' when scanning key in `" << format << "'.");
640 if (fmt.size() > 1) {
642 // it is the beginning of an optional format
646 docstring const newfmt =
647 parseOptions(fmt, optkey, ifpart, elsepart);
648 if (newfmt == fmt) // parse error
651 docstring const val =
652 getValueForKey(optkey, buf, ci, xrefs);
653 if (optkey == "next" && next)
654 ret << ifpart; // without expansion
655 else if (optkey == "second" && second) {
657 ret << expandFormat(ifpart, xrefs, newcounter, buf,
659 } else if (!val.empty()) {
661 ret << expandFormat(ifpart, xrefs, newcounter, buf,
663 } else if (!elsepart.empty()) {
665 ret << expandFormat(elsepart, xrefs, newcounter, buf,
668 // fmt will have been shortened for us already
672 // beginning of rich text
673 scanning_rich = true;
675 ret << from_ascii("{!");
679 // we are here if '{' was not followed by % or !.
680 // So it's just a character.
683 else if (scanning_rich && thischar == '!'
684 && fmt.size() > 1 && fmt[1] == '}') {
686 scanning_rich = false;
688 ret << from_ascii("!}");
691 else if (scanning_key)
692 key += char(thischar);
696 } catch (EncodingException & /* e */) {
697 LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
703 LYXERR0("Never found end of key in `" << format << "'!");
707 LYXERR0("Never found end of rich text in `" << format << "'!");
714 docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
715 Buffer const & buf, CiteItem const & ci) const
717 bool const richtext = ci.richtext;
719 if (!richtext && !info_.empty())
721 if (richtext && !info_richtext_.empty())
722 return info_richtext_;
725 BibTeXInfo::const_iterator it = find(from_ascii("ref"));
730 CiteEngineType const engine_type = buf.params().citeEngineType();
731 DocumentClass const & dc = buf.params().documentClass();
732 docstring const & format =
733 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
735 info_ = expandFormat(format, xrefs, counter, buf,
739 // this probably shouldn't happen
744 info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
745 return info_richtext_;
748 info_ = convertLaTeXCommands(processRichtext(info_, false));
753 docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
754 Buffer const & buf, docstring const & format,
755 CiteItem const & ci, bool next, bool second) const
760 loclabel = expandFormat(format, xrefs, counter, buf, ci, next, second);
762 if (!loclabel.empty() && !next) {
763 loclabel = processRichtext(loclabel, ci.richtext);
764 loclabel = convertLaTeXCommands(loclabel);
771 docstring const & BibTeXInfo::operator[](docstring const & field) const
773 BibTeXInfo::const_iterator it = find(field);
776 static docstring const empty_value = docstring();
781 docstring const & BibTeXInfo::operator[](string const & field) const
783 return operator[](from_ascii(field));
787 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
788 CiteItem const & ci, BibTeXInfoList const xrefs, size_t maxsize) const
790 // anything less is pointless
791 LASSERT(maxsize >= 16, maxsize = 16);
793 bool cleanit = false;
794 if (prefixIs(oldkey, "clean:")) {
795 key = oldkey.substr(6);
799 docstring ret = operator[](key);
800 if (ret.empty() && !xrefs.empty()) {
801 vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
802 vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
803 for (; it != en; ++it) {
804 if (*it && !(**it)[key].empty()) {
812 // FIXME: dialog, textbefore and textafter have nothing to do with this
813 if (key == "dialog" && ci.context == CiteItem::Dialog)
814 ret = from_ascii("x"); // any non-empty string will do
815 else if (key == "export" && ci.context == CiteItem::Export)
816 ret = from_ascii("x"); // any non-empty string will do
817 else if (key == "ifstar" && ci.Starred)
818 ret = from_ascii("x"); // any non-empty string will do
819 else if (key == "ifqualified" && ci.isQualified)
820 ret = from_ascii("x"); // any non-empty string will do
821 else if (key == "entrytype")
823 else if (prefixIs(key, "ifentrytype:")
824 && from_ascii(key.substr(12)) == entry_type_)
825 ret = from_ascii("x"); // any non-empty string will do
826 else if (key == "key")
828 else if (key == "label")
830 else if (key == "modifier" && modifier_ != 0)
832 else if (key == "numericallabel")
834 else if (prefixIs(key, "ifmultiple:")) {
835 // Return whether we have multiple authors
836 docstring const kind = operator[](from_ascii(key.substr(11)));
837 if (multipleAuthors(kind))
838 ret = from_ascii("x"); // any non-empty string will do
840 else if (prefixIs(key, "abbrvnames:")) {
841 // Special key to provide abbreviated name list,
842 // with respect to maxcitenames. Suitable for Bibliography
844 docstring const kind = operator[](from_ascii(key.substr(11)));
845 ret = getAuthorList(&buf, kind, false, false, true);
846 if (ci.forceUpperCase && isLowerCase(ret[0]))
847 ret[0] = uppercase(ret[0]);
848 } else if (prefixIs(key, "fullnames:")) {
849 // Return a full name list. Suitable for Bibliography
851 docstring const kind = operator[](from_ascii(key.substr(10)));
852 ret = getAuthorList(&buf, kind, true, false, true);
853 if (ci.forceUpperCase && isLowerCase(ret[0]))
854 ret[0] = uppercase(ret[0]);
855 } else if (prefixIs(key, "forceabbrvnames:")) {
856 // Special key to provide abbreviated name lists,
857 // irrespective of maxcitenames. Suitable for Bibliography
859 docstring const kind = operator[](from_ascii(key.substr(15)));
860 ret = getAuthorList(&buf, kind, false, true, true);
861 if (ci.forceUpperCase && isLowerCase(ret[0]))
862 ret[0] = uppercase(ret[0]);
863 } else if (prefixIs(key, "abbrvbynames:")) {
864 // Special key to provide abbreviated name list,
865 // with respect to maxcitenames. Suitable for further names inside a
866 // bibliography item // (such as "ed. by ...")
867 docstring const kind = operator[](from_ascii(key.substr(11)));
868 ret = getAuthorList(&buf, kind, false, false, true, false);
869 if (ci.forceUpperCase && isLowerCase(ret[0]))
870 ret[0] = uppercase(ret[0]);
871 } else if (prefixIs(key, "fullbynames:")) {
872 // Return a full name list. Suitable for further names inside a
873 // bibliography item // (such as "ed. by ...")
874 docstring const kind = operator[](from_ascii(key.substr(10)));
875 ret = getAuthorList(&buf, kind, true, false, true, false);
876 if (ci.forceUpperCase && isLowerCase(ret[0]))
877 ret[0] = uppercase(ret[0]);
878 } else if (prefixIs(key, "forceabbrvbynames:")) {
879 // Special key to provide abbreviated name lists,
880 // irrespective of maxcitenames. Suitable for further names inside a
881 // bibliography item // (such as "ed. by ...")
882 docstring const kind = operator[](from_ascii(key.substr(15)));
883 ret = getAuthorList(&buf, kind, false, true, true, false);
884 if (ci.forceUpperCase && isLowerCase(ret[0]))
885 ret[0] = uppercase(ret[0]);
886 } else if (key == "abbrvciteauthor") {
887 // Special key to provide abbreviated author or
888 // editor names (suitable for citation labels),
889 // with respect to maxcitenames.
890 ret = getAuthorOrEditorList(&buf, false, false);
891 if (ci.forceUpperCase && isLowerCase(ret[0]))
892 ret[0] = uppercase(ret[0]);
893 } else if (key == "fullciteauthor") {
894 // Return a full author or editor list (for citation labels)
895 ret = getAuthorOrEditorList(&buf, true, false);
896 if (ci.forceUpperCase && isLowerCase(ret[0]))
897 ret[0] = uppercase(ret[0]);
898 } else if (key == "forceabbrvciteauthor") {
899 // Special key to provide abbreviated author or
900 // editor names (suitable for citation labels),
901 // irrespective of maxcitenames.
902 ret = getAuthorOrEditorList(&buf, false, true);
903 if (ci.forceUpperCase && isLowerCase(ret[0]))
904 ret[0] = uppercase(ret[0]);
905 } else if (key == "bibentry") {
906 // Special key to provide the full bibliography entry: see getInfo()
907 CiteEngineType const engine_type = buf.params().citeEngineType();
908 DocumentClass const & dc = buf.params().documentClass();
909 docstring const & format =
910 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_), false));
912 ret = expandFormat(format, xrefs, counter, buf, ci, false, false);
913 } else if (key == "textbefore")
915 else if (key == "textafter")
917 else if (key == "curpretext")
918 ret = ci.getPretexts()[bib_key_];
919 else if (key == "curposttext")
920 ret = ci.getPosttexts()[bib_key_];
921 else if (key == "year")
926 ret = html::cleanAttr(ret);
928 // make sure it is not too big
929 support::truncateWithEllipsis(ret, maxsize);
934 //////////////////////////////////////////////////////////////////////
938 //////////////////////////////////////////////////////////////////////
942 // A functor for use with sort, leading to case insensitive sorting
943 class compareNoCase: public binary_function<docstring, docstring, bool>
946 bool operator()(docstring const & s1, docstring const & s2) const {
947 return compare_no_case(s1, s2) < 0;
954 vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
956 vector<docstring> result;
957 if (!data.isBibTeX())
959 // Legacy crossref field. This is not nestable.
960 if (!nested && !data["crossref"].empty()) {
961 docstring const xrefkey = data["crossref"];
962 result.push_back(xrefkey);
963 // However, check for nested xdatas
964 BiblioInfo::const_iterator it = find(xrefkey);
966 BibTeXInfo const & xref = it->second;
967 vector<docstring> const nxdata = getXRefs(xref, true);
969 result.insert(result.end(), nxdata.begin(), nxdata.end());
972 // Biblatex's xdata field. Infinitely nestable.
973 // XData field can consist of a comma-separated list of keys
974 vector<docstring> const xdatakeys = getVectorFromString(data["xdata"]);
975 if (!xdatakeys.empty()) {
976 vector<docstring>::const_iterator xit = xdatakeys.begin();
977 vector<docstring>::const_iterator xen = xdatakeys.end();
978 for (; xit != xen; ++xit) {
979 docstring const xdatakey = *xit;
980 result.push_back(xdatakey);
981 BiblioInfo::const_iterator it = find(xdatakey);
983 BibTeXInfo const & xdata = it->second;
984 vector<docstring> const nxdata = getXRefs(xdata, true);
986 result.insert(result.end(), nxdata.begin(), nxdata.end());
994 vector<docstring> const BiblioInfo::getKeys() const
996 vector<docstring> bibkeys;
997 BiblioInfo::const_iterator it = begin();
998 for (; it != end(); ++it)
999 bibkeys.push_back(it->first);
1000 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
1005 vector<docstring> const BiblioInfo::getFields() const
1007 vector<docstring> bibfields;
1008 set<docstring>::const_iterator it = field_names_.begin();
1009 set<docstring>::const_iterator end = field_names_.end();
1010 for (; it != end; ++it)
1011 bibfields.push_back(*it);
1012 sort(bibfields.begin(), bibfields.end());
1017 vector<docstring> const BiblioInfo::getEntries() const
1019 vector<docstring> bibentries;
1020 set<docstring>::const_iterator it = entry_types_.begin();
1021 set<docstring>::const_iterator end = entry_types_.end();
1022 for (; it != end; ++it)
1023 bibentries.push_back(*it);
1024 sort(bibentries.begin(), bibentries.end());
1029 docstring const BiblioInfo::getAuthorOrEditorList(docstring const & key, Buffer const & buf) const
1031 BiblioInfo::const_iterator it = find(key);
1034 BibTeXInfo const & data = it->second;
1035 return data.getAuthorOrEditorList(&buf, false);
1039 docstring const BiblioInfo::getCiteNumber(docstring const & key) const
1041 BiblioInfo::const_iterator it = find(key);
1044 BibTeXInfo const & data = it->second;
1045 return data.citeNumber();
1049 docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
1051 BiblioInfo::const_iterator it = find(key);
1054 BibTeXInfo const & data = it->second;
1055 docstring year = data.getYear();
1057 // let's try the crossrefs
1058 vector<docstring> const xrefs = getXRefs(data);
1062 vector<docstring>::const_iterator it = xrefs.begin();
1063 vector<docstring>::const_iterator en = xrefs.end();
1064 for (; it != en; ++it) {
1065 BiblioInfo::const_iterator const xrefit = find(*it);
1066 if (xrefit == end())
1068 BibTeXInfo const & xref_data = xrefit->second;
1069 year = xref_data.getYear();
1075 if (use_modifier && data.modifier() != 0)
1076 year += data.modifier();
1081 docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
1083 docstring const year = getYear(key, use_modifier);
1085 return buf.B_("No year");
1090 docstring const BiblioInfo::getInfo(docstring const & key,
1091 Buffer const & buf, CiteItem const & ci) const
1093 BiblioInfo::const_iterator it = find(key);
1095 return docstring(_("Bibliography entry not found!"));
1096 BibTeXInfo const & data = it->second;
1097 BibTeXInfoList xrefptrs;
1098 vector<docstring> const xrefs = getXRefs(data);
1099 if (!xrefs.empty()) {
1100 vector<docstring>::const_iterator it = xrefs.begin();
1101 vector<docstring>::const_iterator en = xrefs.end();
1102 for (; it != en; ++it) {
1103 BiblioInfo::const_iterator const xrefit = find(*it);
1104 if (xrefit != end())
1105 xrefptrs.push_back(&(xrefit->second));
1108 return data.getInfo(xrefptrs, buf, ci);
1112 docstring const BiblioInfo::getLabel(vector<docstring> keys,
1113 Buffer const & buf, string const & style, CiteItem const & ci) const
1115 size_t max_size = ci.max_size;
1116 // shorter makes no sense
1117 LASSERT(max_size >= 16, max_size = 16);
1119 // we can't display more than 10 of these, anyway
1120 bool const too_many_keys = keys.size() > 10;
1124 CiteEngineType const engine_type = buf.params().citeEngineType();
1125 DocumentClass const & dc = buf.params().documentClass();
1126 docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, false, "cite"));
1127 docstring ret = format;
1128 vector<docstring>::const_iterator key = keys.begin();
1129 vector<docstring>::const_iterator ken = keys.end();
1130 for (int i = 0; key != ken; ++key, ++i) {
1131 BiblioInfo::const_iterator it = find(*key);
1132 BibTeXInfo empty_data;
1133 empty_data.key(*key);
1134 BibTeXInfo & data = empty_data;
1135 vector<BibTeXInfo const *> xrefptrs;
1138 vector<docstring> const xrefs = getXRefs(data);
1139 if (!xrefs.empty()) {
1140 vector<docstring>::const_iterator it = xrefs.begin();
1141 vector<docstring>::const_iterator en = xrefs.end();
1142 for (; it != en; ++it) {
1143 BiblioInfo::const_iterator const xrefit = find(*it);
1144 if (xrefit != end())
1145 xrefptrs.push_back(&(xrefit->second));
1149 ret = data.getLabel(xrefptrs, buf, ret, ci, key + 1 != ken, i == 1);
1153 ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
1154 support::truncateWithEllipsis(ret, max_size);
1159 bool BiblioInfo::isBibtex(docstring const & key) const
1162 split(key, key1, ',');
1163 BiblioInfo::const_iterator it = find(key1);
1166 return it->second.isBibTeX();
1170 vector<docstring> const BiblioInfo::getCiteStrings(
1171 vector<docstring> const & keys, vector<CitationStyle> const & styles,
1172 Buffer const & buf, CiteItem const & ci) const
1175 return vector<docstring>();
1178 vector<docstring> vec(styles.size());
1179 for (size_t i = 0; i != vec.size(); ++i) {
1180 style = styles[i].name;
1181 vec[i] = getLabel(keys, buf, style, ci);
1188 void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
1190 bimap_.insert(info.begin(), info.end());
1191 field_names_.insert(info.field_names_.begin(), info.field_names_.end());
1192 entry_types_.insert(info.entry_types_.begin(), info.entry_types_.end());
1198 // used in xhtml to sort a list of BibTeXInfo objects
1199 bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
1201 docstring const lauth = lhs->getAuthorOrEditorList();
1202 docstring const rauth = rhs->getAuthorOrEditorList();
1203 docstring const lyear = lhs->getYear();
1204 docstring const ryear = rhs->getYear();
1205 docstring const ltitl = lhs->operator[]("title");
1206 docstring const rtitl = rhs->operator[]("title");
1207 return (lauth < rauth)
1208 || (lauth == rauth && lyear < ryear)
1209 || (lauth == rauth && lyear == ryear && ltitl < rtitl);
1215 void BiblioInfo::collectCitedEntries(Buffer const & buf)
1217 cited_entries_.clear();
1218 // We are going to collect all the citation keys used in the document,
1219 // getting them from the TOC.
1220 // FIXME We may want to collect these differently, in the first case,
1221 // so that we might have them in order of appearance.
1222 set<docstring> citekeys;
1223 shared_ptr<Toc const> toc = buf.tocBackend().toc("citation");
1224 Toc::const_iterator it = toc->begin();
1225 Toc::const_iterator const en = toc->end();
1226 for (; it != en; ++it) {
1227 if (it->str().empty())
1229 vector<docstring> const keys = getVectorFromString(it->str());
1230 citekeys.insert(keys.begin(), keys.end());
1232 if (citekeys.empty())
1235 // We have a set of the keys used in this document.
1236 // We will now convert it to a list of the BibTeXInfo objects used in
1238 vector<BibTeXInfo const *> bi;
1239 set<docstring>::const_iterator cit = citekeys.begin();
1240 set<docstring>::const_iterator const cen = citekeys.end();
1241 for (; cit != cen; ++cit) {
1242 BiblioInfo::const_iterator const bt = find(*cit);
1243 if (bt == end() || !bt->second.isBibTeX())
1245 bi.push_back(&(bt->second));
1248 sort(bi.begin(), bi.end(), lSorter);
1250 // Now we can write the sorted keys
1251 vector<BibTeXInfo const *>::const_iterator bit = bi.begin();
1252 vector<BibTeXInfo const *>::const_iterator ben = bi.end();
1253 for (; bit != ben; ++bit)
1254 cited_entries_.push_back((*bit)->key());
1258 void BiblioInfo::makeCitationLabels(Buffer const & buf)
1260 collectCitedEntries(buf);
1261 CiteEngineType const engine_type = buf.params().citeEngineType();
1262 bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
1266 // used to remember the last one we saw
1267 // we'll be comparing entries to see if we need to add
1268 // modifiers, like "1984a"
1269 map<docstring, BibTeXInfo>::iterator last = bimap_.end();
1271 vector<docstring>::const_iterator it = cited_entries_.begin();
1272 vector<docstring>::const_iterator const en = cited_entries_.end();
1273 for (; it != en; ++it) {
1274 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1275 // this shouldn't happen, but...
1276 if (biit == bimap_.end())
1277 // ...fail gracefully, anyway.
1279 BibTeXInfo & entry = biit->second;
1281 docstring const num = convert<docstring>(++keynumber);
1282 entry.setCiteNumber(num);
1284 // The first test here is checking whether this is the first
1285 // time through the loop. If so, then we do not have anything
1286 // with which to compare.
1287 if (last != bimap_.end()
1288 && entry.getAuthorOrEditorList() == last->second.getAuthorOrEditorList()
1289 // we access the year via getYear() so as to get it from the xref,
1290 // if we need to do so
1291 && getYear(entry.key()) == getYear(last->second.key())) {
1292 if (modifier == 0) {
1293 // so the last one should have been 'a'
1294 last->second.setModifier('a');
1296 } else if (modifier == 'z')
1303 entry.setModifier(modifier);
1304 // remember the last one
1309 it = cited_entries_.begin();
1310 for (; it != en; ++it) {
1311 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1312 // this shouldn't happen, but...
1313 if (biit == bimap_.end())
1314 // ...fail gracefully, anyway.
1316 BibTeXInfo & entry = biit->second;
1318 entry.label(entry.citeNumber());
1320 docstring const auth = entry.getAuthorOrEditorList(&buf, false);
1321 // we do it this way so as to access the xref, if necessary
1322 // note that this also gives us the modifier
1323 docstring const year = getYear(*it, buf, true);
1324 if (!auth.empty() && !year.empty())
1325 entry.label(auth + ' ' + year);
1327 entry.label(entry.key());
1333 //////////////////////////////////////////////////////////////////////
1337 //////////////////////////////////////////////////////////////////////
1340 CitationStyle citationStyleFromString(string const & command,
1341 BufferParams const & params)
1344 if (command.empty())
1347 string const alias = params.getCiteAlias(command);
1348 string cmd = alias.empty() ? command : alias;
1349 if (isUpperCase(command[0])) {
1350 cs.forceUpperCase = true;
1351 cmd[0] = lowercase(cmd[0]);
1354 size_t const n = command.size() - 1;
1355 if (command[n] == '*') {
1356 cs.hasStarredVersion = true;
1357 if (suffixIs(cmd, '*'))
1358 cmd = cmd.substr(0, cmd.size() - 1);
1366 string citationStyleToString(const CitationStyle & cs, bool const latex)
1368 string cmd = latex ? cs.cmd : cs.name;
1369 if (cs.forceUpperCase)
1370 cmd[0] = uppercase(cmd[0]);
1371 if (cs.hasStarredVersion)