[Libreoffice-commits] core.git: 7 commits - editeng/source include/editeng include/svx sc/source sd/inc sd/source svx/Library_svxcore.mk svx/source sw/source

Armin Le Grand alg at apache.org
Tue May 28 07:55:46 PDT 2013


 editeng/source/editeng/editeng.cxx   |    6 +
 editeng/source/editeng/editundo.cxx  |   15 +++-
 editeng/source/editeng/impedit.hxx   |   34 +++++++++-
 editeng/source/outliner/outliner.cxx |   10 ++-
 include/editeng/editeng.hxx          |    4 -
 include/editeng/editund2.hxx         |    6 +
 include/editeng/outliner.hxx         |    4 -
 include/svx/sdrundomanager.hxx       |   65 +++++++++++++++++++
 include/svx/svdedxv.hxx              |   14 +++-
 sc/source/core/data/document.cxx     |    7 +-
 sc/source/ui/inc/drawview.hxx        |    4 +
 sc/source/ui/view/drawview.cxx       |    8 ++
 sd/inc/undo/undomanager.hxx          |   10 +--
 sd/source/core/undo/undomanager.cxx  |    8 +-
 sd/source/ui/view/drviewse.cxx       |    5 -
 svx/Library_svxcore.mk               |    1 
 svx/source/svdraw/sdrundomanager.cxx |  116 +++++++++++++++++++++++++++++++++++
 svx/source/svdraw/svdedxv.cxx        |  106 +++++++++++++++++++++++++++++++
 sw/source/core/draw/dview.cxx        |   12 +++
 sw/source/core/inc/UndoManager.hxx   |    6 -
 sw/source/core/inc/dview.hxx         |    4 +
 sw/source/core/undo/docundo.cxx      |  109 +++++++++++++++++++-------------
 22 files changed, 478 insertions(+), 76 deletions(-)

New commits:
commit 4f298ece2f48d4a632ea50e0f287192f619cb586
Author: Armin Le Grand <alg at apache.org>
Date:   Thu Sep 6 10:38:22 2012 +0000

    Do not enable outliner when it was not before only for temporary undo disable
    
    (cherry picked from commit 68e5157012bc54ad4ce9bcd644cc163d5662ff67)
    
    Change-Id: I2cbdc2a228884dff8000206ced4a5d8930dd6339

diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx
index 6e74e28..43e0b69 100644
--- a/editeng/source/outliner/outliner.cxx
+++ b/editeng/source/outliner/outliner.cxx
@@ -230,10 +230,11 @@ void Outliner::Init( sal_uInt16 nMode )
 
     pEditEngine->SetControlWord( nCtrl );
 
+    const bool bWasUndoEnabled(IsUndoEnabled());
     EnableUndo(false);
     ImplInitDepth( 0, GetMinDepth(), sal_False );
     GetUndoManager().Clear();
-    EnableUndo(true);
+    EnableUndo(bWasUndoEnabled);
 }
 
 void Outliner::SetMaxDepth( sal_Int16 nDepth, sal_Bool bCheckParagraphs )
commit 75326909e5ec58f1ff030af8b35d70dafd036bba
Author: Armin Le Grand <alg at apache.org>
Date:   Fri Aug 10 13:33:02 2012 +0000

    Related: #i120515# do not create undo action when in Init()
    
    (cherry picked from commit 1c02bb1bd719e7e0a47fdcc7463f8c9cd5bbb101)
    
    Change-Id: I57cbc1a19f18d71a27fb87086375b22755443675

diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx
index c5fe66c..6e74e28 100644
--- a/editeng/source/outliner/outliner.cxx
+++ b/editeng/source/outliner/outliner.cxx
@@ -230,9 +230,10 @@ void Outliner::Init( sal_uInt16 nMode )
 
     pEditEngine->SetControlWord( nCtrl );
 
+    EnableUndo(false);
     ImplInitDepth( 0, GetMinDepth(), sal_False );
-
     GetUndoManager().Clear();
+    EnableUndo(true);
 }
 
 void Outliner::SetMaxDepth( sal_Int16 nDepth, sal_Bool bCheckParagraphs )
commit d7b7c9fdfe63deec26c420efc3ff1fd73c21bb27
Author: Armin Le Grand <alg at apache.org>
Date:   Fri Aug 10 13:30:31 2012 +0000

    Resolves: #i120515# Implemented and finetuned the enhanced Undo feature
    
    (see #i120498#) for sw
    
    (cherry picked from commit fb2580f1c8ae0cd1418c257823dc2d735607655f)
    
    Conflicts:
    	sw/source/core/draw/dview.cxx
    	sw/source/core/inc/UndoManager.hxx
    	sw/source/core/undo/docundo.cxx
    
    Change-Id: I9970377d66f1104448a2ee7e4fb1cf82bf559cd8

diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index 6cbd572..3d5f69d 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -22,6 +22,9 @@
 #include <svx/svdpagv.hxx>
 #include <svx/fmmodel.hxx>
 #include <sot/exchange.hxx>
+#include <svx/sdrundomanager.hxx>
+#include <editeng/outliner.hxx>
+#include <com/sun/star/embed/EmbedMisc.hpp>
 
 #include "swtypes.hxx"
 #include "pagefrm.hxx"
@@ -53,6 +56,7 @@
 // #i28701#
 #include <sortedobjs.hxx>
 #include <flyfrms.hxx>
+#include <UndoManager.hxx>
 
 using namespace com::sun::star;
 
@@ -952,4 +956,12 @@ void SwDrawView::DeleteMarked()
         pTmpRoot->EndAllAction();   //swmod 080218
 }
 
+// support enhanced text edit for draw objects
+SdrUndoManager* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const
+{
+    SwDoc* pDoc = Imp().GetShell()->GetDoc();
+
+    return pDoc ? dynamic_cast< SdrUndoManager* >(&(pDoc->GetUndoManager())) : 0;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx
index 14696b3..0db1826 100644
--- a/sw/source/core/inc/UndoManager.hxx
+++ b/sw/source/core/inc/UndoManager.hxx
@@ -22,7 +22,7 @@
 
 #include <IDocumentUndoRedo.hxx>
 #include <memory>
-#include <svl/undo.hxx>
+#include <svx/sdrundomanager.hxx>
 
 class IDocumentDrawModelAccess;
 class IDocumentRedlineAccess;
@@ -32,7 +32,7 @@ namespace sw {
 
 class UndoManager
     : public IDocumentUndoRedo
-    , public SfxUndoManager
+    , public SdrUndoManager
 {
 public:
     UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
@@ -102,7 +102,7 @@ private:
     bool impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo);
 
     // UGLY: should not be called
-    using SfxUndoManager::Repeat;
+    using SdrUndoManager::Repeat;
 };
 
 } // namespace sw
