commit 358e4ace560f4a6a3a8435ac9959e38a23cb6d56
Author: Thibaut Cuvelier <[email protected]>
Date:   Fri Feb 19 17:38:22 2021 +0100

    DocBook: implement prepended/appended arguments for all kinds of elements.
    
    Previously, it was just in InsetText.
---
 src/Paragraph.cpp       |   90 ++++++++++++++++++++++++++++++++++------------
 src/Paragraph.h         |    3 +-
 src/insets/InsetERT.cpp |   10 +++++-
 src/output_docbook.cpp  |   54 ++++++++++++++++++++++++----
 4 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index b7616ad..559a61a 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -47,6 +47,7 @@
 
 #include "frontends/alert.h"
 
+#include "insets/InsetArgument.h"
 #include "insets/InsetBibitem.h"
 #include "insets/InsetLabel.h"
 #include "insets/InsetSpecialChar.h"
@@ -3419,35 +3420,55 @@ std::tuple<vector<xml::FontTag>, 
vector<xml::EndFontTag>> computeDocBookFontSwit
 } // anonymous namespace
 
 
-std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
+std::tuple<std::vector<docstring>, std::vector<docstring>, 
std::vector<docstring>>
+    Paragraph::simpleDocBookOnePar(Buffer const & buf,
                                                       OutputParams const & 
runparams,
                                                       Font const & outerfont,
                                                       pos_type initial,
                                                       bool is_last_par,
                                                       bool ignore_fonts) const
 {
-       // Track whether we have opened these tags
-       DocBookFontState fs;
+       std::vector<docstring> prependedParagraphs;
+       std::vector<docstring> generatedParagraphs;
+       std::vector<docstring> appendedParagraphs;
+       odocstringstream os;
 
-       Layout const & style = *d->layout_;
-       FontInfo font_old =
-                       style.labeltype == LABEL_MANUAL ? style.labelfont : 
style.font;
+       // If there is an argument that must be output before the main tag, do 
it before handling the rest of the paragraph.
+       // Also tag all arguments that shouldn't go in the main content right 
now, so that they are never generated at the
+       // wrong place.
+       OutputParams rp = runparams;
+    for (pos_type i = initial; i < size(); ++i) {
+        if (getInset(i) && getInset(i)->lyxCode() == ARG_CODE) {
+            const InsetArgument * arg = getInset(i)->asInsetArgument();
+            if (arg->docbookargumentbeforemaintag()) {
+                auto xs_local = XMLStream(os);
+                arg->docbook(xs_local, rp);
+
+                prependedParagraphs.push_back(os.str());
+                os.str(from_ascii(""));
+
+                rp.docbook_prepended_arguments.insert(arg);
+            } else if (arg->docbookargumentaftermaintag()) {
+                rp.docbook_appended_arguments.insert(arg);
+            }
+        }
+    }
 
-       string const default_family =
-                       buf.masterBuffer()->params().fonts_default_family;
+    // State variables for the main loop.
+    auto xs = new XMLStream(os); // XMLStream has no copy constructor: to 
create a new object, the only solution
+    // is to hold a pointer to the XMLStream (xs = XMLStream(os) is not 
allowed once the first object is built).
+    std::vector<char_type> delayedChars; // When a font tag ends with a space, 
output it after the closing font tag.
+    // This requires to store delayed characters at some point.
 
-       vector<xml::FontTag> tagsToOpen;
-       vector<xml::EndFontTag> tagsToClose;
+    DocBookFontState fs; // Track whether we have opened font tags
+    DocBookFontState old_fs = fs;
 
-       std::vector<docstring> generatedParagraphs;
-       DocBookFontState old_fs = fs;
-       odocstringstream os;
-       auto * xs = new XMLStream(os); // XMLStream has no copy constructor: to 
create a new object, the only solution
-       // is to hold a pointer to the XMLStream (xs = XMLStream(os) is not 
allowed once the first object is built).
+    Layout const & style = *d->layout_;
+    FontInfo font_old = style.labeltype == LABEL_MANUAL ? style.labelfont : 
style.font;
+    string const default_family = 
buf.masterBuffer()->params().fonts_default_family;
 
