]> git.lyx.org Git - features.git/commitdiff
DocBook: fix case with emphasis at end of footnote
authorScott Kostyshak <skostysh@lyx.org>
Mon, 25 Sep 2023 14:41:21 +0000 (10:41 -0400)
committerScott Kostyshak <skostysh@lyx.org>
Mon, 25 Sep 2023 14:41:21 +0000 (10:41 -0400)
For ML discussion, see here:

  https://www.mail-archive.com/search?l=mid&q=CAK0LPyiusCMu-X7KpgO0d1-rh4e3%3DRwR5ooXE_fdb7UVuB0VUA%40mail.gmail.com

Patch from Thibaut Cuvelier.

src/Paragraph.cpp
src/xml.cpp
src/xml.h

index a9b186b1a65b9b25744285d84679791d06126050..3718bd4a98362d377ba4910417df46dbba51a93b 100644 (file)
@@ -3673,6 +3673,7 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
     // 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).
+       xs->startDivision(false);
     std::vector<docstring> 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.
 
@@ -3696,8 +3697,8 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
                if (isDeleted(i))
                        continue;
 
-               // If this is an InsetNewline, generate a new paragraph. Also reset the fonts, so that tags are closed in
-               // this paragraph.
+               // If this is an InsetNewline, generate a new paragraph (this is the reason why generatedParagraphs is a list
+               // of paragraphs). Also reset the fonts, so that tags are closed in this paragraph.
                if (getInset(i) && getInset(i)->lyxCode() == NEWLINE_CODE) {
                        if (!ignore_fonts_i)
                                xs->closeFontTags();
@@ -3705,11 +3706,14 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
                        // Output one paragraph (i.e. one string entry in generatedParagraphs).
                        generatedParagraphs.push_back(os.str());
 
+                       xs->endDivision();
+
                        // Create a new XMLStream for the new paragraph, completely independent of the previous one. This implies
                        // that the string stream must be reset.
                        os.str(from_ascii(""));
                        delete xs;
                        xs = new XMLStream(os);
+                       xs->startDivision(false);
 
                        // Restore the fonts for the new paragraph, so that the right tags are opened for the new entry.
                        if (!ignore_fonts_i) {
@@ -3744,11 +3748,12 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
                        vector<xml::FontTag>::const_iterator sen = tagsToOpen.end();
                        for (; sit != sen; ++sit)
                                *xs << *sit;
-
-                       tagsToClose.clear();
-                       tagsToOpen.clear();
                }
 
+               // The font tags are no longer useful; free their memory right now.
+               tagsToClose.clear();
+               tagsToOpen.clear();
+
         // Finally, write the next character or inset.
                if (Inset const * inset = getInset(i)) {
                    bool inset_is_argument_elsewhere = getInset(i)->asInsetArgument() &&
@@ -3781,12 +3786,21 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
                }
        }
 
+       // Ensure that the tags are closed at the right place. Otherwise, there might be an open font tag with no content
+       // that no other code cares to close.
+       *xs << xml::NullTag();
+
        // FIXME, this code is just imported from XHTML
        // I'm worried about what happens if a branch, say, is itself
        // wrapped in some font stuff. I think that will not work.
        if (!ignore_fonts)
                xs->closeFontTags();
 
+       // Close the potentially remaining tags, like pending font tags.
+       // There is no need to check for ignore_fonts, as these tags won't be
+       // inserted in the stack in the first place if ignore_fonts is false.
+       xs->endDivision();
+
        // Deal with the delayed characters *after* closing font tags.
        if (!delayedChars.empty()) {
                for (const docstring &c: delayedChars)
index 53ccb8a8c83ee3cc7255e9cadf93b71f82d3458d..5b81024336481a9c612e639bd221e435d8f29717 100644 (file)
@@ -287,6 +287,16 @@ XMLStream &XMLStream::operator<<(docstring const &d)
 }
 
 
+XMLStream &XMLStream::operator<<(xml::NullTag const &)
+{
+       is_last_tag_cr_ = false;
+       clearTagDeque();
+       // Don't output anything to os_, by definition of a NullTag (as opposed to text output).
+       escape_ = ESCAPE_ALL;
+       return *this;
+}
+
+
 XMLStream &XMLStream::operator<<(const char *s)
 {
        is_last_tag_cr_ = false;
index 03710c1c729a8783a4b8a35333e32179cfa3ea25..346e42d78cd803d9cf99c7a06afd9db3058d9670 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -31,6 +31,7 @@ namespace xml {
 struct StartTag;
 struct EndTag;
 struct CompTag;
+struct NullTag;
 struct ParTag;
 struct FontTag;
 struct CR;
@@ -67,6 +68,8 @@ public:
        ///
        XMLStream & operator<<(char);
        ///
+       XMLStream & operator<<(xml::NullTag const &);
+       ///
        XMLStream & operator<<(xml::StartTag const &);
        ///
        XMLStream & operator<<(xml::EndTag const &);
@@ -274,6 +277,16 @@ struct ParTag : public StartTag
 };
 
 
+/// A special tag that doesn't produce any XML output, but makes the XMLStream behave as it it output some text.
+struct NullTag : public StartTag
+{
+       ///
+       NullTag(): StartTag("NULLTAG", from_utf8(""), true) {}
+       ///
+       ~NullTag() override = default;
+};
+
+
 ///
 enum FontTypes {
        // ranges