commit 59acb375d1f44f59726b50343c6bdf96f54206b3
Author: Thibaut Cuvelier <[email protected]>
Date:   Sat Nov 28 22:43:00 2020 +0100

    DocBook: add layout parameters to control the special case and argument 
positioning.
    
    Only for flex insets.
    
    Also add similar checks in InsetText to avoid bibliographies in paragraphs.
---
 lib/scripts/layout2layout.py |   13 ++++++++++-
 src/Layout.h                 |    1 +
 src/OutputParams.h           |    4 +++
 src/Paragraph.cpp            |    1 +
 src/TextClass.cpp            |    2 +-
 src/insets/InsetArgument.cpp |    5 ++++
 src/insets/InsetArgument.h   |    4 +++
 src/insets/InsetLayout.cpp   |   13 ++++++++++++
 src/insets/InsetLayout.h     |    8 +++++++
 src/insets/InsetText.cpp     |   45 ++++++++++++++++++++++++++++++++++++++++-
 src/output_docbook.cpp       |   36 ++++++++++++++++++++++++++++++++-
 11 files changed, 126 insertions(+), 6 deletions(-)

diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py
index 29159b0..b2393ea 100644
--- a/lib/scripts/layout2layout.py
+++ b/lib/scripts/layout2layout.py
@@ -11,7 +11,7 @@
 # This script will update a .layout file to current format
 
 # The latest layout format is also defined in src/TextClass.cpp
-currentFormat = 87
+currentFormat = 88
 
 
 # Incremented to format 4, 6 April 2007, lasgouttes
@@ -296,7 +296,10 @@ currentFormat = 87
 # Incremented to format 86, 20 October 2020 by tcuvelier
 # New tag DocBookSection.
 
-# Incremeted to format 87, 2 November 2020 by rkh
+# Incremented to format 87, 2 November 2020 by rkh
+
+# Incremented to format 88, 28 November 2020 by tcuvelier
+# New tag DocBookNotInPara.
 
 # Do not forget to document format change in Customization
 # Manual (section "Declaring a new text class").
@@ -358,6 +361,7 @@ def concatenate_label(old, new):
     else:
         return b'"' + old + new + b'"'
 
+
 # appends a string to a list unless it's already there
 def addstring(s, l):
     if l.count(s) > 0:
@@ -547,6 +551,11 @@ def convert(lines, end_format):
                 i += 1
             continue
 
+        if 87 <= format <= 88:
+            # nothing to do.
+            i += 1
+            continue
+
         if format == 86:
             if lines[i].lstrip().lower().startswith(b"stepmastercounter"):
                 pattern = re.compile(b"stepmastercounter", re.IGNORECASE)
diff --git a/src/Layout.h b/src/Layout.h
index cb8f537..dfb5afe 100644
--- a/src/Layout.h
+++ b/src/Layout.h
@@ -115,6 +115,7 @@ public:
                docstring docbooktag;
                docstring docbooktagtype;
                docstring docbookattr;
+               bool docbookargumentbeforemaintag = false;
        };
        ///
        typedef std::map<std::string, latexarg> LaTeXArgMap;
diff --git a/src/OutputParams.h b/src/OutputParams.h
index 7e0a4b2..1cd16d2 100644
--- a/src/OutputParams.h
+++ b/src/OutputParams.h
@@ -26,6 +26,7 @@ class Encoding;
 class ExportData;
 class Font;
 class Language;
+class InsetArgument;
 
 class OutputParams {
 public:
@@ -382,6 +383,9 @@ public:
        /// Should wrappers be ignored? Mostly useful to avoid generation of 
<abstract>.
        bool docbook_ignore_wrapper = false;
 
+       /// Some parameters are output before the rest of the paragraph, they 
should not be generated a second time.
+       std::set<InsetArgument const *> docbook_prepended_arguments = {};
+
        /// Are we generating this material for inclusion in a TOC-like entity?
        bool for_toc = false;
 
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index aa6bd30..1e92259 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -865,6 +865,7 @@ int Paragraph::eraseChars(pos_type start, pos_type end, 
bool trackChanges)
        return end - i;
 }
 
