]> git.lyx.org Git - features.git/blobdiff - src/insets/InsetCitation.cpp
Make the generation of children's tocs more robust
[features.git] / src / insets / InsetCitation.cpp
index a6cb6af8aa419d1347a6d40d7d098088e4ebfd07..0a5da5b1192f63a04d4210e7f1489e64e35c461c 100644 (file)
@@ -82,13 +82,69 @@ bool InsetCitation::isCompatibleCommand(string const &)
 }
 
 
+CitationStyle InsetCitation::getCitationStyle(BufferParams const & bp, string const & input,
+                                 vector<CitationStyle> const & valid_styles) const
+{
+       CitationStyle cs = valid_styles[0];
+       cs.forceUpperCase = false;
+       cs.hasStarredVersion = false;
+
+       string normalized_input = input;
+       string::size_type const n = input.size() - 1;
+       if (isUpperCase(input[0]))
+               normalized_input[0] = lowercase(input[0]);
+       if (input[n] == '*')
+               normalized_input = normalized_input.substr(0, n);
+
+       string const alias = bp.getCiteAlias(normalized_input);
+       if (!alias.empty())
+               normalized_input = alias;
+
+       vector<CitationStyle>::const_iterator it  = valid_styles.begin();
+       vector<CitationStyle>::const_iterator end = valid_styles.end();
+       for (; it != end; ++it) {
+               CitationStyle this_cs = *it;
+               if (this_cs.name == normalized_input) {
+                       cs = *it;
+                       break;
+               }
+       }
+
+       return cs;
+}
+
+
 void InsetCitation::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
-       if (cmd.action() == LFUN_INSET_MODIFY) {
+       switch (cmd.action()) {
+       case LFUN_INSET_MODIFY: {
                buffer().removeBiblioTempFiles();
                cache.recalculate = true;
+               if (cmd.getArg(0) == "toggleparam") {
+                       string cmdname = getCmdName();
+                       string const alias =
+                               buffer().masterParams().getCiteAlias(cmdname);
+                       if (!alias.empty())
+                               cmdname = alias;
+                       string const par = cmd.getArg(1);
+                       string newcmdname = cmdname;
+                       if (par == "star") {
+                               if (suffixIs(cmdname, "*"))
+                                       newcmdname = rtrim(cmdname, "*");
+                               else
+                                       newcmdname = cmdname + "*";
+                       } else if (par == "casing") {
+                               if (isUpperCase(cmdname[0]))
+                                       newcmdname[0] = lowercase(cmdname[0]);
+                               else
+                                       newcmdname[0] = uppercase(newcmdname[0]);
+                       }
+                       cmd = FuncRequest(LFUN_INSET_MODIFY, "changetype " + newcmdname);
+               }
+       }
+       default:
+               InsetCommand::doDispatch(cur, cmd);
        }
-       InsetCommand::doDispatch(cur, cmd);
 }
 
 
@@ -100,14 +156,35 @@ bool InsetCitation::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_INSET_MODIFY:
                if (cmd.getArg(0) == "changetype") {
                        string cmdname = getCmdName();
-                       string const alias = buffer().params().getCiteAlias(cmdname);
+                       string const alias =
+                               buffer().masterParams().getCiteAlias(cmdname);
                        if (!alias.empty())
                                cmdname = alias;
+                       if (suffixIs(cmdname, "*"))
+                               cmdname = rtrim(cmdname, "*");
                        string const newtype = cmd.getArg(1);
                        status.setEnabled(isCompatibleCommand(newtype));
                        status.setOnOff(newtype == cmdname);
                }
-               status.setEnabled(true);
+               if (cmd.getArg(0) == "toggleparam") {
+                       string cmdname = getCmdName();
+                       string const alias =
+                               buffer().masterParams().getCiteAlias(cmdname);
+                       if (!alias.empty())
+                               cmdname = alias;
+                       vector<CitationStyle> citation_styles =
+                               buffer().masterParams().citeStyles();
+                       CitationStyle cs = getCitationStyle(buffer().masterParams(),
+                                                           cmdname, citation_styles);
+                       if (cmd.getArg(1) == "star") {
+                               status.setEnabled(cs.hasStarredVersion);
+                               status.setOnOff(suffixIs(cmdname, "*"));
+                       }
+                       else if (cmd.getArg(1) == "casing") {
+                               status.setEnabled(cs.forceUpperCase);
+                               status.setOnOff(isUpperCase(cmdname[0]));
+                       }
+               }
                return true;
        default:
                return InsetCommand::getStatus(cur, cmd, status);
@@ -164,11 +241,21 @@ docstring InsetCitation::toolTip(BufferView const & bv, int, int) const
 
        docstring tip;
        tip += "<ol>";
+       int count = 0;
        for (docstring const & key : keys) {
                docstring const key_info = bi.getInfo(key, buffer(), ci);
+               // limit to reasonable size.
+               if (count > 9 && keys.size() > 11) {
+                       tip.push_back(0x2026);// HORIZONTAL ELLIPSIS
+                       tip += "<p>"
+                               + bformat(_("+ %1$d more entries."), int(keys.size() - count))
+                               + "</p>";
+                       break;
+               }
                if (key_info.empty())
                        continue;
                tip += "<li>" + key_info + "</li>";
+               ++count;
        }
        tip += "</ol>";
        return tip;
@@ -177,7 +264,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,17 +340,16 @@ 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
-       string const alias = buf.params().getCiteAlias(cite_type);
+       string const alias = buf.masterParams().getCiteAlias(cite_type);
        if (!alias.empty())
                cite_type = alias;
 
@@ -279,6 +364,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;
@@ -334,7 +420,7 @@ void InsetCitation::updateBuffer(ParIterator const &, UpdateType)
 
 
 void InsetCitation::addToToc(DocIterator const & cpit, bool output_active,
-                                                        UpdateType) const
+                                                        UpdateType, TocBackend & backend) const
 {
        // NOTE
        // BiblioInfo::collectCitedEntries() uses the TOC to collect the citations 
@@ -342,8 +428,9 @@ void InsetCitation::addToToc(DocIterator const & cpit, bool output_active,
        // by both XHTML and plaintext output. So, if we change what goes into the TOC,
        // then we will also need to change that routine.
        docstring const tocitem = getParam("key");
-       shared_ptr<Toc> toc = buffer().tocBackend().toc("citation");
-       toc->push_back(TocItem(cpit, 0, tocitem, output_active));
+       TocBuilder & b = backend.builder("citation");
+       b.pushItem(cpit, tocitem, output_active);
+       b.pop();
 }
 
 
@@ -421,9 +508,19 @@ void InsetCitation::forOutliner(docstring & os, size_t const, bool const) const
 // engine, e.g. \cite[]{} for the basic engine.
 void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
 {
-       vector<CitationStyle> citation_styles = buffer().params().citeStyles();
-       CitationStyle cs = asValidLatexCommand(buffer().params(), getCmdName(), citation_styles);
        BiblioInfo const & bi = buffer().masterBibInfo();
+       if (getCmdName() == "keyonly") {
+               // Special command to only return the key
+               if (!bi.isBibtex(getParam("key")))
+                       // escape chars with bibitems
+                       os << escape(cleanupWhitespace(getParam("key")));
+               else
+                       os << cleanupWhitespace(getParam("key"));
+               return;
+       }
+       vector<CitationStyle> citation_styles = buffer().masterParams().citeStyles();
+       CitationStyle cs = asValidLatexCommand(buffer().masterParams(),
+                                              getCmdName(), citation_styles);
        // FIXME UNICODE
        docstring const cite_str = from_utf8(citationStyleToString(cs, true));