commit eba2f0479eb5af6b61d9a82e89daea253d9b6bf6
Author: Juergen Spitzmueller <sp...@lyx.org>
Date:   Sat Jan 7 17:32:45 2017 +0100

    Implement display of starred cite commands
    
    This entails a change of getAbbrAuthor to getAuthorList (the default is
    still abbreviated with respect to MaxCiteItems, but the list can be, at
    explicit request, shortened or full notwithstanding MaxCiteItems.
---
 lib/citeengines/basic.citeengine   |    1 +
 lib/citeengines/jurabib.citeengine |    6 ++
 lib/citeengines/natbib.citeengine  |   32 ++++++++----
 src/BiblioInfo.cpp                 |   96 +++++++++++++++++++++++++++---------
 src/BiblioInfo.h                   |   13 +++--
 src/frontends/qt4/GuiCitation.cpp  |    3 +-
 src/frontends/qt4/Menus.cpp        |    1 +
 src/insets/InsetCitation.cpp       |    7 +--
 8 files changed, 114 insertions(+), 45 deletions(-)

diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine
index a850f07..f8d5c5b 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 50c74bd..220dd64 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 0eee3cc..f3a0385 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 8a17925..44e517a 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]);
-
-       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]));
+       CiteEngineType const engine_type = buf ? buf->params().citeEngineType()
+                                              : ENGINE_TYPE_DEFAULT;
+
+       // 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<docstring>::const_iterator it = authors.begin();
+       vector<docstring>::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<docstring> 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 af55c44..3fc7866 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<docstring> const getFields() const;
        /// \return a sorted vector of BibTeX entry types in use
        std::vector<docstring> 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 9e5bfab..d73f3d3 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<docstring> ret = bi.getCiteStrings(keys, styles, 
documentBuffer(), ci);
diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp
index 78b596f..fd2d0f3 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<docstring> citeStrings =
diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp
index a6cb6af..e47f311 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<CitationStyle> 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;

Reply via email to