summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx38
-rw-r--r--sw/source/filter/html/htmlatr.cxx30
-rw-r--r--sw/source/filter/html/wrthtml.cxx8
-rw-r--r--sw/source/filter/html/wrthtml.hxx3
4 files changed, 78 insertions, 1 deletions
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index cb2d697d7664..25583638aa44 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -1669,6 +1669,44 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTableBackground)
assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:table[2]/reqif-xhtml:tr[2]", "style");
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testLeadingTab)
+{
+ // Given a document with leading tabs:
+ loadURL("private:factory/swriter", nullptr);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("\t first");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("\t\t second");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("thi \t rd");
+
+ // When exporting to HTML, using LeadingTabWidth=2:
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aStoreProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+ comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+ comphelper::makePropertyValue("LeadingTabWidth", static_cast<sal_Int32>(2)),
+ };
+ xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+ // Then make sure that leading tabs are replaced with 2 nbsps:
+ SvMemoryStream aStream;
+ HtmlExportTest::wrapFragment(maTempFile, aStream);
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ CPPUNIT_ASSERT(pDoc);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: <nbsp><nbsp><space>first
+ // - Actual : <tab><space>first
+ // i.e. the leading tab was not replaced by 2 nbsps.
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:p[1]", u"\xa0\xa0 first");
+ // Test a leading tab that is not at the start of the paragraph:
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:p[2]", u"\xa0\xa0\xa0\xa0 second");
+ // Test a tab which is not leading:
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:p[3]", u"thi \t rd");
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx
index 46abffd664a9..31a28db4f9b3 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -2358,6 +2358,8 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode )
{
HTMLOutContext aContext( rHTMLWrt.m_eDestEnc );
+ // Tabs are leading till there is a non-tab since the start of the paragraph.
+ bool bLeadingTab = true;
for( ; nStrPos < nEnd; nStrPos++ )
{
// output the frames that are anchored to the current position
@@ -2491,7 +2493,33 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode )
rHTMLWrt.OutPointFieldmarks(aMarkPos);
}
else
- HTMLOutFuncs::Out_Char( rWrt.Strm(), c, aContext, &rHTMLWrt.m_aNonConvertableCharacters );
+ {
+ bool bConsumed = false;
+ if (c == '\t')
+ {
+ if (bLeadingTab && rHTMLWrt.m_nLeadingTabWidth.has_value())
+ {
+ // Consume a tab if it's leading and we know the number of NBSPs to
+ // be used as a replacement.
+ for (sal_Int32 i = 0; i < *rHTMLWrt.m_nLeadingTabWidth; ++i)
+ {
+ rWrt.Strm().WriteCharPtr("&#160;");
+ }
+ bConsumed = true;
+ }
+ }
+ else
+ {
+ // Not a tab -> later tabs are no longer leading.
+ bLeadingTab = false;
+ }
+
+ if (!bConsumed)
+ {
+ HTMLOutFuncs::Out_Char(rWrt.Strm(), c, aContext,
+ &rHTMLWrt.m_aNonConvertableCharacters);
+ }
+ }
// if a paragraph's last character is a hard line break
// then we need to add an extra <br>
diff --git a/sw/source/filter/html/wrthtml.cxx b/sw/source/filter/html/wrthtml.cxx
index e5ac25005de0..62e43946a49c 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -306,6 +306,14 @@ void SwHTMLWriter::SetupFilterFromPropertyValues(
// XHTML namespace implies XHTML.
mbXHTML = true;
}
+
+ it = aStoreMap.find("LeadingTabWidth");
+ if (it != aStoreMap.end())
+ {
+ sal_Int32 nVal{};
+ it->second >>= nVal;
+ m_nLeadingTabWidth.emplace(nVal);
+ }
}
ErrCode SwHTMLWriter::WriteStream()
diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx
index 0774efc41da1..592a403c57de 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -423,6 +423,9 @@ public:
OUString m_aRTFOLEMimeType;
+ /// If set, replace leading tabs with this many non-breaking spaces.
+ std::optional<sal_Int32> m_nLeadingTabWidth;
+
/// Construct an instance of SwHTMLWriter and optionally give it
/// the filter options directly, which can also be set via SetupFilterOptions().
explicit SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOptions = "" );