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 if (!regex_match(date, sm, yreg))
421 // cannot parse year.
423 year = from_ascii(sm[1]);
424 // check for an endyear
425 if (regex_match(date, sm, ereg))
426 year += char_type(0x2013) + from_ascii(sm[1]);
430 docstring const opt = label();
435 docstring tmp = split(opt, authors, '(');
437 // we don't have author (year)
440 tmp = split(tmp, year, ')');
447 docstring parseOptions(docstring const & format, string & optkey,
448 docstring & ifpart, docstring & elsepart);
450 // Calls parseOptions to deal with an embedded option, such as:
451 // {%number%[[, no.~%number%]]}
452 // which must appear at the start of format. ifelsepart gets the
453 // whole of the option, and we return what's left after the option.
454 // we return format if there is an error.
455 docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
457 LASSERT(format[0] == '{' && format[1] == '%', return format);
461 docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
462 if (format == rest) { // parse error
463 LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
466 LASSERT(rest.size() <= format.size(),
467 { ifelsepart = docstring(); return format; });
468 ifelsepart = format.substr(0, format.size() - rest.size());
473 // Gets a "clause" from a format string, where the clause is
474 // delimited by '[[' and ']]'. Returns what is left after the
475 // clause is removed, and returns format if there is an error.
476 docstring getClause(docstring const & format, docstring & clause)
478 docstring fmt = format;
481 // we'll remove characters from the front of fmt as we
483 while (!fmt.empty()) {
484 if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
489 // check for an embedded option
490 if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
492 docstring const rest = parseEmbeddedOption(fmt, part);
494 LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
499 } else { // it's just a normal character
508 // parse an options string, which must appear at the start of the
509 // format parameter. puts the parsed bits in optkey, ifpart, and
510 // elsepart and returns what's left after the option is removed.
511 // if there's an error, it returns format itself.
512 docstring parseOptions(docstring const & format, string & optkey,
513 docstring & ifpart, docstring & elsepart)
515 LASSERT(format[0] == '{' && format[1] == '%', return format);
517 docstring fmt = format.substr(2);
518 size_t pos = fmt.find('%'); // end of key
519 if (pos == string::npos) {
520 LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
523 optkey = to_utf8(fmt.substr(0, pos));
524 fmt = fmt.substr(pos + 1);
525 // [[format]] should be next
526 if (fmt[0] != '[' || fmt[1] != '[') {
527 LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
531 docstring curfmt = fmt;
532 fmt = getClause(curfmt, ifpart);
534 LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
538 if (fmt[0] == '}') // we're done, no else clause
539 return fmt.substr(1);
541 // else part should follow
542 if (fmt[0] != '[' || fmt[1] != '[') {
543 LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
548 fmt = getClause(curfmt, elsepart);
550 if (fmt == curfmt || fmt[0] != '}') {
551 LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
554 return fmt.substr(1);
561 Bug #9131 revealed an oddity in how we are generating citation information
562 when more than one key is given. We end up building a longer and longer format
563 string as we go, which we then have to re-parse, over and over and over again,
564 rather than generating the information for the individual keys and then putting
565 all of that together. We do that to deal with the way separators work, from what
566 I can tell, but it still feels like a hack. Fixing this would require quite a
567 bit of work, however.
569 docstring BibTeXInfo::expandFormat(docstring const & format,
570 BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
571 CiteItem const & ci, bool next, bool second) const
573 // incorrect use of macros could put us in an infinite loop
574 static int const max_passes = 5000;
575 // the use of overly large keys can lead to performance problems, due
576 // to eventual attempts to convert LaTeX macros to unicode. See bug
577 // #8944. By default, the size is limited to 128 (in CiteItem), but
578 // for specific purposes (such as XHTML export), it needs to be enlarged
579 // This is perhaps not the best solution, but it will have to do for now.
580 size_t const max_keysize = ci.max_key_size;
581 odocstringstream ret; // return value
583 bool scanning_key = false;
584 bool scanning_rich = false;
586 CiteEngineType const engine_type = buf.params().citeEngineType();
587 docstring fmt = format;
588 // we'll remove characters from the front of fmt as we
590 while (!fmt.empty()) {
591 if (counter > max_passes) {
592 LYXERR0("Recursion limit reached while parsing `"
597 char_type thischar = fmt[0];
598 if (thischar == '%') {
599 // beginning or end of key
602 scanning_key = false;
603 // so we replace the key with its value, which may be empty
607 buf.params().documentClass().getCiteMacro(engine_type, key);
608 fmt = from_utf8(val) + fmt.substr(1);
611 } else if (key[0] == '_') {
612 // a translatable bit
614 buf.params().documentClass().getCiteMacro(engine_type, key);
615 docstring const trans =
616 translateIfPossible(from_utf8(val), buf.params().language->code());
619 docstring const val =
620 getValueForKey(key, buf, ci, xrefs, max_keysize);
622 ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
625 ret << from_ascii("{!</span>!}");
633 else if (thischar == '{') {
634 // beginning of option?
636 LYXERR0("ERROR: Found `{' when scanning key in `" << format << "'.");
639 if (fmt.size() > 1) {
641 // it is the beginning of an optional format
645 docstring const newfmt =
646 parseOptions(fmt, optkey, ifpart, elsepart);
647 if (newfmt == fmt) // parse error
650 docstring const val =
651 getValueForKey(optkey, buf, ci, xrefs);
652 if (optkey == "next" && next)
653 ret << ifpart; // without expansion
654 else if (optkey == "second" && second) {
656 ret << expandFormat(ifpart, xrefs, newcounter, buf,
658 } else if (!val.empty()) {
660 ret << expandFormat(ifpart, xrefs, newcounter, buf,
662 } else if (!elsepart.empty()) {
664 ret << expandFormat(elsepart, xrefs, newcounter, buf,
667 // fmt will have been shortened for us already
671 // beginning of rich text
672 scanning_rich = true;
674 ret << from_ascii("{!");
678 // we are here if '{' was not followed by % or !.
679 // So it's just a character.
682 else if (scanning_rich && thischar == '!'
683 && fmt.size() > 1 && fmt[1] == '}') {
685 scanning_rich = false;
687 ret << from_ascii("!}");
690 else if (scanning_key)
691 key += char(thischar);
695 } catch (EncodingException & /* e */) {
696 LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
702 LYXERR0("Never found end of key in `" << format << "'!");
706 LYXERR0("Never found end of rich text in `" << format << "'!");
713 docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
714 Buffer const & buf, CiteItem const & ci) const
716 bool const richtext = ci.richtext;
718 if (!richtext && !info_.empty())
720 if (richtext && !info_richtext_.empty())
721 return info_richtext_;
724 BibTeXInfo::const_iterator it = find(from_ascii("ref"));
729 CiteEngineType const engine_type = buf.params().citeEngineType();
730 DocumentClass const & dc = buf.params().documentClass();
731 docstring const & format =
732 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
734 info_ = expandFormat(format, xrefs, counter, buf,
738 // this probably shouldn't happen
743 info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
744 return info_richtext_;
747 info_ = convertLaTeXCommands(processRichtext(info_, false));
752 docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
753 Buffer const & buf, docstring const & format,
754 CiteItem const & ci, bool next, bool second) const
759 loclabel = expandFormat(format, xrefs, counter, buf, ci, next, second);
761 if (!loclabel.empty() && !next) {
762 loclabel = processRichtext(loclabel, ci.richtext);
763 loclabel = convertLaTeXCommands(loclabel);
770 docstring const & BibTeXInfo::operator[](docstring const & field) const
772 BibTeXInfo::const_iterator it = find(field);
775 static docstring const empty_value = docstring();
780 docstring const & BibTeXInfo::operator[](string const & field) const
782 return operator[](from_ascii(field));
786 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
787 CiteItem const & ci, BibTeXInfoList const xrefs, size_t maxsize) const
789 // anything less is pointless
790 LASSERT(maxsize >= 16, maxsize = 16);
792 bool cleanit = false;
793 if (prefixIs(oldkey, "clean:")) {
794 key = oldkey.substr(6);
798 docstring ret = operator[](key);
799 if (ret.empty() && !xrefs.empty()) {
800 vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
801 vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
802 for (; it != en; ++it) {
803 if (*it && !(**it)[key].empty()) {
811 // FIXME: dialog, textbefore and textafter have nothing to do with this
812 if (key == "dialog" && ci.context == CiteItem::Dialog)
813 ret = from_ascii("x"); // any non-empty string will do
814 else if (key == "export" && ci.context == CiteItem::Export)
815 ret = from_ascii("x"); // any non-empty string will do
816 else if (key == "ifstar" && ci.Starred)
817 ret = from_ascii("x"); // any non-empty string will do
818 else if (key == "ifqualified" && ci.isQualified)
819 ret = from_ascii("x"); // any non-empty string will do
820 else if (key == "entrytype")
822 else if (prefixIs(key, "ifentrytype:")
823 && from_ascii(key.substr(12)) == entry_type_)
824 ret = from_ascii("x"); // any non-empty string will do
825 else if (key == "key")
827 else if (key == "label")
829 else if (key == "modifier" && modifier_ != 0)
831 else if (key == "numericallabel")
833 else if (prefixIs(key, "ifmultiple:")) {
834 // Return whether we have multiple authors
835 docstring const kind = operator[](from_ascii(key.substr(11)));
836 if (multipleAuthors(kind))
837 ret = from_ascii("x"); // any non-empty string will do
839 else if (prefixIs(key, "abbrvnames:")) {
840 // Special key to provide abbreviated name list,
841 // with respect to maxcitenames. Suitable for Bibliography
843 docstring const kind = operator[](from_ascii(key.substr(11)));
844 ret = getAuthorList(&buf, kind, false, false, true);
845 if (ci.forceUpperCase && isLowerCase(ret[0]))
846 ret[0] = uppercase(ret[0]);
847 } else if (prefixIs(key, "fullnames:")) {
848 // Return a full name list. Suitable for Bibliography
850 docstring const kind = operator[](from_ascii(key.substr(10)));
851 ret = getAuthorList(&buf, kind, true, false, true);
852 if (ci.forceUpperCase && isLowerCase(ret[0]))
853 ret[0] = uppercase(ret[0]);
854 } else if (prefixIs(key, "forceabbrvnames:")) {
855 // Special key to provide abbreviated name lists,
856 // irrespective of maxcitenames. Suitable for Bibliography
858 docstring const kind = operator[](from_ascii(key.substr(15)));
859 ret = getAuthorList(&buf, kind, false, true, true);
860 if (ci.forceUpperCase && isLowerCase(ret[0]))
861 ret[0] = uppercase(ret[0]);
862 } else if (prefixIs(key, "abbrvbynames:")) {
863 // Special key to provide abbreviated name list,
864 // with respect to maxcitenames. Suitable for further names inside a
865 // bibliography item // (such as "ed. by ...")
866 docstring const kind = operator[](from_ascii(key.substr(11)));
867 ret = getAuthorList(&buf, kind, false, false, true, false);
868 if (ci.forceUpperCase && isLowerCase(ret[0]))
869 ret[0] = uppercase(ret[0]);
870 } else if (prefixIs(key, "fullbynames:")) {
871 // Return a full name list. Suitable for further names inside a
872 // bibliography item // (such as "ed. by ...")
873 docstring const kind = operator[](from_ascii(key.substr(10)));
874 ret = getAuthorList(&buf, kind, true, false, true, false);
875 if (ci.forceUpperCase && isLowerCase(ret[0]))
876 ret[0] = uppercase(ret[0]);
877 } else if (prefixIs(key, "forceabbrvbynames:")) {
878 // Special key to provide abbreviated name lists,
879 // irrespective of maxcitenames. Suitable for further names inside a
880 // bibliography item // (such as "ed. by ...")
881 docstring const kind = operator[](from_ascii(key.substr(15)));
882 ret = getAuthorList(&buf, kind, false, true, true, false);
883 if (ci.forceUpperCase && isLowerCase(ret[0]))
884 ret[0] = uppercase(ret[0]);
885 } else if (key == "abbrvciteauthor") {
886 // Special key to provide abbreviated author or
887 // editor names (suitable for citation labels),
888 // with respect to maxcitenames.
889 ret = getAuthorOrEditorList(&buf, false, false);
890 if (ci.forceUpperCase && isLowerCase(ret[0]))
891 ret[0] = uppercase(ret[0]);
892 } else if (key == "fullciteauthor") {
893 // Return a full author or editor list (for citation labels)
894 ret = getAuthorOrEditorList(&buf, true, false);
895 if (ci.forceUpperCase && isLowerCase(ret[0]))
896 ret[0] = uppercase(ret[0]);
897 } else if (key == "forceabbrvciteauthor") {
898 // Special key to provide abbreviated author or
899 // editor names (suitable for citation labels),
900 // irrespective of maxcitenames.
901 ret = getAuthorOrEditorList(&buf, false, true);
902 if (ci.forceUpperCase && isLowerCase(ret[0]))
903 ret[0] = uppercase(ret[0]);
904 } else if (key == "bibentry") {
905 // Special key to provide the full bibliography entry: see getInfo()
906 CiteEngineType const engine_type = buf.params().citeEngineType();
907 DocumentClass const & dc = buf.params().documentClass();
908 docstring const & format =
909 from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_), false));
911 ret = expandFormat(format, xrefs, counter, buf, ci, false, false);
912 } else if (key == "textbefore")
914 else if (key == "textafter")
916 else if (key == "curpretext")
917 ret = ci.getPretexts()[bib_key_];
918 else if (key == "curposttext")
919 ret = ci.getPosttexts()[bib_key_];
920 else if (key == "year")
925 ret = html::cleanAttr(ret);
927 // make sure it is not too big
928 support::truncateWithEllipsis(ret, maxsize);
933 //////////////////////////////////////////////////////////////////////
937 //////////////////////////////////////////////////////////////////////
941 // A functor for use with sort, leading to case insensitive sorting
942 class compareNoCase: public binary_function<docstring, docstring, bool>
945 bool operator()(docstring const & s1, docstring const & s2) const {
946 return compare_no_case(s1, s2) < 0;
953 vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
955 vector<docstring> result;
956 if (!data.isBibTeX())
958 // Legacy crossref field. This is not nestable.
959 if (!nested && !data["crossref"].empty()) {
960 docstring const xrefkey = data["crossref"];
961 result.push_back(xrefkey);
962 // However, check for nested xdatas
963 BiblioInfo::const_iterator it = find(xrefkey);
965 BibTeXInfo const & xref = it->second;
966 vector<docstring> const nxdata = getXRefs(xref, true);
968 result.insert(result.end(), nxdata.begin(), nxdata.end());
971 // Biblatex's xdata field. Infinitely nestable.
972 // XData field can consist of a comma-separated list of keys
973 vector<docstring> const xdatakeys = getVectorFromString(data["xdata"]);
974 if (!xdatakeys.empty()) {
975 vector<docstring>::const_iterator xit = xdatakeys.begin();
976 vector<docstring>::const_iterator xen = xdatakeys.end();
977 for (; xit != xen; ++xit) {
978 docstring const xdatakey = *xit;
979 result.push_back(xdatakey);
980 BiblioInfo::const_iterator it = find(xdatakey);
982 BibTeXInfo const & xdata = it->second;
983 vector<docstring> const nxdata = getXRefs(xdata, true);
985 result.insert(result.end(), nxdata.begin(), nxdata.end());
993 vector<docstring> const BiblioInfo::getKeys() const
995 vector<docstring> bibkeys;
996 BiblioInfo::const_iterator it = begin();
997 for (; it != end(); ++it)
998 bibkeys.push_back(it->first);
999 sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
1004 vector<docstring> const BiblioInfo::getFields() const
1006 vector<docstring> bibfields;
1007 set<docstring>::const_iterator it = field_names_.begin();
1008 set<docstring>::const_iterator end = field_names_.end();
1009 for (; it != end; ++it)
1010 bibfields.push_back(*it);
1011 sort(bibfields.begin(), bibfields.end());
1016 vector<docstring> const BiblioInfo::getEntries() const
1018 vector<docstring> bibentries;
1019 set<docstring>::const_iterator it = entry_types_.begin();
1020 set<docstring>::const_iterator end = entry_types_.end();
1021 for (; it != end; ++it)
1022 bibentries.push_back(*it);
1023 sort(bibentries.begin(), bibentries.end());
1028 docstring const BiblioInfo::getAuthorOrEditorList(docstring const & key, Buffer const & buf) const
1030 BiblioInfo::const_iterator it = find(key);
1033 BibTeXInfo const & data = it->second;
1034 return data.getAuthorOrEditorList(&buf, false);
1038 docstring const BiblioInfo::getCiteNumber(docstring const & key) const
1040 BiblioInfo::const_iterator it = find(key);
1043 BibTeXInfo const & data = it->second;
1044 return data.citeNumber();
1048 docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
1050 BiblioInfo::const_iterator it = find(key);
1053 BibTeXInfo const & data = it->second;
1054 docstring year = data.getYear();
1056 // let's try the crossrefs
1057 vector<docstring> const xrefs = getXRefs(data);
1061 vector<docstring>::const_iterator it = xrefs.begin();
1062 vector<docstring>::const_iterator en = xrefs.end();
1063 for (; it != en; ++it) {
1064 BiblioInfo::const_iterator const xrefit = find(*it);
1065 if (xrefit == end())
1067 BibTeXInfo const & xref_data = xrefit->second;
1068 year = xref_data.getYear();
1074 if (use_modifier && data.modifier() != 0)
1075 year += data.modifier();
1080 docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
1082 docstring const year = getYear(key, use_modifier);
1084 return buf.B_("No year");
1089 docstring const BiblioInfo::getInfo(docstring const & key,
1090 Buffer const & buf, CiteItem const & ci) const
1092 BiblioInfo::const_iterator it = find(key);
1094 return docstring(_("Bibliography entry not found!"));
1095 BibTeXInfo const & data = it->second;
1096 BibTeXInfoList xrefptrs;
1097 vector<docstring> const xrefs = getXRefs(data);
1098 if (!xrefs.empty()) {
1099 vector<docstring>::const_iterator it = xrefs.begin();
1100 vector<docstring>::const_iterator en = xrefs.end();
1101 for (; it != en; ++it) {
1102 BiblioInfo::const_iterator const xrefit = find(*it);
1103 if (xrefit != end())
1104 xrefptrs.push_back(&(xrefit->second));
1107 return data.getInfo(xrefptrs, buf, ci);
1111 docstring const BiblioInfo::getLabel(vector<docstring> keys,
1112 Buffer const & buf, string const & style, CiteItem const & ci) const
1114 size_t max_size = ci.max_size;
1115 // shorter makes no sense
1116 LASSERT(max_size >= 16, max_size = 16);
1118 // we can't display more than 10 of these, anyway
1119 bool const too_many_keys = keys.size() > 10;
1123 CiteEngineType const engine_type = buf.params().citeEngineType();
1124 DocumentClass const & dc = buf.params().documentClass();
1125 docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, false, "cite"));
1126 docstring ret = format;
1127 vector<docstring>::const_iterator key = keys.begin();
1128 vector<docstring>::const_iterator ken = keys.end();
1129 for (int i = 0; key != ken; ++key, ++i) {
1130 BiblioInfo::const_iterator it = find(*key);
1131 BibTeXInfo empty_data;
1132 empty_data.key(*key);
1133 BibTeXInfo & data = empty_data;
1134 vector<BibTeXInfo const *> xrefptrs;
1137 vector<docstring> const xrefs = getXRefs(data);
1138 if (!xrefs.empty()) {
1139 vector<docstring>::const_iterator it = xrefs.begin();
1140 vector<docstring>::const_iterator en = xrefs.end();
1141 for (; it != en; ++it) {
1142 BiblioInfo::const_iterator const xrefit = find(*it);
1143 if (xrefit != end())
1144 xrefptrs.push_back(&(xrefit->second));
1148 ret = data.getLabel(xrefptrs, buf, ret, ci, key + 1 != ken, i == 1);
1152 ret.push_back(0x2026);//HORIZONTAL ELLIPSIS
1153 support::truncateWithEllipsis(ret, max_size);
1158 bool BiblioInfo::isBibtex(docstring const & key) const
1161 split(key, key1, ',');
1162 BiblioInfo::const_iterator it = find(key1);
1165 return it->second.isBibTeX();
1169 vector<docstring> const BiblioInfo::getCiteStrings(
1170 vector<docstring> const & keys, vector<CitationStyle> const & styles,
1171 Buffer const & buf, CiteItem const & ci) const
1174 return vector<docstring>();
1177 vector<docstring> vec(styles.size());
1178 for (size_t i = 0; i != vec.size(); ++i) {
1179 style = styles[i].name;
1180 vec[i] = getLabel(keys, buf, style, ci);
1187 void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
1189 bimap_.insert(info.begin(), info.end());
1190 field_names_.insert(info.field_names_.begin(), info.field_names_.end());
1191 entry_types_.insert(info.entry_types_.begin(), info.entry_types_.end());
1197 // used in xhtml to sort a list of BibTeXInfo objects
1198 bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
1200 docstring const lauth = lhs->getAuthorOrEditorList();
1201 docstring const rauth = rhs->getAuthorOrEditorList();
1202 docstring const lyear = lhs->getYear();
1203 docstring const ryear = rhs->getYear();
1204 docstring const ltitl = lhs->operator[]("title");
1205 docstring const rtitl = rhs->operator[]("title");
1206 return (lauth < rauth)
1207 || (lauth == rauth && lyear < ryear)
1208 || (lauth == rauth && lyear == ryear && ltitl < rtitl);
1214 void BiblioInfo::collectCitedEntries(Buffer const & buf)
1216 cited_entries_.clear();
1217 // We are going to collect all the citation keys used in the document,
1218 // getting them from the TOC.
1219 // FIXME We may want to collect these differently, in the first case,
1220 // so that we might have them in order of appearance.
1221 set<docstring> citekeys;
1222 shared_ptr<Toc const> toc = buf.tocBackend().toc("citation");
1223 Toc::const_iterator it = toc->begin();
1224 Toc::const_iterator const en = toc->end();
1225 for (; it != en; ++it) {
1226 if (it->str().empty())
1228 vector<docstring> const keys = getVectorFromString(it->str());
1229 citekeys.insert(keys.begin(), keys.end());
1231 if (citekeys.empty())
1234 // We have a set of the keys used in this document.
1235 // We will now convert it to a list of the BibTeXInfo objects used in
1237 vector<BibTeXInfo const *> bi;
1238 set<docstring>::const_iterator cit = citekeys.begin();
1239 set<docstring>::const_iterator const cen = citekeys.end();
1240 for (; cit != cen; ++cit) {
1241 BiblioInfo::const_iterator const bt = find(*cit);
1242 if (bt == end() || !bt->second.isBibTeX())
1244 bi.push_back(&(bt->second));
1247 sort(bi.begin(), bi.end(), lSorter);
1249 // Now we can write the sorted keys
1250 vector<BibTeXInfo const *>::const_iterator bit = bi.begin();
1251 vector<BibTeXInfo const *>::const_iterator ben = bi.end();
1252 for (; bit != ben; ++bit)
1253 cited_entries_.push_back((*bit)->key());
1257 void BiblioInfo::makeCitationLabels(Buffer const & buf)
1259 collectCitedEntries(buf);
1260 CiteEngineType const engine_type = buf.params().citeEngineType();
1261 bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
1265 // used to remember the last one we saw
1266 // we'll be comparing entries to see if we need to add
1267 // modifiers, like "1984a"
1268 map<docstring, BibTeXInfo>::iterator last = bimap_.end();
1270 vector<docstring>::const_iterator it = cited_entries_.begin();
1271 vector<docstring>::const_iterator const en = cited_entries_.end();
1272 for (; it != en; ++it) {
1273 map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
1274 // this shouldn't happen, but...
1275 if (biit == bimap_.end())
1276 // ...fail gracefully, anyway.
1278 BibTeXInfo & entry = biit->second;
1280 docstring const num = convert<docstring>(++keynumber);
1281 entry.setCiteNumber(num);
1283 // The first test here is checking whether this is the first
1284 // time through the loop. If so, then we do not have anything
1285 // with which to compare.
1286 if (last != bimap_.end()
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)