tdf#113790: skip charfmt grabbag items existing in autofmt grabbag

Change-Id: Icc0065c1da9471cb36bfef0da45e2f67381a1a31
Reviewed-on: https://gerrit.libreoffice.org/44706
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/sw/qa/extras/uiwriter/data/tdf113790.docx b/sw/qa/extras/uiwriter/data/tdf113790.docx
new file mode 100644
index 0000000..b6334aa
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf113790.docx
Binary files differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 34f0e21..7b09d0a 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -285,6 +285,7 @@ public:
    void testTdf99689TableOfContents();
    void testTdf99689TableOfFigures();
    void testTdf99689TableOfTables();
    void testTdf113790();

    CPPUNIT_TEST_SUITE(SwUiWriterTest);
    CPPUNIT_TEST(testReplaceForward);
@@ -452,6 +453,7 @@ public:
    CPPUNIT_TEST(testTdf99689TableOfContents);
    CPPUNIT_TEST(testTdf99689TableOfFigures);
    CPPUNIT_TEST(testTdf99689TableOfTables);
    CPPUNIT_TEST(testTdf113790);
    CPPUNIT_TEST_SUITE_END();

private:
@@ -5553,6 +5555,29 @@ void SwUiWriterTest::testParagraphOfTextRange()
    CPPUNIT_ASSERT_EQUAL(OUString("In section"), xParagraph->getString());
}

void SwUiWriterTest::testTdf113790()
{
    SwDoc* pDoc = createDoc("tdf113790.docx");
    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
    // Create the clipboard document.
    SwDoc aClipboard;
    aClipboard.SetClipBoard(true);

    // Go to fourth line - to "ABCD" bulleted list item
    pWrtShell->Down(/*bSelect=*/false, 4);
    pWrtShell->SelPara(nullptr);
    CPPUNIT_ASSERT_EQUAL(OUString("ABCD"), pWrtShell->GetSelText());
    pWrtShell->Copy(&aClipboard);

    // Go down to next-to-last (empty) line above "Title3"
    pWrtShell->Down(/*bSelect=*/false, 4);
    pWrtShell->Paste(&aClipboard);

    // Save it as DOCX & load it again
    reload("Office Open XML Text", "tdf113790.docx");
    CPPUNIT_ASSERT(dynamic_cast<SwXTextDocument *>(mxComponent.get()));
}

CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
CPPUNIT_PLUGIN_IMPLEMENT();

diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index b1c1d7a..a9d5146 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -40,6 +40,7 @@
#include <editeng/formatbreakitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/tstpitem.hxx>
#include <svl/grabbagitem.hxx>
#include <svl/urihelper.hxx>
#include <svl/whiter.hxx>
#include <fmtpdsc.hxx>
@@ -462,6 +463,25 @@ void SwWW8AttrIter::OutAttr( sal_Int32 nSwPos, bool bRuby , bool bWriteCombChars
    if ( pCharFormatItem )
        ClearOverridesFromSet( *pCharFormatItem, aExportSet );

    // tdf#113790: AutoFormat style overwrites char style, so remove all
    // elements from CHARFMT grab bag which are set in AUTOFMT grab bag
    if (const SfxGrabBagItem *pAutoFmtGrabBag = dynamic_cast<const SfxGrabBagItem*>(pGrabBag))
    {
        if (const SfxGrabBagItem *pCharFmtGrabBag = aExportSet.GetItem<SfxGrabBagItem>(RES_CHRATR_GRABBAG, false))
        {
            std::unique_ptr<SfxPoolItem> pNewItem(pCharFmtGrabBag->Clone());
            SfxGrabBagItem* pNewCharFmtGrabBag = dynamic_cast<SfxGrabBagItem*>(pNewItem.get());
            assert(pNewCharFmtGrabBag);
            auto & rNewFmtMap = pNewCharFmtGrabBag->GetGrabBag();
            for (auto const & item : pAutoFmtGrabBag->GetGrabBag())
            {
                if (item.second.hasValue())
                    rNewFmtMap.erase(item.first);
            }
            aExportSet.Put(*pNewCharFmtGrabBag);
        }
    }

    ww8::PoolItems aExportItems;
    GetPoolItems( aExportSet, aExportItems, false );