+
 // Handle combining characters
 int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams,
                otexstream & os, char_type c, char_type next,
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index cd87cca..a58ae6d 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -59,7 +59,7 @@ namespace lyx {
 // You should also run the development/tools/updatelayouts.py script,
 // to update the format of all of our layout files.
 //
-int const LAYOUT_FORMAT = 87; // rkh: master --> parent for counters
+int const LAYOUT_FORMAT = 88; // tcuvelier: add DocBookNotInPara
 
 
 // Layout format for the current lyx file format. Controls which format is
diff --git a/src/insets/InsetArgument.cpp b/src/insets/InsetArgument.cpp
index 8f1d762..2ae80ca 100644
--- a/src/insets/InsetArgument.cpp
+++ b/src/insets/InsetArgument.cpp
@@ -126,6 +126,7 @@ void InsetArgument::updateBuffer(ParIterator const & it, 
UpdateType utype, bool
                docbooktag_ = (*lait).second.docbooktag;
                docbooktagtype_ = (*lait).second.docbooktagtype;
                docbookattr_ = (*lait).second.docbookattr;
+               docbookargumentbeforemaintag_ = 
(*lait).second.docbookargumentbeforemaintag;
                pass_thru_local_ = false;
                if (lait->second.is_toc_caption) {
                        is_toc_caption_ = true;
@@ -312,6 +313,10 @@ InsetLayout::InsetDecoration InsetArgument::decoration() 
const
 
 
 void InsetArgument::docbook(XMLStream & xs, OutputParams const & rp) const {
+       // Ignore arguments that have already been output.
+       if (rp.docbook_prepended_arguments.find(this) != 
rp.docbook_prepended_arguments.end())
+               return;
+
        if (docbooktag_ != from_ascii("NONE") && docbooktag_ != 
from_ascii("IGNORE")) {
                // TODO: implement docbooktagtype_.
                xs << xml::StartTag(docbooktag_, docbookattr_);
diff --git a/src/insets/InsetArgument.h b/src/insets/InsetArgument.h
index d5d54a6..1c63e5c 100644
--- a/src/insets/InsetArgument.h
+++ b/src/insets/InsetArgument.h
@@ -39,6 +39,8 @@ public:
 
        std::string name() const { return name_; }
 
+       bool docbookargumentbeforemaintag() const { return 
docbookargumentbeforemaintag_; }
+
        /// \name Public functions inherited from Inset class
        //@{
        ///
@@ -131,6 +133,8 @@ private:
        docstring docbooktagtype_;
        /// DocBook attributes.
        docstring docbookattr_;
+       ///
+       bool docbookargumentbeforemaintag_ = false;
 
 protected:
        /// \name Protected functions inherited from Inset class
diff --git a/src/insets/InsetLayout.cpp b/src/insets/InsetLayout.cpp
index 62030d0..5b5308d 100644
--- a/src/insets/InsetLayout.cpp
+++ b/src/insets/InsetLayout.cpp
@@ -95,6 +95,8 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
                IL_DOCBOOKTAGTYPE,
                IL_DOCBOOKSECTION,
                IL_DOCBOOKININFO,
+               IL_DOCBOOKARGUMENTBEFOREMAINTAG,
+               IL_DOCBOOKNOTINPARA,
                IL_DOCBOOKWRAPPERTAG,
                IL_DOCBOOKWRAPPERTAGTYPE,
                IL_DOCBOOKWRAPPERATTR,
@@ -148,6 +150,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & 
tclass,
                { "custompars", IL_CUSTOMPARS },
                { "decoration", IL_DECORATION },
                { "display", IL_DISPLAY },
+               { "docbookargumentbeforemaintag", 
IL_DOCBOOKARGUMENTBEFOREMAINTAG },
                { "docbookattr", IL_DOCBOOKATTR },
                { "docbookininfo", IL_DOCBOOKININFO },
                { "docbookitemattr", IL_DOCBOOKITEMATTR },
@@ -156,6 +159,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & 
tclass,
                { "docbookitemwrapperattr", IL_DOCBOOKITEMWRAPPERATTR },
                { "docbookitemwrappertag", IL_DOCBOOKITEMWRAPPERTAG },
                { "docbookitemwrappertagtype", IL_DOCBOOKITEMWRAPPERTAGTYPE },
+               { "docbooknotinpara", IL_DOCBOOKNOTINPARA },
                { "docbooksection", IL_DOCBOOKSECTION },
                { "docbooktag", IL_DOCBOOKTAG },
                { "docbooktagtype", IL_DOCBOOKTAGTYPE },
@@ -514,6 +518,12 @@ bool InsetLayout::read(Lexer & lex, TextClass const & 
tclass,
                case IL_DOCBOOKININFO:
                        lex >> docbookininfo_;
                        break;
+               case IL_DOCBOOKARGUMENTBEFOREMAINTAG:
+                       lex >> docbookargumentbeforemaintag_;
+                       break;
+               case IL_DOCBOOKNOTINPARA:
+                       lex >> docbooknotinpara_;
+                       break;
                case IL_DOCBOOKSECTION:
                        lex >> docbooksection_;
                        break;
@@ -819,6 +829,9 @@ void InsetLayout::readArgument(Lexer & lex)
                } else if (tok == "docbooktagtype") {
                        lex.next();
                        arg.docbooktagtype = lex.getDocString();
+               } else if (tok == "docbookargumentbeforemaintag") {
+                       lex.next();
+                       arg.docbookargumentbeforemaintag = lex.getBool();
                } else {
                        lex.printError("Unknown tag");
                        error = true;
diff --git a/src/insets/InsetLayout.h b/src/insets/InsetLayout.h
index 09abe71..88143d5 100644
--- a/src/insets/InsetLayout.h
+++ b/src/insets/InsetLayout.h
@@ -158,6 +158,10 @@ public:
        ///
        bool docbooksection() const { return docbooksection_; }
        ///
+       bool docbooknotinpara() const { return docbooknotinpara_; }
+       ///
+       bool docbookargumentbeforemaintag() const { return 
docbookargumentbeforemaintag_; }
+       ///
        std::string docbookwrappertag() const { return docbookwrappertag_; }
        ///
        std::string docbookwrappertagtype() const;
@@ -311,6 +315,10 @@ private:
        ///
        mutable std::string docbookininfo_;
        ///
+       bool docbooknotinpara_ = false;
+       ///
+       bool docbookargumentbeforemaintag_ = false;
+       ///
        bool docbooksection_ = false;
        ///
        std::string docbookwrappertag_;
diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp
index 2c757a9..bf1fe62 100644
--- a/src/insets/InsetText.cpp
+++ b/src/insets/InsetText.cpp
@@ -621,8 +621,35 @@ void InsetText::docbook(XMLStream & xs, OutputParams const 
& rp, XHTMLOptions op
        if (!rp.docbook_generate_info && il.docbookininfo() != "never")
                return;
 
+       // In some cases, the input parameters must be overridden for outer 
tags.
+       bool writeOuterTag = opts & WriteOuterTag;
+       if (writeOuterTag) {
+               // For each paragraph, if there are only Bibitems and the 
corresponding text, don't write the outer tags.
+               bool allBibitems = std::all_of(text().paragraphs().begin(), 
text().paragraphs().end(), [](Paragraph const & par) {
+                       auto nInsets = std::distance(par.insetList().begin(), 
par.insetList().end());
+                       auto parSize = (size_t) par.size();
+                       return nInsets == 1 && parSize > 1 && 
par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE;
+               });
+               writeOuterTag = !allBibitems;
+       }
+
+       // Detect arguments that should be output before the paragraph.
+       // Don't reuse runparams.docbook_prepended_arguments, as the same 
object is used in InsetArgument to determine
+       // whether the inset should be output or not, whatever the context 
(i.e. position with respect to the wrapper).
+       std::set<InsetArgument const *> prependedArguments;
+       for (auto const & par : paragraphs()) {
+               for (pos_type i = 0; i < par.size(); ++i) {
+                       if (par.getInset(i) && par.getInset(i)->lyxCode() == 
ARG_CODE) {
+                               InsetArgument const *arg = 
par.getInset(i)->asInsetArgument();
+                               if (arg->docbookargumentbeforemaintag())
+                                       
prependedArguments.insert(par.getInset(i)->asInsetArgument());
+                       }
+               }
+       }
+
        // Start outputting this inset.
-       if (opts & WriteOuterTag) {
+       // - First, wrapper around the inset and its main tag.
+       if (writeOuterTag) {
                if (!il.docbookwrappertag().empty() && il.docbookwrappertag() 
!= "NONE" && il.docbookwrappertag() != "IGNORE")
                        xml::openTag(xs, il.docbookwrappertag(), 
il.docbookwrapperattr(), il.docbookwrappertagtype());
 
@@ -634,7 +661,19 @@ void InsetText::docbook(XMLStream & xs, OutputParams const 
& rp, XHTMLOptions op
                                attrs += from_ascii(" xlink:href=\"") + 
text_.asString() + from_ascii("\"");
                        xml::openTag(xs, il.docbooktag(), attrs, 
il.docbooktagtype());
                }
+       }
+
+       // - Think about the arguments.
+       OutputParams np = runparams;
+       np.docbook_in_par = true;
+       for (auto const & arg : prependedArguments)
+               arg->docbook(xs, np);
+
+       // - Mark the newly generated arguments are not-to-be-generated-again.
+       runparams.docbook_prepended_arguments = std::move(prependedArguments);
 
+       // - Deal with the first item.
+       if (writeOuterTag) {
                if (!il.docbookitemwrappertag().empty() && 
il.docbookitemwrappertag() != "NONE" && il.docbookitemwrappertag() != "IGNORE")
                        xml::openTag(xs, il.docbookitemwrappertag(), 
il.docbookitemwrapperattr(), il.docbookitemwrappertagtype());
 
@@ -650,11 +689,13 @@ void InsetText::docbook(XMLStream & xs, OutputParams 
const & rp, XHTMLOptions op
        if (il.isPassThru())
                runparams.pass_thru = true;
 
+       // - Write the main content of the inset.
        xs.startDivision(false);
        docbookParagraphs(text_, buffer(), xs, runparams);
        xs.endDivision();
 
-       if (opts & WriteOuterTag) {
+       // - Close the required tags.
+       if (writeOuterTag) {
                if (!il.docbookitemtag().empty() && il.docbookitemtag() != 
"NONE" && il.docbookitemtag() != "IGNORE")
                        xml::closeTag(xs, il.docbookitemtag(), 
il.docbookitemtagtype());
 
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index d815abc..aaa3860 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -347,7 +347,7 @@ void makeParagraph(
                        special_case = true;
        }
 
-       size_t nInsets = std::distance(par->insetList().begin(), 
par->insetList().end());
+       auto nInsets = std::distance(par->insetList().begin(), 
par->insetList().end());
        auto parSize = (size_t) par->size();
 
        // Plain layouts must be ignored.
@@ -377,6 +377,40 @@ void makeParagraph(
        };
        special_case |= nInsets == parSize && 
std::all_of(par->insetList().begin(), par->insetList().end(), 
isLyxCodeSpecialCase);
 
+       // Flex elements (InsetLayout) have their own parameter to control the 
special case.
+       auto isFlexSpecialCase = [](InsetList::Element inset) {
+               if (inset.inset->lyxCode() != FLEX_CODE)
+                       return false;
+               // Standard condition: check the parameter.
+               if (inset.inset->getLayout().docbooknotinpara())
+                       return true;
+
+               // If the parameter is not set, maybe the flex inset only 
contains things that should match the standard
+               // condition. In this case, isLyxCodeSpecialCase must also 
check for bibitems...
+               auto isLyxCodeSpecialCase = [](InsetList::Element inset) {
+                       return lyxCodeSpecialCases.find(inset.inset->lyxCode()) 
!= lyxCodeSpecialCases.end() ||
+                                       inset.inset->lyxCode() == BIBITEM_CODE;
+               };
+               if (InsetText * text = inset.inset->asInsetText()) {
+                       for (auto const & par : text->paragraphs()) {
+                               auto nInsets = 
std::distance(par.insetList().begin(), par.insetList().end());
+                               auto parSize = (size_t) par.size();
+
+                               if (nInsets == 1 && 
par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE)
+                                       return true;
+                               if (nInsets != parSize)
+                                       return false;
+                               if (!std::all_of(par.insetList().begin(), 
par.insetList().end(), isLyxCodeSpecialCase))
+                                       return false;
+                       }
+                       return true;
+               }
+
+               // No case matched: give up.
+               return false;
+       };
+       special_case |= nInsets == parSize && 
std::all_of(par->insetList().begin(), par->insetList().end(), 
isFlexSpecialCase);
+
        // Open a paragraph if it is allowed, we are not already within a 
paragraph, and the insets in the paragraph do
        // not forbid paragraphs (aka special cases).
        bool const open_par = runparams.docbook_make_pars
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to