include/svtools/parhtml.hxx                              |    1 
 sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt |   25 ++
 sw/qa/extras/htmlexport/htmlexport.cxx                   |  147 +++++++++++++++
 sw/source/filter/html/htmlatr.cxx                        |   86 ++++++--
 sw/source/filter/html/swhtml.cxx                         |    2 
 sw/source/filter/html/wrthtml.cxx                        |    1 
 sw/source/filter/html/wrthtml.hxx                        |    3 
 7 files changed, 241 insertions(+), 24 deletions(-)

New commits:
commit 2da3c1f0bf180e44e82d6ef9bbcd33129026a3dc
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Nov 14 11:05:05 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Nov 23 14:14:09 2023 +0100

    Limit PreserveSpaces HTML/ReqIF export option to proper space characters
    
    We only need to care about SPACE, TAB, LF, and CR. We don't need to care
    about LF in some cases, because it gets converted to a <br/> element, and
    handled specially. And we don't need to care about other "whitespace"
    characters, like control characters and Unicode space.
    
    Our own object placeholder characters were treated as "space", which was
    wrong.
    
    One peculiarity needs to be noted. In ReqIF case, a SPACE before LF needs
    no 'xml:space="preserve"', but an LF before SPACE needs one, because it
    needs to disambiguate between a <br> followed by a significant space vs.
    a <br> followed by a pretty-printed newline.
    
    Change-Id: I74273592df05bb94d8e4ecaea2c069c0e086b7d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159853
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/include/svtools/parhtml.hxx b/include/svtools/parhtml.hxx
index 5ce3d27cb61d..22dfe2769e2a 100644
--- a/include/svtools/parhtml.hxx
+++ b/include/svtools/parhtml.hxx
@@ -189,6 +189,7 @@ protected:
 
     void SetNamespace(std::u16string_view rNamespace);
 
+    bool GetPreserveSpaces() const { return m_bPreserveSpaces; }
     void SetPreserveSpaces(bool val) { m_bPreserveSpaces = val; }
 
 public:
