tdf#59674 Word export: set a tabstop at numbering IndentAt
...if the specified tabstop would be ignored - for the benefit
of MS Word.
After the numbering character, the tab in Writer stops at
A.) IndentAt, or B.) a non-default tabstop.
In other words, Writer ignores default tabstops.
(Caveat, LO ignores IndentAt when numbering sets a larger tabstop.)
However, MS Word does NOT necessarily stop at IndentAt,
but it stops at default tabstops, or a specified tabstop.
It only seems to stop at IndentAt if there are only
default tabstops that are farther than IndentAt.
In other words, Word usually ignores IndentAt.
(This is true for .doc and .rtf formats. It is also true for .docx
format with MS Word 2003, but not with MS Word 2016.)
In this patch, I only try to fix Word ignoring the IndentAt.
[A basically-unsolvable edge case is when the tabstop is larger than
the first line indent, but still not behind the numbering character.]
This patch could regress if paragraph-level tabstops define the position.
In that case, we have introduced another tabstop at the indentAt
position, and so a SECOND tabstop on the FIRST line might end up
at the wrong position. This is an EXTREMELY unlikely situation,
and in fact, both LO and Word seem to tabstop there anyway,
so I no longer think it would cause a regression. Go figure.
I heavily modified an existing unit test because
although that fix "works" and was an "easy fix"
it probably ought to have calculated the IndentAt and used that
instead of zero to replace the LO default values.
It works, however, so I won't bother doing anything about it.
(Also, the paragraph used doesn't matter - it is the same list.)
Change-Id: Ia13ac880ab63c610b26c99ab77903e08ebdebe35
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99529
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
index 3e91958..47fa3b7 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
@@ -273,28 +273,19 @@ DECLARE_OOXMLEXPORT_TEST(testTdf134260, "tdf134260.docx")
// - Expected: 0
// - Actual : 1270
auto xNum1Levels
= getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
CPPUNIT_ASSERT_EQUAL(
sal_Int32(0),
comphelper::SequenceAsHashMap(xNum1Levels->getByIndex(0))["ListtabStopPosition"]
.get<sal_Int32>());
auto xNum2Levels
= getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(2), "NumberingRules");
CPPUNIT_ASSERT_EQUAL(
sal_Int32(0),
comphelper::SequenceAsHashMap(xNum2Levels->getByIndex(0))["ListtabStopPosition"]
.get<sal_Int32>());
auto xNum3Levels
auto xNumLevels
= getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(3), "NumberingRules");
sal_Int32 nTabPosExpected = mbExported ? 1270 : 0;
CPPUNIT_ASSERT_EQUAL(
sal_Int32(0),
comphelper::SequenceAsHashMap(xNum3Levels->getByIndex(0))["ListtabStopPosition"]
nTabPosExpected,
comphelper::SequenceAsHashMap(xNumLevels->getByIndex(0))["ListtabStopPosition"]
.get<sal_Int32>());
nTabPosExpected = mbExported ? 2598 : 0;
CPPUNIT_ASSERT_EQUAL(
nTabPosExpected,
comphelper::SequenceAsHashMap(xNumLevels->getByIndex(1))["ListtabStopPosition"]
.get<sal_Int32>());
}
diff --git a/sw/qa/extras/ww8export/data/tdf59674_numberingTabStop.odt b/sw/qa/extras/ww8export/data/tdf59674_numberingTabStop.odt
new file mode 100644
index 0000000..5edcbae
--- /dev/null
+++ b/sw/qa/extras/ww8export/data/tdf59674_numberingTabStop.odt
Binary files differ
diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index 460937c..512cce9 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -136,6 +136,18 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testChicagoNumberingFootnote)
CPPUNIT_ASSERT_EQUAL(nExpected, nActual);
}
DECLARE_WW8EXPORT_TEST(testTdf59674_numberingTabStop, "tdf59674_numberingTabStop.odt")
{
// This bug is mainly for MS Word. The round-trip looked fine in LO. Test exporting a non-useless value.
auto xNum1Levels = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(2), "NumberingRules");
sal_Int32 nTabPos2 = comphelper::SequenceAsHashMap(xNum1Levels->getByIndex(0))["ListtabStopPosition"].get<sal_Int32>();
xNum1Levels.set(getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(3), "NumberingRules"));
sal_Int32 nTabPos3 = comphelper::SequenceAsHashMap(xNum1Levels->getByIndex(0))["ListtabStopPosition"].get<sal_Int32>();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1281), nTabPos2);
CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), nTabPos3); //previously 640
}
DECLARE_WW8EXPORT_TEST(testdf79553_lineNumbers, "tdf79553_lineNumbers.doc")
{
bool bValue = false;
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index 3efd99c..da7182a 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -595,8 +595,18 @@ void MSWordExportBase::NumberingLevel(
{
nIndentAt = static_cast<sal_Int16>(rFormat.GetIndentAt());
nFirstLineIndex = static_cast<sal_Int16>(rFormat.GetFirstLineIndent());
nListTabPos = rFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
static_cast<sal_Int16>( rFormat.GetListtabPos() ) : 0;
nListTabPos = 0;
if ( rFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
{
nListTabPos = static_cast<sal_Int16>( rFormat.GetListtabPos() );
// Writer usually treats nIndentAt as a tabstop, but Word doesn't (at least for .doc and .rtf).
// NOTE: There will still be problems if the tabstop is only SLIGHTLY larger than the align-at position,
// i.e. if the tab position is not behind the numbering character. Oh well. Better design your document better.
const sal_Int32 nStart = nIndentAt + nFirstLineIndex; // nFirstLineIndex is a negative offset
if ( nListTabPos <= nStart )
nListTabPos = nIndentAt;
}
}
AttrOutput().NumberingLevel( nLvl,