]> git.lyx.org Git - lyx.git/blobdiff - src/BiblioInfo.cpp
Natbib authoryear uses (Ref1; Ref2) by default.
[lyx.git] / src / BiblioInfo.cpp
index 4ad119cefd0db38e3e8ff89f6c4a312a16c0efa4..db397a4f7df91c0a8ebf87f60de19591783f1ca5 100644 (file)
@@ -20,6 +20,7 @@
 #include "Encoding.h"
 #include "InsetIterator.h"
 #include "Language.h"
+#include "output_xhtml.h"
 #include "Paragraph.h"
 #include "TextClass.h"
 #include "TocBackend.h"
@@ -254,7 +255,7 @@ BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
 {}
 
 
-docstring const BibTeXInfo::getAbbreviatedAuthor(bool jurabib_style, string lang) const
+docstring const BibTeXInfo::getAbbreviatedAuthor(bool jurabib_style) const
 {
        if (!is_bibtex_) {
                docstring const opt = label();
@@ -293,18 +294,33 @@ docstring const BibTeXInfo::getAbbreviatedAuthor(bool jurabib_style, string lang
                return shortauthor;
        }
 
-       if (authors.size() == 2)
-               return bformat(translateIfPossible(from_ascii("%1$s and %2$s"), lang),
+       if (authors.size() == 2 && authors[1] != "others")
+               return bformat(from_ascii("%1$s and %2$s"),
                        familyName(authors[0]), familyName(authors[1]));
 
-       if (authors.size() > 2)
-               return bformat(translateIfPossible(from_ascii("%1$s et al."), lang),
+       if (authors.size() >= 2)
+               return bformat(from_ascii("%1$s et al."),
                        familyName(authors[0]));
 
        return familyName(authors[0]);
 }
 
 
+docstring const BibTeXInfo::getAbbreviatedAuthor(Buffer const & buf, bool jurabib_style) const
+{
+       docstring const author = getAbbreviatedAuthor(jurabib_style);
+       if (!is_bibtex_)
+               return author;
+       vector<docstring> const authors = getVectorFromString(author, from_ascii(" and "));
+       if (authors.size() == 2)
+               return bformat(buf.B_("%1$s and %2$s"), authors[0], authors[1]);
+       docstring::size_type const idx = author.rfind(from_ascii(" et al."));
+       if (idx != docstring::npos)
+               return bformat(buf.B_("%1$s et al."), author.substr(0, idx));
+       return author;
+}
+
+
 docstring const BibTeXInfo::getYear() const
 {
        if (is_bibtex_)
@@ -354,9 +370,10 @@ string parseEmbeddedOption(string const & format, string & ifelsepart)
                LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
                return format;
        }
-       LASSERT(rest.size() <= format.size(), /* */);
+       LASSERT(rest.size() <= format.size(),
+               { ifelsepart = ""; return format; });
        ifelsepart = format.substr(0, format.size() - rest.size());
-               return rest;
+       return rest;
 }
 
 
@@ -456,7 +473,6 @@ docstring BibTeXInfo::expandFormat(string const & format,
        static int max_passes = 5000;
        docstring ret; // return value
        string key;
-       string lang = buf.params().language->code();
        bool scanning_key = false;
        bool scanning_rich = false;
 
@@ -480,8 +496,6 @@ docstring BibTeXInfo::expandFormat(string const & format,
                                // so we replace the key with its value, which may be empty
                                if (key[0] == '!') {
                                        // macro
-                                       // FIXME: instead of passing the buf, just past the macros
-                                       // FIXME: and the language code
                                        string const val =
                                                buf.params().documentClass().getCiteMacro(engine_type, key);
                                        fmt = val + fmt.substr(1);
@@ -491,14 +505,16 @@ docstring BibTeXInfo::expandFormat(string const & format,
                                        string const val =
                                                buf.params().documentClass().getCiteMacro(engine_type, key);
                                        docstring const trans =
-                                               translateIfPossible(from_utf8(val), lang);
+                                               translateIfPossible(from_utf8(val), buf.params().language->code());
                                        ret += trans;
                                } else {
                                        docstring const val =
-                                               getValueForKey(key, before, after, dialog, xref, lang);
-                                       ret += from_ascii("{!<span class=\"bib-" + key + "\">!}");
+                                               getValueForKey(key, buf, before, after, dialog, xref);
+                                       if (!scanning_rich)
+                                               ret += from_ascii("{!<span class=\"bib-" + key + "\">!}");
                                        ret += val;
-                                       ret += from_ascii("{!</span>!}");
+                                       if (!scanning_rich)
+                                               ret += from_ascii("{!</span>!}");
                                }
                        } else {
                                // beginning of key
@@ -524,7 +540,7 @@ docstring BibTeXInfo::expandFormat(string const & format,
                                                return _("ERROR!");
                                        fmt = newfmt;
                                        docstring const val =
-                                               getValueForKey(optkey, before, after, dialog, xref, lang);
+                                               getValueForKey(optkey, buf, before, after, dialog, xref);
                                        if (optkey == "next" && next)
                                                ret += from_utf8(ifpart); // without expansion
                                        else if (!val.empty())
@@ -577,8 +593,10 @@ docstring BibTeXInfo::expandFormat(string const & format,
 docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
        Buffer const & buf, bool richtext) const
 {
-       if (!info_.empty())
+       if (!richtext && !info_.empty())
                return info_;
+       if (richtext && !info_richtext_.empty())
+               return info_richtext_;
 
        if (!is_bibtex_) {
                BibTeXInfo::const_iterator it = find(from_ascii("ref"));
@@ -593,8 +611,12 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
        info_ = expandFormat(format, xref, counter, buf,
                docstring(), docstring(), docstring(), false);
 
-       if (!info_.empty())
-               info_ = convertLaTeXCommands(info_);
+       if (!info_.empty()) {
+               info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
+               info_ = convertLaTeXCommands(processRichtext(info_, false));
+               if (richtext)
+                       return info_richtext_;
+       }
        return info_;
 }
 
@@ -605,14 +627,6 @@ docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
 {
        docstring loclabel;
 
-       /*
-       if (!is_bibtex_) {
-               BibTeXInfo::const_iterator it = find(from_ascii("ref"));
-               label_ = it->second;
-               return label_;
-       }
-       */
-
        int counter = 0;
        loclabel = expandFormat(format, xref, counter, buf,
                before, after, dialog, next);
@@ -641,48 +655,66 @@ docstring const & BibTeXInfo::operator[](string const & field) const
 }
 
 
-docstring BibTeXInfo::getValueForKey(string const & key,
+docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
        docstring const & before, docstring const & after, docstring const & dialog,
-       BibTeXInfo const * const xref, string lang) const
+       BibTeXInfo const * const xref) const
 {
+       string key = oldkey;
+       bool cleanit = false;
+       if (prefixIs(oldkey, "clean:")) {
+               key = oldkey.substr(6);
+               cleanit = true;
+       }
+               
        docstring ret = operator[](key);
        if (ret.empty() && xref)
                ret = (*xref)[key];
-       if (!ret.empty())
-               return ret;
-       // some special keys
-       // FIXME: dialog, textbefore and textafter have nothing to do with this
-       if (key == "dialog")
-               return dialog;
-       else if (key == "entrytype")
-               return entry_type_;
-       else if (key == "key")
-               return bib_key_;
-       else if (key == "label")
-               return label_;
-       else if (key == "abbrvauthor")
-               // Special key to provide abbreviated author names.
-               return getAbbreviatedAuthor(false, lang);
-       else if (key == "shortauthor")
-               // When shortauthor is not defined, jurabib automatically
-               // provides jurabib-style abbreviated author names. We do
-               // this as well.
-               return getAbbreviatedAuthor(true, lang);
-       else if (key == "shorttitle") {
-               // When shorttitle is not defined, jurabib uses for `article'
-               // and `periodical' entries the form `journal volume [year]'
-               // and for other types of entries it uses the `title' field.
-               if (entry_type_ == "article" || entry_type_ == "periodical")
-                       return operator[]("journal") + " " + operator[]("volume")
-                               + " [" + operator[]("year") + "]";
-               else
-                       return operator[]("title");
-       } else if (key == "textbefore")
-               return before;
-       else if (key == "textafter")
-               return after;
-       else if (key == "year")
-               return getYear();
+       if (ret.empty()) {
+               // some special keys
+               // FIXME: dialog, textbefore and textafter have nothing to do with this
+               if (key == "dialog")
+                       ret = dialog;
+               else if (key == "entrytype")
+                       ret = entry_type_;
+               else if (key == "key")
+                       ret = bib_key_;
+               else if (key == "label")
+                       ret = label_;
+               else if (key == "abbrvauthor")
+                       // Special key to provide abbreviated author names.
+                       ret = getAbbreviatedAuthor(buf, false);
+               else if (key == "shortauthor")
+                       // When shortauthor is not defined, jurabib automatically
+                       // provides jurabib-style abbreviated author names. We do
+                       // this as well.
+                       ret = getAbbreviatedAuthor(buf, true);
+               else if (key == "shorttitle") {
+                       // When shorttitle is not defined, jurabib uses for `article'
+                       // and `periodical' entries the form `journal volume [year]'
+                       // and for other types of entries it uses the `title' field.
+                       if (entry_type_ == "article" || entry_type_ == "periodical")
+                               ret = operator[]("journal") + " " + operator[]("volume")
+                                       + " [" + operator[]("year") + "]";
+                       else
+                               ret = operator[]("title");
+               } else if (key == "bibentry") {
+                       // Special key to provide the full bibliography entry: see getInfo()
+                       CiteEngineType const engine_type = buf.params().citeEngineType();
+                       DocumentClass const & dc = buf.params().documentClass();
+                       string const & format = dc.getCiteFormat(engine_type, to_utf8(entry_type_));
+                       int counter = 0;
+                       ret = expandFormat(format, xref, counter, buf,
+                               docstring(), docstring(), docstring(), false);
+               } else if (key == "textbefore")
+                       ret = before;
+               else if (key == "textafter")
+                       ret = after;
+               else if (key == "year")
+                       ret = getYear();
+       }
+       if (cleanit)
+               return html::cleanAttr(ret);
+       
        return ret;
 }
 
@@ -742,13 +774,13 @@ vector<docstring> const BiblioInfo::getEntries() const
 }
 
 
-docstring const BiblioInfo::getAbbreviatedAuthor(docstring const & key, string lang) const
+docstring const BiblioInfo::getAbbreviatedAuthor(docstring const & key, Buffer const & buf) const
 {
        BiblioInfo::const_iterator it = find(key);
        if (it == end())
                return docstring();
        BibTeXInfo const & data = it->second;
-       return data.getAbbreviatedAuthor(false, lang);
+       return data.getAbbreviatedAuthor(buf, false);
 }
 
 
@@ -762,7 +794,7 @@ docstring const BiblioInfo::getCiteNumber(docstring const & key) const
 }
 
 
-docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier, string lang) const
+docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) const
 {
        BiblioInfo::const_iterator it = find(key);
        if (it == end())
@@ -774,11 +806,11 @@ docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier, st
                docstring const xref = data.getXRef();
                if (xref.empty())
                        // no luck
-                       return translateIfPossible(from_ascii("No year"), lang);
+                       return docstring();
                BiblioInfo::const_iterator const xrefit = find(xref);
                if (xrefit == end())
                        // no luck again
-                       return translateIfPossible(from_ascii("No year"), lang);
+                       return docstring();
                BibTeXInfo const & xref_data = xrefit->second;
                year = xref_data.getYear();
        }
@@ -788,6 +820,15 @@ docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier, st
 }
 
 
+docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
+{
+       docstring const year = getYear(key, use_modifier);
+       if (year.empty())
+               return buf.B_("No year");
+       return year;
+}
+
+
 docstring const BiblioInfo::getInfo(docstring const & key,
        Buffer const & buf, bool richtext) const
 {
@@ -983,6 +1024,28 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf)
                        last = biit;
                }
        }
+       // Set the labels
+       it = cited_entries_.begin();
+       for (; it != en; ++it) {
+               map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
+               // this shouldn't happen, but...
+               if (biit == bimap_.end())
+                       // ...fail gracefully, anyway.
+                       continue;
+               BibTeXInfo & entry = biit->second;
+               if (numbers) {
+                       entry.label(entry.citeNumber());
+               } else {
+                       docstring const auth = entry.getAbbreviatedAuthor(buf, false);
+                       // we do it this way so as to access the xref, if necessary
+                       // note that this also gives us the modifier
+                       docstring const year = getYear(*it, buf, true);
+                       if (!auth.empty() && !year.empty())
+                               entry.label(auth + ' ' + year);
+                       else
+                               entry.label(entry.key());
+               }
+       }
 }