Add undo operation for deleting a bookmark + unit test, related fdo#51741

(cherry picked from commit 9338bea6e8dfab8d360fe8ab19dd5d75071bfc2a)

Conflicts:
	sw/qa/extras/uiwriter/uiwriter.cxx
	sw/source/core/undo/unbkmk.cxx

Change-Id: I79d8d3c30b6b0b2cc253963fdd50019aec033e12
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 2ed5298..23b1e7d 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -57,6 +57,7 @@ public:
    void testChineseConversionTraditionalToSimplified();
    void testChineseConversionSimplifiedToTraditional();
    void testFdo85554();
    void testBookmarkUndo();

    CPPUNIT_TEST_SUITE(SwUiWriterTest);
    CPPUNIT_TEST(testReplaceForward);
@@ -80,6 +81,7 @@ public:
    CPPUNIT_TEST(testChineseConversionTraditionalToSimplified);
    CPPUNIT_TEST(testChineseConversionSimplifiedToTraditional);
    CPPUNIT_TEST(testFdo85554);
    CPPUNIT_TEST(testBookmarkUndo);

    CPPUNIT_TEST_SUITE_END();

@@ -586,6 +588,40 @@ void SwUiWriterTest::testFdo85554()
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xDrawPage->getCount());
}

void SwUiWriterTest::testBookmarkUndo()
{
    SwDoc* pDoc = createDoc();
    sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
    IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    SwPaM aPaM( SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1) );

    pMarkAccess->makeMark(aPaM, OUString("Mark"), IDocumentMarkAccess::BOOKMARK);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
    rUndoManager.Undo();
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
    rUndoManager.Redo();
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());

    IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark("Mark");
    CPPUNIT_ASSERT(ppBkmk != pMarkAccess->getAllMarksEnd());

    pMarkAccess->renameMark(ppBkmk->get(), "Mark_");
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd());
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());
    rUndoManager.Undo();
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark") != pMarkAccess->getAllMarksEnd());
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") == pMarkAccess->getAllMarksEnd());
    rUndoManager.Redo();
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark") == pMarkAccess->getAllMarksEnd());
    CPPUNIT_ASSERT(pMarkAccess->findMark("Mark_") != pMarkAccess->getAllMarksEnd());

    pMarkAccess->deleteMark( pMarkAccess->findMark("Mark_") );
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
    rUndoManager.Undo();
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
    rUndoManager.Redo();
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
}

CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index d79fffc..666a118 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -276,7 +276,11 @@ namespace sw { namespace mark
    {
        DdeBookmark::DeregisterFromDoc(io_pDoc);

        // fdo#51741 Bookmark should mark document as modified when deleted
        if (io_pDoc->GetIDocumentUndoRedo().DoesUndo())
        {
            io_pDoc->GetIDocumentUndoRedo().AppendUndo(
                    new SwUndoDeleteBookmark(*this));
        }
        io_pDoc->getIDocumentState().SetModified();
    }

diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index d6d3d27..9567c3a 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -29,6 +29,7 @@
#include <doc.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentState.hxx>
#include <IDocumentUndoRedo.hxx>
#include <docary.hxx>
#include <xmloff/odffields.hxx>
#include <editsh.hxx>
@@ -49,6 +50,7 @@
#include <sfx2/linkmgr.hxx>
#include <swserv.hxx>
#include <swundo.hxx>
#include <UndoBookmark.hxx>
#include <unocrsr.hxx>
#include <viscrs.hxx>
#include <edimp.hxx>
@@ -550,12 +552,18 @@ namespace sw { namespace mark
            return false;
        if (::sw::mark::MarkBase* pMarkBase = dynamic_cast< ::sw::mark::MarkBase* >(io_pMark))
        {
            m_aMarkNamesSet.erase(pMarkBase->GetName());
            const OUString sOldName(pMarkBase->GetName());
            m_aMarkNamesSet.erase(sOldName);
            m_aMarkNamesSet.insert(rNewName);
            pMarkBase->SetName(rNewName);

            // fdo#51741 Bookmark should mark document as modified when renamed
            if (dynamic_cast< ::sw::mark::Bookmark* >(io_pMark)) {
            if (dynamic_cast< ::sw::mark::Bookmark* >(io_pMark))
            {
                if (m_pDoc->GetIDocumentUndoRedo().DoesUndo())
                {
                    m_pDoc->GetIDocumentUndoRedo().AppendUndo(
                            new SwUndoRenameBookmark(sOldName, rNewName));
                }
                m_pDoc->getIDocumentState().SetModified();
            }
        }
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
index eaa0fcb..c4215e2 100644
--- a/sw/source/core/inc/UndoBookmark.hxx
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -67,15 +67,22 @@ public:
    virtual void RedoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
};

class SwUndoDeleteBookmark : public SwUndoBookmark
{
public:
    SwUndoDeleteBookmark( const ::sw::mark::IMark& );

    virtual void UndoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
    virtual void RedoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
};

class SwUndoRenameBookmark : public SwUndo
{
    const OUString m_sOldName;
    const OUString m_sNewName;
    const sal_uLong m_nNode;
    const sal_Int32 m_nCntnt;

public:
    SwUndoRenameBookmark( const ::sw::mark::IMark&, const OUString& rNewName );
    SwUndoRenameBookmark( const OUString& rOldName, const OUString& rNewName );
    virtual ~SwUndoRenameBookmark();

private:
diff --git a/sw/source/core/undo/unbkmk.cxx b/sw/source/core/undo/unbkmk.cxx
index 3501ed5..ef0ad13 100644
--- a/sw/source/core/undo/unbkmk.cxx
+++ b/sw/source/core/undo/unbkmk.cxx
@@ -86,12 +86,25 @@ void SwUndoInsBookmark::RedoImpl(::sw::UndoRedoContext & rContext)
    SetInDoc( &rContext.GetDoc() );
}

SwUndoRenameBookmark::SwUndoRenameBookmark( const ::sw::mark::IMark& rBkmk, const OUString& rOldName )
SwUndoDeleteBookmark::SwUndoDeleteBookmark( const ::sw::mark::IMark& rBkmk )
    : SwUndoBookmark( UNDO_DELBOOKMARK, rBkmk )
{
}

void SwUndoDeleteBookmark::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SetInDoc( &rContext.GetDoc() );
}

void SwUndoDeleteBookmark::RedoImpl(::sw::UndoRedoContext & rContext)
{
    ResetInDoc( &rContext.GetDoc() );
}

SwUndoRenameBookmark::SwUndoRenameBookmark( const OUString& rOldName, const OUString& rNewName )
    : SwUndo( UNDO_BOOKMARK_RENAME )
    , m_sOldName( rOldName )
    , m_sNewName( rBkmk.GetName() )
    , m_nNode( rBkmk.GetMarkPos().nNode.GetIndex() )
    , m_nCntnt( rBkmk.GetMarkPos().nContent.GetIndex() )
    , m_sNewName( rNewName )
{
}

diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
index f42beb3..2f252f9 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -24,7 +24,6 @@
#include <vcl/svapp.hxx>

#include <TextCursorHelper.hxx>
#include <UndoBookmark.hxx>
#include <unotextrange.hxx>
#include <unomap.hxx>
#include <unoprnms.hxx>
@@ -32,7 +31,6 @@
#include <crossrefbookmark.hxx>
#include <doc.hxx>
#include <IDocumentState.hxx>
#include <IDocumentUndoRedo.hxx>
#include <docary.hxx>
#include <swundo.hxx>
#include <docsh.hxx>
@@ -349,15 +347,7 @@ throw (uno::RuntimeException, std::exception)
        *aPam.GetMark() = m_pImpl->m_pRegisteredBookmark->GetOtherMarkPos();
    }

    const OUString sOldName(m_pImpl->m_pRegisteredBookmark->GetName());
    if (pMarkAccess->renameMark(m_pImpl->m_pRegisteredBookmark, rName))
    {
        if (m_pImpl->m_pDoc->GetIDocumentUndoRedo().DoesUndo())
        {
            m_pImpl->m_pDoc->GetIDocumentUndoRedo().AppendUndo(
                    new SwUndoRenameBookmark(*m_pImpl->m_pRegisteredBookmark, sOldName));
        }
    }
    pMarkAccess->renameMark(m_pImpl->m_pRegisteredBookmark, rName);
}

OUString SAL_CALL