tdf#121456: sw: DOCX: tabs export and TABS_RELATIVE_TO_INDENT prop

In DOCX, w:pos specifies the position of the current custom tab stop
with respect to the current page margins.
But in ODT, zero position could be page margins or paragraph indent
according to used settings DocumentSettingId::TABS_RELATIVE_TO_INDENT

Added new unit test.

Change-Id: Ic56a8527380b6562f4239df1edce0c9b4649af24
Reviewed-on: https://gerrit.libreoffice.org/63460
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf121456_tabsOffset.odt b/sw/qa/extras/ooxmlexport/data/tdf121456_tabsOffset.odt
new file mode 100755
index 0000000..ff8d540
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf121456_tabsOffset.odt
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 40e9fb1..2728c75b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -120,6 +120,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf63561_clearTabs2, "tdf63561_clearTabs2.docx")
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), getProperty< uno::Sequence<style::TabStop> >(getParagraph(4), "ParaTabStops").getLength());
}

DECLARE_OOXMLEXPORT_TEST(testTdf121456_tabsOffset, "tdf121456_tabsOffset.odt")
{
    for (int i=2; i<8; i++)
    {
        uno::Sequence< style::TabStop > stops = getProperty< uno::Sequence<style::TabStop> >(getParagraph( i ), "ParaTabStops");
        CPPUNIT_ASSERT_EQUAL( sal_Int32(1), stops.getLength());
        CPPUNIT_ASSERT_EQUAL( css::style::TabAlign_RIGHT, stops[ 0 ].Alignment );
        CPPUNIT_ASSERT_EQUAL( sal_Int32(17000), stops[ 0 ].Position );
    }
}

DECLARE_OOXMLEXPORT_TEST(testTdf106174_rtlParaAlign, "tdf106174_rtlParaAlign.docx")
{
    CPPUNIT_ASSERT_EQUAL(sal_Int16(style::ParagraphAdjust_CENTER), getProperty<sal_Int16>(getParagraph(1), "ParaAdjust"));
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 241c222..c576fec 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -7707,7 +7707,7 @@ void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
}

static void impl_WriteTabElement( FSHelperPtr const & pSerializer,
                                  const SvxTabStop& rTab )
                                  const SvxTabStop& rTab, long tabsOffset )
{
    FastAttributeList *pTabElementAttrList = FastSerializerHelper::createAttrList();

@@ -7729,9 +7729,11 @@ static void impl_WriteTabElement( FSHelperPtr const & pSerializer,
        break;
    }

    // Because GetTabPos already includes indent, we don't need to add nCurrentLeft (CurrentLeft is indentation information)
    //pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
    pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::number( rTab.GetTabPos()                ) );
    // Write position according to used offset of the whole paragraph.
    // In DOCX, w:pos specifies the position of the current custom tab stop with respect to the current page margins.
    // But in ODT, zero position could be page margins or paragraph indent according to used settings.
    // This is handled outside of this method and provided for us in tabsOffset parameter.
    pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::number( rTab.GetTabPos() + tabsOffset ) );

    sal_Unicode cFillChar = rTab.GetFill();

@@ -7770,6 +7772,13 @@ void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )

    m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );

    // Get offset for tabs
    // In DOCX, w:pos specifies the position of the current custom tab stop with respect to the current page margins.
    // But in ODT, zero position could be page margins or paragraph indent according to used settings.
    long tabsOffset = 0;
    if (m_rExport.m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT))
        tabsOffset = m_rExport.GetItem(RES_LR_SPACE).GetTextLeft();

    // clear unused inherited tabs - otherwise the style will add them back in
    sal_Int32 nCurrTab = 0;
    for ( sal_uInt16 i = 0; i < nInheritedTabCount; ++i )
@@ -7789,7 +7798,7 @@ void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
    for (sal_uInt16 i = 0; i < nCount; i++ )
    {
        if( rTabStop[i].GetAdjustment() != SvxTabAdjust::Default )
            impl_WriteTabElement( m_pSerializer, rTabStop[i] );
            impl_WriteTabElement( m_pSerializer, rTabStop[i], tabsOffset );
        else
            GetExport().setDefaultTabStop( rTabStop[i].GetTabPos());
    }