diff --git a/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt 
b/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt
new file mode 100644
index 000000000000..e0d9a3506e9f
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:p>No special spaces</text:p>
+   <text:p><text:s/>Leading space</text:p>
+   <text:p>Trailing space </text:p>
+   <text:p>Double <text:s/>space</text:p>
+   <text:p><text:line-break/>Leading/trailing breaks<text:line-break/></text:p>
+   <text:p><text:line-break/> Leading break + space</text:p>
+   <text:p>Trailing space + break <text:line-break/></text:p>
+   <text:p>Middle<text:line-break/>break</text:p>
+   <text:p>Middle space <text:line-break/>+ break</text:p>
+   <text:p>Middle break<text:line-break/> + space</text:p>
+   <text:p>Trailing space and SVG <draw:frame text:anchor-type="as-char" 
svg:width="5.59mm" svg:height="5.59mm" draw:z-index="0"><draw:image 
draw:mime-type="image/svg+xml">
+      
<office:binary-data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0
+       cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDIw
+       IDIwIiBzdHJva2U9ImJsYWNrIj4KPHBhdGggZD0iTTEsMUwxOSwxOSIvPgo8L3N2Zz4=
+      </office:binary-data>
+     </draw:image>
+    </draw:frame></text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index c436411daf52..161357ffbdba 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -2835,6 +2835,153 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqIF_PreserveSpaces)
     CPPUNIT_ASSERT_EQUAL(paraText, getParagraph(1)->getString());
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_NoPreserveSpaces)
+{
+    // Test cases where "PreserveSpaces" should not introduce respective markup
+
+    const auto assertXPath_NoWhiteSpaceInStyle
+        = [this](const xmlDocUniquePtr& pDoc, const OString& rXPath) {
+              xmlXPathObjectPtr pXmlObj = getXPathNode(pDoc, rXPath);
+              xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+              CPPUNIT_ASSERT_EQUAL_MESSAGE(rXPath.getStr(), 1, 
xmlXPathNodeSetGetLength(pXmlNodes));
+              xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
+              if (xmlChar* prop = xmlGetProp(pXmlNode, BAD_CAST("style")))
+              {
+                  OUString style = OUString::fromUtf8(reinterpret_cast<const 
char*>(prop));
+                  CPPUNIT_ASSERT_MESSAGE(rXPath.getStr(), 
style.indexOf("white-space:") < 0);
+              }
+              xmlXPathFreeObject(pXmlObj);
+          };
+    const auto assertXPath_HasWhiteSpaceInStyle
+        = [this](const xmlDocUniquePtr& pDoc, const OString& rXPath) {
+              const OUString style = getXPath(pDoc, rXPath, "style"_ostr);
+              CPPUNIT_ASSERT_MESSAGE(rXPath.getStr(), 
style.indexOf("white-space: pre-wrap") >= 0);
+          };
+
+    createSwDoc("test_no_space_preserve.fodt");
+
+    // Export to plain HTML, using PreserveSpaces:
+    saveWithParams({
+        comphelper::makePropertyValue("FilterName", u"HTML (StarWriter)"_ustr),
+        comphelper::makePropertyValue("PreserveSpaces", true),
+    });
+
+    htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
+    CPPUNIT_ASSERT(pHtmlDoc);
+
+    // No whitespace preservation, where no leading / trailing / double 
whitespace
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[1]"_ostr);
+    // Whitespace preserved for a leading space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[2]"_ostr);
+    // Whitespace preserved for a trailing space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[3]"_ostr);
+    // Whitespace preserved for a double space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[4]"_ostr);
+    // No whitespace preservation for leading / trailing breaks
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[5]"_ostr);
+    // Whitespace preserved for a leading break + space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[6]"_ostr);
+    // Whitespace preserved for a trailing space + break
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[7]"_ostr);
+    // No whitespace preservation for a middle break
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[8]"_ostr);
+    // Whitespace preserved for a middle space + break
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[9]"_ostr);
+    // Whitespace preserved for a middle break + space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[10]"_ostr);
+    // No whitespace preservation for a trailing space and SVG
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[11]"_ostr);
+
+    // Test import
+
+    setImportFilterName("HTML (StarWriter)");
+    load(maTempFile.GetURL());
+
+    CPPUNIT_ASSERT_EQUAL(u"No special spaces"_ustr, 
getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(u" Leading space"_ustr, getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space "_ustr, 
getParagraph(3)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Double  space"_ustr, getParagraph(4)->getString());
+    // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced 
with para spacing
+    CPPUNIT_ASSERT_EQUAL(u"\nLeading/trailing breaks"_ustr, 
getParagraph(5)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"\n Leading break + space"_ustr, 
getParagraph(6)->getString());
+    // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced 
with para spacing
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space + break "_ustr, 
getParagraph(7)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle\nbreak"_ustr, getParagraph(8)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle space \n+ break"_ustr, 
getParagraph(9)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle break\n + space"_ustr, 
getParagraph(10)->getString());
+    // The SVG is replaced by a space in SwXParagraph::getString()
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space and SVG  "_ustr, 
getParagraph(11)->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoPreserveSpaces)
+{
+    // Test cases where "PreserveSpaces" should not introduce respective markup
+
+    createSwDoc("test_no_space_preserve.fodt");
+
+    // Export to ReqIF, using PreserveSpaces:
+    saveWithParams({
+        comphelper::makePropertyValue("FilterName", u"HTML (StarWriter)"_ustr),
+        comphelper::makePropertyValue("FilterOptions", 
u"xhtmlns=reqif-xhtml"_ustr),
+        comphelper::makePropertyValue("PreserveSpaces", true),
+    });
+
+    xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
+
+    // No whitespace preservation, where no leading / trailing / double 
whitespace
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[1]"_ostr,
+                           "space"_ostr);
+    // Whitespace preserved for a leading space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]"_ostr, "space"_ostr,
+                u"preserve"_ustr);
+    // Whitespace preserved for a trailing space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[3]"_ostr, "space"_ostr,
+                u"preserve"_ustr);
+    // Whitespace preserved for a double space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[4]"_ostr, "space"_ostr,
+                u"preserve"_ustr);
+    // No whitespace preservation for leading / trailing breaks
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[5]"_ostr,
+                           "space"_ostr);
+    // Whitespace preserved for a leading break + space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[6]"_ostr, "space"_ostr,
+                u"preserve"_ustr);
+    // No whitespace preservation for a trailing space + break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[7]"_ostr,
+                           "space"_ostr);
+    // No whitespace preservation for a middle break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[8]"_ostr,
+                           "space"_ostr);
+    // No whitespace preservation for a middle space + break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[9]"_ostr,
+                           "space"_ostr);
+    // Whitespace preserved for a middle break + space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[10]"_ostr, "space"_ostr,
+                u"preserve"_ustr);
+    // No whitespace preservation for a trailing space and SVG
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[11]"_ostr,
+                           "space"_ostr);
+
+    // Test import
+
+    setImportFilterOptions("xhtmlns=reqif-xhtml");
+    setImportFilterName("HTML (StarWriter)");
+    load(maTempFile.GetURL());
+
+    CPPUNIT_ASSERT_EQUAL(u"No special spaces"_ustr, 
getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(u" Leading space"_ustr, getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space "_ustr, 
getParagraph(3)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Double  space"_ustr, getParagraph(4)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"\nLeading/trailing breaks\n"_ustr, 
getParagraph(5)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"\n Leading break + space"_ustr, 
getParagraph(6)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space + break \n"_ustr, 
getParagraph(7)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle\nbreak"_ustr, getParagraph(8)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle space \n+ break"_ustr, 
getParagraph(9)->getString());
+    CPPUNIT_ASSERT_EQUAL(u"Middle break\n + space"_ustr, 
getParagraph(10)->getString());
+    // The SVG is replaced by a space in SwXParagraph::getString()
+    CPPUNIT_ASSERT_EQUAL(u"Trailing space and SVG  "_ustr, 
getParagraph(11)->getString());
+}
+
 CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_ExportFormulasAsPDF)
 {
     // Given a document with a formula:
diff --git a/sw/source/filter/html/htmlatr.cxx 
b/sw/source/filter/html/htmlatr.cxx
index 48a3e0e4cb14..8a20167c8bc4 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -772,7 +772,7 @@ static void OutHTML_SwFormat( SwHTMLWriter& rWrt, const 
SwFormat& rFormat,
     if( rInfo.bInNumberBulletList && bNumberedForListItem )
     {
         HtmlWriter html(rWrt.Strm(), rWrt.maNamespace);
-        html.prettyPrint(rWrt.m_bPrettyPrint);
+        html.prettyPrint(rWrt.IsPrettyPrint());
         html.start(OOO_STRING_SVTOOLS_HTML_li ""_ostr);
         if (!bNumbered)
         {
@@ -1015,7 +1015,7 @@ static void OutHTML_SwFormatOff( SwHTMLWriter& rWrt, 
const SwHTMLTextCollOutputI
 
     if( rInfo.ShouldOutputToken() )
     {
-        if (rWrt.m_bPrettyPrint && rWrt.IsLFPossible())
+        if (rWrt.IsPrettyPrint() && rWrt.IsLFPossible())
             rWrt.OutNewLine( true );
 
         // if necessary, for BLOCKQUOTE, ADDRESS and DD another paragraph token
@@ -2012,26 +2012,70 @@ void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rWrt, 
sal_Int32 nPos )
     }
 }
 
-static bool NeedPreserveWhitespace(std::u16string_view str)
+static constexpr bool IsLF(sal_Unicode ch) { return ch == '\n'; }
+
+static constexpr bool IsWhitespaceExcludingLF(sal_Unicode ch)
+{
+    return ch == ' ' || ch == '\t' || ch == '\r';
+}
+
+static constexpr bool IsWhitespaceIncludingLF(sal_Unicode ch)
+{
+    return IsWhitespaceExcludingLF(ch) || IsLF(ch);
+}
+
+static bool NeedPreserveWhitespace(std::u16string_view str, bool xml)
 {
     if (str.empty())
         return false;
     // leading / trailing spaces
-    if (o3tl::internal::implIsWhitespace(str.front())
-        || o3tl::internal::implIsWhitespace(str.back()))
+    // A leading / trailing \n would turn into a leading / trailing <br/>,
+    // and will not disappear, even without space preserving option
+    if (IsWhitespaceExcludingLF(str.front()) || 
IsWhitespaceExcludingLF(str.back()))
         return true;
-    bool bWasSpace = false;
-    for (auto ch : str)
+    for (size_t i = 0; i < str.size(); ++i)
     {
-        if (o3tl::internal::implIsWhitespace(ch))
+        if (xml)
         {
-            if (bWasSpace)
-                return true; // Second whitespace in a row
-            else
-                bWasSpace = true;
+            // No need to consider \n, which convert to <br/>, when it's after 
a space
+            // (but handle it *before* a space)
+            if (IsWhitespaceIncludingLF(str[i]))
+            {
+                do
+                {
+                    ++i;
+                    if (i == str.size())
+                        return false;
+                } while (IsLF(str[i]));
+                if (IsWhitespaceExcludingLF(str[i]))
+                    return true; // Second whitespace in a row
+            }
+        }
+        else // html
+        {
+            // Only consider \n, when an adjacent space is not \n - which 
would be eaten
+            // without a space preserving option
+            if (IsWhitespaceExcludingLF(str[i]))
+            {
+                ++i;
+                if (i == str.size())
+                    return false;
+                if (IsWhitespaceIncludingLF(str[i]))
+                    return true; // Any whitespace after a non-LF whitespace
+            }
+            else if (IsLF(str[i]))
+            {
+                do
+                {
+                    ++i;
+                    if (i == str.size())
+                        return false;
+                }
+                while (IsLF(str[i]));
+                if (IsWhitespaceExcludingLF(str[i]))
+                    return true; // A non-LF whitespace after a LF
+            }
         }
-        else
-            bWasSpace = false;
     }
     return false;
 }
@@ -2067,7 +2111,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
         rWrt.SetLFPossible(true);
 
         HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
-        aHtml.prettyPrint(rWrt.m_bPrettyPrint);
+        aHtml.prettyPrint(rWrt.IsPrettyPrint());
         aHtml.start(OOO_STRING_SVTOOLS_HTML_horzrule ""_ostr);
 
         const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
@@ -2250,7 +2294,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
     bool bOldLFPossible = rWrt.IsLFPossible();
     bool bOldSpacePreserve = rWrt.IsSpacePreserve();
     if (rWrt.IsPreserveSpacesOnWritePrefSet())
-        rWrt.SetSpacePreserve(NeedPreserveWhitespace(rStr));
+        rWrt.SetSpacePreserve(NeedPreserveWhitespace(rStr, rWrt.mbReqIF));
     OutHTML_SwFormat( rWrt, rFormat, pNd->GetpSwAttrSet(), aFormatInfo );
 
     // If we didn't open a new line before the paragraph tag, we do that now
@@ -2265,7 +2309,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
     // now it's a good opportunity again for an LF - if it is still allowed
     // FIXME: for LOK case we set rWrt.m_nWishLineLen as -1, for now keep old 
flow
     // when LOK side will be fixed - don't insert new line at the beginning
-    if( rWrt.IsLFPossible() && rWrt.m_bPrettyPrint && rWrt.m_nWishLineLen >= 0 
&&
+    if( rWrt.IsLFPossible() && rWrt.IsPrettyPrint() && rWrt.m_nWishLineLen >= 
0 &&
         rWrt.GetLineLen() >= rWrt.m_nWishLineLen )
     {
         rWrt.OutNewLine();
@@ -2504,7 +2548,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
                         nWordLen = nEnd;
                     nWordLen -= nStrPos;
 
-                    if( rWrt.m_bPrettyPrint && rWrt.m_nWishLineLen >= 0 &&
+                    if( rWrt.IsPrettyPrint() && rWrt.m_nWishLineLen >= 0 &&
                         (nLineLen >= rWrt.m_nWishLineLen ||
                         (nLineLen+nWordLen) >= rWrt.m_nWishLineLen ) )
                     {
@@ -2520,7 +2564,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
                     {
                         HTMLOutFuncs::FlushToAscii( rWrt.Strm() );
                         HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
-                        aHtml.prettyPrint(rWrt.m_bPrettyPrint);
+                        aHtml.prettyPrint(rWrt.IsPrettyPrint());
                         aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak 
""_ostr);
                     }
                     else if (c == CH_TXT_ATR_FORMELEMENT)
@@ -2599,7 +2643,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
         else
         {
             HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
-            aHtml.prettyPrint(rWrt.m_bPrettyPrint);
+            aHtml.prettyPrint(rWrt.IsPrettyPrint());
             aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr);
             const SvxULSpaceItem& rULSpace = 
pNd->GetSwAttrSet().Get(RES_UL_SPACE);
             if (rULSpace.GetLower() > 0 && !bEndOfCell)
@@ -2626,7 +2670,7 @@ SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, 
const SwContentNode& rNode
         }
 
         HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
-        aHtml.prettyPrint(rWrt.m_bPrettyPrint);
+        aHtml.prettyPrint(rWrt.IsPrettyPrint());
         aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr);
         aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, pString);
         aHtml.end();
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
index 01670a3d2220..072d6a2b23c7 100644
--- a/sw/source/filter/html/swhtml.cxx
+++ b/sw/source/filter/html/swhtml.cxx
@@ -1523,7 +1523,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken )
     case HtmlTokenId::TEXTTOKEN:
     case HtmlTokenId::CDATA:
         // insert string without spanning attributes at the end.
-        if( !aToken.isEmpty() && ' '==aToken[0] && !IsReadPRE() )
+        if (!aToken.isEmpty() && ' ' == aToken[0] && !IsReadPRE() && 
!GetPreserveSpaces())
         {
             sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex();
             const SwTextNode* pTextNode = nPos ? 
m_pPam->GetPoint()->GetNode().GetTextNode() : nullptr;
diff --git a/sw/source/filter/html/wrthtml.cxx 
b/sw/source/filter/html/wrthtml.cxx
index 3c9a1d2a168b..43c62f074703 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -153,7 +153,6 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, 
std::u16string_view rFilte
     , mbEmbedImages(false)
     , m_bCfgPrintLayout( false )
     , m_bParaDotLeaders( false )
-    , m_bPrettyPrint( true )
 {
     SetBaseURL(rBaseURL);
 
diff --git a/sw/source/filter/html/wrthtml.hxx 
b/sw/source/filter/html/wrthtml.hxx
index e8c03f39151a..07a8281be13d 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -278,6 +278,7 @@ class SW_DLLPUBLIC SwHTMLWriter : public Writer
 
     FieldUnit m_eCSS1Unit;
 
+    bool m_bPrettyPrint = true; // Allows to add new lines to make it more 
readable
     bool m_bLFPossible = false; // a line break can be inserted
     bool m_bSpacePreserve = false; // Using xml::space="preserve", or 
"white-space: pre-wrap" style
     bool m_bPreserveSpacesOnWrite = false; // If export should use 
m_bSpacePreserve
@@ -419,7 +420,6 @@ public:
 #define sCSS2_P_CLASS_leaders "leaders"
     bool m_bCfgPrintLayout : 1;       // PrintLayout option for TOC dot leaders
     bool m_bParaDotLeaders : 1;       // for TOC dot leaders
-    bool m_bPrettyPrint : 1;          // Allows to add new lines to make it 
more readable
     // 26
 
     /// Tracks which text portion attributes are currently open: a which id -> 
open count map.
@@ -623,6 +623,7 @@ public:
     /// Determines the prefix string needed to respect the requested namespace 
alias.
     OString GetNamespace() const;
 
+    bool IsPrettyPrint() const { return !m_bSpacePreserve && m_bPrettyPrint; }
     bool IsLFPossible() const { return !m_bSpacePreserve && m_bLFPossible; }
     void SetLFPossible(bool val) { m_bLFPossible = val; }
     bool IsSpacePreserve() const { return m_bSpacePreserve; }

Reply via email to