From 249d899298f29c4564d30daf38e2d3682affe5a3 Mon Sep 17 00:00:00 2001 From: Thibaut Cuvelier Date: Mon, 5 Oct 2020 16:22:58 +0200 Subject: [PATCH] DocBook: clean output when fonts span over text that ends with a space --- src/Paragraph.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index bdda5d012b..32547ed5e3 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -3358,6 +3358,10 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, 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). + // 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 delayedChars; + // Parsing main loop. for (pos_type i = initial; i < size(); ++i) { // Don't show deleted material in the output. @@ -3399,6 +3403,13 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, for (; cit != cen; ++cit) *xs << *cit; + // Deal with the delayed characters *after* closing font tags. + if (!delayedChars.empty()) { + for (char_type c: delayedChars) + *xs << c; + delayedChars.clear(); + } + vector::const_iterator sit = tagsToOpen.begin(); vector::const_iterator sen = tagsToOpen.end(); for (; sit != sen; ++sit) @@ -3419,7 +3430,10 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, } } else { char_type c = getUChar(buf.masterBuffer()->params(), runparams, i); - *xs << c; + if (std::isspace(c) && !ignore_fonts) + delayedChars.push_back(c); + else + *xs << c; } font_old = font.fontInfo(); } @@ -3430,7 +3444,13 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, if (!ignore_fonts) xs->closeFontTags(); - // In listings, new lines are very important. Avoid generating one for the last line. + // Deal with the delayed characters *after* closing font tags. + if (!delayedChars.empty()) + for (char_type c: delayedChars) + *xs << c; + + // 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) *xs << xml::CR();