-       // When a font tag ends with a space, output it after the closing font 
tag. This requires to store delayed
-       // characters at some point.
-       std::vector<char_type> delayedChars;
+    vector<xml::FontTag> tagsToOpen;
+    vector<xml::EndFontTag> tagsToClose;
 
        // Parsing main loop.
        for (pos_type i = initial; i < size(); ++i) {
@@ -3511,8 +3532,13 @@ std::vector<docstring> 
Paragraph::simpleDocBookOnePar(Buffer const & buf,
 
         // Finally, write the next character or inset.
                if (Inset const * inset = getInset(i)) {
-                       if (!runparams.for_toc || inset->isInToc()) {
-                               OutputParams np = runparams;
+                   bool inset_is_argument_elsewhere = 
getInset(i)->asInsetArgument() &&
+                           
rp.docbook_appended_arguments.find(inset->asInsetArgument()) != 
rp.docbook_appended_arguments.end() &&
+                           
rp.docbook_prepended_arguments.find(inset->asInsetArgument()) != 
rp.docbook_prepended_arguments.end();
+
+                       if ((!rp.for_toc || inset->isInToc()) && 
!inset_is_argument_elsewhere) {
+                           // Arguments may need to be output
+                               OutputParams np = rp;
                                np.local_font = &font;
 
                                // TODO: special case will bite here.
@@ -3520,7 +3546,7 @@ std::vector<docstring> 
Paragraph::simpleDocBookOnePar(Buffer const & buf,
                                inset->docbook(*xs, np);
                        }
                } else {
-                       char_type c = getUChar(buf.masterBuffer()->params(), 
runparams, i);
+                       char_type c = getUChar(buf.masterBuffer()->params(), 
rp, i);
                        if (lyx::isSpace(c) && !ignore_fonts)
                                delayedChars.push_back(c);
                        else
@@ -3542,14 +3568,30 @@ std::vector<docstring> 
Paragraph::simpleDocBookOnePar(Buffer const & buf,
 
        // In listings, new lines (i.e. \n characters in the output) are very 
important. Avoid generating one for the
        // last line to get a clean output.
-       if (runparams.docbook_in_listing && !is_last_par)
+       if (rp.docbook_in_listing && !is_last_par)
                *xs << xml::CR();
 
        // Finalise the last (and most likely only) paragraph.
        generatedParagraphs.push_back(os.str());
-       delete xs;
+    os.str(from_ascii(""));
+    delete xs;
+
+    // If there is an argument that must be output after the main tag, do it 
after handling the rest of the paragraph.
+    for (pos_type i = initial; i < size(); ++i) {
+        if (getInset(i) && getInset(i)->lyxCode() == ARG_CODE) {
+            const InsetArgument * arg = getInset(i)->asInsetArgument();
+            if (arg->docbookargumentaftermaintag()) {
+                // Don't use rp, as this argument would not generate anything.
+                auto xs_local = XMLStream(os);
+                arg->docbook(xs_local, runparams);
+
+                appendedParagraphs.push_back(os.str());
+                os.str(from_ascii(""));
+            }
+        }
+    }
 
-       return generatedParagraphs;
+       return std::tuple(prependedParagraphs, generatedParagraphs, 
appendedParagraphs);
 }
 
 
diff --git a/src/Paragraph.h b/src/Paragraph.h
index c67a507..67f41dd 100644
--- a/src/Paragraph.h
+++ b/src/Paragraph.h
@@ -204,7 +204,8 @@ public:
        pos_type firstWordLyXHTML(XMLStream & xs, OutputParams const & 
runparams) const;
 
        /// Outputs to stream the DocBook representation, one element per 
paragraph.
-       std::vector<docstring> simpleDocBookOnePar(Buffer const & buf,
+       std::tuple<std::vector<docstring>, std::vector<docstring>, 
std::vector<docstring>>
+       simpleDocBookOnePar(Buffer const & buf,
                                                                           
OutputParams const & runparams,
                                                                           Font 
const & outerfont,
                                                                           
pos_type initial = 0,
diff --git a/src/insets/InsetERT.cpp b/src/insets/InsetERT.cpp
index 559fef2..61adfbd 100644
--- a/src/insets/InsetERT.cpp
+++ b/src/insets/InsetERT.cpp
@@ -98,7 +98,13 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & 
runparams) const
        // in an ERT, use simple line breaks.
        // New line after each paragraph of the ERT, save the last one.
        while (true) { // For each paragraph in the ERT...
-               auto pars = par->simpleDocBookOnePar(buffer(), runparams, 
text().outerFont(distance(begin, par)), 0, false, true);
+        std::vector<docstring> pars_prepend;
+        std::vector<docstring> pars;
+        std::vector<docstring> pars_append;
+        tie(pars_prepend, pars, pars_append) = 
par->simpleDocBookOnePar(buffer(), runparams, text().outerFont(distance(begin, 
par)), 0, false, true);
+
+        for (docstring const & parXML : pars_prepend)
+            xs << XMLStream::ESCAPE_NONE << parXML;
                auto p = pars.begin();
                while (true) { // For each line of this ERT paragraph...
                        os << *p;
@@ -108,6 +114,8 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & 
runparams) const
                        else
                                break;
                }
+        for (docstring const & parXML : pars_append)
+            xs << XMLStream::ESCAPE_NONE << parXML;
 
                ++par;
                if (par != end)
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index e039d70..582fab0 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -286,9 +286,17 @@ void makeBibliography(
 
        // Generate the entry. Concatenate the different parts of the paragraph 
if any.
        auto const begin = text.paragraphs().begin();
-       auto pars = par->simpleDocBookOnePar(buf, runparams, 
text.outerFont(std::distance(begin, par)), 0);
+       std::vector<docstring> pars_prepend;
+       std::vector<docstring> pars;
+       std::vector<docstring> pars_append;
+       tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, 
runparams, text.outerFont(std::distance(begin, par)), 0);
+
+       for (auto & parXML : pars_prepend)
+               xs << XMLStream::ESCAPE_NONE << parXML;
        for (auto & parXML : pars)
                xs << XMLStream::ESCAPE_NONE << parXML;
+       for (auto & parXML : pars_append)
+               xs << XMLStream::ESCAPE_NONE << parXML;
 
        // End the precooked bibliography entry.
        xs << xml::EndTag("bibliomixed");
@@ -432,7 +440,14 @@ void makeParagraph(
        // Open and close tags around each contained paragraph.
        auto nextpar = par;
        ++nextpar;
-       auto pars = par->simpleDocBookOnePar(buf, runparams, 
text.outerFont(distance(begin, par)), 0, nextpar == end, special_case);
+
+       std::vector<docstring> pars_prepend;
+       std::vector<docstring> pars;
+       std::vector<docstring> pars_append;
+       tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, 
runparams, text.outerFont(distance(begin, par)), 0, nextpar == end, 
special_case);
+
+       for (docstring const & parXML : pars_prepend)
+           xs << XMLStream::ESCAPE_NONE << parXML;
        for (docstring const & parXML : pars) {
                if (!xml::isNotOnlySpace(parXML))
                        continue;
@@ -445,6 +460,8 @@ void makeParagraph(
                if (close_par)
                        closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : 
nullptr, runparams);
        }
+       for (docstring const & parXML : pars_append)
+           xs << XMLStream::ESCAPE_NONE << parXML;
 }
 
 
@@ -480,8 +497,13 @@ void makeEnvironment(Text const &text,
                // Nothing to do (otherwise, infinite loops).
        } else if (style.latextype == LATEX_ENVIRONMENT) {
                // Generate the paragraph, if need be.
-               auto pars = par->simpleDocBookOnePar(buf, runparams, 
text.outerFont(std::distance(text.paragraphs().begin(), par)), 0, false, 
ignoreFonts);
+               std::vector<docstring> pars_prepend;
+        std::vector<docstring> pars;
+        std::vector<docstring> pars_append;
+        tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, 
runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), 0, 
false, ignoreFonts);
 
+        for (docstring const & parXML : pars_prepend)
+            xs << XMLStream::ESCAPE_NONE << parXML;
                if (mimicListing) {
                        auto p = pars.begin();
                        while (p != pars.end()) {
@@ -504,6 +526,8 @@ void makeEnvironment(Text const &text,
                                xml::closeTag(xs, 
par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
                        }
                }
+        for (docstring const & parXML : pars_append)
+            xs << XMLStream::ESCAPE_NONE << parXML;
        } else {
                makeAny(text, buf, xs, runparams, par);
        }
@@ -604,14 +628,21 @@ ParagraphList::const_iterator makeListEnvironment(Text 
const &text,
 
                // Generate the content of the item.
                if (sep < par->size()) {
-                       auto pars = par->simpleDocBookOnePar(buf, runparams,
+            std::vector<docstring> pars_prepend;
+            std::vector<docstring> pars;
+            std::vector<docstring> pars_append;
+            tie(pars_prepend, pars, pars_append) = 
par->simpleDocBookOnePar(buf, runparams,
                                                             
text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+            for (docstring const & parXML : pars_prepend)
+                xs << XMLStream::ESCAPE_NONE << parXML;
                        for (auto &p : pars) {
                                xml::openTag(xs, 
par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(),
                                             
par->layout().docbookiteminnertagtype());
                                xs << XMLStream::ESCAPE_NONE << p;
                                xml::closeTag(xs, 
par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
                        }
+            for (docstring const & parXML : pars_append)
+                xs << XMLStream::ESCAPE_NONE << parXML;
                } else {
                        // DocBook doesn't like emptiness.
                        xml::compTag(xs, par->layout().docbookiteminnertag(), 
par->layout().docbookiteminnerattr(),
@@ -656,14 +687,23 @@ void makeCommand(
 
        // Generate this command.
        auto prevpar = text.paragraphs().getParagraphBefore(par);
-       openParTag(xs, &*par, prevpar, runparams);
 
-       auto pars = par->simpleDocBookOnePar(buf, 
runparams,text.outerFont(distance(begin, par)));
+    std::vector<docstring> pars_prepend;
+    std::vector<docstring> pars;
+    std::vector<docstring> pars_append;
+    tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, 
runparams,text.outerFont(distance(begin, par)));
+
+    for (docstring const & parXML : pars_prepend)
+        xs << XMLStream::ESCAPE_NONE << parXML;
+
+    openParTag(xs, &*par, prevpar, runparams);
        for (auto & parXML : pars)
                // TODO: decide what to do with openParTag/closeParTag in new 
lines.
                xs << XMLStream::ESCAPE_NONE << parXML;
+    closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr, runparams);
 
-       closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr, 
runparams);
+    for (docstring const & parXML : pars_append)
+        xs << XMLStream::ESCAPE_NONE << parXML;
 }
 
 
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to