summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcanvas/source/directx/dx_canvashelper_texturefill.cxx2
-rw-r--r--comphelper/inc/comphelper/TypeGeneration.hxx1
-rw-r--r--comphelper/inc/comphelper/asyncnotification.hxx3
-rwxr-xr-xcomphelper/inc/comphelper/flagguard.hxx83
-rw-r--r--comphelper/inc/comphelper/scopeguard.hxx15
-rw-r--r--comphelper/source/misc/scopeguard.cxx10
-rw-r--r--comphelper/source/property/TypeGeneration.cxx4
-rw-r--r--svl/inc/svl/undo.hxx352
-rw-r--r--svl/source/undo/undo.cxx1203
-rw-r--r--svtools/inc/svtools/textdata.hxx20
-rw-r--r--svtools/inc/svtools/texteng.hxx13
-rw-r--r--svtools/inc/svtools/xtextedt.hxx4
-rw-r--r--svtools/source/edit/texteng.cxx16
-rw-r--r--svtools/source/edit/textundo.cxx29
-rw-r--r--svtools/source/edit/textundo.hxx8
-rw-r--r--svtools/source/edit/textview.cxx32
-rw-r--r--svtools/source/edit/xtextedt.cxx8
-rw-r--r--toolkit/source/awt/vclxwindow.cxx29
18 files changed, 1389 insertions, 443 deletions
diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx
index 80224aa3d53c..17d5a2983f7c 100755
--- a/canvas/source/directx/dx_canvashelper_texturefill.cxx
+++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx
@@ -227,6 +227,7 @@ namespace dxcanvas
Gdiplus::SolidBrush aBackgroundBrush( rColors[0] );
rGraphics->FillPath( &aBackgroundBrush, pFillPath.get() );
+ Gdiplus::Matrix aMatrix;
// scale focus according to aspect ratio: for wider-than-tall
// bounds (nAspectRatio > 1.0), the focus must have non-zero
// width. Specifically, a bound rect twice as wide as tall has
@@ -383,7 +384,6 @@ namespace dxcanvas
// one sets both, only the translational components of the
// texture is respected.
- Gdiplus::Matrix aMatrix;
tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
texture.AffineTransform );
GraphicsPathSharedPtr pGradientPath(
diff --git a/comphelper/inc/comphelper/TypeGeneration.hxx b/comphelper/inc/comphelper/TypeGeneration.hxx
index 6660e560f4af..08401cb39944 100644
--- a/comphelper/inc/comphelper/TypeGeneration.hxx
+++ b/comphelper/inc/comphelper/TypeGeneration.hxx
@@ -115,6 +115,7 @@ namespace comphelper
CPPUTYPE_SEQNAMEDVALUE, //getCppuType( (Sequence<beans::NamedValue>*)0 )
CPPUTYPE_REFXGRAPHIC, //getCppuType( Reference< graphic::XGraphic >*)0)
CPPUTYPE_TABLEBORDERDISTANCES, //getCppuType( (table::TableBorderDistances*)0 )
+ CPPUTPYE_REFEMBEDDEDOBJECT, // XEmbeddedObject::static_type
CPPUTYPE_END
};
diff --git a/comphelper/inc/comphelper/asyncnotification.hxx b/comphelper/inc/comphelper/asyncnotification.hxx
index fc4dfcd48dd9..22d901728ef7 100644
--- a/comphelper/inc/comphelper/asyncnotification.hxx
+++ b/comphelper/inc/comphelper/asyncnotification.hxx
@@ -131,8 +131,9 @@ namespace comphelper
virtual oslInterlockedCount SAL_CALL acquire();
virtual oslInterlockedCount SAL_CALL release();
- /// creates (starts) the thread
using AsyncEventNotifier_TBASE::create;
+ using AsyncEventNotifier_TBASE::join;
+ using AsyncEventNotifier_TBASE::getIdentifier;
using AsyncEventNotifier_TBASE::operator new;
using AsyncEventNotifier_TBASE::operator delete;
diff --git a/comphelper/inc/comphelper/flagguard.hxx b/comphelper/inc/comphelper/flagguard.hxx
new file mode 100755
index 000000000000..4fc1f4e97833
--- /dev/null
+++ b/comphelper/inc/comphelper/flagguard.hxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef COMPHELPER_FLAGGUARD_HXX
+#define COMPHELPER_FLAGGUARD_HXX
+
+#include "comphelper/scopeguard.hxx"
+
+//......................................................................................................................
+namespace comphelper
+{
+//......................................................................................................................
+
+ //==================================================================================================================
+ //= FlagRestorationGuard
+ //==================================================================================================================
+ class COMPHELPER_DLLPUBLIC FlagRestorationGuard : public ScopeGuard
+ {
+ public:
+ FlagRestorationGuard( bool& i_flagRef, bool i_temporaryValue, exc_handling i_excHandling = IGNORE_EXCEPTIONS )
+ :ScopeGuard( ::boost::bind( RestoreFlag, ::boost::ref( i_flagRef ), !!i_flagRef ), i_excHandling )
+ {
+ i_flagRef = i_temporaryValue;
+ }
+
+ ~FlagRestorationGuard();
+
+ private:
+ static void RestoreFlag( bool& i_flagRef, bool i_originalValue )
+ {
+ i_flagRef = i_originalValue;
+ }
+ };
+
+ //==================================================================================================================
+ //= FlagGuard
+ //==================================================================================================================
+ class COMPHELPER_DLLPUBLIC FlagGuard : public ScopeGuard
+ {
+ public:
+ explicit FlagGuard( bool& i_flagRef, exc_handling i_excHandling = IGNORE_EXCEPTIONS )
+ :ScopeGuard( ::boost::bind( ResetFlag, ::boost::ref( i_flagRef ) ), i_excHandling )
+ {
+ i_flagRef = true;
+ }
+
+ ~FlagGuard();
+
+ private:
+ static void ResetFlag( bool& i_flagRef )
+ {
+ i_flagRef = false;
+ }
+ };
+
+//......................................................................................................................
+} // namespace comphelper
+//......................................................................................................................
+
+#endif // COMPHELPER_FLAGGUARD_HXX
diff --git a/comphelper/inc/comphelper/scopeguard.hxx b/comphelper/inc/comphelper/scopeguard.hxx
index 1fdd179404a2..e9c8f7ecc625 100644
--- a/comphelper/inc/comphelper/scopeguard.hxx
+++ b/comphelper/inc/comphelper/scopeguard.hxx
@@ -67,21 +67,6 @@ private:
exc_handling const m_excHandling;
};
-class COMPHELPER_DLLPUBLIC FlagGuard : ScopeGuard
-{
-public:
- explicit FlagGuard( bool& i_flagRef, exc_handling i_excHandling = IGNORE_EXCEPTIONS )
- :ScopeGuard( ::boost::bind( ResetFlag, ::boost::ref( i_flagRef ) ), i_excHandling )
- {
- }
-
-private:
- static void ResetFlag( bool& i_flagRef )
- {
- i_flagRef = false;
- }
-};
-
} // namespace comphelper
#endif // ! defined(INCLUDED_COMPHELPER_SCOPEGUARD_HXX)
diff --git a/comphelper/source/misc/scopeguard.cxx b/comphelper/source/misc/scopeguard.cxx
index 7ce478d8bea0..ccd5b618605b 100644
--- a/comphelper/source/misc/scopeguard.cxx
+++ b/comphelper/source/misc/scopeguard.cxx
@@ -28,7 +28,7 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"
-#include "comphelper/scopeguard.hxx"
+#include "comphelper/flagguard.hxx"
#include "osl/diagnose.h"
#include "com/sun/star/uno/Exception.hpp"
@@ -67,5 +67,13 @@ void ScopeGuard::dismiss()
m_func.clear();
}
+FlagGuard::~FlagGuard()
+{
+}
+
+FlagRestorationGuard::~FlagRestorationGuard()
+{
+}
+
} // namespace comphelper
diff --git a/comphelper/source/property/TypeGeneration.cxx b/comphelper/source/property/TypeGeneration.cxx
index bf880330ce75..649e50711d28 100644
--- a/comphelper/source/property/TypeGeneration.cxx
+++ b/comphelper/source/property/TypeGeneration.cxx
@@ -132,7 +132,8 @@
// --> OD 2004-08-09 #i28749#
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
// <--
-#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
using ::rtl::OUString;
using namespace ::com::sun::star;
@@ -230,6 +231,7 @@ namespace comphelper
case CPPUTYPE_SEQNAMEDVALUE: pType = &::getCppuType( (Sequence<beans::NamedValue>*)0 ); break;
case CPPUTYPE_REFXGRAPHIC: pType = &::getCppuType( (Reference< graphic::XGraphic >*)0); break;
case CPPUTYPE_TABLEBORDERDISTANCES: pType = &::getCppuType( (table::TableBorderDistances*)0 ); break;
+ case CPPUTPYE_REFEMBEDDEDOBJECT: pType = &embed::XEmbeddedObject::static_type(); break;
default:
OSL_ASSERT( "Unknown CPPU type" );
}
diff --git a/svl/inc/svl/undo.hxx b/svl/inc/svl/undo.hxx
index 5aea03207626..08d2fa6c5b84 100644
--- a/svl/inc/svl/undo.hxx
+++ b/svl/inc/svl/undo.hxx
@@ -32,6 +32,10 @@
#include <tools/string.hxx>
#include <svl/svarray.hxx>
+#include <boost/scoped_ptr.hpp>
+
+#include <vector>
+
//====================================================================
class SVL_DLLPUBLIC SfxRepeatTarget
@@ -43,6 +47,14 @@ public:
//====================================================================
+class SVL_DLLPUBLIC SfxUndoContext
+{
+public:
+ virtual ~SfxUndoContext() = 0;
+};
+
+//====================================================================
+
class SVL_DLLPUBLIC SfxUndoAction
{
BOOL bLinked;
@@ -54,14 +66,16 @@ public:
virtual BOOL IsLinked();
virtual void SetLinked( BOOL bIsLinked = TRUE );
virtual void Undo();
+ virtual void UndoWithContext( SfxUndoContext& i_context );
virtual void Redo();
+ virtual void RedoWithContext( SfxUndoContext& i_context );
virtual void Repeat(SfxRepeatTarget&);
virtual BOOL CanRepeat(SfxRepeatTarget&) const;
virtual BOOL Merge( SfxUndoAction *pNextAction );
- virtual UniString GetComment() const;
- virtual UniString GetRepeatComment(SfxRepeatTarget&) const;
+ virtual UniString GetComment() const;
+ virtual UniString GetRepeatComment(SfxRepeatTarget&) const;
virtual USHORT GetId() const;
private:
@@ -70,19 +84,67 @@ private:
//========================================================================
-SV_DECL_PTRARR( SfxUndoActions, SfxUndoAction*, 20, 8 )
+/// is a mark on the Undo stack
+typedef sal_Int32 UndoStackMark;
+#define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
+
+//========================================================================
+
+struct MarkedUndoAction
+{
+ SfxUndoAction* pAction;
+ ::std::vector< UndoStackMark > aMarks;
+
+ MarkedUndoAction( SfxUndoAction* i_action )
+ :pAction( i_action )
+ ,aMarks()
+ {
+ }
+};
+
+class SfxUndoActions
+{
+private:
+ ::std::vector< MarkedUndoAction > m_aActions;
+
+public:
+ SfxUndoActions()
+ {
+ }
+
+ bool empty() const { return m_aActions.empty(); }
+ size_t size() const { return m_aActions.size(); }
+
+ const MarkedUndoAction& operator[]( size_t i ) const { return m_aActions[i]; }
+ MarkedUndoAction& operator[]( size_t i ) { return m_aActions[i]; }
+
+ void Remove( size_t i_pos )
+ {
+ m_aActions.erase( m_aActions.begin() + i_pos );
+ }
+
+ void Remove( size_t i_pos, size_t i_count )
+ {
+ m_aActions.erase( m_aActions.begin() + i_pos, m_aActions.begin() + i_pos + i_count );
+ }
+
+ void Insert( SfxUndoAction* i_action, size_t i_pos )
+ {
+ m_aActions.insert( m_aActions.begin() + i_pos, MarkedUndoAction( i_action ) );
+ }
+};
//====================================================================
-/** do not make use of this implementation details, unless you
+/** do not make use of these implementation details, unless you
really really have to! */
struct SVL_DLLPUBLIC SfxUndoArray
{
SfxUndoActions aUndoActions;
- USHORT nMaxUndoActions;
- USHORT nCurUndoAction;
+ size_t nMaxUndoActions;
+ size_t nCurUndoAction;
SfxUndoArray *pFatherUndoArray;
- SfxUndoArray(USHORT nMax=0):
+ SfxUndoArray(size_t nMax=0):
nMaxUndoActions(nMax), nCurUndoAction(0),
pFatherUndoArray(0) {}
~SfxUndoArray();
@@ -90,7 +152,7 @@ struct SVL_DLLPUBLIC SfxUndoArray
//=========================================================================
-/** do not make use of this implementation details, unless you
+/** do not make use of these implementation details, unless you
really really have to! */
class SVL_DLLPUBLIC SfxListUndoAction : public SfxUndoAction, public SfxUndoArray
@@ -111,14 +173,16 @@ class SVL_DLLPUBLIC SfxListUndoAction : public SfxUndoAction, public SfxUndoArra
SfxListUndoAction( const UniString &rComment,
const UniString rRepeatComment, USHORT Id, SfxUndoArray *pFather);
virtual void Undo();
+ virtual void UndoWithContext( SfxUndoContext& i_context );
virtual void Redo();
+ virtual void RedoWithContext( SfxUndoContext& i_context );
virtual void Repeat(SfxRepeatTarget&);
virtual BOOL CanRepeat(SfxRepeatTarget&) const;
virtual BOOL Merge( SfxUndoAction *pNextAction );
- virtual UniString GetComment() const;
- virtual UniString GetRepeatComment(SfxRepeatTarget&) const;
+ virtual UniString GetComment() const;
+ virtual UniString GetRepeatComment(SfxRepeatTarget&) const;
virtual USHORT GetId() const;
void SetComment( const UniString& rComment );
@@ -126,70 +190,242 @@ class SVL_DLLPUBLIC SfxListUndoAction : public SfxUndoAction, public SfxUndoArra
private:
USHORT nId;
- UniString aComment, aRepeatComment;
+ UniString aComment;
+ UniString aRepeatComment;
};
//=========================================================================
-class SVL_DLLPUBLIC SfxUndoManager
+/** is a callback interface for notifications about state changes of an SfxUndoManager
+*/
+class SAL_NO_VTABLE SfxUndoListener
{
- friend class SfxLinkUndoAction;
+public:
+ virtual void actionUndone( const String& i_actionComment ) = 0;
+ virtual void actionRedone( const String& i_actionComment ) = 0;
+ virtual void undoActionAdded( const String& i_actionComment ) = 0;
+ virtual void cleared() = 0;
+ virtual void clearedRedo() = 0;
+ virtual void resetAll() = 0;
+ virtual void listActionEntered( const String& i_comment ) = 0;
+ virtual void listActionLeft( const String& i_comment ) = 0;
+ virtual void listActionLeftAndMerged() = 0;
+ virtual void listActionCancelled() = 0;
+ virtual void undoManagerDying() = 0;
+};
- SfxUndoArray *pUndoArray;
- SfxUndoArray *pActUndoArray;
- SfxUndoArray *pFatherUndoArray;
+//=========================================================================
- bool mbUndoEnabled;
-public:
- SfxUndoManager( USHORT nMaxUndoActionCount = 20 );
- virtual ~SfxUndoManager();
+namespace svl
+{
+ class SAL_NO_VTABLE IUndoManager
+ {
+ public:
+ enum
+ {
+ CurrentLevel = true,
+ TopLevel = false
+ };
- virtual void SetMaxUndoActionCount( USHORT nMaxUndoActionCount );
- virtual USHORT GetMaxUndoActionCount() const;
- virtual void Clear();
+ virtual ~IUndoManager() { };
- virtual void AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerg=FALSE );
+ virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount ) = 0;
+ virtual size_t GetMaxUndoActionCount() const = 0;
- virtual USHORT GetUndoActionCount() const;
- virtual USHORT GetUndoActionId(USHORT nNo=0) const;
- virtual UniString GetUndoActionComment( USHORT nNo=0 ) const;
- /** returns the nNo'th undo action from the top */
- SfxUndoAction* GetUndoAction( USHORT nNo=0 ) const;
+ virtual void AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerg=FALSE ) = 0;
- virtual BOOL Undo( USHORT nCount=1 );
- virtual void Undo( SfxUndoAction &rAction );
+ virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0;
+ virtual USHORT GetUndoActionId() const = 0;
+ virtual UniString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0;
+ virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const = 0;
- virtual USHORT GetRedoActionCount() const;
- virtual USHORT GetRedoActionId(USHORT nNo=0) const;
- virtual UniString GetRedoActionComment( USHORT nNo=0 ) const;
+ virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0;
+ virtual UniString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0;
- virtual BOOL Redo( USHORT nCount=1 );
- virtual void Redo( SfxUndoAction &rAction );
- virtual void ClearRedo();
+ virtual BOOL Undo() = 0;
+ virtual BOOL Redo() = 0;
+
+ /** clears both the Redo and the Undo stack.
+
+ Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
+ */
+ virtual void Clear() = 0;
+
+ /** clears the Redo stack.
- virtual USHORT GetRepeatActionCount() const;
- virtual UniString GetRepeatActionComment( SfxRepeatTarget &rTarget, USHORT nNo = 0) const;
- virtual BOOL Repeat( SfxRepeatTarget &rTarget, USHORT nFrom=0, USHORT nCount=1 );
- virtual void Repeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction );
- virtual BOOL CanRepeat( SfxRepeatTarget &rTarget, USHORT nNo = 0 ) const;
- virtual BOOL CanRepeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction ) const;
+ Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
+ */
+ virtual void ClearRedo() = 0;
+ /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
+ Redo stack.
+
+ Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
+ followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
+ atomar operation, also resulting in only one notification.
+ */
+ virtual void Reset() = 0;
+
+ /** determines whether an Undo or Redo is currently running
+ */
+ virtual bool IsDoing() const = 0;
+
+ virtual size_t GetRepeatActionCount() const = 0;
+ virtual UniString GetRepeatActionComment( SfxRepeatTarget &rTarget) const = 0;
+ virtual BOOL Repeat( SfxRepeatTarget &rTarget ) = 0;
+ virtual BOOL CanRepeat( SfxRepeatTarget &rTarget ) const = 0;
+
+ virtual void EnterListAction(const UniString &rComment, const UniString& rRepeatComment, USHORT nId=0) = 0;
+
+ /** leaves the list action entered with EnterListAction
+ @return the number of the sub actions in the list which has just been left. Note that in case no such
+ actions exist, the list action does not contribute to the Undo stack, but is silently removed.
+ */
+ virtual size_t LeaveListAction() = 0;
+
+ /** leaves the list action entered with EnterListAction, and forcefully merges the previous
+ action on the stack into the newly created list action.
+
+ Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
+ AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
+ stack will now still contain one undo action: the newly created list action, whose first child is the
+ original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
+ the comment of A.
+
+ Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
+ hidden from the user.
+
+ @return the number of the sub actions in the list which has just been left. Note that in case no such
+ actions exist, the list action does not contribute to the Undo stack, but is silently removed.
+ */
+ virtual size_t LeaveAndMergeListAction() = 0;
+
+ /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
+ virtual bool IsInListAction() const = 0;
+
+ /// determines how many nested list actions are currently open
+ virtual size_t GetListActionDepth() const = 0;
+
+ /** clears the redo stack and removes the top undo action */
+ virtual void RemoveLastUndoAction() = 0;
+
+ // enables (true) or disables (false) recording of undo actions
+ // If undo actions are added while undo is disabled, they are deleted.
+ // Disabling undo does not clear the current undo buffer!
+ virtual void EnableUndo( bool bEnable ) = 0;
+
+ // returns true if undo is currently enabled
+ // This returns false if undo was disabled using EnableUndo( false ) and
+ // also during the runtime of the Undo() and Redo() methods.
+ virtual bool IsUndoEnabled() const = 0;
+
+ /// adds a new listener to be notified about changes in the UndoManager's state
+ virtual void AddUndoListener( SfxUndoListener& i_listener ) = 0;
+ virtual void RemoveUndoListener( SfxUndoListener& i_listener ) = 0;
+ };
+}
+
+//=========================================================================
+
+namespace svl { namespace undo { namespace impl
+{
+ class UndoManagerGuard;
+ class LockGuard;
+} } }
+
+struct SfxUndoManager_Data;
+class SVL_DLLPUBLIC SfxUndoManager : public ::svl::IUndoManager
+{
+ friend class SfxLinkUndoAction;
+
+ ::boost::scoped_ptr< SfxUndoManager_Data >
+ m_pData;
+public:
+ SfxUndoManager( size_t nMaxUndoActionCount = 20 );
+ virtual ~SfxUndoManager();
+
+ // IUndoManager overridables
+ virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount );
+ virtual size_t GetMaxUndoActionCount() const;
+ virtual void AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerg=FALSE );
+ virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const;
+ virtual USHORT GetUndoActionId() const;
+ virtual UniString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
+ virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const;
+ virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const;
+ virtual UniString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
+ virtual BOOL Undo();
+ virtual BOOL Redo();
+ virtual void Clear();
+ virtual void ClearRedo();
+ virtual void Reset();
+ virtual bool IsDoing() const;
+ virtual size_t GetRepeatActionCount() const;
+ virtual UniString GetRepeatActionComment( SfxRepeatTarget &rTarget) const;
+ virtual BOOL Repeat( SfxRepeatTarget &rTarget );
+ virtual BOOL CanRepeat( SfxRepeatTarget &rTarget ) const;
virtual void EnterListAction(const UniString &rComment, const UniString& rRepeatComment, USHORT nId=0);
- virtual void LeaveListAction();
+ virtual size_t LeaveListAction();
+ virtual size_t LeaveAndMergeListAction();
+ virtual bool IsInListAction() const;
+ virtual size_t GetListActionDepth() const;
+ virtual void RemoveLastUndoAction();
+ virtual void EnableUndo( bool bEnable );
+ virtual bool IsUndoEnabled() const;
+ virtual void AddUndoListener( SfxUndoListener& i_listener );
+ virtual void RemoveUndoListener( SfxUndoListener& i_listener );
+
+ /** marks the current top-level element of the Undo stack, and returns a unique ID for it
+ */
+ UndoStackMark MarkTopUndoAction();
+
+ /** removes a mark given by its ID.
+
+ After the call, the mark ID is invalid.
+ */
+ void RemoveMark( UndoStackMark const i_mark );
+
+ /** determines whether the top action on the Undo stack has a given mark
+ */
+ bool HasTopUndoActionMark( UndoStackMark const i_mark );
+
+ /** removes the oldest Undo actions from the stack
+ */
+ void RemoveOldestUndoActions( size_t const i_count );
+
+protected:
+ BOOL UndoWithContext( SfxUndoContext& i_context );
+ BOOL RedoWithContext( SfxUndoContext& i_context );
+
+ void ImplClearRedo_NoLock( bool const i_currentLevel );
- /** clears the redo stack and removes the top undo action */
- void RemoveLastUndoAction();
+ /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
+ as soon as those levels are reached.
- // enables (true) or disables (false) recording of undo actions
- // If undo actions are added while undo is disabled, they are deleted.
- // Disabling undo does not clear the current undo buffer!
- void EnableUndo( bool bEnable );
+ If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
+ ->Clear.
- // returns true if undo is currently enabled
- // This returns false if undo was disabled using EnableUndo( false ) and
- // also during the runtime of the Undo() and Redo() methods.
- bool IsUndoEnabled() const { return mbUndoEnabled; }
+ Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
+ undo actions on the then-current level are removed, too. This is continued until the top level is reached.
+ */
+ void ClearAllLevels();
+
+private:
+ size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
+ bool ImplAddUndoAction_NoNotify( SfxUndoAction* pAction, bool bTryMerge, bool bClearRedo, ::svl::undo::impl::UndoManagerGuard& i_guard );
+ void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard& i_guard, bool const i_currentLevel );
+ void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard& i_guard );
+ void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard& i_guard );
+ size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel = CurrentLevel ) const;
+ bool ImplIsUndoEnabled_Lock() const;
+ bool ImplIsInListAction_Lock() const;
+ void ImplEnableUndo_Lock( bool const i_enable );
+
+ BOOL ImplUndo( SfxUndoContext* i_contextOrNull );
+ BOOL ImplRedo( SfxUndoContext* i_contextOrNull );
+
+ friend class ::svl::undo::impl::LockGuard;
};
//=========================================================================
@@ -213,7 +449,7 @@ class SVL_DLLPUBLIC SfxLinkUndoAction : public SfxUndoAction
{
public:
TYPEINFO();
- SfxLinkUndoAction(SfxUndoManager *pManager);
+ SfxLinkUndoAction(::svl::IUndoManager *pManager);
~SfxLinkUndoAction();
virtual void Undo();
@@ -222,14 +458,14 @@ public:
virtual void Repeat(SfxRepeatTarget&r);
- virtual UniString GetComment() const;
- virtual UniString GetRepeatComment(SfxRepeatTarget&r) const;
+ virtual UniString GetComment() const;
+ virtual UniString GetRepeatComment(SfxRepeatTarget&r) const;
virtual USHORT GetId() const;
SfxUndoAction* GetAction() const { return pAction; }
protected:
- SfxUndoManager *pUndoManager;
+ ::svl::IUndoManager *pUndoManager;
SfxUndoAction *pAction;
};
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index fa5eca964a8c..fd789e6a4aac 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -30,10 +30,16 @@
#include <com/sun/star/uno/Exception.hpp>
+#include <comphelper/flagguard.hxx>
#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
#include <svl/undo.hxx>
+#include <vector>
+#include <list>
+#include <limits>
+
using ::com::sun::star::uno::Exception;
// STATIC DATA -----------------------------------------------------------
@@ -55,6 +61,12 @@ SfxRepeatTarget::~SfxRepeatTarget()
//------------------------------------------------------------------------
+SfxUndoContext::~SfxUndoContext()
+{
+}
+
+//------------------------------------------------------------------------
+
BOOL SfxUndoAction::IsLinked()
{
return bLinked;
@@ -117,7 +129,6 @@ XubString SfxUndoAction::GetRepeatComment(SfxRepeatTarget&) const
//------------------------------------------------------------------------
-
void SfxUndoAction::Undo()
{
// die sind nur konzeptuell pure virtual
@@ -126,6 +137,14 @@ void SfxUndoAction::Undo()
//------------------------------------------------------------------------
+void SfxUndoAction::UndoWithContext( SfxUndoContext& i_context )
+{
+ (void)i_context;
+ Undo();
+}
+
+//------------------------------------------------------------------------
+
void SfxUndoAction::Redo()
{
// die sind nur konzeptuell pure virtual
@@ -134,6 +153,14 @@ void SfxUndoAction::Redo()
//------------------------------------------------------------------------
+void SfxUndoAction::RedoWithContext( SfxUndoContext& i_context )
+{
+ (void)i_context;
+ Redo();
+}
+
+//------------------------------------------------------------------------
+
void SfxUndoAction::Repeat(SfxRepeatTarget&)
{
// die sind nur konzeptuell pure virtual
@@ -150,206 +177,554 @@ BOOL SfxUndoAction::CanRepeat(SfxRepeatTarget&) const
//========================================================================
+typedef ::std::vector< SfxUndoListener* > UndoListeners;
+
+struct SVL_DLLPRIVATE SfxUndoManager_Data
+{
+ ::osl::Mutex aMutex;
+ SfxUndoArray* pUndoArray;
+ SfxUndoArray* pActUndoArray;
+ SfxUndoArray* pFatherUndoArray;
+
+ sal_Int32 mnLockCount;
+ sal_Int32 mnMarks;
+ sal_Int32 mnEmptyMark;
+ bool mbDoing;
+ bool mbClearUntilTopLevel;
+
+ UndoListeners aListeners;
+
+ SfxUndoManager_Data( size_t i_nMaxUndoActionCount )
+ :pUndoArray( new SfxUndoArray( i_nMaxUndoActionCount ) )
+ ,pActUndoArray( NULL )
+ ,pFatherUndoArray( NULL )
+ ,mnLockCount( 0 )
+ ,mnMarks( 0 )
+ ,mnEmptyMark(MARK_INVALID)
+ ,mbDoing( false )
+ ,mbClearUntilTopLevel( false )
+ {
+ pActUndoArray = pUndoArray;
+ }
+
+ ~SfxUndoManager_Data()
+ {
+ delete pUndoArray;
+ }
+};
+
+//========================================================================
-SfxUndoManager::SfxUndoManager( USHORT nMaxUndoActionCount )
- : pFatherUndoArray(0)
- , mbUndoEnabled( true )
+namespace svl { namespace undo { namespace impl
{
- pUndoArray=new SfxUndoArray(nMaxUndoActionCount);
- pActUndoArray=pUndoArray;
+ //--------------------------------------------------------------------
+ class SVL_DLLPRIVATE LockGuard
+ {
+ public:
+ LockGuard( SfxUndoManager& i_manager )
+ :m_manager( i_manager )
+ {
+ m_manager.ImplEnableUndo_Lock( false );
+ }
+
+ ~LockGuard()
+ {
+ m_manager.ImplEnableUndo_Lock( true );
+ }
+
+ private:
+ SfxUndoManager& m_manager;
+ };
+
+ //--------------------------------------------------------------------
+ typedef void ( SfxUndoListener::*UndoListenerVoidMethod )();
+ typedef void ( SfxUndoListener::*UndoListenerStringMethod )( const String& );
+
+ //--------------------------------------------------------------------
+ struct SVL_DLLPRIVATE NotifyUndoListener : public ::std::unary_function< SfxUndoListener*, void >
+ {
+ NotifyUndoListener()
+ :m_notificationMethod( NULL )
+ ,m_altNotificationMethod( NULL )
+ ,m_sActionComment()
+ {
+ }
+ NotifyUndoListener( UndoListenerVoidMethod i_notificationMethod )
+ :m_notificationMethod( i_notificationMethod )
+ ,m_altNotificationMethod( NULL )
+ ,m_sActionComment()
+ {
+ }
+
+ NotifyUndoListener( UndoListenerStringMethod i_notificationMethod, const String& i_actionComment )
+ :m_notificationMethod( NULL )
+ ,m_altNotificationMethod( i_notificationMethod )
+ ,m_sActionComment( i_actionComment )
+ {
+ }
+
+ bool is() const
+ {
+ return ( m_notificationMethod != NULL ) || ( m_altNotificationMethod != NULL );
+ }
+
+ void operator()( SfxUndoListener* i_listener ) const
+ {
+ OSL_PRECOND( is(), "NotifyUndoListener: this will crash!" );
+ if ( m_altNotificationMethod != NULL )
+ {
+ ( i_listener->*m_altNotificationMethod )( m_sActionComment );
+ }
+ else
+ {
+ ( i_listener->*m_notificationMethod )();
+ }
+ }
+
+ private:
+ UndoListenerVoidMethod m_notificationMethod;
+ UndoListenerStringMethod m_altNotificationMethod;
+ String m_sActionComment;
+ };
+
+ //--------------------------------------------------------------------
+ class SVL_DLLPRIVATE UndoManagerGuard
+ {
+ public:
+ UndoManagerGuard( SfxUndoManager_Data& i_managerData )
+ :m_rManagerData( i_managerData )
+ ,m_aGuard( i_managerData.aMutex )
+ ,m_notifiers()
+ {
+ }
+
+ ~UndoManagerGuard();
+
+ void clear()
+ {
+ m_aGuard.clear();
+ }
+
+ void reset()
+ {
+ m_aGuard.reset();
+ }
+
+ void cancelNotifications()
+ {
+ m_notifiers.clear();
+ }
+
+ /** marks the given Undo action for deletion
+
+ The Undo action will be put into a list, whose members will be deleted from within the destructor of the
+ UndoManagerGuard. This deletion will happen without the UndoManager's mutex locked.
+ */
+ void markForDeletion( SfxUndoAction* i_action )
+ {
+ // remember
+ if ( i_action )
+ m_aUndoActionsCleanup.push_back( i_action );
+ }
+
+ /** schedules the given SfxUndoListener method to be called for all registered listeners.
+
+ The notification will happen after the Undo manager's mutex has been released, and after all pending
+ deletions of Undo actions are done.
+ */
+ void scheduleNotification( UndoListenerVoidMethod i_notificationMethod )
+ {
+ m_notifiers.push_back( NotifyUndoListener( i_notificationMethod ) );
+ }
+
+ void scheduleNotification( UndoListenerStringMethod i_notificationMethod, const String& i_actionComment )
+ {
+ m_notifiers.push_back( NotifyUndoListener( i_notificationMethod, i_actionComment ) );
+ }
+
+ private:
+ SfxUndoManager_Data& m_rManagerData;
+ ::osl::ResettableMutexGuard m_aGuard;
+ ::std::list< SfxUndoAction* > m_aUndoActionsCleanup;
+ ::std::list< NotifyUndoListener > m_notifiers;
+ };
+
+ UndoManagerGuard::~UndoManagerGuard()
+ {
+ // copy members
+ UndoListeners aListenersCopy( m_rManagerData.aListeners );
+
+ // release mutex
+ m_aGuard.clear();
+
+ // delete all actions
+ while ( !m_aUndoActionsCleanup.empty() )
+ {
+ SfxUndoAction* pAction = m_aUndoActionsCleanup.front();
+ m_aUndoActionsCleanup.pop_front();
+ try
+ {
+ delete pAction;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ // handle scheduled notification
+ for ( ::std::list< NotifyUndoListener >::const_iterator notifier = m_notifiers.begin();
+ notifier != m_notifiers.end();
+ ++notifier
+ )
+ {
+ if ( notifier->is() )
+ ::std::for_each( aListenersCopy.begin(), aListenersCopy.end(), *notifier );
+ }
+ }
+} } }
+
+using namespace ::svl::undo::impl;
+
+//========================================================================
+
+SfxUndoManager::SfxUndoManager( size_t nMaxUndoActionCount )
+ :m_pData( new SfxUndoManager_Data( nMaxUndoActionCount ) )
+{
}
//------------------------------------------------------------------------
-
SfxUndoManager::~SfxUndoManager()
{
- delete pUndoArray;
+ UndoListeners aListenersCopy;
+ {
+ UndoManagerGuard aGuard( *m_pData );
+ aListenersCopy = m_pData->aListeners;
+ }
+
+ ::std::for_each( aListenersCopy.begin(), aListenersCopy.end(),
+ NotifyUndoListener( &SfxUndoListener::undoManagerDying ) );
}
//------------------------------------------------------------------------
-void SfxUndoManager::EnableUndo( bool bEnable )
+void SfxUndoManager::EnableUndo( bool i_enable )
{
- mbUndoEnabled = bEnable;
+ UndoManagerGuard aGuard( *m_pData );
+ ImplEnableUndo_Lock( i_enable );
+
}
//------------------------------------------------------------------------
+void SfxUndoManager::ImplEnableUndo_Lock( bool const i_enable )
+{
+ if ( !i_enable )
+ ++m_pData->mnLockCount;
+ else
+ {
+ OSL_PRECOND( m_pData->mnLockCount > 0, "SfxUndoManager::ImplEnableUndo_NoNotify: not disabled, so why enabling?" );
+ if ( m_pData->mnLockCount > 0 )
+ --m_pData->mnLockCount;
+ }
+}
-void SfxUndoManager::SetMaxUndoActionCount( USHORT nMaxUndoActionCount )
+//------------------------------------------------------------------------
+
+bool SfxUndoManager::IsUndoEnabled() const
{
+ UndoManagerGuard aGuard( *m_pData );
+ return ImplIsUndoEnabled_Lock();
+}
+
+//------------------------------------------------------------------------
+
+bool SfxUndoManager::ImplIsUndoEnabled_Lock() const
+{
+ return m_pData->mnLockCount == 0;
+}
+
+//------------------------------------------------------------------------
+
+void SfxUndoManager::SetMaxUndoActionCount( size_t nMaxUndoActionCount )
+{
+ UndoManagerGuard aGuard( *m_pData );
+
// Remove entries from the pActUndoArray when we have to reduce
// the number of entries due to a lower nMaxUndoActionCount.
// Both redo and undo action entries will be removed until we reached the
// new nMaxUndoActionCount.
- long nNumToDelete = pActUndoArray->aUndoActions.Count() - nMaxUndoActionCount;
- if ( nNumToDelete > 0 )
+ long nNumToDelete = m_pData->pActUndoArray->aUndoActions.size() - nMaxUndoActionCount;
+ while ( nNumToDelete > 0 )
{
- while ( nNumToDelete > 0 )
+ size_t nPos = m_pData->pActUndoArray->aUndoActions.size();
+ if ( nPos > m_pData->pActUndoArray->nCurUndoAction )
{
- USHORT nPos = pActUndoArray->aUndoActions.Count();
- if ( nPos > pActUndoArray->nCurUndoAction )
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[nPos-1].pAction;
+ if ( !pAction->IsLinked() )
{
- if ( !pActUndoArray->aUndoActions[nPos-1]->IsLinked() )
- {
- delete pActUndoArray->aUndoActions[nPos-1];
- pActUndoArray->aUndoActions.Remove( nPos-1 );
- --nNumToDelete;
- }
+ aGuard.markForDeletion( pAction );
+ m_pData->pActUndoArray->aUndoActions.Remove( nPos-1 );
+ --nNumToDelete;
}
+ }
- if ( nNumToDelete > 0 && pActUndoArray->nCurUndoAction > 0 )
+ if ( nNumToDelete > 0 && m_pData->pActUndoArray->nCurUndoAction > 0 )
+ {
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[0].pAction;
+ if ( !pAction->IsLinked() )
{
- if ( !pActUndoArray->aUndoActions[0]->IsLinked() )
- {
- delete pActUndoArray->aUndoActions[0];
- pActUndoArray->aUndoActions.Remove(0);
- --pActUndoArray->nCurUndoAction;
- --nNumToDelete;
- }
+ aGuard.markForDeletion( pAction );
+ m_pData->pActUndoArray->aUndoActions.Remove(0);
+ --m_pData->pActUndoArray->nCurUndoAction;
+ --nNumToDelete;
}
-
- if ( nPos == pActUndoArray->aUndoActions.Count() )
- break; // Cannot delete more entries
}
+
+ if ( nPos == m_pData->pActUndoArray->aUndoActions.size() )
+ break; // Cannot delete more entries
}
- pActUndoArray->nMaxUndoActions = nMaxUndoActionCount;
+ m_pData->pActUndoArray->nMaxUndoActions = nMaxUndoActionCount;
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetMaxUndoActionCount() const
+size_t SfxUndoManager::GetMaxUndoActionCount() const
{
- return pActUndoArray->nMaxUndoActions;
+ UndoManagerGuard aGuard( *m_pData );
+ return m_pData->pActUndoArray->nMaxUndoActions;
}
//------------------------------------------------------------------------
-void SfxUndoManager::Clear()
+void SfxUndoManager::ImplClearCurrentLevel_NoNotify( UndoManagerGuard& i_guard )
{
- while ( pActUndoArray->aUndoActions.Count() )
+ // clear array
+ while ( !m_pData->pActUndoArray->aUndoActions.empty() )
{
- SfxUndoAction *pAction=
- pActUndoArray->aUndoActions[pActUndoArray->aUndoActions.Count() - 1];
- pActUndoArray->aUndoActions.Remove( pActUndoArray->aUndoActions.Count() - 1 );
- delete pAction;
+ size_t deletePos = m_pData->pActUndoArray->aUndoActions.size() - 1;
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ deletePos ].pAction;
+ i_guard.markForDeletion( pAction );
+ m_pData->pActUndoArray->aUndoActions.Remove( deletePos );
}
- pActUndoArray->nCurUndoAction = 0;
+ m_pData->pActUndoArray->nCurUndoAction = 0;
+
+ m_pData->mnMarks = 0;
+ m_pData->mnEmptyMark = MARK_INVALID;
}
//------------------------------------------------------------------------
-void SfxUndoManager::ClearRedo()
+void SfxUndoManager::Clear()
{
- while ( pActUndoArray->aUndoActions.Count() > pActUndoArray->nCurUndoAction )
- {
- SfxUndoAction *pAction=
- pActUndoArray->aUndoActions[pActUndoArray->aUndoActions.Count() - 1];
- pActUndoArray->aUndoActions.Remove( pActUndoArray->aUndoActions.Count() - 1 );
- delete pAction;
- }
+ UndoManagerGuard aGuard( *m_pData );
+
+ OSL_ENSURE( !ImplIsInListAction_Lock(), "SfxUndoManager::Clear: suspicious call - do you really wish to clear the current level?" );
+ ImplClearCurrentLevel_NoNotify( aGuard );
+
+ // notify listeners
+ aGuard.scheduleNotification( &SfxUndoListener::cleared );
}
//------------------------------------------------------------------------
-void SfxUndoManager::AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerge )
+void SfxUndoManager::ClearAllLevels()
{
- if( mbUndoEnabled )
+ UndoManagerGuard aGuard( *m_pData );
+ ImplClearCurrentLevel_NoNotify( aGuard );
+
+ if ( ImplIsInListAction_Lock() )
+ {
+ m_pData->mbClearUntilTopLevel = true;
+ }
+ else
{
- // Redo-Actions loeschen
- for ( USHORT nPos = pActUndoArray->aUndoActions.Count();
- nPos > pActUndoArray->nCurUndoAction; --nPos )
- delete pActUndoArray->aUndoActions[nPos-1];
+ aGuard.scheduleNotification( &SfxUndoListener::cleared );
+ }
+}
- pActUndoArray->aUndoActions.Remove(
- pActUndoArray->nCurUndoAction,
- pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction );
+//------------------------------------------------------------------------
- if ( pActUndoArray->nMaxUndoActions )
- {
- SfxUndoAction *pTmpAction = pActUndoArray->nCurUndoAction ?
- pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1] : 0;
+void SfxUndoManager::ImplClearRedo_NoLock( bool const i_currentLevel )
+{
+ UndoManagerGuard aGuard( *m_pData );
+ ImplClearRedo( aGuard, i_currentLevel );
+}
- if ( !bTryMerge || !(pTmpAction && pTmpAction->Merge(pAction)) )
- {
- // auf Max-Anzahl anpassen
- if( pActUndoArray == pUndoArray )
- while( pActUndoArray->aUndoActions.Count() >=
- pActUndoArray->nMaxUndoActions &&
- !pActUndoArray->aUndoActions[0]->IsLinked() )
- {
- delete pActUndoArray->aUndoActions[0];
- pActUndoArray->aUndoActions.Remove(0);
- --pActUndoArray->nCurUndoAction;
- }
-
- // neue Action anh"angen
- const SfxUndoAction* pTemp = pAction;
- pActUndoArray->aUndoActions.Insert(
- pTemp, pActUndoArray->nCurUndoAction++ );
- return;
- }
- }
- }
- delete pAction;
+//------------------------------------------------------------------------
+
+void SfxUndoManager::ClearRedo()
+{
+ OSL_ENSURE( !IsInListAction(), "SfxUndoManager::ClearRedo: suspicious call - do you really wish to clear the current level?" );
+ ImplClearRedo_NoLock( CurrentLevel );
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetUndoActionCount() const
+void SfxUndoManager::Reset()
{
- return pActUndoArray->nCurUndoAction;
+ UndoManagerGuard aGuard( *m_pData );
+
+ // clear all locks
+ while ( !ImplIsUndoEnabled_Lock() )
+ ImplEnableUndo_Lock( true );
+
+ // cancel all list actions
+ while ( IsInListAction() )
+ ImplLeaveListAction( false, aGuard );
+
+ // clear both stacks
+ ImplClearCurrentLevel_NoNotify( aGuard );
+
+ // cancel the notifications scheduled by ImplLeaveListAction,
+ // as we want to do an own, dedicated notification
+ aGuard.cancelNotifications();
+
+ // schedule notification
+ aGuard.scheduleNotification( &SfxUndoListener::resetAll );
}
//------------------------------------------------------------------------
-XubString SfxUndoManager::GetUndoActionComment( USHORT nNo ) const
+void SfxUndoManager::ImplClearUndo( UndoManagerGuard& i_guard )
{
- DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoActionComment(), illegal id!" );
- if( nNo < pActUndoArray->nCurUndoAction )
+ while ( m_pData->pActUndoArray->nCurUndoAction > 0 )
{
- return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]->GetComment(); //!
+ SfxUndoAction* pUndoAction = m_pData->pActUndoArray->aUndoActions[0].pAction;
+ m_pData->pActUndoArray->aUndoActions.Remove( 0 );
+ i_guard.markForDeletion( pUndoAction );
+ --m_pData->pActUndoArray->nCurUndoAction;
}
- else
+ // TODO: notifications? We don't have clearedUndo, only cleared and clearedRedo at the SfxUndoListener
+}
+
+//------------------------------------------------------------------------
+
+void SfxUndoManager::ImplClearRedo( UndoManagerGuard& i_guard, bool const i_currentLevel )
+{
+ SfxUndoArray* pUndoArray = ( i_currentLevel == IUndoManager::CurrentLevel ) ? m_pData->pActUndoArray : m_pData->pUndoArray;
+
+ // clearance
+ while ( pUndoArray->aUndoActions.size() > pUndoArray->nCurUndoAction )
{
- XubString aEmpty;
- return aEmpty;
+ size_t deletePos = pUndoArray->aUndoActions.size() - 1;
+ SfxUndoAction* pAction = pUndoArray->aUndoActions[ deletePos ].pAction;
+ pUndoArray->aUndoActions.Remove( deletePos );
+ i_guard.markForDeletion( pAction );
}
+
+ // notification - only if the top level's stack was cleared
+ if ( i_currentLevel == IUndoManager::TopLevel )
+ i_guard.scheduleNotification( &SfxUndoListener::clearedRedo );
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetUndoActionId( USHORT nNo ) const
+bool SfxUndoManager::ImplAddUndoAction_NoNotify( SfxUndoAction *pAction, bool bTryMerge, bool bClearRedo, UndoManagerGuard& i_guard )
{
- DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoActionId(), illegal id!" );
- if( nNo < pActUndoArray->nCurUndoAction )
+ if ( !ImplIsUndoEnabled_Lock() || ( m_pData->pActUndoArray->nMaxUndoActions == 0 ) )
{
- return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]->GetId(); //!
+ i_guard.markForDeletion( pAction );
+ return false;
}
- else
+
+ // merge, if required
+ SfxUndoAction* pMergeWithAction = m_pData->pActUndoArray->nCurUndoAction ?
+ m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1].pAction : NULL;
+ if ( bTryMerge && ( !pMergeWithAction || !pMergeWithAction->Merge( pAction ) ) )
{
- return 0;
+ i_guard.markForDeletion( pAction );
+ return false;
}
+
+ // clear redo stack, if requested
+ if ( bClearRedo && ( ImplGetRedoActionCount_Lock( CurrentLevel ) > 0 ) )
+ ImplClearRedo( i_guard, IUndoManager::CurrentLevel );
+
+ // respect max number
+ if( m_pData->pActUndoArray == m_pData->pUndoArray )
+ {
+ while( m_pData->pActUndoArray->aUndoActions.size() >=
+ m_pData->pActUndoArray->nMaxUndoActions &&
+ !m_pData->pActUndoArray->aUndoActions[0].pAction->IsLinked() )
+ {
+ i_guard.markForDeletion( m_pData->pActUndoArray->aUndoActions[0].pAction );
+ m_pData->pActUndoArray->aUndoActions.Remove(0);
+ --m_pData->pActUndoArray->nCurUndoAction;
+ }
+ }
+
+ // append new action
+ m_pData->pActUndoArray->aUndoActions.Insert( pAction, m_pData->pActUndoArray->nCurUndoAction++ );
+ return true;
}
//------------------------------------------------------------------------
-SfxUndoAction* SfxUndoManager::GetUndoAction( USHORT nNo ) const
+void SfxUndoManager::AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerge )
{
- DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoAction(), illegal id!" );
- if( nNo < pActUndoArray->nCurUndoAction )
+ UndoManagerGuard aGuard( *m_pData );
+
+ // add
+ if ( ImplAddUndoAction_NoNotify( pAction, bTryMerge, true, aGuard ) )
{
- return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]; //!
+ // notify listeners
+ aGuard.scheduleNotification( &SfxUndoListener::undoActionAdded, pAction->GetComment() );
}
- else
+}
+
+//------------------------------------------------------------------------
+
+size_t SfxUndoManager::GetUndoActionCount( bool const i_currentLevel ) const
+{
+ UndoManagerGuard aGuard( *m_pData );
+ const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
+ return pUndoArray->nCurUndoAction;
+}
+
+//------------------------------------------------------------------------
+
+XubString SfxUndoManager::GetUndoActionComment( size_t nNo, bool const i_currentLevel ) const
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ String sComment;
+ const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
+ DBG_ASSERT( nNo < pUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoActionComment: illegal index!" );
+ if( nNo < pUndoArray->nCurUndoAction )
{
- return 0;
+ sComment = pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction - 1 - nNo ].pAction->GetComment();
}
+ return sComment;
+}
+
+//------------------------------------------------------------------------
+
+USHORT SfxUndoManager::GetUndoActionId() const
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ DBG_ASSERT( m_pData->pActUndoArray->nCurUndoAction > 0, "svl::SfxUndoManager::GetUndoActionId(), illegal id!" );
+ if ( m_pData->pActUndoArray->nCurUndoAction == 0 )
+ return NULL;
+ return m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1].pAction->GetId();
+}
+
+//------------------------------------------------------------------------
+
+SfxUndoAction* SfxUndoManager::GetUndoAction( size_t nNo ) const
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ DBG_ASSERT( nNo < m_pData->pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoAction(), illegal id!" );
+ if( nNo >= m_pData->pActUndoArray->nCurUndoAction )
+ return NULL;
+ return m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1-nNo].pAction;
}
//------------------------------------------------------------------------
@@ -357,158 +732,235 @@ SfxUndoAction* SfxUndoManager::GetUndoAction( USHORT nNo ) const
/** clears the redo stack and removes the top undo action */
void SfxUndoManager::RemoveLastUndoAction()
{
- DBG_ASSERT( pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::RemoveLastUndoAction(), no action to remove?!" );
- if( pActUndoArray->nCurUndoAction )
- {
- pActUndoArray->nCurUndoAction--;
+ UndoManagerGuard aGuard( *m_pData );
- // delete redo-actions and top action
- USHORT nPos;
- for ( nPos = pActUndoArray->aUndoActions.Count(); nPos > pActUndoArray->nCurUndoAction; --nPos )
- delete pActUndoArray->aUndoActions[nPos-1];
+ ENSURE_OR_RETURN_VOID( m_pData->pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::RemoveLastUndoAction(), no action to remove?!" );
- pActUndoArray->aUndoActions.Remove(
- pActUndoArray->nCurUndoAction,
- pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction );
+ m_pData->pActUndoArray->nCurUndoAction--;
+
+ // delete redo-actions and top action
+ for ( size_t nPos = m_pData->pActUndoArray->aUndoActions.size(); nPos > m_pData->pActUndoArray->nCurUndoAction; --nPos )
+ {
+ aGuard.markForDeletion( m_pData->pActUndoArray->aUndoActions[nPos-1].pAction );
}
+
+ m_pData->pActUndoArray->aUndoActions.Remove(
+ m_pData->pActUndoArray->nCurUndoAction,
+ m_pData->pActUndoArray->aUndoActions.size() - m_pData->pActUndoArray->nCurUndoAction );
}
//------------------------------------------------------------------------
-BOOL SfxUndoManager::Undo( USHORT )
+bool SfxUndoManager::IsDoing() const
{
- bool bUndoWasEnabled = mbUndoEnabled;
- mbUndoEnabled = false;
+ UndoManagerGuard aGuard( *m_pData );
+ return m_pData->mbDoing;
+}
- BOOL bRet = FALSE;
+//------------------------------------------------------------------------
- try
- {
- DBG_ASSERT( pActUndoArray == pUndoArray, "svl::SfxUndoManager::Undo(), LeaveListAction() not yet called!" );
- if ( pActUndoArray->nCurUndoAction )
- {
- Undo( *pActUndoArray->aUndoActions[ --pActUndoArray->nCurUndoAction ] );
- bRet = TRUE;
- }
- }
- catch( Exception& e )
- {
- mbUndoEnabled = bUndoWasEnabled;
- throw e;
- }
- mbUndoEnabled = bUndoWasEnabled;
- return bRet;
+BOOL SfxUndoManager::Undo()
+{
+ return ImplUndo( NULL );
+}
+
+//------------------------------------------------------------------------
+
+BOOL SfxUndoManager::UndoWithContext( SfxUndoContext& i_context )
+{
+ return ImplUndo( &i_context );
}
//------------------------------------------------------------------------
-void SfxUndoManager::Undo( SfxUndoAction &rAction )
+BOOL SfxUndoManager::ImplUndo( SfxUndoContext* i_contextOrNull )
{
- bool bUndoWasEnabled = mbUndoEnabled;
- mbUndoEnabled = false;
+ UndoManagerGuard aGuard( *m_pData );
+ OSL_ENSURE( !IsDoing(), "SfxUndoManager::Undo: *nested* Undo/Redo actions? How this?" );
+
+ ::comphelper::FlagGuard aDoingGuard( m_pData->mbDoing );
+ LockGuard aLockGuard( *this );
+
+ if ( ImplIsInListAction_Lock() )
+ {
+ OSL_ENSURE( false, "SfxUndoManager::Undo: not possible when within a list action!" );
+ return FALSE;
+ }
+
+ if ( m_pData->pActUndoArray->nCurUndoAction == 0 )
+ {
+ OSL_ENSURE( false, "SfxUndoManager::Undo: undo stack is empty!" );
+ return FALSE;
+ }
+
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ --m_pData->pActUndoArray->nCurUndoAction ].pAction;
+ const String sActionComment = pAction->GetComment();
try
{
- rAction.Undo();
+ // clear the guard/mutex before calling into the SfxUndoAction - this can be an extension-implemented UNO component
+ // nowadays ...
+ aGuard.clear();
+ if ( i_contextOrNull != NULL )
+ pAction->UndoWithContext( *i_contextOrNull );
+ else
+ pAction->Undo();
+ aGuard.reset();
}
- catch( Exception& e )
+ catch( ... )
{
- mbUndoEnabled = bUndoWasEnabled;
- throw e;
+ aGuard.reset();
+
+ // in theory, somebody might have tampered with all of *m_pData while the mutex was unlocked. So, see if
+ // we still find pAction in our current Undo array
+ size_t nCurAction = 0;
+ while ( nCurAction < m_pData->pActUndoArray->aUndoActions.size() )
+ {
+ if ( m_pData->pActUndoArray->aUndoActions[ nCurAction++ ].pAction == pAction )
+ {
+ // the Undo action is still there ...
+ // assume the error is a permanent failure, and clear the Undo stack
+ ImplClearUndo( aGuard );
+ throw;
+ }
+ }
+ OSL_ENSURE( false, "SfxUndoManager::Undo: can't clear the Undo stack after the failure - some other party was faster ..." );
+ throw;
}
- mbUndoEnabled = bUndoWasEnabled;
+ aGuard.scheduleNotification( &SfxUndoListener::actionUndone, sActionComment );
+
+ return TRUE;
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetRedoActionCount() const
+size_t SfxUndoManager::GetRedoActionCount( bool const i_currentLevel ) const
{
- return pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction; //!
+ UndoManagerGuard aGuard( *m_pData );
+ return ImplGetRedoActionCount_Lock( i_currentLevel );
}
//------------------------------------------------------------------------
-XubString SfxUndoManager::GetRedoActionComment( USHORT nNo ) const
+size_t SfxUndoManager::ImplGetRedoActionCount_Lock( bool const i_currentLevel ) const
{
- return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction+nNo]->GetComment(); //!
+ const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
+ return pUndoArray->aUndoActions.size() - pUndoArray->nCurUndoAction;
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetRedoActionId( USHORT nNo ) const
+XubString SfxUndoManager::GetRedoActionComment( size_t nNo, bool const i_currentLevel ) const
{
- return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction+nNo]->GetId(); //!
+ UndoManagerGuard aGuard( *m_pData );
+ const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
+ return pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction + nNo ].pAction->GetComment();
}
//------------------------------------------------------------------------
-BOOL SfxUndoManager::Redo( USHORT )
+BOOL SfxUndoManager::Redo()
{
- bool bUndoWasEnabled = mbUndoEnabled;
- mbUndoEnabled = false;
-
- BOOL bRet = FALSE;
+ return ImplRedo( NULL );
+}
- try
- {
- if ( pActUndoArray->aUndoActions.Count() > pActUndoArray->nCurUndoAction )
- {
- Redo( *pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction++] );
- bRet = TRUE;
- }
- }
- catch( Exception& e )
- {
- mbUndoEnabled = bUndoWasEnabled;
- throw e;
- }
+//------------------------------------------------------------------------
- mbUndoEnabled = bUndoWasEnabled;
- return bRet;
+BOOL SfxUndoManager::RedoWithContext( SfxUndoContext& i_context )
+{
+ return ImplRedo( &i_context );
}
//------------------------------------------------------------------------
-void SfxUndoManager::Redo( SfxUndoAction &rAction )
+BOOL SfxUndoManager::ImplRedo( SfxUndoContext* i_contextOrNull )
{
- bool bUndoWasEnabled = mbUndoEnabled;
- mbUndoEnabled = false;
+ UndoManagerGuard aGuard( *m_pData );
+ OSL_ENSURE( !IsDoing(), "SfxUndoManager::Redo: *nested* Undo/Redo actions? How this?" );
+ ::comphelper::FlagGuard aDoingGuard( m_pData->mbDoing );
+ LockGuard aLockGuard( *this );
+
+ if ( ImplIsInListAction_Lock() )
+ {
+ OSL_ENSURE( false, "SfxUndoManager::Redo: not possible when within a list action!" );
+ return FALSE;
+ }
+
+ if ( m_pData->pActUndoArray->nCurUndoAction >= m_pData->pActUndoArray->aUndoActions.size() )
+ {
+ OSL_ENSURE( false, "SfxUndoManager::Redo: redo stack is empty!" );
+ return FALSE;
+ }
+
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction++ ].pAction;
+ const String sActionComment = pAction->GetComment();
try
{
- rAction.Redo();
+ // clear the guard/mutex before calling into the SfxUndoAction - this can be a extension-implemented UNO component
+ // nowadays ...
+ aGuard.clear();
+ if ( i_contextOrNull != NULL )
+ pAction->RedoWithContext( *i_contextOrNull );
+ else
+ pAction->Redo();
+ aGuard.reset();
}
- catch( Exception& e )
+ catch( ... )
{
- mbUndoEnabled = bUndoWasEnabled;
- throw e;
+ aGuard.reset();
+
+ // in theory, somebody might have tampered with all of *m_pData while the mutex was unlocked. So, see if
+ // we still find pAction in our current Undo array
+ size_t nCurAction = 0;
+ while ( nCurAction < m_pData->pActUndoArray->aUndoActions.size() )
+ {
+ if ( m_pData->pActUndoArray->aUndoActions[ nCurAction ].pAction == pAction )
+ {
+ // the Undo action is still there ...
+ // assume the error is a permanent failure, and clear the Undo stack
+ ImplClearRedo( aGuard, IUndoManager::CurrentLevel );
+ throw;
+ }
+ ++nCurAction;
+ }
+ OSL_ENSURE( false, "SfxUndoManager::Redo: can't clear the Undo stack after the failure - some other party was faster ..." );
+ throw;
}
- mbUndoEnabled = bUndoWasEnabled;
+ aGuard.scheduleNotification( &SfxUndoListener::actionRedone, sActionComment );
+
+ return TRUE;
}
//------------------------------------------------------------------------
-USHORT SfxUndoManager::GetRepeatActionCount() const
+size_t SfxUndoManager::GetRepeatActionCount() const
{
- return pActUndoArray->aUndoActions.Count();
+ UndoManagerGuard aGuard( *m_pData );
+ return m_pData->pActUndoArray->aUndoActions.size();
}
//------------------------------------------------------------------------
-XubString SfxUndoManager::GetRepeatActionComment( SfxRepeatTarget &rTarget, USHORT nNo ) const
+XubString SfxUndoManager::GetRepeatActionComment( SfxRepeatTarget &rTarget) const
{
- return pActUndoArray->aUndoActions[ pActUndoArray->aUndoActions.Count() - 1 - nNo ]
+ UndoManagerGuard aGuard( *m_pData );
+ return m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->aUndoActions.size() - 1 ].pAction
->GetRepeatComment(rTarget);
}
//------------------------------------------------------------------------
-BOOL SfxUndoManager::Repeat( SfxRepeatTarget &rTarget, USHORT /*nFrom*/, USHORT /*nCount*/ )
+BOOL SfxUndoManager::Repeat( SfxRepeatTarget &rTarget )
{
- if ( pActUndoArray->aUndoActions.Count() )
+ UndoManagerGuard aGuard( *m_pData );
+ if ( !m_pData->pActUndoArray->aUndoActions.empty() )
{
- Repeat( rTarget, *pActUndoArray->aUndoActions[ pActUndoArray->aUndoActions.Count() - 1 ] );
+ SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->aUndoActions.size() - 1 ].pAction;
+ aGuard.clear();
+ if ( pAction->CanRepeat( rTarget ) )
+ pAction->Repeat( rTarget );
return TRUE;
}
@@ -517,30 +969,41 @@ BOOL SfxUndoManager::Repeat( SfxRepeatTarget &rTarget, USHORT /*nFrom*/, USHORT
//------------------------------------------------------------------------
-void SfxUndoManager::Repeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction )
+BOOL SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget ) const
{
- if ( rAction.CanRepeat(rTarget) )
- rAction.Repeat(rTarget);
+ UndoManagerGuard aGuard( *m_pData );
+ if ( !m_pData->pActUndoArray->aUndoActions.empty() )
+ {
+ size_t nActionNo = m_pData->pActUndoArray->aUndoActions.size() - 1;
+ return m_pData->pActUndoArray->aUndoActions[nActionNo].pAction->CanRepeat(rTarget);
+ }
+ return FALSE;
}
//------------------------------------------------------------------------
-BOOL SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction ) const
+void SfxUndoManager::AddUndoListener( SfxUndoListener& i_listener )
{
- return rAction.CanRepeat(rTarget);
+ UndoManagerGuard aGuard( *m_pData );
+ m_pData->aListeners.push_back( &i_listener );
}
//------------------------------------------------------------------------
-BOOL SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget, USHORT nNo ) const
+void SfxUndoManager::RemoveUndoListener( SfxUndoListener& i_listener )
{
- if ( pActUndoArray->aUndoActions.Count() > nNo )
+ UndoManagerGuard aGuard( *m_pData );
+ for ( UndoListeners::iterator lookup = m_pData->aListeners.begin();
+ lookup != m_pData->aListeners.end();
+ ++lookup
+ )
{
- USHORT nActionNo = pActUndoArray->aUndoActions.Count() - 1 - nNo;
- return pActUndoArray->aUndoActions[nActionNo]->CanRepeat(rTarget);
+ if ( (*lookup) == &i_listener )
+ {
+ m_pData->aListeners.erase( lookup );
+ break;
+ }
}
-
- return FALSE;
}
//------------------------------------------------------------------------
@@ -554,69 +1017,270 @@ void SfxUndoManager::EnterListAction(
*/
{
- if( !mbUndoEnabled )
+ UndoManagerGuard aGuard( *m_pData );
+
+ if( !ImplIsUndoEnabled_Lock() )
return;
- if ( !pUndoArray->nMaxUndoActions )
+ if ( !m_pData->pUndoArray->nMaxUndoActions )
return;
- pFatherUndoArray=pActUndoArray;
- SfxListUndoAction *pAction=new SfxListUndoAction(
- rComment, rRepeatComment, nId, pActUndoArray);
- AddUndoAction( pAction );
- pActUndoArray=pAction;
+ m_pData->pFatherUndoArray = m_pData->pActUndoArray;
+ SfxListUndoAction* pAction = new SfxListUndoAction( rComment, rRepeatComment, nId, m_pData->pActUndoArray );
+ OSL_VERIFY( ImplAddUndoAction_NoNotify( pAction, false, false, aGuard ) );
+ // expected to succeed: all conditions under which it could fail should have been checked already
+ m_pData->pActUndoArray = pAction;
+
+ // notification
+ aGuard.scheduleNotification( &SfxUndoListener::listActionEntered, rComment );
}
//------------------------------------------------------------------------
-void SfxUndoManager::LeaveListAction()
+bool SfxUndoManager::IsInListAction() const
+{
+ UndoManagerGuard aGuard( *m_pData );
+ return ImplIsInListAction_Lock();
+}
-/* [Beschreibung]
+//------------------------------------------------------------------------
- Verlaesst die aktuelle ListAction und geht eine Ebene nach oben.
-*/
+bool SfxUndoManager::ImplIsInListAction_Lock() const
{
- if ( !mbUndoEnabled )
- return;
+ return ( m_pData->pActUndoArray != m_pData->pUndoArray );
+}
- if ( !pUndoArray->nMaxUndoActions )
- return;
+//------------------------------------------------------------------------
+
+size_t SfxUndoManager::GetListActionDepth() const
+{
+ UndoManagerGuard aGuard( *m_pData );
+ size_t nDepth(0);
- if( pActUndoArray == pUndoArray )
+ SfxUndoArray* pLookup( m_pData->pActUndoArray );
+ while ( pLookup != m_pData->pUndoArray )
{
- DBG_ERROR( "svl::SfxUndoManager::LeaveListAction(), called without calling EnterListAction()!" );
- return;
+ pLookup = pLookup->pFatherUndoArray;
+ ++nDepth;
}
- DBG_ASSERT(pActUndoArray->pFatherUndoArray,"svl::SfxUndoManager::LeaveListAction(), no father undo array!?");
+ return nDepth;
+}
+
+//------------------------------------------------------------------------
- SfxUndoArray* pTmp=pActUndoArray;
- pActUndoArray=pActUndoArray->pFatherUndoArray;
+size_t SfxUndoManager::LeaveListAction()
+{
+ UndoManagerGuard aGuard( *m_pData );
+ size_t nCount = ImplLeaveListAction( false, aGuard );
- // If no undo action where added, delete the undo list action
- SfxUndoAction *pTmpAction= pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1];
- if(!pTmp->nCurUndoAction)
+ if ( m_pData->mbClearUntilTopLevel )
{
- pActUndoArray->aUndoActions.Remove( --pActUndoArray->nCurUndoAction);
- delete pTmpAction;
+ ImplClearCurrentLevel_NoNotify( aGuard );
+ if ( !ImplIsInListAction_Lock() )
+ {
+ m_pData->mbClearUntilTopLevel = false;
+ aGuard.scheduleNotification( &SfxUndoListener::cleared );
+ }
+ nCount = 0;
}
- else
+
+ return nCount;
+}
+
+//------------------------------------------------------------------------
+
+size_t SfxUndoManager::LeaveAndMergeListAction()
+{
+ UndoManagerGuard aGuard( *m_pData );
+ return ImplLeaveListAction( true, aGuard );
+}
+
+//------------------------------------------------------------------------
+
+size_t SfxUndoManager::ImplLeaveListAction( const bool i_merge, UndoManagerGuard& i_guard )
+{
+ if ( !ImplIsUndoEnabled_Lock() )
+ return 0;
+
+ if ( !m_pData->pUndoArray->nMaxUndoActions )
+ return 0;
+
+ if( !ImplIsInListAction_Lock() )
+ {
+ DBG_ERROR( "svl::SfxUndoManager::ImplLeaveListAction, called without calling EnterListAction()!" );
+ return 0;
+ }
+
+ DBG_ASSERT( m_pData->pActUndoArray->pFatherUndoArray, "SfxUndoManager::ImplLeaveListAction, no father undo array!?" );
+
+ // the array/level which we're about to leave
+ SfxUndoArray* pArrayToLeave = m_pData->pActUndoArray;
+ // one step up
+ m_pData->pActUndoArray = m_pData->pActUndoArray->pFatherUndoArray;
+
+ // If no undo actions were added to the list, delete the list action
+ const size_t nListActionElements = pArrayToLeave->nCurUndoAction;
+ if ( nListActionElements == 0 )
+ {
+ SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ].pAction;
+ m_pData->pActUndoArray->aUndoActions.Remove( --m_pData->pActUndoArray->nCurUndoAction );
+ i_guard.markForDeletion( pCurrentAction );
+
+ i_guard.scheduleNotification( &SfxUndoListener::listActionCancelled );
+ return 0;
+ }
+
+ // now that it is finally clear the list action is non-trivial, and does participate in the Undo stack, clear
+ // the redo stack
+ ImplClearRedo( i_guard, IUndoManager::CurrentLevel );
+
+ SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ].pAction;
+ SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction * >( pCurrentAction );
+ ENSURE_OR_RETURN( pListAction, "SfxUndoManager::ImplLeaveListAction: list action expected at this position!", nListActionElements );
+
+ if ( i_merge )
+ {
+ // merge the list action with its predecessor on the same level
+ OSL_ENSURE( m_pData->pActUndoArray->nCurUndoAction > 1,
+ "SfxUndoManager::ImplLeaveListAction: cannot merge the list action if there's no other action on the same level - check this beforehand!" );
+ if ( m_pData->pActUndoArray->nCurUndoAction > 1 )
+ {
+ SfxUndoAction* pPreviousAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction - 2 ].pAction;
+ m_pData->pActUndoArray->aUndoActions.Remove( m_pData->pActUndoArray->nCurUndoAction - 2 );
+ --m_pData->pActUndoArray->nCurUndoAction;
+ pListAction->aUndoActions.Insert( pPreviousAction, 0 );
+ ++pListAction->nCurUndoAction;
+
+ pListAction->SetComment( pPreviousAction->GetComment() );
+ }
+ }
+
+ // if the undo array has no comment, try to get it from its children
+ if ( pListAction->GetComment().Len() == 0 )
+ {
+ for( size_t n = 0; n < pListAction->aUndoActions.size(); n++ )
+ {
+ if( pListAction->aUndoActions[n].pAction->GetComment().Len() )
+ {
+ pListAction->SetComment( pListAction->aUndoActions[n].pAction->GetComment() );
+ break;
+ }
+ }
+ }
+
+ // notify listeners
+ i_guard.scheduleNotification( &SfxUndoListener::listActionLeft, pListAction->GetComment() );
+
+ // outta here
+ return nListActionElements;
+}
+
+//------------------------------------------------------------------------
+UndoStackMark SfxUndoManager::MarkTopUndoAction()
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ OSL_ENSURE( !IsInListAction(),
+ "SfxUndoManager::MarkTopUndoAction(): suspicious call!" );
+ OSL_ENSURE((m_pData->mnMarks + 1) < (m_pData->mnEmptyMark - 1),
+ "SfxUndoManager::MarkTopUndoAction(): mark overflow!");
+
+ size_t const nActionPos = m_pData->pUndoArray->nCurUndoAction;
+ if (0 == nActionPos)
+ {
+ --m_pData->mnEmptyMark;
+ return m_pData->mnEmptyMark;
+ }
+
+ m_pData->pUndoArray->aUndoActions[ nActionPos-1 ].aMarks.push_back(
+ ++m_pData->mnMarks );
+ return m_pData->mnMarks;
+}
+
+//------------------------------------------------------------------------
+void SfxUndoManager::RemoveMark( UndoStackMark const i_mark )
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ if ((m_pData->mnEmptyMark < i_mark) || (MARK_INVALID == i_mark))
{
- // if the undo array has no comment, try to get it from its children
- SfxListUndoAction* pList = dynamic_cast< SfxListUndoAction * >( pTmpAction );
- if( pList && pList->GetComment().Len() == 0 )
+ return; // nothing to remove
+ }
+ else if (i_mark == m_pData->mnEmptyMark)
+ {
+ --m_pData->mnEmptyMark; // never returned from MarkTop => invalid
+ return;
+ }
+
+ for ( size_t i=0; i<m_pData->pUndoArray->aUndoActions.size(); ++i )
+ {
+ MarkedUndoAction& rAction = m_pData->pUndoArray->aUndoActions[i];
+ for ( ::std::vector< UndoStackMark >::iterator markPos = rAction.aMarks.begin();
+ markPos != rAction.aMarks.end();
+ ++markPos
+ )
{
- USHORT n;
- for( n = 0; n < pList->aUndoActions.Count(); n++ )
+ if ( *markPos == i_mark )
{
- if( pList->aUndoActions[n]->GetComment().Len() )
- {
- pList->SetComment( pList->aUndoActions[n]->GetComment() );
- break;
- }
+ rAction.aMarks.erase( markPos );
+ return;
}
}
}
+ OSL_ENSURE( false, "SfxUndoManager::RemoveMark: mark not found!" );
+ // TODO: this might be too offensive. There are situations where we implicitly remove marks
+ // without our clients, in particular the client which created the mark, having a chance to know
+ // about this.
+}
+
+//------------------------------------------------------------------------
+bool SfxUndoManager::HasTopUndoActionMark( UndoStackMark const i_mark )
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ size_t nActionPos = m_pData->pUndoArray->nCurUndoAction;
+ if ( nActionPos == 0 )
+ {
+ return (i_mark == m_pData->mnEmptyMark);
+ }
+
+ const MarkedUndoAction& rAction =
+ m_pData->pUndoArray->aUndoActions[ nActionPos-1 ];
+ for ( ::std::vector< UndoStackMark >::const_iterator markPos = rAction.aMarks.begin();
+ markPos != rAction.aMarks.end();
+ ++markPos
+ )
+ {
+ if ( *markPos == i_mark )
+ return true;
+ }
+
+ return false;
+}
+
+//------------------------------------------------------------------------
+
+void SfxUndoManager::RemoveOldestUndoActions( size_t const i_count )
+{
+ UndoManagerGuard aGuard( *m_pData );
+
+ size_t nActionsToRemove = i_count;
+ while ( nActionsToRemove )
+ {
+ SfxUndoAction* pActionToRemove = m_pData->pUndoArray->aUndoActions[0].pAction;
+
+ if ( IsInListAction() && ( m_pData->pUndoArray->nCurUndoAction == 1 ) )
+ {
+ OSL_ENSURE( false, "SfxUndoManager::RemoveOldestUndoActions: cannot remove a not-yet-closed list action!" );
+ return;
+ }
+
+ aGuard.markForDeletion( pActionToRemove );
+ m_pData->pUndoArray->aUndoActions.Remove( 0 );
+ --m_pData->pUndoArray->nCurUndoAction;
+ --nActionsToRemove;
+ }
}
//------------------------------------------------------------------------
@@ -667,8 +1331,17 @@ SfxListUndoAction::SfxListUndoAction
void SfxListUndoAction::Undo()
{
- for(INT16 i=nCurUndoAction-1;i>=0;i--)
- aUndoActions[i]->Undo();
+ for(size_t i=nCurUndoAction;i>0;)
+ aUndoActions[--i].pAction->Undo();
+ nCurUndoAction=0;
+}
+
+//------------------------------------------------------------------------
+
+void SfxListUndoAction::UndoWithContext( SfxUndoContext& i_context )
+{
+ for(size_t i=nCurUndoAction;i>0;)
+ aUndoActions[--i].pAction->UndoWithContext( i_context );
nCurUndoAction=0;
}
@@ -676,25 +1349,34 @@ void SfxListUndoAction::Undo()
void SfxListUndoAction::Redo()
{
- for(USHORT i=nCurUndoAction;i<aUndoActions.Count();i++)
- aUndoActions[i]->Redo();
- nCurUndoAction = aUndoActions.Count();
+ for(size_t i=nCurUndoAction;i<aUndoActions.size();i++)
+ aUndoActions[i].pAction->Redo();
+ nCurUndoAction = aUndoActions.size();
+}
+
+//------------------------------------------------------------------------
+
+void SfxListUndoAction::RedoWithContext( SfxUndoContext& i_context )
+{
+ for(size_t i=nCurUndoAction;i<aUndoActions.size();i++)
+ aUndoActions[i].pAction->RedoWithContext( i_context );
+ nCurUndoAction = aUndoActions.size();
}
//------------------------------------------------------------------------
void SfxListUndoAction::Repeat(SfxRepeatTarget&rTarget)
{
- for(USHORT i=0;i<nCurUndoAction;i++)
- aUndoActions[i]->Repeat(rTarget);
+ for(size_t i=0;i<nCurUndoAction;i++)
+ aUndoActions[i].pAction->Repeat(rTarget);
}
//------------------------------------------------------------------------
BOOL SfxListUndoAction::CanRepeat(SfxRepeatTarget&r) const
{
- for(USHORT i=0;i<nCurUndoAction;i++)
- if(!aUndoActions[i]->CanRepeat(r))
+ for(size_t i=0;i<nCurUndoAction;i++)
+ if(!aUndoActions[i].pAction->CanRepeat(r))
return FALSE;
return TRUE;
}
@@ -703,12 +1385,12 @@ BOOL SfxListUndoAction::CanRepeat(SfxRepeatTarget&r) const
BOOL SfxListUndoAction::Merge( SfxUndoAction *pNextAction )
{
- return aUndoActions.Count() && aUndoActions[aUndoActions.Count()-1]->Merge( pNextAction );
+ return !aUndoActions.empty() && aUndoActions[aUndoActions.size()-1].pAction->Merge( pNextAction );
}
//------------------------------------------------------------------------
-SfxLinkUndoAction::SfxLinkUndoAction(SfxUndoManager *pManager)
+SfxLinkUndoAction::SfxLinkUndoAction(::svl::IUndoManager *pManager)
/* [Beschreibung]
Richtet eine LinkAction ein, die auf einen weiteren UndoManager zeigt.
@@ -718,10 +1400,15 @@ SfxLinkUndoAction::SfxLinkUndoAction(SfxUndoManager *pManager)
{
pUndoManager = pManager;
+ SfxUndoManager* pUndoManagerImplementation = dynamic_cast< SfxUndoManager* >( pManager );
+ ENSURE_OR_THROW( pUndoManagerImplementation != NULL, "unsupported undo manager implementation!" );
+ // yes, this cast is dirty. But reaching into the the SfxUndoManager's implementation,
+ // directly accessing its internal stack, and tampering with an action on that stack
+ // is dirty, too.
if ( pManager->GetMaxUndoActionCount() )
{
- USHORT nPos = pManager->GetUndoActionCount()-1;
- pAction = pManager->pActUndoArray->aUndoActions[nPos];
+ size_t nPos = pManager->GetUndoActionCount()-1;
+ pAction = pUndoManagerImplementation->m_pData->pActUndoArray->aUndoActions[nPos].pAction;
pAction->SetLinked();
}
else
@@ -733,7 +1420,7 @@ SfxLinkUndoAction::SfxLinkUndoAction(SfxUndoManager *pManager)
void SfxLinkUndoAction::Undo()
{
if ( pAction )
- pUndoManager->Undo(1);
+ pUndoManager->Undo();
}
//------------------------------------------------------------------------
@@ -741,7 +1428,7 @@ void SfxLinkUndoAction::Undo()
void SfxLinkUndoAction::Redo()
{
if ( pAction )
- pUndoManager->Redo(1);
+ pUndoManager->Redo();
}
//------------------------------------------------------------------------
@@ -749,7 +1436,7 @@ void SfxLinkUndoAction::Redo()
BOOL SfxLinkUndoAction::CanRepeat(SfxRepeatTarget& r) const
{
- return pAction && pUndoManager->CanRepeat(r,*pAction);
+ return pAction && pAction->CanRepeat(r);
}
@@ -758,8 +1445,8 @@ BOOL SfxLinkUndoAction::CanRepeat(SfxRepeatTarget& r) const
void SfxLinkUndoAction::Repeat(SfxRepeatTarget&r)
{
- if ( pAction )
- pUndoManager->Repeat(r,*pAction);
+ if ( pAction && pAction->CanRepeat( r ) )
+ pAction->Repeat( r );
}
@@ -797,11 +1484,10 @@ SfxLinkUndoAction::~SfxLinkUndoAction()
SfxUndoArray::~SfxUndoArray()
{
- while ( aUndoActions.Count() )
+ while ( !aUndoActions.empty() )
{
- SfxUndoAction *pAction =
- aUndoActions[ aUndoActions.Count() - 1 ];
- aUndoActions.Remove( aUndoActions.Count() - 1 );
+ SfxUndoAction *pAction = aUndoActions[ aUndoActions.size() - 1 ].pAction;
+ aUndoActions.Remove( aUndoActions.size() - 1 );
delete pAction;
}
}
@@ -811,6 +1497,3 @@ USHORT SfxLinkUndoAction::GetId() const
{
return pAction ? pAction->GetId() : 0;
}
-
-
-
diff --git a/svtools/inc/svtools/textdata.hxx b/svtools/inc/svtools/textdata.hxx
index 809d64248eb6..d0182e6a2c77 100644
--- a/svtools/inc/svtools/textdata.hxx
+++ b/svtools/inc/svtools/textdata.hxx
@@ -33,26 +33,6 @@
#include <svl/smplhint.hxx>
#include <tools/string.hxx>
-#define TEXTUNDO_START 100
-#define TEXTUNDO_REMOVECHARS 100
-#define TEXTUNDO_CONNECTPARAS 101
-#define TEXTUNDO_SPLITPARA 102
-#define TEXTUNDO_INSERTCHARS 103
-#define TEXTUNDO_DELCONTENT 104
-#define TEXTUNDO_DELETE 105
-#define TEXTUNDO_CUT 106
-#define TEXTUNDO_PASTE 107
-#define TEXTUNDO_INSERT 108
-#define TEXTUNDO_ATTRIBS 109
-#define TEXTUNDO_DRAGANDDROP 110
-#define TEXTUNDO_READ 111
-#define TEXTUNDO_END 149
-
-#define XTEXTUNDO_START 150
-#define XTEXTUNDO_END 199
-
-#define TEXTUNDO_USER 200
-
// Fuer Notify, wenn alle Absaetze geloescht wurden...
#define TEXT_PARA_ALL 0xFFFFFFFF
diff --git a/svtools/inc/svtools/texteng.hxx b/svtools/inc/svtools/texteng.hxx
index ef27edee2efe..ee49316c317f 100644
--- a/svtools/inc/svtools/texteng.hxx
+++ b/svtools/inc/svtools/texteng.hxx
@@ -39,7 +39,6 @@ class TextAttrib;
class TextCharAttrib;
class TextUndo;
class TextUndoManager;
-class SfxUndoManager;
class EditSelFunctionSet;
class EditSelEngine;
class IdleFormatter;
@@ -49,6 +48,11 @@ class SfxUndoAction;
class KeyEvent;
class Timer;
+namespace svl
+{
+ class IUndoManager;
+}
+
class TextLine;
class TETextPortion;
#include <svl/brdcst.hxx>
@@ -280,9 +284,10 @@ public:
BOOL IsRightToLeft() const { return mbRightToLeft; }
BOOL HasUndoManager() const { return mpUndoManager ? TRUE : FALSE; }
- SfxUndoManager& GetUndoManager();
- void UndoActionStart( USHORT nId );
- void UndoActionEnd( USHORT nId );
+ ::svl::IUndoManager&
+ GetUndoManager();
+ void UndoActionStart( USHORT nId = 0 );
+ void UndoActionEnd();
void InsertUndo( TextUndo* pUndo, BOOL bTryMerge = FALSE );
BOOL IsInUndo() { return mbIsInUndo; }
void SetIsInUndo( BOOL bInUndo ) { mbIsInUndo = bInUndo; }
diff --git a/svtools/inc/svtools/xtextedt.hxx b/svtools/inc/svtools/xtextedt.hxx
index 46c6441e005e..e95ba0b09359 100644
--- a/svtools/inc/svtools/xtextedt.hxx
+++ b/svtools/inc/svtools/xtextedt.hxx
@@ -31,10 +31,6 @@
#include <svtools/texteng.hxx>
#include <svtools/textview.hxx>
-#define XTEXTUNDO_REPLACEALL (XTEXTUNDO_START+1)
-#define XTEXTUNDO_INDENTBLOCK 122
-#define XTEXTUNDO_UNINDENTBLOCK 123
-
namespace com {
namespace sun {
namespace star {
diff --git a/svtools/source/edit/texteng.cxx b/svtools/source/edit/texteng.cxx
index e0e136089d78..c0afe8962009 100644
--- a/svtools/source/edit/texteng.cxx
+++ b/svtools/source/edit/texteng.cxx
@@ -763,7 +763,7 @@ TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel,
BOOL bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );
if ( bUndoAction )
- UndoActionStart( TEXTUNDO_INSERT );
+ UndoActionStart();
if ( rCurSel.HasRange() )
{
@@ -847,7 +847,7 @@ TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel,
TextModified();
if ( bUndoAction )
- UndoActionEnd( TEXTUNDO_INSERT );
+ UndoActionEnd();
}
return aPaM;
@@ -856,7 +856,7 @@ TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel,
TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, const XubString& rStr )
{
- UndoActionStart( TEXTUNDO_INSERT );
+ UndoActionStart();
TextPaM aPaM;
@@ -908,7 +908,7 @@ TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, const XubString
break;
}
- UndoActionEnd( TEXTUNDO_INSERT );
+ UndoActionEnd();
TextModified();
return aPaM;
@@ -1430,7 +1430,7 @@ void TextEngine::EnableUndo( BOOL bEnable )
mbUndoEnabled = bEnable;
}
-SfxUndoManager& TextEngine::GetUndoManager()
+::svl::IUndoManager& TextEngine::GetUndoManager()
{
if ( !mpUndoManager )
mpUndoManager = new TextUndoManager( this );
@@ -1447,7 +1447,7 @@ void TextEngine::UndoActionStart( USHORT nId )
}
}
-void TextEngine::UndoActionEnd( USHORT )
+void TextEngine::UndoActionEnd()
{
if ( IsUndoEnabled() && !IsInUndo() )
GetUndoManager().LeaveListAction();
@@ -2640,7 +2640,7 @@ BOOL TextEngine::Read( SvStream& rInput, const TextSelection* pSel )
BOOL bUpdate = GetUpdateMode();
SetUpdateMode( FALSE );
- UndoActionStart( TEXTUNDO_READ );
+ UndoActionStart();
TextSelection aSel;
if ( pSel )
aSel = *pSel;
@@ -2666,7 +2666,7 @@ BOOL TextEngine::Read( SvStream& rInput, const TextSelection* pSel )
aSel = ImpInsertParaBreak( aSel.GetEnd() );
}
- UndoActionEnd( TEXTUNDO_READ );
+ UndoActionEnd();
TextSelection aNewSel( aSel.GetEnd(), aSel.GetEnd() );
diff --git a/svtools/source/edit/textundo.cxx b/svtools/source/edit/textundo.cxx
index 4c243de16c31..2ad5e318e92f 100644
--- a/svtools/source/edit/textundo.cxx
+++ b/svtools/source/edit/textundo.cxx
@@ -54,7 +54,7 @@ TextUndoManager::~TextUndoManager()
{
}
-BOOL __EXPORT TextUndoManager::Undo( USHORT nCount )
+BOOL __EXPORT TextUndoManager::Undo()
{
if ( GetUndoActionCount() == 0 )
return FALSE;
@@ -62,7 +62,7 @@ BOOL __EXPORT TextUndoManager::Undo( USHORT nCount )
UndoRedoStart();
mpTextEngine->SetIsInUndo( TRUE );
- BOOL bDone = SfxUndoManager::Undo( nCount );
+ BOOL bDone = SfxUndoManager::Undo();
mpTextEngine->SetIsInUndo( FALSE );
UndoRedoEnd();
@@ -70,7 +70,7 @@ BOOL __EXPORT TextUndoManager::Undo( USHORT nCount )
return bDone;
}
-BOOL __EXPORT TextUndoManager::Redo( USHORT nCount )
+BOOL __EXPORT TextUndoManager::Redo()
{
if ( GetRedoActionCount() == 0 )
return FALSE;
@@ -79,7 +79,7 @@ BOOL __EXPORT TextUndoManager::Redo( USHORT nCount )
UndoRedoStart();
mpTextEngine->SetIsInUndo( TRUE );
- BOOL bDone = SfxUndoManager::Redo( nCount );
+ BOOL bDone = SfxUndoManager::Redo();
mpTextEngine->SetIsInUndo( FALSE );
UndoRedoEnd();
@@ -110,9 +110,8 @@ void TextUndoManager::UndoRedoEnd()
}
-TextUndo::TextUndo( USHORT nI, TextEngine* p )
+TextUndo::TextUndo( TextEngine* p )
{
- mnId = nI;
mpTextEngine = p;
}
@@ -120,12 +119,6 @@ TextUndo::~TextUndo()
{
}
-USHORT __EXPORT TextUndo::GetId() const
-{
- //nId sollte mal entfallen => GetId ueberall ueberladen...
- return mnId;
-}
-
XubString __EXPORT TextUndo::GetComment() const
{
// return mpTextEngine->GetUndoComment( this );
@@ -140,7 +133,7 @@ void TextUndo::SetSelection( const TextSelection& rSel )
TextUndoDelPara::TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, ULONG nPara )
- : TextUndo( TEXTUNDO_DELCONTENT, pTextEngine )
+ : TextUndo( pTextEngine )
{
mpNode = pNode;
mnPara = nPara;
@@ -191,7 +184,7 @@ void __EXPORT TextUndoDelPara::Redo()
// TextUndoConnectParas
// ------------------------------------------------------------------------
TextUndoConnectParas::TextUndoConnectParas( TextEngine* pTextEngine, ULONG nPara, USHORT nPos )
- : TextUndo( TEXTUNDO_CONNECTPARAS, pTextEngine )
+ : TextUndo( pTextEngine )
{
mnPara = nPara;
mnSepPos = nPos;
@@ -215,7 +208,7 @@ void __EXPORT TextUndoConnectParas::Redo()
TextUndoSplitPara::TextUndoSplitPara( TextEngine* pTextEngine, ULONG nPara, USHORT nPos )
- : TextUndo( TEXTUNDO_SPLITPARA, pTextEngine )
+ : TextUndo( pTextEngine )
{
mnPara = nPara;
mnSepPos = nPos;
@@ -239,7 +232,7 @@ void __EXPORT TextUndoSplitPara::Redo()
TextUndoInsertChars::TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr )
- : TextUndo( TEXTUNDO_INSERTCHARS, pTextEngine ),
+ : TextUndo( pTextEngine ),
maTextPaM( rTextPaM ), maText( rStr )
{
}
@@ -281,7 +274,7 @@ BOOL __EXPORT TextUndoInsertChars::Merge( SfxUndoAction* pNextAction )
TextUndoRemoveChars::TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr )
- : TextUndo( TEXTUNDO_REMOVECHARS, pTextEngine ),
+ : TextUndo( pTextEngine ),
maTextPaM( rTextPaM ), maText( rStr )
{
}
@@ -304,7 +297,7 @@ void __EXPORT TextUndoRemoveChars::Redo()
TextUndoSetAttribs::TextUndoSetAttribs( TextEngine* pTextEngine, const TextSelection& rSel )
- : TextUndo( TEXTUNDO_ATTRIBS, pTextEngine ), maSelection( rSel )
+ : TextUndo( pTextEngine ), maSelection( rSel )
{
maSelection.Justify();
// aNewAttribs.Set( rNewItems );
diff --git a/svtools/source/edit/textundo.hxx b/svtools/source/edit/textundo.hxx
index cc26c0b51ef6..69b5fc393744 100644
--- a/svtools/source/edit/textundo.hxx
+++ b/svtools/source/edit/textundo.hxx
@@ -47,16 +47,15 @@ public:
~TextUndoManager();
using SfxUndoManager::Undo;
- virtual BOOL Undo( USHORT nCount=1 );
+ virtual BOOL Undo();
using SfxUndoManager::Redo;
- virtual BOOL Redo( USHORT nCount=1 );
+ virtual BOOL Redo();
};
class TextUndo : public SfxUndoAction
{
private:
- USHORT mnId;
TextEngine* mpTextEngine;
protected:
@@ -69,7 +68,7 @@ protected:
public:
TYPEINFO();
- TextUndo( USHORT nId, TextEngine* pTextEngine );
+ TextUndo( TextEngine* pTextEngine );
virtual ~TextUndo();
TextEngine* GetTextEngine() const { return mpTextEngine; }
@@ -78,7 +77,6 @@ public:
virtual void Redo() = 0;
virtual XubString GetComment() const;
- virtual USHORT GetId() const;
};
#endif // _TEXTUNDO_HXX
diff --git a/svtools/source/edit/textview.cxx b/svtools/source/edit/textview.cxx
index 48cd23bdcc6f..64c6470be1e8 100644
--- a/svtools/source/edit/textview.cxx
+++ b/svtools/source/edit/textview.cxx
@@ -311,9 +311,9 @@ void TextView::DeleteSelected()
{
// HideSelection();
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_DELETE );
+ mpImpl->mpTextEngine->UndoActionStart();
TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_DELETE );
+ mpImpl->mpTextEngine->UndoActionEnd();
ImpSetSelection( aPaM );
mpImpl->mpTextEngine->FormatAndUpdate( this );
@@ -695,7 +695,7 @@ BOOL TextView::KeyInput( const KeyEvent& rKeyEvent )
default: break;
}
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_DELETE );
+ mpImpl->mpTextEngine->UndoActionStart();
if(mpImpl->mbSupportProtectAttribute)
{
//expand selection to include all protected content - if there is any
@@ -717,7 +717,7 @@ BOOL TextView::KeyInput( const KeyEvent& rKeyEvent )
}
}
aCurSel = ImpDelete( nDel, nMode );
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_DELETE );
+ mpImpl->mpTextEngine->UndoActionEnd();
bModified = TRUE;
bAllowIdle = FALSE;
}
@@ -745,7 +745,7 @@ BOOL TextView::KeyInput( const KeyEvent& rKeyEvent )
if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() &&
!rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( 'x' ) )
{
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionStart();
aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel );
if ( mpImpl->mbAutoIndent )
{
@@ -760,7 +760,7 @@ BOOL TextView::KeyInput( const KeyEvent& rKeyEvent )
if ( n )
aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().Copy( 0, n ) );
}
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionEnd();
bModified = TRUE;
}
else
@@ -1122,21 +1122,21 @@ void TextView::Scroll( long ndX, long ndY )
void TextView::Undo()
{
mpImpl->mpTextEngine->SetActiveView( this );
- mpImpl->mpTextEngine->GetUndoManager().Undo( 1 );
+ mpImpl->mpTextEngine->GetUndoManager().Undo();
}
void TextView::Redo()
{
mpImpl->mpTextEngine->SetActiveView( this );
- mpImpl->mpTextEngine->GetUndoManager().Redo( 0 );
+ mpImpl->mpTextEngine->GetUndoManager().Redo();
}
void TextView::Cut()
{
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_CUT );
+ mpImpl->mpTextEngine->UndoActionStart();
Copy();
DeleteSelected();
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_CUT );
+ mpImpl->mpTextEngine->UndoActionEnd();
}
void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
@@ -1370,7 +1370,7 @@ void TextView::InsertText( const XubString& rStr, BOOL bSelect )
void TextView::InsertNewText( const rtl::OUString& rStr, BOOL bSelect )
{
// HideSelection();
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionStart();
/* #i87633#
break inserted text into chunks that fit into the underlying String
@@ -1405,7 +1405,7 @@ void TextView::InsertNewText( const rtl::OUString& rStr, BOOL bSelect )
nLen -= nChunkLen;
nPos += nChunkLen;
}
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionEnd();
mpImpl->mpTextEngine->FormatAndUpdate( this );
}
@@ -1417,9 +1417,9 @@ void TextView::InsertText( const XubString& rStr, BOOL bSelect )
TextSelection aNewSel( mpImpl->maSelection );
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionStart();
TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_INSERT );
+ mpImpl->mpTextEngine->UndoActionEnd();
if ( bSelect )
{
@@ -2169,7 +2169,7 @@ void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEv
HideSelection();
ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
- mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_DRAGANDDROP );
+ mpImpl->mpTextEngine->UndoActionStart();
String aText;
uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
@@ -2247,7 +2247,7 @@ void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEv
mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
}
- mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_DRAGANDDROP );
+ mpImpl->mpTextEngine->UndoActionEnd();
delete mpImpl->mpDDInfo;
mpImpl->mpDDInfo = 0;
diff --git a/svtools/source/edit/xtextedt.cxx b/svtools/source/edit/xtextedt.cxx
index 0a4907edcadd..10e05a58676a 100644
--- a/svtools/source/edit/xtextedt.cxx
+++ b/svtools/source/edit/xtextedt.cxx
@@ -327,7 +327,7 @@ USHORT ExtTextView::Replace( const util::SearchOptions& rSearchOptions, BOOL bAl
BOOL bFound = pTextEngine->Search( aSel, rSearchOptions, TRUE );
if ( bFound )
- pTextEngine->UndoActionStart( XTEXTUNDO_REPLACEALL );
+ pTextEngine->UndoActionStart();
while ( bFound )
{
nFound++;
@@ -341,7 +341,7 @@ USHORT ExtTextView::Replace( const util::SearchOptions& rSearchOptions, BOOL bAl
{
SetSelection( aSel.GetStart() );
pTextEngine->FormatAndUpdate( this );
- pTextEngine->UndoActionEnd( XTEXTUNDO_REPLACEALL );
+ pTextEngine->UndoActionEnd();
}
}
return nFound;
@@ -355,7 +355,7 @@ BOOL ExtTextView::ImpIndentBlock( BOOL bRight )
aSel.Justify();
HideSelection();
- GetTextEngine()->UndoActionStart( bRight ? XTEXTUNDO_INDENTBLOCK : XTEXTUNDO_UNINDENTBLOCK );
+ GetTextEngine()->UndoActionStart();
ULONG nStartPara = aSel.GetStart().GetPara();
ULONG nEndPara = aSel.GetEnd().GetPara();
@@ -386,7 +386,7 @@ BOOL ExtTextView::ImpIndentBlock( BOOL bRight )
}
}
- GetTextEngine()->UndoActionEnd( bRight ? XTEXTUNDO_INDENTBLOCK : XTEXTUNDO_UNINDENTBLOCK );
+ GetTextEngine()->UndoActionEnd();
BOOL bRange = aSel.HasRange();
if ( bRight )
diff --git a/toolkit/source/awt/vclxwindow.cxx b/toolkit/source/awt/vclxwindow.cxx
index 808f3578ef97..5d25e2f7b29b 100644
--- a/toolkit/source/awt/vclxwindow.cxx
+++ b/toolkit/source/awt/vclxwindow.cxx
@@ -65,6 +65,7 @@
#include <vcl/tabpage.hxx>
#include <vcl/button.hxx>
#include <comphelper/asyncnotification.hxx>
+#include <comphelper/flagguard.hxx>
#include <toolkit/helper/solarrelease.hxx>
#include "stylesettings.hxx"
#include <tools/urlobj.hxx>
@@ -95,32 +96,6 @@ namespace MouseWheelBehavior = ::com::sun::star::awt::MouseWheelBehavior;
using ::toolkit::ReleaseSolarMutex;
//====================================================================
-//= misc helpers
-//====================================================================
-namespace
-{
- //................................................................
- //. FlagGuard
- //................................................................
- class FlagGuard
- {
- private:
- bool& m_rFlag;
-
- public:
- FlagGuard( bool& _rFlag )
- :m_rFlag( _rFlag )
- {
- m_rFlag = true;
- }
- ~FlagGuard()
- {
- m_rFlag = false;
- }
- };
-}
-
-//====================================================================
//= VCLXWindowImpl
//====================================================================
class SAL_DLLPRIVATE VCLXWindowImpl
@@ -2347,7 +2322,7 @@ void VCLXWindow::draw( sal_Int32 nX, sal_Int32 nY ) throw(::com::sun::star::uno:
// #i40647# / 2005-01-18 / frank.schoenheit@sun.com
if ( !mpImpl->getDrawingOntoParent_ref() )
{
- FlagGuard aDrawingflagGuard( mpImpl->getDrawingOntoParent_ref() );
+ ::comphelper::FlagGuard aDrawingflagGuard( mpImpl->getDrawingOntoParent_ref() );
BOOL bWasVisible = pWindow->IsVisible();
Point aOldPos( pWindow->GetPosPixel() );