tdf#123703 RTF import: fix length of space character sequence

A default RTF space character is longer by an extra six-per-em
space in a space sequence. To get the same layout of documents
formatted with consecutive spaces, insert six-per-em space before
every space in a space sequence. Extra spaces are removed during
the RTF export.

Note: This is a workaround to get the same layout in documents based on
RTF templates, often used for example by bussiness applications.
Instead of adding a new RTF specific core/text layout feature,
with this workaround the layout will be compatible with ODT and DOCX
documents, too. (In contrast, MSO's DOCX export messes up the document
layout silently, shortening the length of the space sequence.)

Change-Id: I620807e1d4497e86c18732e5aa3131cf817ed94a
Reviewed-on: https://gerrit.libreoffice.org/77172
Reviewed-by: László Németh <nemeth@numbertext.org>
Tested-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/rtfexport/data/tdf123703.rtf b/sw/qa/extras/rtfexport/data/tdf123703.rtf
new file mode 100644
index 0000000..f657da1
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf123703.rtf
@@ -0,0 +1,31 @@
{\rtf1
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
word                                                                                                                  word2\par
}
diff --git a/sw/qa/extras/rtfexport/rtfexport3.cxx b/sw/qa/extras/rtfexport/rtfexport3.cxx
index abdda75..8845e89 100644
--- a/sw/qa/extras/rtfexport/rtfexport3.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport3.cxx
@@ -254,6 +254,17 @@ DECLARE_RTFEXPORT_TEST(testTabs, "tabs.rtf")
    CPPUNIT_ASSERT_EQUAL(style::TabAlign_DECIMAL, rTabStop.Alignment);
}

DECLARE_RTFEXPORT_TEST(testTdf123703, "tdf123703.rtf")
{
#if !defined(MACOSX)
    // This was 1, because of normal space character width in consecutive spaces
    CPPUNIT_ASSERT_EQUAL(2, getPages());
#else
    // still 1 here
    CPPUNIT_ASSERT_EQUAL(1, getPages());
#endif
}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index e215420..7336d85 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -1706,6 +1706,17 @@ OUString SwWW8AttrIter::GetSnippet(const OUString &rStr, sal_Int32 nCurrentPos,
    aSnippet = aSnippet.replace(CHAR_HARDHYPHEN, 0x1e);
    aSnippet = aSnippet.replace(CHAR_SOFTHYPHEN, 0x1f);

    // tdf#123703 revert import workaround for longer space characters in consecutive spaces
    sal_Int32 nPos;
    if ((nPos = aSnippet.indexOf(0x2006)) > -1)
    {
        const sal_Unicode aExtraSpace[5] = { 0x2006, 0x20, 0x2006, 0x20, 0 };
        const sal_Unicode aExtraSpace2[4] = { 0x20, 0x2006, 0x20, 0 };
        OUString sDoubleSpace("  ");
        aSnippet = aSnippet.replaceAll(aExtraSpace, sDoubleSpace, nPos)
                           .replaceAll(aExtraSpace2, sDoubleSpace);
    }

    m_rExport.m_aCurrentCharPropStarts.push( nCurrentPos );
    const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index c53acd9..eea7bff 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1718,7 +1718,21 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, const Proper
                        GetTopFieldContext()->SetHyperlinkStyle(sHyperlinkStyleName);
                    }

                    xTextRange = xTextAppend->appendTextPortion(rString, aValues);
#if !defined(MACOSX) // TODO: check layout differences and support all platforms, if needed
                    sal_Int32 nPos;
                    OUString sDoubleSpace("  ");
                    if (IsRTFImport() && (nPos = rString.indexOf(sDoubleSpace)) > -1)
                    {
                        // tdf#123703 an RTF space character is longer by an extra six-em-space in a space sequence,
                        // insert them to keep RTF document layout formatted by consecutive spaces
                        const sal_Unicode aExtraSpace[5] = { 0x2006, 0x20, 0x2006, 0x20, 0 };
                        const sal_Unicode aExtraSpace2[4] = { 0x20, 0x2006, 0x20, 0 };
                        xTextRange = xTextAppend->appendTextPortion(rString.replaceAll(sDoubleSpace, aExtraSpace, nPos)
                                                                           .replaceAll(sDoubleSpace, aExtraSpace2, nPos), aValues);
                    }
                    else
#endif
                        xTextRange = xTextAppend->appendTextPortion(rString, aValues);
                }
            }