diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine index a850f07f98..f8d5c5baef 100644 --- a/lib/citeengines/basic.citeengine +++ b/lib/citeengines/basic.citeengine @@ -43,6 +43,7 @@ CiteFormat default # MACROS # # 1. Translatable bits (need to be marked by _ prefix) + # Note that preceding and trailing spaces matter. # _notcited not cited _addtobib Add to bibliography only. diff --git a/lib/citeengines/jurabib.citeengine b/lib/citeengines/jurabib.citeengine index 50c74bdb05..220dd640a7 100644 --- a/lib/citeengines/jurabib.citeengine +++ b/lib/citeengines/jurabib.citeengine @@ -109,6 +109,7 @@ CiteFormat authoryear # MACROS # # 1. Translatable bits (need to be marked by _ prefix) + # Note that preceding and trailing spaces matter. # _notcited not cited _addtobib Add to bibliography only. @@ -116,6 +117,11 @@ CiteFormat authoryear _bibentry Bibliography entry. _before before _shorttitle short title + # The following are handled by BiblioInfo + _etal et al. + _namesep / + _lastnamesep / + _pairnamesep / # # 2. Macros re-used in the style definitions diff --git a/lib/citeengines/natbib.citeengine b/lib/citeengines/natbib.citeengine index 0eee3cc840..f3a0385094 100644 --- a/lib/citeengines/natbib.citeengine +++ b/lib/citeengines/natbib.citeengine @@ -106,9 +106,15 @@ CiteFormat default # MACROS # # 1. Translatable bits (need to be marked by _ prefix) + # Note that preceding and trailing spaces matter. # _notcited not cited _addtobib Add to bibliography only. + # The following are handled by BiblioInfo + _etal et al. + _namesep , [[separate author names in citation, except for last name]] + _lastnamesep , and [[separate name of last author in citation]] + _pairnamesep and [[separate two authors in citation]] # # 2. Macros re-used in the style definitions @@ -120,6 +126,10 @@ CiteFormat default # "Author et al." or "??" !abbrvauthor {%abbrvauthor%[[%abbrvauthor%]][[??]]} + # "Author, ..." or "??" + !fullauthor {%fullauthor%[[%fullauthor%]][[??]]} + # Handle starred command: abbr. or full author list + !makeauthor {%ifstar%[[%!fullauthor%]][[%!abbrvauthor%]]} # "prenote " !textbefore {%textbefore%[[%textbefore% ]]} # ", postnote" @@ -129,6 +139,8 @@ CiteFormat default # "...; Author..." !nextauthor {%next%[[%!sep% %!startlink%%!abbrvauthor%%!endlink%%!nextauthor%]]} + # Handle starred command: abbr. or full author list + !makenextauthor {%next%[[%!sep% %!startlink%%!makeauthor%%!endlink%%!makenextauthor%]]} # "..., CiteKey..." !nextkey {%next%[[%!sep% %key%%!nextkey%]]} # "..., Year..." @@ -155,14 +167,14 @@ CiteFormat authoryear !close ) # "Author et al. (cf. Year..." - !makecitet %!startlink%%!abbrvauthor%%!endlink% %!open%%!textbefore%%!year%%!nextcitet% + !makecitet %!startlink%%!makeauthor%%!endlink% %!open%%!textbefore%%!year%%!nextcitet% # "Author et al. cf. Year..." [sic!] - !makecitealt %!startlink%%!abbrvauthor% %!textbefore%%!year%%!endlink%%!nextcitealt% + !makecitealt %!startlink%%!makeauthor% %!textbefore%%!year%%!endlink%%!nextcitealt% # "Author et al., Year..." - !makecitealp %!startlink%%!abbrvauthor%, %!year%%!endlink%%!nextcitealp% + !makecitealp %!startlink%%!makeauthor%, %!year%%!endlink%%!nextcitealp% # "...); Nextauthor (Year..." - !nextcitet {%next%[[%!close%%!sep% %!startlink%%!abbrvauthor%%!endlink% %!open%%!year%%!nextcitet%]]} + !nextcitet {%next%[[%!close%%!sep% %!startlink%%!makeauthor%%!endlink% %!open%%!year%%!nextcitet%]]} # "...; NextAuthor et al. Year..." !nextcitealt {%next%[[%!sep% %!makecitealt%]]} # "...; NextAuthor et al., Year..." @@ -183,7 +195,7 @@ CiteFormat authoryear # "Author cf. Year; NextAuthor Year, p. xx" [sic!] citealt %!makecitealt%%!textafter% # "Author; NextAuthor, p. xx" - citeauthor %!startlink%%!abbrvauthor%%!endlink%%!nextauthor%%!textafter% + citeauthor %!startlink%%!makeauthor%%!endlink%%!makenextauthor%%!textafter% # "Year; NextYear, p. xx" citeyear %!startlink%%!year%%!endlink%%!nextyear%%!textafter% @@ -200,16 +212,16 @@ CiteFormat numerical !close ] # "Author [cf. ID..." - !makecitet %!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet% + !makecitet %!makeauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet% # "Author cf. ID..." - !makecitealt %!abbrvauthor% %!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt% + !makecitealt %!makeauthor% %!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt% # "ID..." !hashkey {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nexthashkey%]]} # "...], NextAuthor [ID..." - !nextcitet {%next%[[%!close%%!sep% %!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]} + !nextcitet {%next%[[%!close%%!sep% %!makeauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]} # "..., NextAuthor ID..." - !nextcitealt {%next%[[%!sep% %!abbrvauthor% {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt%]]} + !nextcitealt {%next%[[%!sep% %!makeauthor% {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt%]]} # FIXME: What is this? !nexthashid {%next%[[%!sep% #ID%!nexthashid%]]} # "..., NextID..." @@ -230,7 +242,7 @@ CiteFormat numerical # "Author cf. ID, NextAuthor ID, p. xx" citealt %!makecitealt%%!textafter% # "Author, NextAuthor" - citeauthor %!startlink%%!abbrvauthor%%!endlink%%!nextauthor% + citeauthor %!startlink%%!makeauthor%%!endlink%%!makenextauthor% # "Year, NextYear" citeyear %!startlink%%!year%%!endlink%%!nextyear% diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp index 8a17925856..44e517a18f 100644 --- a/src/BiblioInfo.cpp +++ b/src/BiblioInfo.cpp @@ -256,9 +256,13 @@ BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type) {} -docstring const BibTeXInfo::getAbbreviatedAuthor( - Buffer const * buf, bool jurabib_style) const +docstring const BibTeXInfo::getAuthorList( + Buffer const * buf, bool full, bool forceshort) const { + // Maxnames treshold depend on engine + size_t maxnames = buf ? + buf->params().documentClass().max_citenames() : 2; + if (!is_bibtex_) { docstring const opt = label(); if (opt.empty()) @@ -295,21 +299,51 @@ docstring const BibTeXInfo::getAbbreviatedAuthor( shortauthor += "/" + familyName(authors[2]); return convertLaTeXCommands(shortauthor); } + docstring retval; - docstring retval = familyName(authors[0]); + CiteEngineType const engine_type = buf ? buf->params().citeEngineType() + : ENGINE_TYPE_DEFAULT; - if (authors.size() == 2 && authors[1] != "others") { - docstring const dformat = buf ? - buf->B_("%1$s and %2$s") : from_ascii("%1$s and %2$s"); - retval = bformat(dformat, familyName(authors[0]), familyName(authors[1])); - } else if (authors.size() >= 2) { - // we get here either if the author list is longer than two names - // or if the second 'name' is "others". we do the same thing either - // way. - docstring const dformat = buf ? - buf->B_("%1$s et al.") : from_ascii("%1$s et al."); - retval = bformat(dformat, familyName(authors[0])); + // These are defined in the styles + string const etal = + buf ? buf->params().documentClass().getCiteMacro(engine_type, "_etal") + : " et al."; + string const namesep = + buf ? buf->params().documentClass().getCiteMacro(engine_type, "_namesep") + : ", "; + string const lastnamesep = + buf ? buf->params().documentClass().getCiteMacro(engine_type, "_lastnamesep") + : ", and "; + string const pairnamesep = + buf ? buf->params().documentClass().getCiteMacro(engine_type, "_pairnamesep") + : " and "; + + // Shorten the list (with et al.) if forceshort is set + // and the list can actually be shorten, else if maxcitenames + // is passed and full is not set. + bool shorten = forceshort && authors.size() > 1; + vector::const_iterator it = authors.begin(); + vector::const_iterator en = authors.end(); + for (size_t i = 0; it != en; ++it, ++i) { + if (i >= maxnames && !full) { + shorten = true; + break; + } + if (*it == "others") { + retval += buf ? buf->B_(etal) : from_ascii(etal); + break; + } + if (i > 0 && i == authors.size() - 1) { + if (authors.size() == 2) + retval += buf ? buf->B_(pairnamesep) : from_ascii(pairnamesep); + else + retval += buf ? buf->B_(lastnamesep) : from_ascii(lastnamesep); + } else if (i > 0) + retval += buf ? buf->B_(namesep) : from_ascii(namesep); + retval += familyName(*it); } + if (shorten) + retval = familyName(authors[0]) + (buf ? buf->B_(etal) : from_ascii(etal)); return convertLaTeXCommands(retval); } @@ -717,6 +751,8 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, // FIXME: dialog, textbefore and textafter have nothing to do with this if (key == "dialog" && ci.context == CiteItem::Dialog) ret = from_ascii("x"); // any non-empty string will do + else if (key == "ifstar" && ci.Starred) + ret = from_ascii("x"); // any non-empty string will do else if (key == "entrytype") ret = entry_type_; else if (key == "key") @@ -727,9 +763,6 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, ret = modifier_; else if (key == "numericallabel") ret = cite_number_; - 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 @@ -744,6 +777,21 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf, + " [" + operator[]("year") + "]"; else ret = operator[]("title"); + else if (key == "abbrvauthor") { + // Special key to provide abbreviated author names, + // with respect to maxcitenames. + ret = getAuthorList(&buf, false, false); + if (ci.forceUpperCase && isLowerCase(ret[0])) + ret[0] = uppercase(ret[0]); + } else if (key == "fullauthor") { + // Return a full author list + ret = getAuthorList(&buf, true, false); + if (ci.forceUpperCase && isLowerCase(ret[0])) + ret[0] = uppercase(ret[0]); + } else if (key == "forceabbrvauthor") { + // Special key to provide abbreviated author names, + // irrespective of maxcitenames. + ret = getAuthorList(&buf, false, true); if (ci.forceUpperCase && isLowerCase(ret[0])) ret[0] = uppercase(ret[0]); } else if (key == "bibentry") { @@ -866,13 +914,13 @@ vector const BiblioInfo::getEntries() const } -docstring const BiblioInfo::getAbbreviatedAuthor(docstring const & key, Buffer const & buf) const +docstring const BiblioInfo::getAuthorList(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(&buf, false); + return data.getAuthorList(&buf, false); } @@ -1038,8 +1086,8 @@ namespace { // used in xhtml to sort a list of BibTeXInfo objects bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs) { - docstring const lauth = lhs->getAbbreviatedAuthor(); - docstring const rauth = rhs->getAbbreviatedAuthor(); + docstring const lauth = lhs->getAuthorList(); + docstring const rauth = rhs->getAuthorList(); docstring const lyear = lhs->getYear(); docstring const ryear = rhs->getYear(); docstring const ltitl = lhs->operator[]("title"); @@ -1127,7 +1175,7 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf) // the first test. // coverity[FORWARD_NULL] if (it != cited_entries_.begin() - && entry.getAbbreviatedAuthor() == last->second.getAbbreviatedAuthor() + && entry.getAuthorList() == last->second.getAuthorList() // we access the year via getYear() so as to get it from the xref, // if we need to do so && getYear(entry.key()) == getYear(last->second.key())) { @@ -1159,7 +1207,7 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf) if (numbers) { entry.label(entry.citeNumber()); } else { - docstring const auth = entry.getAbbreviatedAuthor(&buf, false); + docstring const auth = entry.getAuthorList(&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); diff --git a/src/BiblioInfo.h b/src/BiblioInfo.h index af55c44e09..3fc786621c 100644 --- a/src/BiblioInfo.h +++ b/src/BiblioInfo.h @@ -55,11 +55,12 @@ public: BibTeXInfo(bool ib) : is_bibtex_(ib), modifier_(0) {} /// constructor that sets the entryType BibTeXInfo(docstring const & key, docstring const & type); - /// \return the short form of an authorlist, used for sorting - /// this will be translated to the UI language if buf is null + /// \return the an authorlist (short form by default), + /// used for sorting. + /// This will be translated to the UI language if buf is null /// otherwise, it will be translated to the buffer language. - docstring const getAbbreviatedAuthor( - Buffer const * buf = 0, bool jurabib_style = false) const; + docstring const getAuthorList(Buffer const * buf = 0, bool full = false, + bool forceshort = false) const; /// docstring const getYear() const; /// \return formatted BibTeX data suitable for framing. @@ -178,8 +179,8 @@ public: std::vector const getFields() const; /// \return a sorted vector of BibTeX entry types in use std::vector const getEntries() const; - /// \return the short form of an authorlist - docstring const getAbbreviatedAuthor(docstring const & key, Buffer const & buf) const; + /// \return authorlist (abbreviated form by default) + docstring const getAuthorList(docstring const & key, Buffer const & buf) const; /// \return the year from the bibtex data record for \param key /// if \param use_modifier is true, then we will also append any /// modifier for this entry (e.g., 1998b). diff --git a/src/frontends/qt4/GuiCitation.cpp b/src/frontends/qt4/GuiCitation.cpp index 9e5bfab845..d73f3d3542 100644 --- a/src/frontends/qt4/GuiCitation.cpp +++ b/src/frontends/qt4/GuiCitation.cpp @@ -125,7 +125,7 @@ GuiCitation::GuiCitation(GuiView & lv) connect(citationStyleCO, SIGNAL(activated(int)), this, SLOT(on_citationStyleCO_currentIndexChanged(int))); connect(starredCB, SIGNAL(clicked()), - this, SLOT(changed())); + this, SLOT(updateStyles())); connect(forceuppercaseCB, SIGNAL(clicked()), this, SLOT(updateStyles())); connect(textBeforeED, SIGNAL(textChanged(QString)), @@ -686,6 +686,7 @@ QStringList GuiCitation::citationStyles(BiblioInfo const & bi, size_t max_size) ci.textBefore = qstring_to_ucs4(textBeforeED->text()); ci.textAfter = qstring_to_ucs4(textAfterED->text()); ci.forceUpperCase = forceuppercaseCB->isChecked(); + ci.Starred = starredCB->isChecked(); ci.context = CiteItem::Dialog; ci.max_size = max_size; vector ret = bi.getCiteStrings(keys, styles, documentBuffer(), ci); diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp index 78b596f5b0..fd2d0f39e7 100644 --- a/src/frontends/qt4/Menus.cpp +++ b/src/frontends/qt4/Menus.cpp @@ -1554,6 +1554,7 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv) ci.textBefore = citinset->getParam("before"); ci.textAfter = citinset->getParam("after"); ci.forceUpperCase = force; + ci.Starred = star; ci.context = CiteItem::Dialog; ci.max_size = 40; vector citeStrings = diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp index a6cb6af8aa..e47f31189f 100644 --- a/src/insets/InsetCitation.cpp +++ b/src/insets/InsetCitation.cpp @@ -177,7 +177,6 @@ docstring InsetCitation::toolTip(BufferView const & bv, int, int) const namespace { - CitationStyle asValidLatexCommand(BufferParams const & bp, string const & input, vector const & valid_styles) { @@ -254,13 +253,12 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const if (key.empty()) return _("No citations selected!"); - // We don't currently use the full or forceUCase fields. string cite_type = getCmdName(); bool const uppercase = isUpperCase(cite_type[0]); if (uppercase) cite_type[0] = lowercase(cite_type[0]); - if (cite_type[cite_type.size() - 1] == '*') - // and this would mean FULL + bool const starred = (cite_type[cite_type.size() - 1] == '*'); + if (starred) cite_type = cite_type.substr(0, cite_type.size() - 1); // handle alias @@ -279,6 +277,7 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const ci.textBefore = getParam("before"); ci.textAfter = getParam("after"); ci.forceUpperCase = uppercase; + ci.Starred = starred; ci.max_size = UINT_MAX; if (for_xhtml) { ci.max_key_size = UINT_MAX;