diff --git a/sw/source/core/inc/dview.hxx b/sw/source/core/inc/dview.hxx
index e722be6..66aa2c3 100644
--- a/sw/source/core/inc/dview.hxx
+++ b/sw/source/core/inc/dview.hxx
@@ -26,6 +26,7 @@ class SwViewImp;
 class SwFrm;
 class SwFlyFrm;
 class SwAnchoredObject;
+class SdrUndoManager;
 
 class SwDrawView : public FmFormView
 {
@@ -74,6 +75,9 @@ protected:
     using FmFormView::CheckSingleSdrObjectHit;
     virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const;
 
+    // support enhanced text edit for draw objects
+    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const;
+
 public:
     SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice* pOutDev=NULL );
 
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
index f38cd4c..79ad862 100644
--- a/sw/source/core/undo/docundo.cxx
+++ b/sw/source/core/undo/docundo.cxx
@@ -65,7 +65,7 @@ UndoManager::UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
     OSL_ASSERT(m_pUndoNodes.get());
     // writer expects it to be disabled initially
     // Undo is enabled by SwEditShell constructor
-    SfxUndoManager::EnableUndo(false);
+    SdrUndoManager::EnableUndo(false);
 }
 SAL_WNODEPRECATED_DECLARATIONS_POP
 
@@ -86,18 +86,28 @@ bool UndoManager::IsUndoNodes(SwNodes const& rNodes) const
 
 void UndoManager::DoUndo(bool const bDoUndo)
 {
-    EnableUndo(bDoUndo);
-
-    SdrModel *const pSdrModel = m_rDrawModelAccess.GetDrawModel();
-    if( pSdrModel )
+    if(!isTextEditActive())
     {
-        pSdrModel->EnableUndo(bDoUndo);
+        EnableUndo(bDoUndo);
+
+        SdrModel *const pSdrModel = m_rDrawModelAccess.GetDrawModel();
+        if( pSdrModel )
+        {
+            pSdrModel->EnableUndo(bDoUndo);
+        }
     }
 }
 
 bool UndoManager::DoesUndo() const
 {
-    return IsUndoEnabled();
+    if(isTextEditActive())
+    {
+        return false;
+    }
+    else
+    {
+        return IsUndoEnabled();
+    }
 }
 
 void UndoManager::DoGroupUndo(bool const bDoUndo)
@@ -156,11 +166,11 @@ void UndoManager::UnLockUndoNoModifiedPosition()
 
 SwUndo* UndoManager::GetLastUndo()
 {
-    if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+    if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
     {
         return 0;
     }
-    SfxUndoAction *const pAction( SfxUndoManager::GetUndoAction(0) );
+    SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
     return dynamic_cast<SwUndo*>(pAction);
 }
 
@@ -171,14 +181,14 @@ void UndoManager::AppendUndo(SwUndo *const pUndo)
 
 void UndoManager::ClearRedo()
 {
-    return SfxUndoManager::ImplClearRedo_NoLock(TopLevel);
+    return SdrUndoManager::ImplClearRedo_NoLock(TopLevel);
 }
 
 void UndoManager::DelAllUndoObj()
 {
     ::sw::UndoGuard const undoGuard(*this);
 
-    SfxUndoManager::ClearAllLevels();
+    SdrUndoManager::ClearAllLevels();
 
     m_UndoSaveMark = MARK_INVALID;
 }
@@ -207,7 +217,7 @@ UndoManager::StartUndo(SwUndoId const i_eUndoId,
         comment = pRewriter->Apply(comment);
     }
 
-    SfxUndoManager::EnterListAction(comment, comment, eUndoId);
+    SdrUndoManager::EnterListAction(comment, comment, eUndoId);
 
     return eUndoId;
 }
@@ -227,8 +237,8 @@ UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
                 "EndUndo(): no Undo ID, but rewriter given?");
 
     SfxUndoAction *const pLastUndo(
-        (0 == SfxUndoManager::GetUndoActionCount(CurrentLevel))
-            ? 0 : SfxUndoManager::GetUndoAction(0) );
+        (0 == SdrUndoManager::GetUndoActionCount(CurrentLevel))
+            ? 0 : SdrUndoManager::GetUndoAction(0) );
 
     int const nCount = LeaveListAction();
 
