DocBook: fix case with emphasis at end of footnote

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.
This commit is contained in:
Scott Kostyshak 2023-09-25 10:41:21 -04:00
parent 549969a563
commit ff9dfa96f2
3 changed files with 42 additions and 5 deletions

View File

@ -3673,6 +3673,7 @@ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring
// State variables for the main loop. // State variables for the main loop.
auto xs = new XMLStream(os); // XMLStream has no copy constructor: to create a new object, the only solution 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). // 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. 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. // 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)) if (isDeleted(i))
continue; continue;
// If this is an InsetNewline, generate a new paragraph. Also reset the fonts, so that tags are closed in // If this is an InsetNewline, generate a new paragraph (this is the reason why generatedParagraphs is a list
// this paragraph. // of paragraphs). Also reset the fonts, so that tags are closed in this paragraph.
if (getInset(i) && getInset(i)->lyxCode() == NEWLINE_CODE) { if (getInset(i) && getInset(i)->lyxCode() == NEWLINE_CODE) {
if (!ignore_fonts_i) if (!ignore_fonts_i)
xs->closeFontTags(); 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). // Output one paragraph (i.e. one string entry in generatedParagraphs).
generatedParagraphs.push_back(os.str()); generatedParagraphs.push_back(os.str());
xs->endDivision();
// Create a new XMLStream for the new paragraph, completely independent of the previous one. This implies // Create a new XMLStream for the new paragraph, completely independent of the previous one. This implies
// that the string stream must be reset. // that the string stream must be reset.
os.str(from_ascii("")); os.str(from_ascii(""));
delete xs; delete xs;
xs = new XMLStream(os); 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. // Restore the fonts for the new paragraph, so that the right tags are opened for the new entry.
if (!ignore_fonts_i) { 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(); vector<xml::FontTag>::const_iterator sen = tagsToOpen.end();
for (; sit != sen; ++sit) for (; sit != sen; ++sit)
*xs << *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. // Finally, write the next character or inset.
if (Inset const * inset = getInset(i)) { if (Inset const * inset = getInset(i)) {
bool inset_is_argument_elsewhere = getInset(i)->asInsetArgument() && 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 // FIXME, this code is just imported from XHTML
// I'm worried about what happens if a branch, say, is itself // I'm worried about what happens if a branch, say, is itself
// wrapped in some font stuff. I think that will not work. // wrapped in some font stuff. I think that will not work.
if (!ignore_fonts) if (!ignore_fonts)
xs->closeFontTags(); 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. // Deal with the delayed characters *after* closing font tags.
if (!delayedChars.empty()) { if (!delayedChars.empty()) {
for (const docstring &c: delayedChars) for (const docstring &c: delayedChars)

View 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) XMLStream &XMLStream::operator<<(const char *s)
{ {
is_last_tag_cr_ = false; is_last_tag_cr_ = false;

View File

@ -31,6 +31,7 @@ namespace xml {
struct StartTag; struct StartTag;
struct EndTag; struct EndTag;
struct CompTag; struct CompTag;
struct NullTag;
struct ParTag; struct ParTag;
struct FontTag; struct FontTag;
struct CR; struct CR;
@ -67,6 +68,8 @@ public:
/// ///
XMLStream & operator<<(char); XMLStream & operator<<(char);
/// ///
XMLStream & operator<<(xml::NullTag const &);
///
XMLStream & operator<<(xml::StartTag const &); XMLStream & operator<<(xml::StartTag const &);
/// ///
XMLStream & operator<<(xml::EndTag 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 { enum FontTypes {
// ranges // ranges