@@ -236,7 +246,7 @@ UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
     {
         OSL_ASSERT(pLastUndo);
         OSL_ASSERT(UNDO_START != eUndoId);
-        SfxUndoAction *const pUndoAction(SfxUndoManager::GetUndoAction(0));
+        SfxUndoAction *const pUndoAction(SdrUndoManager::GetUndoAction(0));
         SfxListUndoAction *const pListAction(
             dynamic_cast<SfxListUndoAction*>(pUndoAction));
         OSL_ASSERT(pListAction);
@@ -283,12 +293,13 @@ UndoManager::GetLastUndoInfo(
 {
     // this is actually expected to work on the current level,
     // but that was really not obvious from the previous implementation...
-    if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+    if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
     {
         return false;
     }
 
-    SfxUndoAction *const pAction( SfxUndoManager::GetUndoAction(0) );
+    SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
+
     if (o_pStr)
     {
         *o_pStr = pAction->GetComment();
@@ -304,15 +315,15 @@ UndoManager::GetLastUndoInfo(
 
 SwUndoComments_t UndoManager::GetUndoComments() const
 {
-    OSL_ENSURE(!SfxUndoManager::IsInListAction(),
+    OSL_ENSURE(!SdrUndoManager::IsInListAction(),
             "GetUndoComments() called while in list action?");
 
     SwUndoComments_t ret;
-    sal_uInt16 const nUndoCount(SfxUndoManager::GetUndoActionCount(TopLevel));
+    sal_uInt16 const nUndoCount(SdrUndoManager::GetUndoActionCount(TopLevel));
     for (sal_uInt16 n = 0; n < nUndoCount; ++n)
     {
         OUString const comment(
-                SfxUndoManager::GetUndoActionComment(n, TopLevel));
+                SdrUndoManager::GetUndoActionComment(n, TopLevel));
         ret.push_back(comment);
     }
 
@@ -323,14 +334,14 @@ SwUndoComments_t UndoManager::GetUndoComments() const
 /**************** REDO ******************/
 bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr) const
 {
-    if (!SfxUndoManager::GetRedoActionCount(CurrentLevel))
+    if (!SdrUndoManager::GetRedoActionCount(CurrentLevel))
     {
         return false;
     }
 
     if (o_pStr)
     {
-        *o_pStr = SfxUndoManager::GetRedoActionComment(0, CurrentLevel);
+        *o_pStr = SdrUndoManager::GetRedoActionComment(0, CurrentLevel);
     }
 
     return true;
@@ -339,15 +350,15 @@ bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr) const
 
 SwUndoComments_t UndoManager::GetRedoComments() const
 {
-    OSL_ENSURE(!SfxUndoManager::IsInListAction(),
+    OSL_ENSURE(!SdrUndoManager::IsInListAction(),
             "GetRedoComments() called while in list action?");
 
     SwUndoComments_t ret;
-    sal_uInt16 const nRedoCount(SfxUndoManager::GetRedoActionCount(TopLevel));
+    sal_uInt16 const nRedoCount(SdrUndoManager::GetRedoActionCount(TopLevel));
     for (sal_uInt16 n = 0; n < nRedoCount; ++n)
     {
         OUString const comment(
-                SfxUndoManager::GetRedoActionComment(n, TopLevel));
+                SdrUndoManager::GetRedoActionComment(n, TopLevel));
         ret.push_back(comment);
     }
 
@@ -373,19 +384,19 @@ SwUndoId UndoManager::GetRepeatInfo(OUString *const o_pStr) const
 
 SwUndo * UndoManager::RemoveLastUndo()
 {
-    if (SfxUndoManager::GetRedoActionCount(CurrentLevel) ||
-        SfxUndoManager::GetRedoActionCount(TopLevel))
+    if (SdrUndoManager::GetRedoActionCount(CurrentLevel) ||
+        SdrUndoManager::GetRedoActionCount(TopLevel))
     {
         OSL_ENSURE(false, "RemoveLastUndoAction(): there are Redo actions?");
         return 0;
     }
-    if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+    if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
     {
         OSL_ENSURE(false, "RemoveLastUndoAction(): no Undo actions");
         return 0;
     }
     SfxUndoAction *const pLastUndo(GetUndoAction(0));
-    SfxUndoManager::RemoveLastUndoAction();
+    SdrUndoManager::RemoveLastUndoAction();
     return dynamic_cast<SwUndo *>(pLastUndo);
 }
 
@@ -393,9 +404,9 @@ SwUndo * UndoManager::RemoveLastUndo()
 
 void UndoManager::EnableUndo(bool bEnable)
 {
-    // SfxUndoManager does not have a counter anymore, but reverted to the old behavior of
+    // SdrUndoManager does not have a counter anymore, but reverted to the old behavior of
     // having a simple boolean flag for locking. So, simply forward.
-    SfxUndoManager::EnableUndo(bEnable);
+    SdrUndoManager::EnableUndo(bEnable);
 }
 
 void UndoManager::AddUndoAction(SfxUndoAction *pAction, sal_Bool bTryMerge)
@@ -408,7 +419,7 @@ void UndoManager::AddUndoAction(SfxUndoAction *pAction, sal_Bool bTryMerge)
             pUndo->SetRedlineMode( m_rRedlineAccess.GetRedlineMode() );
         }
     }
-    SfxUndoManager::AddUndoAction(pAction, bTryMerge);
+    SdrUndoManager::AddUndoAction(pAction, bTryMerge);
     // if the undo nodes array is too large, delete some actions
     while (UNDO_ACTION_LIMIT < GetUndoNodes().Count())
     {
@@ -473,17 +484,17 @@ bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)
     // N.B. these may throw!
     if (UNDO == undoOrRedo)
     {
-        bRet = SfxUndoManager::UndoWithContext(context);
+        bRet = SdrUndoManager::UndoWithContext(context);
     }
     else
     {
-        bRet = SfxUndoManager::RedoWithContext(context);
+        bRet = SdrUndoManager::RedoWithContext(context);
     }
 
     if (bRet)
     {
         // if we are at the "last save" position, the document is not modified
-        if (SfxUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
+        if (SdrUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
         {
             m_rState.ResetModified();
         }
@@ -500,31 +511,43 @@ bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)
 
 sal_Bool UndoManager::Undo()
 {
-    bool const bRet = impl_DoUndoRedo(UNDO);
-    return bRet;
+    if(isTextEditActive())
+    {
+        return SdrUndoManager::Undo();
+    }
+    else
+    {
+        return impl_DoUndoRedo(UNDO);
+    }
 }
 
 sal_Bool UndoManager::Redo()
 {
-    bool const bRet = impl_DoUndoRedo(REDO);
-    return bRet;
+    if(isTextEditActive())
+    {
+        return SdrUndoManager::Redo();
+    }
+    else
+    {
+        return impl_DoUndoRedo(REDO);
+    }
 }
 
-/** N.B.: this does _not_ call SfxUndoManager::Repeat because it is not
+/** N.B.: this does _not_ call SdrUndoManager::Repeat because it is not
           possible to wrap a list action around it:
-          calling EnterListAction here will cause SfxUndoManager::Repeat
+          calling EnterListAction here will cause SdrUndoManager::Repeat
           to repeat the list action!
  */
 bool
 UndoManager::Repeat(::sw::RepeatContext & rContext,
         sal_uInt16 const nRepeatCount)
 {
-    if (SfxUndoManager::IsInListAction())
+    if (SdrUndoManager::IsInListAction())
     {
         OSL_ENSURE(false, "repeat in open list action???");
         return false;
     }
-    if (!SfxUndoManager::GetUndoActionCount(TopLevel))
+    if (!SdrUndoManager::GetUndoActionCount(TopLevel))
     {
         return false;
     }
commit c726a1b12c9fdc91f32e6bed4d6dbd1edf73f9f8
Author: Armin Le Grand <alg at apache.org>
Date:   Fri Aug 10 13:27:36 2012 +0000

    Related: #i120515# Implemented and finetuned the enhanced Undo feature
    
    (see #i120498#) for sc
    
    (cherry picked from commit 472c175d1bb809db1dc997d9712d6ecb3fbe731c)
    
    Conflicts:
    	sc/source/core/data/document.cxx
    	sc/source/ui/view/drawview.cxx
    
    Change-Id: I4ae171807b80e3f6c9f44028bd04dfac9338e627

diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 34ae049..9a9201c 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -25,6 +25,7 @@
 #include "editeng/editobj.hxx"
 #include <svx/pageitem.hxx>
 #include <editeng/editeng.hxx>
+#include <svx/sdrundomanager.hxx>
 #include <svx/svditer.hxx>
 #include <svx/svdpage.hxx>
 #include <svx/svdocapt.hxx>
@@ -5869,7 +5870,11 @@ bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
 SfxUndoManager* ScDocument::GetUndoManager()
 {
     if (!mpUndoManager)
-        mpUndoManager = new SfxUndoManager;
+    {
+        // to support enhanced text edit for draw objects, use an SdrUndoManager
+        mpUndoManager = new SdrUndoManager;
+    }
+
     return mpUndoManager;
 }
 
diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx
index f5de693..ab6f9c6 100644
--- a/sc/source/ui/inc/drawview.hxx
+++ b/sc/source/ui/inc/drawview.hxx
@@ -29,6 +29,7 @@ namespace com { namespace sun { namespace star { namespace datatransfer { class
 class ScDocument;
 class ScViewData;
 class ScDrawObjData;
+class SdrUndoManager;
 
 class ScDrawView: public FmFormView
 {
@@ -53,6 +54,9 @@ protected:
 
     void ImplClearCalcDropMarker();
 
+    // support enhanced text edit for draw objects
+    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const;
+
 public:
                     ScDrawView( OutputDevice* pOut, ScViewData* pData );
     virtual         ~ScDrawView();
diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx
index a51c66a..88395f4 100644
--- a/sc/source/ui/view/drawview.cxx
+++ b/sc/source/ui/view/drawview.cxx
@@ -33,6 +33,7 @@
 #include <svx/sdrpaintwindow.hxx>
 #include <sfx2/bindings.hxx>
 #include <sfx2/viewfrm.hxx>
+#include <svx/sdrundomanager.hxx>
 
 #include "drawview.hxx"
 #include "global.hxx"
@@ -849,4 +850,11 @@ void ScDrawView::SyncForGrid( SdrObject* pObj )
         pObj->SetGridOffset( aGridOff );
     }
 }
+
+// support enhanced text edit for draw objects
+SdrUndoManager* ScDrawView::getSdrUndoManagerForEnhancedTextEdit() const
+{
+    return pDoc ? dynamic_cast< SdrUndoManager* >(pDoc->GetUndoManager()) : 0;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 71e37a5c3886ff35d7240a9fb6b30aceec057782
Author: Armin Le Grand <alg at apache.org>
Date:   Fri Aug 10 13:19:02 2012 +0000

    Related: #i120498# fixed error with half text edit undone
    
    extended as preparation for #i120515#
    
    (cherry picked from commit ddd9492911585313faf1769f88323a8421bf93db)
    
    Conflicts:
    	svx/inc/svx/sdrundomanager.hxx
    	svx/inc/svx/svdedxv.hxx
    
    Change-Id: I50272a5719ee6e6a1a7fd1bafe9d94f480b1dbf5

diff --git a/include/svx/sdrundomanager.hxx b/include/svx/sdrundomanager.hxx
index 0d899f6..860742f 100644
--- a/include/svx/sdrundomanager.hxx
+++ b/include/svx/sdrundomanager.hxx
@@ -33,6 +33,11 @@ private:
 
     Link            maEndTextEditHdl;
     SfxUndoAction*  mpLastUndoActionBeforeTextEdit;
+    bool            mbEndTextEditTriggeredFromUndo;
+
+protected:
+    // call to check for TextEdit active
+    bool isTextEditActive() const;
 
 public:
     SdrUndoManager(sal_uInt16 nMaxUndoActionCount = 20);
@@ -47,6 +52,11 @@ public:
     // reset all text edit actions will be removed from this undo manager to
     // restore the state before activation
     void SetEndTextEditHdl(const Link& rLink);
+
+    // check from outside if we are inside a callback for ending text edit. This
+    // is needed to detect inside end text edit if it is a regular one or triggered
+    // by a last undo during text edit
+    bool isEndTextEditTriggeredFromUndo() { return mbEndTextEditTriggeredFromUndo; }
 };
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index c0d8a2a..0bdad27 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -116,6 +116,12 @@ private:
     SVX_DLLPRIVATE void ImpClearVars();
 
 protected:
+    // central method to get an SdrUndoManager for enhanced TextEdit. Default will
+    // try to return a dynamic_casted GetModel()->GetSdrUndoManager(). Applications
+    // which want to use this feature will need to overload this virtual method,
+    // provide their document UndoManager and derive it from SdrUndoManager.
+    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const;
+
     OutlinerView* ImpFindOutlinerView(Window* pWin) const;
 
     // Eine neue OutlinerView auf dem Heap anlegen und alle erforderlichen Parameter setzen.
diff --git a/svx/source/svdraw/sdrundomanager.cxx b/svx/source/svdraw/sdrundomanager.cxx
index 88e0c6c..c28654c 100644
--- a/svx/source/svdraw/sdrundomanager.cxx
+++ b/svx/source/svdraw/sdrundomanager.cxx
@@ -23,7 +23,8 @@
 SdrUndoManager::SdrUndoManager(sal_uInt16 nMaxUndoActionCount)
 :   EditUndoManager(nMaxUndoActionCount),
     maEndTextEditHdl(),
-    mpLastUndoActionBeforeTextEdit(0)
+    mpLastUndoActionBeforeTextEdit(0),
+    mbEndTextEditTriggeredFromUndo(false)
 {
 }
 
@@ -33,10 +34,10 @@ SdrUndoManager::~SdrUndoManager()
 
 sal_Bool SdrUndoManager::Undo()
 {
-    sal_Bool bRetval(sal_False);
-
-    if(maEndTextEditHdl.IsSet())
+    if(isTextEditActive())
     {
+        sal_Bool bRetval(sal_False);
+
         // we are in text edit mode
         if(GetUndoActionCount() && mpLastUndoActionBeforeTextEdit != GetUndoAction(0))
         {
@@ -46,24 +47,25 @@ sal_Bool SdrUndoManager::Undo()
         else
         {
             // no more text edit undo, end text edit
+            mbEndTextEditTriggeredFromUndo = true;
             maEndTextEditHdl.Call(this);
+            mbEndTextEditTriggeredFromUndo = false;
         }
-    }
 
-    if(!bRetval && GetUndoActionCount())
+        return bRetval;
+    }
+    else
     {
         // no undo triggered up to now, trigger local one
-        bRetval = SfxUndoManager::Undo();
+        return SfxUndoManager::Undo();
     }
-
-    return bRetval;
 }
 
 sal_Bool SdrUndoManager::Redo()
 {
     sal_Bool bRetval(sal_False);
 
-    if(maEndTextEditHdl.IsSet())
+    if(isTextEditActive())
     {
         // we are in text edit mode
         bRetval = EditUndoManager::Redo();
@@ -82,7 +84,7 @@ void SdrUndoManager::SetEndTextEditHdl(const Link& rLink)
 {
     maEndTextEditHdl = rLink;
 
-    if(maEndTextEditHdl.IsSet())
+    if(isTextEditActive())
     {
         // text edit start, remember last non-textedit action for later cleanup
         mpLastUndoActionBeforeTextEdit = GetUndoActionCount() ? GetUndoAction(0) : 0;
@@ -105,5 +107,10 @@ void SdrUndoManager::SetEndTextEditHdl(const Link& rLink)
     }
 }
 
+bool SdrUndoManager::isTextEditActive() const
+{
+    return maEndTextEditHdl.IsSet();
+}
+
 //////////////////////////////////////////////////////////////////////////////
 // eof
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 6a5e571..6d39a5b 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -526,6 +526,12 @@ IMPL_LINK(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, /*pUndoManager*/)
     return 0;
 }
 
+SdrUndoManager* SdrObjEditView::getSdrUndoManagerForEnhancedTextEdit() const
+{
+    // default returns registered UndoManager
+    return GetModel() ? dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager()) : 0;
+}
+
 sal_Bool SdrObjEditView::SdrBeginTextEdit(
     SdrObject* pObj, SdrPageView* pPV, Window* pWin,
     sal_Bool bIsNewObj, SdrOutliner* pGivenOutliner,
@@ -754,7 +760,7 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit(
 
             if(IsUndoEnabled())
             {
-                SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager());
+                SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit();
 
                 if(pSdrUndoManager)
                 {
@@ -763,7 +769,8 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit(
                     // it that text edit starts by setting a callback if it needs to end text edit mode.
                     if(mpOldTextEditUndoManager)
                     {
-                        // should not happen, delete it
+                        // should not happen, delete it since it was probably forgotten somewhere
+                        OSL_ENSURE(false, "Deleting forgotten old TextEditUndoManager, should be checked (!)");
                         delete mpOldTextEditUndoManager;
                         mpOldTextEditUndoManager = 0;
                     }
@@ -830,7 +837,8 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally)
     SdrOutliner*  pTEOutliner    =pTextEditOutliner;
     OutlinerView* pTEOutlinerView=pTextEditOutlinerView;
     Cursor*       pTECursorMerker=pTextEditCursorMerker;
-    SdrUndoManager* pExtraUndoEditUndoManager = 0;
+    SdrUndoManager* pUndoEditUndoManager = 0;
+    bool bNeedToUndoSavedRedoTextEdit(false);
 
     if(IsUndoEnabled() && GetModel() && pTEObj && pTEOutliner)
     {
@@ -841,18 +849,26 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally)
         if(pOriginal)
         {
             // check if we got back our document undo manager
-            SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager());
+            SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit();
 
             if(pSdrUndoManager && dynamic_cast< SdrUndoManager* >(pOriginal) == pSdrUndoManager)
             {
-                // We are ending text edit; execute all redos to create a complete text change
-                // undo action for the redo buffer. Also mark this state when at least one redo was
-                // executed; the created TextChange needs to be undone plus the first real undo
-                // outside the text edit changes
-                while(pSdrUndoManager->GetRedoActionCount())
+                if(pSdrUndoManager->isEndTextEditTriggeredFromUndo())
                 {
-                    pExtraUndoEditUndoManager = pSdrUndoManager;
-                    pSdrUndoManager->Redo();
+                    // remember the UndoManager where missing Undos have to be triggered after end
+                    // text edit. When the undo had triggered the end text edit, the original action
+                    // which had to be undone originally is not yet undone.
+                    pUndoEditUndoManager = pSdrUndoManager;
+
+                    // We are ending text edit; if text edit was triggered from undo, execute all redos
+                    // to create a complete text change undo action for the redo buffer. Also mark this
+                    // state when at least one redo was executed; the created extra TextChange needs to
+                    // be undone in addition to the first real undo outside the text edit changes
+                    while(pSdrUndoManager->GetRedoActionCount())
+                    {
+                        bNeedToUndoSavedRedoTextEdit = true;
+                        pSdrUndoManager->Redo();
+                    }
                 }
 
                 // reset the callback link and let the undo manager cleanup all text edit
@@ -1059,12 +1075,19 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally)
         ((SfxBroadcaster*)pTEObj->GetBroadcaster())->Broadcast(aHint);
     }
 
-    if(pExtraUndoEditUndoManager)
+    if(pUndoEditUndoManager)
     {
-        // undo the text edit action since it was created as part of a EndTextEdit
-        // callback from undo itself. This needs to be done after the call to
-        // FmFormView::SdrEndTextEdit since it gets created there
-        pExtraUndoEditUndoManager->Undo();
+        if(bNeedToUndoSavedRedoTextEdit)
+        {
+            // undo the text edit action since it was created as part of an EndTextEdit
+            // callback from undo itself. This needs to be done after the call to
+            // FmFormView::SdrEndTextEdit since it gets created there
+            pUndoEditUndoManager->Undo();
+        }
+
+        // trigger the Undo which was not executed, but lead to this
+        // end text edit
+        pUndoEditUndoManager->Undo();
     }
 
     return eRet;
commit 12a4200e8ff7f045efcc7e9d15a24b15b248c437
Author: Armin Le Grand <alg at apache.org>
Date:   Thu Aug 9 08:42:27 2012 +0000

    Related: #i120498# Enhanced Undo/Redo and user experience...
    
    when editing texts in graphic objects and/or tables
    
    (cherry picked from commit a096725779b210c7a2706e72596fd7c80e049fdd)
    
    Conflicts:
    	editeng/inc/editeng/editeng.hxx
    	editeng/inc/editeng/editund2.hxx
    	editeng/inc/editeng/outliner.hxx
    	editeng/source/editeng/editundo.cxx
    	editeng/source/editeng/impedit.hxx
    	editeng/source/outliner/outliner.cxx
    	sd/source/core/undo/undomanager.cxx
    	sd/source/ui/view/drviewse.cxx
    	svx/Library_svxcore.mk
    	svx/Package_inc.mk
    	svx/inc/svx/svdedxv.hxx
    	svx/source/svdraw/svdedxv.cxx
    
    Change-Id: I40e3ef2dff681f9b6f2f6b5d35507071f8110533
    
    Comment unused variable pNewEditUndoManager to silence the compiler
    
    (cherry picked from commit 568655083af7830e7b9edf56ef862ddf9a99003b)
    
    Change-Id: Ib7179ee6c34ce03a75942978831c3a55968f161f
    
    Removed unused variable
    
    (cherry picked from commit 0bbde4414badfd40234de4a4c9f750194f5d1d5e)
    
    Change-Id: I39e7f25426e8e7d1367102d603b0f6c84d96622f

diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index 1edc5ae..9bf29e5 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -134,6 +134,12 @@ sal_Bool EditEngine::IsInUndo()
     return pImpEditEngine->GetUndoManager();
 }
 
+::svl::IUndoManager* EditEngine::SetUndoManager(::svl::IUndoManager* pNew)
+{
+    DBG_CHKTHIS( EditEngine, 0 );
+    return pImpEditEngine->SetUndoManager(pNew);
+}
+
 void EditEngine::UndoActionStart( sal_uInt16 nId )
 {
     DBG_CHKTHIS( EditEngine, 0 );
diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx
index 2f548e3..dfc8df1 100644
--- a/editeng/source/editeng/editundo.cxx
+++ b/editeng/source/editeng/editundo.cxx
@@ -37,11 +37,20 @@ static void lcl_DoSetSelection( EditView* pView, sal_uInt16 nPara )
     pView->GetImpEditView()->SetEditSelection( aSel );
 }
 
-EditUndoManager::EditUndoManager(EditEngine* pEE) : mpEditEngine(pEE) {}
+EditUndoManager::EditUndoManager(sal_uInt16 nMaxUndoActionCount )
+:   SfxUndoManager(nMaxUndoActionCount),
+    mpEditEngine(0)
+{
+}
+
+void EditUndoManager::SetEditEngine(EditEngine* pNew)
+{
+    mpEditEngine = pNew;
+}
 
 sal_Bool EditUndoManager::Undo()
 {
-    if ( GetUndoActionCount() == 0 )
+    if ( !mpEditEngine || GetUndoActionCount() == 0 )
         return sal_False;
 
     DBG_ASSERT( mpEditEngine->GetActiveView(), "Active View?" );
@@ -76,7 +85,7 @@ sal_Bool EditUndoManager::Undo()
 
 sal_Bool EditUndoManager::Redo()
 {
-    if ( GetRedoActionCount() == 0 )
+    if ( !mpEditEngine || GetRedoActionCount() == 0 )
         return sal_False;
 
     DBG_ASSERT( mpEditEngine->GetActiveView(), "Active View?" );
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index b6dbcdc..55b98f1 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -681,6 +681,7 @@ public:
                             ~ImpEditEngine();
 
     inline EditUndoManager& GetUndoManager();
+    inline ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew);
 
     void                    SetUpdateMode( bool bUp, EditView* pCurView = 0, sal_Bool bForceUpdate = sal_False );
     bool                    GetUpdateMode() const   { return bUpdate; }
@@ -1072,10 +1073,32 @@ inline void ImpEditEngine::IdleFormatAndUpdate( EditView* pCurView )
 inline EditUndoManager& ImpEditEngine::GetUndoManager()
 {
     if ( !pUndoManager )
-        pUndoManager = new EditUndoManager(pEditEngine);
+    {
+        pUndoManager = new EditUndoManager();
+        pUndoManager->SetEditEngine(pEditEngine);
+    }
     return *pUndoManager;
 }
 
+inline ::svl::IUndoManager* ImpEditEngine::SetUndoManager(::svl::IUndoManager* pNew)
+{
+    ::svl::IUndoManager* pRetval = pUndoManager;
+
+    if(pUndoManager)
+    {
+        pUndoManager->SetEditEngine(0);
+    }
+
+    pUndoManager = dynamic_cast< EditUndoManager* >(pNew);
+
+    if(pUndoManager)
+    {
+        pUndoManager->SetEditEngine(pEditEngine);
+    }
+
+    return pRetval;
+}
+
 inline const ParaPortion* ImpEditEngine::FindParaPortion( const ContentNode* pNode ) const
 {
     sal_Int32 nPos = aEditDoc.GetPos( pNode );
diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx
index c8971da..c5fe66c 100644
--- a/editeng/source/outliner/outliner.cxx
+++ b/editeng/source/outliner/outliner.cxx
@@ -1218,6 +1218,12 @@ void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara )
     return pEditEngine->GetUndoManager();
 }
 
+::svl::IUndoManager* Outliner::SetUndoManager(::svl::IUndoManager* pNew)
+{
+    DBG_CHKTHIS(Outliner,0);
+    return pEditEngine->SetUndoManager(pNew);
+}
+
 void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount )
 {
     DBG_CHKTHIS(Outliner,0);
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index e55dbac..a3ba78d 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -303,8 +303,8 @@ public:
 
     void            ShowParagraph( sal_Int32 nParagraph, sal_Bool bShow = sal_True );
 
-    ::svl::IUndoManager&
-                    GetUndoManager();
+    ::svl::IUndoManager& GetUndoManager();
+    ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew);
     void            UndoActionStart( sal_uInt16 nId );
     void            UndoActionStart(sal_uInt16 nId, const ESelection& rSel);
     void            UndoActionEnd( sal_uInt16 nId );
diff --git a/include/editeng/editund2.hxx b/include/editeng/editund2.hxx
index 2312aee..b810628 100644
--- a/include/editeng/editund2.hxx
+++ b/include/editeng/editund2.hxx
@@ -25,14 +25,16 @@
 
 class EditEngine;
 
-class EDITENG_DLLPRIVATE EditUndoManager : public SfxUndoManager
+class EDITENG_DLLPUBLIC EditUndoManager : public SfxUndoManager
 {
     using SfxUndoManager::Undo;
     using SfxUndoManager::Redo;
+    friend class ImpEditEngine;
 
     EditEngine* mpEditEngine;
+    void SetEditEngine(EditEngine* pNew);
 public:
-    EditUndoManager(EditEngine* pEE);
+    EditUndoManager(sal_uInt16 nMaxUndoActionCount = 20);
 
     virtual sal_Bool Undo();
     virtual sal_Bool Redo();
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index 9848b6a..8b4b92e 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -891,8 +891,8 @@ public:
 
     sal_uLong           Read( SvStream& rInput, const String& rBaseURL, sal_uInt16, SvKeyValueIterator* pHTTPHeaderAttrs = NULL );
 
-    ::svl::IUndoManager&
-                    GetUndoManager();
+    ::svl::IUndoManager& GetUndoManager();
+    ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew);
 
     void            QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel );
     void            QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel );
diff --git a/include/svx/sdrundomanager.hxx b/include/svx/sdrundomanager.hxx
new file mode 100644
index 0000000..0d899f6
--- /dev/null
+++ b/include/svx/sdrundomanager.hxx
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef _SDR_UNDOMANAGER_HXX
+#define _SDR_UNDOMANAGER_HXX
+
+#include "svx/svxdllapi.h"
+#include <sal/types.h>
+#include <editeng/editund2.hxx>
+#include <tools/link.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SVX_DLLPUBLIC SdrUndoManager : public EditUndoManager
+{
+private:
+    using EditUndoManager::Undo;
+    using EditUndoManager::Redo;
+
+    Link            maEndTextEditHdl;
+    SfxUndoAction*  mpLastUndoActionBeforeTextEdit;
+
+public:
+    SdrUndoManager(sal_uInt16 nMaxUndoActionCount = 20);
+    virtual ~SdrUndoManager();
+
+    /// react depending on edit mode and if no more undo is possible
+    virtual sal_Bool Undo();
+    virtual sal_Bool Redo();
+
+    // Call for the view which starts the interactive text edit. Use link to
+    // activate (start text edit) and empty link to reset (end text edit). On
+    // reset all text edit actions will be removed from this undo manager to
+    // restore the state before activation
+    void SetEndTextEditHdl(const Link& rLink);
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif //_SDR_UNDOMANAGER_HXX
+// eof
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index f1ec629..c0d8a2a 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -38,6 +38,7 @@ class EditStatus;
 class EditFieldInfo;
 class ImpSdrEditPara;
 struct PasteOrDropInfos;
+class SdrUndoManager;
 
 namespace com { namespace sun { namespace star { namespace uno {
     class Any;
@@ -97,7 +98,7 @@ protected:
     Link                        aOldCalcFieldValueLink; // Zum rufen des alten Handlers
     Point                       aMacroDownPos;
 
-    sal_uInt16                      nMacroTol;
+    sal_uInt16                  nMacroTol;
 
     unsigned                    bTextEditDontDelete : 1;   // Outliner und View bei SdrEndTextEdit nicht deleten (f. Rechtschreibpruefung)
     unsigned                    bTextEditOnlyOneView : 1;  // Nur eine OutlinerView (f. Rechtschreibpruefung)
@@ -110,6 +111,8 @@ protected:
     rtl::Reference< sdr::SelectionController > mxLastSelectionController;
 
 private:
+    ::svl::IUndoManager* mpOldTextEditUndoManager;
+
     SVX_DLLPRIVATE void ImpClearVars();
 
 protected:
@@ -130,6 +133,9 @@ protected:
     DECL_LINK(ImpOutlinerStatusEventHdl,EditStatus*);
     DECL_LINK(ImpOutlinerCalcFieldValueHdl,EditFieldInfo*);
 
+    // link for EndTextEditHdl
+    DECL_LINK(EndTextEditHdl, SdrUndoManager*);
+
     void ImpMacroUp(const Point& rUpPos);
     void ImpMacroDown(const Point& rDownPos);
 
diff --git a/sd/inc/undo/undomanager.hxx b/sd/inc/undo/undomanager.hxx
index 3aa9efd..14fa2d9 100644
--- a/sd/inc/undo/undomanager.hxx
+++ b/sd/inc/undo/undomanager.hxx
@@ -20,13 +20,13 @@
 #ifndef _SD_UNDOMANAGER_HXX
 #define _SD_UNDOMANAGER_HXX
 
-#include "misc/scopelock.hxx"
-#include <svl/undo.hxx>
+#include <misc/scopelock.hxx>
+#include <svx/sdrundomanager.hxx>
 
 namespace sd
 {
 
-class UndoManager : public SfxUndoManager
+class UndoManager : public SdrUndoManager
 {
 public:
     UndoManager( sal_uInt16 nMaxUndoActionCount = 20 );
@@ -40,8 +40,8 @@ public:
     void SetLinkedUndoManager (::svl::IUndoManager* pLinkedUndoManager);
 
 private:
-    using SfxUndoManager::Undo;
-    using SfxUndoManager::Redo;
+    using SdrUndoManager::Undo;
+    using SdrUndoManager::Redo;
 
     /** Used when the outline view is visible as a last resort to
         synchronize the undo managers.
diff --git a/sd/source/core/undo/undomanager.cxx b/sd/source/core/undo/undomanager.cxx
index 35d91cc..a2fc653 100644
--- a/sd/source/core/undo/undomanager.cxx
+++ b/sd/source/core/undo/undomanager.cxx
@@ -17,12 +17,12 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include "undo/undomanager.hxx"
+#include <undo/undomanager.hxx>
 
 using namespace sd;
 
 UndoManager::UndoManager( sal_uInt16 nMaxUndoActionCount /* = 20 */ )
-: SfxUndoManager( nMaxUndoActionCount )
+: SdrUndoManager( nMaxUndoActionCount )
 , mpLinkedUndoManager(NULL)
 {
 }
@@ -32,7 +32,7 @@ void UndoManager::EnterListAction(const OUString &rComment, const OUString& rRep
     if( !IsDoing() )
     {
         ClearLinkedRedoActions();
-        SfxUndoManager::EnterListAction( rComment, rRepeatComment, nId );
+        SdrUndoManager::EnterListAction( rComment, rRepeatComment, nId );
     }
 }
 
@@ -41,7 +41,7 @@ void UndoManager::AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg /* =
     if( !IsDoing() )
     {
         ClearLinkedRedoActions();
-        SfxUndoManager::AddUndoAction( pAction, bTryMerg );
+        SdrUndoManager::AddUndoAction( pAction, bTryMerg );
     }
     else
     {
diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx
index 36d8f78..6651519 100644
--- a/sd/source/ui/view/drviewse.cxx
+++ b/sd/source/ui/view/drviewse.cxx
@@ -625,11 +625,6 @@ void DrawViewShell::FuPermanent(SfxRequest& rReq)
     }
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// service routine for Undo/Redo implementation
-extern SfxUndoManager* ImpGetUndoManagerFromViewShell(DrawViewShell& rDViewShell);
-
-
 void DrawViewShell::FuSupport(SfxRequest& rReq)
 {
     if( rReq.GetSlot() == SID_STYLE_FAMILY && rReq.GetArgs())
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 94fbf16..21a03bf 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -254,6 +254,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
     svx/source/svdraw/sdrmasterpagedescriptor \
     svx/source/svdraw/sdrpagewindow \
     svx/source/svdraw/sdrpaintwindow \
+    svx/source/svdraw/sdrundomanager \
     svx/source/svdraw/selectioncontroller \
     svx/source/svdraw/svdattr \
     svx/source/svdraw/svdcrtv \
diff --git a/svx/source/svdraw/sdrundomanager.cxx b/svx/source/svdraw/sdrundomanager.cxx
new file mode 100644
index 0000000..88e0c6c
--- /dev/null
+++ b/svx/source/svdraw/sdrundomanager.cxx
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/sdrundomanager.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+SdrUndoManager::SdrUndoManager(sal_uInt16 nMaxUndoActionCount)
+:   EditUndoManager(nMaxUndoActionCount),
+    maEndTextEditHdl(),
+    mpLastUndoActionBeforeTextEdit(0)
+{
+}
+
+SdrUndoManager::~SdrUndoManager()
+{
+}
+
+sal_Bool SdrUndoManager::Undo()
+{
+    sal_Bool bRetval(sal_False);
+
+    if(maEndTextEditHdl.IsSet())
+    {
+        // we are in text edit mode
+        if(GetUndoActionCount() && mpLastUndoActionBeforeTextEdit != GetUndoAction(0))
+        {
+            // there is an undo action for text edit, trigger it
+            bRetval = EditUndoManager::Undo();
+        }
+        else
+        {
+            // no more text edit undo, end text edit
+            maEndTextEditHdl.Call(this);
+        }
+    }
+
+    if(!bRetval && GetUndoActionCount())
+    {
+        // no undo triggered up to now, trigger local one
+        bRetval = SfxUndoManager::Undo();
+    }
+
+    return bRetval;
+}
+
+sal_Bool SdrUndoManager::Redo()
+{
+    sal_Bool bRetval(sal_False);
+
+    if(maEndTextEditHdl.IsSet())
+    {
+        // we are in text edit mode
+        bRetval = EditUndoManager::Redo();
+    }
+
+    if(!bRetval)
+    {
+        // no redo triggered up to now, trigger local one
+        bRetval = SfxUndoManager::Redo();
+    }
+
+    return bRetval;
+}
+
+void SdrUndoManager::SetEndTextEditHdl(const Link& rLink)
+{
+    maEndTextEditHdl = rLink;
+
+    if(maEndTextEditHdl.IsSet())
+    {
+        // text edit start, remember last non-textedit action for later cleanup
+        mpLastUndoActionBeforeTextEdit = GetUndoActionCount() ? GetUndoAction(0) : 0;
+    }
+    else
+    {
+        // text edit ends, pop all textedit actions up to the remembered non-textedit action from the start
+        // to set back the UndoManager to the state before text edit started. If that action is already gone
+        // (due to being removed from the undo stack in the meantime), all need to be removed anyways
+        while(GetUndoActionCount() && mpLastUndoActionBeforeTextEdit != GetUndoAction(0))
+        {
+            RemoveLastUndoAction();
+        }
+
+        // urgently needed: RemoveLastUndoAction does NOT correct the Redo stack by itself (!)
+        ClearRedo();
+
+        // forget marker again
+        mpLastUndoActionBeforeTextEdit = 0;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 6134278..6a5e571 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -63,6 +63,7 @@
 #include <svtools/colorcfg.hxx>
 #include <vcl/svapp.hxx>
 #include <svx/sdrpaintwindow.hxx>
+#include <svx/sdrundomanager.hxx>
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -87,7 +88,8 @@ void SdrObjEditView::ImpClearVars()
 }
 
 SdrObjEditView::SdrObjEditView(SdrModel* pModel1, OutputDevice* pOut):
-    SdrGlueEditView(pModel1,pOut)
+    SdrGlueEditView(pModel1,pOut),
+    mpOldTextEditUndoManager(0)
 {
     ImpClearVars();
 }
@@ -95,8 +97,10 @@ SdrObjEditView::SdrObjEditView(SdrModel* pModel1, OutputDevice* pOut):
 SdrObjEditView::~SdrObjEditView()
 {
     pTextEditWin = NULL;            // so there's no ShowCursor in SdrEndTextEdit
-    if (IsTextEdit()) SdrEndTextEdit();
+    if (IsTextEdit())
+        SdrEndTextEdit();
     delete pTextEditOutliner;
+    delete mpOldTextEditUndoManager;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -516,6 +520,12 @@ IMPL_LINK(SdrObjEditView,ImpOutlinerCalcFieldValueHdl,EditFieldInfo*,pFI)
     return 0;
 }
 
+IMPL_LINK(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, /*pUndoManager*/)
+{
+    SdrEndTextEdit();
+    return 0;
+}
+
 sal_Bool SdrObjEditView::SdrBeginTextEdit(
     SdrObject* pObj, SdrPageView* pPV, Window* pWin,
     sal_Bool bIsNewObj, SdrOutliner* pGivenOutliner,
@@ -742,6 +752,31 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit(
             if( mxSelectionController.is() )
                 mxSelectionController->onSelectionHasChanged();
 
+            if(IsUndoEnabled())
+            {
+                SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager());
+
+                if(pSdrUndoManager)
+                {
+                    // we have an outliner, undo manager and it's an EditUndoManager, exchange
+                    // the document undo manager and the default one from the outliner and tell
+                    // it that text edit starts by setting a callback if it needs to end text edit mode.
+                    if(mpOldTextEditUndoManager)
+                    {
+                        // should not happen, delete it
+                        delete mpOldTextEditUndoManager;
+                        mpOldTextEditUndoManager = 0;
+                    }
+
+                    mpOldTextEditUndoManager = pTextEditOutliner->SetUndoManager(pSdrUndoManager);
+                    pSdrUndoManager->SetEndTextEditHdl(LINK(this, SdrObjEditView, EndTextEditHdl));
+                }
+                else
+                {
+                    OSL_ENSURE(false, "The document undo manager is not derived from SdrUndoManager (!)");
+                }
+            }
+
             return sal_True; // ran fine, let TextEdit run now
         }
         else
@@ -795,6 +830,42 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally)
     SdrOutliner*  pTEOutliner    =pTextEditOutliner;
     OutlinerView* pTEOutlinerView=pTextEditOutlinerView;
     Cursor*       pTECursorMerker=pTextEditCursorMerker;
+    SdrUndoManager* pExtraUndoEditUndoManager = 0;
+
+    if(IsUndoEnabled() && GetModel() && pTEObj && pTEOutliner)
+    {
+        // change back the UndoManager to the remembered original one
+        ::svl::IUndoManager* pOriginal = pTEOutliner->SetUndoManager(mpOldTextEditUndoManager);
+        mpOldTextEditUndoManager = 0;
+
+        if(pOriginal)
+        {
+            // check if we got back our document undo manager
+            SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager());
+
+            if(pSdrUndoManager && dynamic_cast< SdrUndoManager* >(pOriginal) == pSdrUndoManager)
+            {
+                // We are ending text edit; execute all redos to create a complete text change
+                // undo action for the redo buffer. Also mark this state when at least one redo was
+                // executed; the created TextChange needs to be undone plus the first real undo
+                // outside the text edit changes
+                while(pSdrUndoManager->GetRedoActionCount())
+                {
+                    pExtraUndoEditUndoManager = pSdrUndoManager;
+                    pSdrUndoManager->Redo();
+                }
+
+                // reset the callback link and let the undo manager cleanup all text edit
+                // undo actions to get the stack back to the form before the text edit
+                pSdrUndoManager->SetEndTextEditHdl(Link());
+            }
+            else
+            {
+                OSL_ENSURE(false, "´Got UndoManager back in SdrEndTextEdit which is NOT the expected document UndoManager (!)");
+                delete pOriginal;
+            }
+        }
+    }
 
     if( GetModel() && mxTextEditObj.is() )
     {
@@ -988,6 +1059,14 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally)
         ((SfxBroadcaster*)pTEObj->GetBroadcaster())->Broadcast(aHint);
     }
 
+    if(pExtraUndoEditUndoManager)
+    {
+        // undo the text edit action since it was created as part of a EndTextEdit
+        // callback from undo itself. This needs to be done after the call to
+        // FmFormView::SdrEndTextEdit since it gets created there
+        pExtraUndoEditUndoManager->Undo();
+    }
+
     return eRet;
 }
 
commit 64b07d99aa0b31b3d04519afe6afe0cdf36bcd6f
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue May 28 15:32:19 2013 +0100

    pause notifications while undoing to keep a11y out until we're done
    
    Block them together and announce after undoing that all is done.  This stops
    a11y trampling in before we're actually finished, querying for the new text,
    which unsets the invalid flags as the new layout is now up-to-date, but
    unfortunately results in the view not redrawing as the layout is apparently
    valid and doesn't need to be redrawn.
    
    To reproduce, enter a drawing rectangle in draw, enter some text, and (without
    leaving edit more) press ctrl-z. The text appears to not change. But the model
    has changed except the view didn't get to hear about it because a11y swooped in
    between that model change and the view checking to see if the model changed.
    And the format update there unsets the model-changed flag.
    
    Change-Id: If2552ef3680b9bd64a2e28a3e9cdbb9e2d45f329

diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 9b3a9e3..b6dbcdc 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -735,7 +735,14 @@ public:
 
     void                EnableUndo( bool bEnable );
     bool                IsUndoEnabled()         { return bUndoEnabled; }
-    void                SetUndoMode( bool b )   { bIsInUndo = b; }
+    void                SetUndoMode( bool b )
+    {
+        bIsInUndo = b;
+        if (bIsInUndo)
+            EnterBlockNotifications();
+        else
+            LeaveBlockNotifications();
+    }
     bool                IsInUndo()              { return bIsInUndo; }
 
     void                SetCallParaInsertedOrDeleted( bool b ) { bCallParaInsertedOrDeleted = b; }


More information about the Libreoffice-commits mailing list