1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5efeef26fSAndrew Rist * distributed with this work for additional information
6efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist * software distributed under the License is distributed on an
15efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17efeef26fSAndrew Rist * specific language governing permissions and limitations
18efeef26fSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20efeef26fSAndrew Rist *************************************************************/
21efeef26fSAndrew Rist
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_sw.hxx"
24cdf0e10cSrcweir
25cdf0e10cSrcweir #include <UndoManager.hxx>
26cdf0e10cSrcweir #include <unotools/undoopt.hxx>
27cdf0e10cSrcweir #include <vcl/wrkwin.hxx>
28cdf0e10cSrcweir #include <svx/svdmodel.hxx>
29cdf0e10cSrcweir #include <swmodule.hxx>
30cdf0e10cSrcweir #include <doc.hxx>
31cdf0e10cSrcweir #include <ndarr.hxx>
32cdf0e10cSrcweir #include <pam.hxx>
33cdf0e10cSrcweir #include <ndtxt.hxx>
34cdf0e10cSrcweir #include <swundo.hxx>
35cdf0e10cSrcweir #include <UndoCore.hxx>
36cdf0e10cSrcweir #include <rolbck.hxx>
37cdf0e10cSrcweir #include <undo.hrc>
38cdf0e10cSrcweir #include <editsh.hxx>
39cdf0e10cSrcweir #include <unobaseclass.hxx>
40cdf0e10cSrcweir #include <limits>
41*26ea3662SArmin Le Grand #include <drawdoc.hxx>
42cdf0e10cSrcweir
43cdf0e10cSrcweir using namespace ::com::sun::star;
44cdf0e10cSrcweir
45cdf0e10cSrcweir // the undo array should never grow beyond this limit:
46cdf0e10cSrcweir #define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
47cdf0e10cSrcweir
48cdf0e10cSrcweir // UndoManager ///////////////////////////////////////////////////////////
49cdf0e10cSrcweir
50cdf0e10cSrcweir namespace sw {
51cdf0e10cSrcweir
UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,IDocumentDrawModelAccess & rDrawModelAccess,IDocumentRedlineAccess & rRedlineAccess,IDocumentState & rState)52cdf0e10cSrcweir UndoManager::UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
53cdf0e10cSrcweir IDocumentDrawModelAccess & rDrawModelAccess,
54cdf0e10cSrcweir IDocumentRedlineAccess & rRedlineAccess,
55cdf0e10cSrcweir IDocumentState & rState)
56cdf0e10cSrcweir : m_rDrawModelAccess(rDrawModelAccess)
57cdf0e10cSrcweir , m_rRedlineAccess(rRedlineAccess)
58cdf0e10cSrcweir , m_rState(rState)
59cdf0e10cSrcweir , m_pUndoNodes(pUndoNodes)
60cdf0e10cSrcweir , m_bGroupUndo(true)
61cdf0e10cSrcweir , m_bDrawUndo(true)
62cdf0e10cSrcweir , m_bLockUndoNoModifiedPosition(false)
63cdf0e10cSrcweir , m_UndoSaveMark(MARK_INVALID)
64cdf0e10cSrcweir {
65cdf0e10cSrcweir OSL_ASSERT(m_pUndoNodes.get());
66cdf0e10cSrcweir // writer expects it to be disabled initially
67cdf0e10cSrcweir // Undo is enabled by SwEditShell constructor
688218eba2SArmin Le Grand SdrUndoManager::EnableUndo(false);
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
GetUndoNodes() const71cdf0e10cSrcweir SwNodes const& UndoManager::GetUndoNodes() const
72cdf0e10cSrcweir {
73cdf0e10cSrcweir return *m_pUndoNodes;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
GetUndoNodes()76cdf0e10cSrcweir SwNodes & UndoManager::GetUndoNodes()
77cdf0e10cSrcweir {
78cdf0e10cSrcweir return *m_pUndoNodes;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir
IsUndoNodes(SwNodes const & rNodes) const81cdf0e10cSrcweir bool UndoManager::IsUndoNodes(SwNodes const& rNodes) const
82cdf0e10cSrcweir {
83cdf0e10cSrcweir return & rNodes == m_pUndoNodes.get();
84cdf0e10cSrcweir }
85cdf0e10cSrcweir
DoUndo(bool const bDoUndo)86cdf0e10cSrcweir void UndoManager::DoUndo(bool const bDoUndo)
87cdf0e10cSrcweir {
888218eba2SArmin Le Grand if(!isTextEditActive())
898218eba2SArmin Le Grand {
90cdf0e10cSrcweir EnableUndo(bDoUndo);
91cdf0e10cSrcweir
92*26ea3662SArmin Le Grand SwDrawModel*const pSdrModel = m_rDrawModelAccess.GetDrawModel();
93cdf0e10cSrcweir if( pSdrModel )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir pSdrModel->EnableUndo(bDoUndo);
96cdf0e10cSrcweir }
97cdf0e10cSrcweir }
988218eba2SArmin Le Grand }
99cdf0e10cSrcweir
DoesUndo() const100cdf0e10cSrcweir bool UndoManager::DoesUndo() const
101cdf0e10cSrcweir {
1028218eba2SArmin Le Grand if(isTextEditActive())
1038218eba2SArmin Le Grand {
1048218eba2SArmin Le Grand return false;
1058218eba2SArmin Le Grand }
1068218eba2SArmin Le Grand else
1078218eba2SArmin Le Grand {
108cdf0e10cSrcweir return IsUndoEnabled();
109cdf0e10cSrcweir }
1108218eba2SArmin Le Grand }
111cdf0e10cSrcweir
DoGroupUndo(bool const bDoUndo)112cdf0e10cSrcweir void UndoManager::DoGroupUndo(bool const bDoUndo)
113cdf0e10cSrcweir {
114cdf0e10cSrcweir m_bGroupUndo = bDoUndo;
115cdf0e10cSrcweir }
116cdf0e10cSrcweir
DoesGroupUndo() const117cdf0e10cSrcweir bool UndoManager::DoesGroupUndo() const
118cdf0e10cSrcweir {
119cdf0e10cSrcweir return m_bGroupUndo;
120cdf0e10cSrcweir }
121cdf0e10cSrcweir
DoDrawUndo(bool const bDoUndo)122cdf0e10cSrcweir void UndoManager::DoDrawUndo(bool const bDoUndo)
123cdf0e10cSrcweir {
124cdf0e10cSrcweir m_bDrawUndo = bDoUndo;
125cdf0e10cSrcweir }
126cdf0e10cSrcweir
DoesDrawUndo() const127cdf0e10cSrcweir bool UndoManager::DoesDrawUndo() const
128cdf0e10cSrcweir {
129cdf0e10cSrcweir return m_bDrawUndo;
130cdf0e10cSrcweir }
131cdf0e10cSrcweir
132cdf0e10cSrcweir
IsUndoNoResetModified() const133cdf0e10cSrcweir bool UndoManager::IsUndoNoResetModified() const
134cdf0e10cSrcweir {
135cdf0e10cSrcweir return MARK_INVALID == m_UndoSaveMark;
136cdf0e10cSrcweir }
137cdf0e10cSrcweir
SetUndoNoResetModified()138cdf0e10cSrcweir void UndoManager::SetUndoNoResetModified()
139cdf0e10cSrcweir {
140cdf0e10cSrcweir if (MARK_INVALID != m_UndoSaveMark)
141cdf0e10cSrcweir {
142cdf0e10cSrcweir RemoveMark(m_UndoSaveMark);
143cdf0e10cSrcweir m_UndoSaveMark = MARK_INVALID;
144cdf0e10cSrcweir }
145cdf0e10cSrcweir }
146cdf0e10cSrcweir
SetUndoNoModifiedPosition()147cdf0e10cSrcweir void UndoManager::SetUndoNoModifiedPosition()
148cdf0e10cSrcweir {
149cdf0e10cSrcweir if (!m_bLockUndoNoModifiedPosition)
150cdf0e10cSrcweir {
151cdf0e10cSrcweir m_UndoSaveMark = MarkTopUndoAction();
152cdf0e10cSrcweir }
153cdf0e10cSrcweir }
154cdf0e10cSrcweir
LockUndoNoModifiedPosition()155cdf0e10cSrcweir void UndoManager::LockUndoNoModifiedPosition()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir m_bLockUndoNoModifiedPosition = true;
158cdf0e10cSrcweir }
159cdf0e10cSrcweir
UnLockUndoNoModifiedPosition()160cdf0e10cSrcweir void UndoManager::UnLockUndoNoModifiedPosition()
161cdf0e10cSrcweir {
162cdf0e10cSrcweir m_bLockUndoNoModifiedPosition = false;
163cdf0e10cSrcweir }
164cdf0e10cSrcweir
165cdf0e10cSrcweir
GetLastUndo()166cdf0e10cSrcweir SwUndo* UndoManager::GetLastUndo()
167cdf0e10cSrcweir {
1688218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
169cdf0e10cSrcweir {
170cdf0e10cSrcweir return 0;
171cdf0e10cSrcweir }
1728218eba2SArmin Le Grand SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
173cdf0e10cSrcweir return dynamic_cast<SwUndo*>(pAction);
174cdf0e10cSrcweir }
175cdf0e10cSrcweir
AppendUndo(SwUndo * const pUndo)176cdf0e10cSrcweir void UndoManager::AppendUndo(SwUndo *const pUndo)
177cdf0e10cSrcweir {
178cdf0e10cSrcweir AddUndoAction(pUndo);
179cdf0e10cSrcweir }
180cdf0e10cSrcweir
ClearRedo()181cdf0e10cSrcweir void UndoManager::ClearRedo()
182cdf0e10cSrcweir {
1838218eba2SArmin Le Grand return SdrUndoManager::ImplClearRedo_NoLock(TopLevel);
184cdf0e10cSrcweir }
185cdf0e10cSrcweir
DelAllUndoObj()186cdf0e10cSrcweir void UndoManager::DelAllUndoObj()
187cdf0e10cSrcweir {
188cdf0e10cSrcweir ::sw::UndoGuard const undoGuard(*this);
189cdf0e10cSrcweir
1908218eba2SArmin Le Grand SdrUndoManager::ClearAllLevels();
191cdf0e10cSrcweir
192cdf0e10cSrcweir m_UndoSaveMark = MARK_INVALID;
193cdf0e10cSrcweir }
194cdf0e10cSrcweir
195cdf0e10cSrcweir
196cdf0e10cSrcweir /**************** UNDO ******************/
197cdf0e10cSrcweir
198cdf0e10cSrcweir SwUndoId
StartUndo(SwUndoId const i_eUndoId,SwRewriter const * const pRewriter)199cdf0e10cSrcweir UndoManager::StartUndo(SwUndoId const i_eUndoId,
200cdf0e10cSrcweir SwRewriter const*const pRewriter)
201cdf0e10cSrcweir {
202cdf0e10cSrcweir if (!IsUndoEnabled())
203cdf0e10cSrcweir {
204cdf0e10cSrcweir return UNDO_EMPTY;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
207cdf0e10cSrcweir SwUndoId const eUndoId( (0 == i_eUndoId) ? UNDO_START : i_eUndoId );
208cdf0e10cSrcweir
209cdf0e10cSrcweir OSL_ASSERT(UNDO_END != eUndoId);
210cdf0e10cSrcweir String comment( (UNDO_START == eUndoId)
211cdf0e10cSrcweir ? String("??", RTL_TEXTENCODING_ASCII_US)
212cdf0e10cSrcweir : String(SW_RES(UNDO_BASE + eUndoId)) );
213cdf0e10cSrcweir if (pRewriter)
214cdf0e10cSrcweir {
215cdf0e10cSrcweir OSL_ASSERT(UNDO_START != eUndoId);
216cdf0e10cSrcweir comment = pRewriter->Apply(comment);
217cdf0e10cSrcweir }
218cdf0e10cSrcweir
2198218eba2SArmin Le Grand SdrUndoManager::EnterListAction(comment, comment, eUndoId);
220cdf0e10cSrcweir
221cdf0e10cSrcweir return eUndoId;
222cdf0e10cSrcweir }
223cdf0e10cSrcweir
224cdf0e10cSrcweir
225cdf0e10cSrcweir SwUndoId
EndUndo(SwUndoId const i_eUndoId,SwRewriter const * const pRewriter)226cdf0e10cSrcweir UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir if (!IsUndoEnabled())
229cdf0e10cSrcweir {
230cdf0e10cSrcweir return UNDO_EMPTY;
231cdf0e10cSrcweir }
232cdf0e10cSrcweir
233cdf0e10cSrcweir SwUndoId const eUndoId( ((0 == i_eUndoId) || (UNDO_START == i_eUndoId))
234cdf0e10cSrcweir ? UNDO_END : i_eUndoId );
235cdf0e10cSrcweir OSL_ENSURE(!((UNDO_END == eUndoId) && pRewriter),
236cdf0e10cSrcweir "EndUndo(): no Undo ID, but rewriter given?");
237cdf0e10cSrcweir
238cdf0e10cSrcweir SfxUndoAction *const pLastUndo(
2398218eba2SArmin Le Grand (0 == SdrUndoManager::GetUndoActionCount(CurrentLevel))
2408218eba2SArmin Le Grand ? 0 : SdrUndoManager::GetUndoAction(0) );
241cdf0e10cSrcweir
242cdf0e10cSrcweir int const nCount = LeaveListAction();
243cdf0e10cSrcweir
244cdf0e10cSrcweir if (nCount) // otherwise: empty list action not inserted!
245cdf0e10cSrcweir {
246cdf0e10cSrcweir OSL_ASSERT(pLastUndo);
247cdf0e10cSrcweir OSL_ASSERT(UNDO_START != eUndoId);
2488218eba2SArmin Le Grand SfxUndoAction *const pUndoAction(SdrUndoManager::GetUndoAction(0));
249cdf0e10cSrcweir SfxListUndoAction *const pListAction(
250cdf0e10cSrcweir dynamic_cast<SfxListUndoAction*>(pUndoAction));
251cdf0e10cSrcweir OSL_ASSERT(pListAction);
252cdf0e10cSrcweir if (pListAction)
253cdf0e10cSrcweir {
254cdf0e10cSrcweir if (UNDO_END != eUndoId)
255cdf0e10cSrcweir {
256cdf0e10cSrcweir OSL_ENSURE(pListAction->GetId() == eUndoId,
257cdf0e10cSrcweir "EndUndo(): given ID different from StartUndo()");
258cdf0e10cSrcweir // comment set by caller of EndUndo
259cdf0e10cSrcweir String comment = String(SW_RES(UNDO_BASE + eUndoId));
260cdf0e10cSrcweir if (pRewriter)
261cdf0e10cSrcweir {
262cdf0e10cSrcweir comment = pRewriter->Apply(comment);
263cdf0e10cSrcweir }
264cdf0e10cSrcweir pListAction->SetComment(comment);
265cdf0e10cSrcweir }
266cdf0e10cSrcweir else if ((UNDO_START != pListAction->GetId()))
267cdf0e10cSrcweir {
268cdf0e10cSrcweir // comment set by caller of StartUndo: nothing to do here
269cdf0e10cSrcweir }
270cdf0e10cSrcweir else if (pLastUndo)
271cdf0e10cSrcweir {
272cdf0e10cSrcweir // comment was not set at StartUndo or EndUndo:
273cdf0e10cSrcweir // take comment of last contained action
274cdf0e10cSrcweir // (note that this works recursively, i.e. the last contained
275cdf0e10cSrcweir // action may be a list action created by StartUndo/EndUndo)
276cdf0e10cSrcweir String const comment(pLastUndo->GetComment());
277cdf0e10cSrcweir pListAction->SetComment(comment);
278cdf0e10cSrcweir }
279cdf0e10cSrcweir else
280cdf0e10cSrcweir {
281cdf0e10cSrcweir OSL_ENSURE(false, "EndUndo(): no comment?");
282cdf0e10cSrcweir }
283cdf0e10cSrcweir }
284cdf0e10cSrcweir }
285cdf0e10cSrcweir
286cdf0e10cSrcweir return eUndoId;
287cdf0e10cSrcweir }
288cdf0e10cSrcweir
289cdf0e10cSrcweir bool
GetLastUndoInfo(::rtl::OUString * const o_pStr,SwUndoId * const o_pId) const290cdf0e10cSrcweir UndoManager::GetLastUndoInfo(
291cdf0e10cSrcweir ::rtl::OUString *const o_pStr, SwUndoId *const o_pId) const
292cdf0e10cSrcweir {
293cdf0e10cSrcweir // this is actually expected to work on the current level,
294cdf0e10cSrcweir // but that was really not obvious from the previous implementation...
2958218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
296cdf0e10cSrcweir {
297cdf0e10cSrcweir return false;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir
3008218eba2SArmin Le Grand SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
301cdf0e10cSrcweir
302cdf0e10cSrcweir if (o_pStr)
303cdf0e10cSrcweir {
304cdf0e10cSrcweir *o_pStr = pAction->GetComment();
305cdf0e10cSrcweir }
306cdf0e10cSrcweir if (o_pId)
307cdf0e10cSrcweir {
308cdf0e10cSrcweir sal_uInt16 const nId(pAction->GetId());
309cdf0e10cSrcweir *o_pId = static_cast<SwUndoId>(nId);
310cdf0e10cSrcweir }
311cdf0e10cSrcweir
312cdf0e10cSrcweir return true;
313cdf0e10cSrcweir }
314cdf0e10cSrcweir
GetUndoComments() const315cdf0e10cSrcweir SwUndoComments_t UndoManager::GetUndoComments() const
316cdf0e10cSrcweir {
3178218eba2SArmin Le Grand OSL_ENSURE(!SdrUndoManager::IsInListAction(),
318cdf0e10cSrcweir "GetUndoComments() called while in list action?");
319cdf0e10cSrcweir
320cdf0e10cSrcweir SwUndoComments_t ret;
3218218eba2SArmin Le Grand sal_uInt16 const nUndoCount(SdrUndoManager::GetUndoActionCount(TopLevel));
322cdf0e10cSrcweir for (sal_uInt16 n = 0; n < nUndoCount; ++n)
323cdf0e10cSrcweir {
324cdf0e10cSrcweir ::rtl::OUString const comment(
3258218eba2SArmin Le Grand SdrUndoManager::GetUndoActionComment(n, TopLevel));
326cdf0e10cSrcweir ret.push_back(comment);
327cdf0e10cSrcweir }
328cdf0e10cSrcweir
329cdf0e10cSrcweir return ret;
330cdf0e10cSrcweir }
331cdf0e10cSrcweir
332cdf0e10cSrcweir
333cdf0e10cSrcweir /**************** REDO ******************/
334cdf0e10cSrcweir
GetFirstRedoInfo(::rtl::OUString * const o_pStr,SwUndoId * const o_pId) const33589358e0fSOliver-Rainer Wittmann bool UndoManager::GetFirstRedoInfo(::rtl::OUString *const o_pStr,
33689358e0fSOliver-Rainer Wittmann SwUndoId *const o_pId) const
337cdf0e10cSrcweir {
3388218eba2SArmin Le Grand if (!SdrUndoManager::GetRedoActionCount(CurrentLevel))
339cdf0e10cSrcweir {
340cdf0e10cSrcweir return false;
341cdf0e10cSrcweir }
342cdf0e10cSrcweir
34389358e0fSOliver-Rainer Wittmann SfxUndoAction *const pAction( SdrUndoManager::GetRedoAction(0, CurrentLevel) );
34489358e0fSOliver-Rainer Wittmann if ( pAction == NULL )
34589358e0fSOliver-Rainer Wittmann {
34689358e0fSOliver-Rainer Wittmann return false;
34789358e0fSOliver-Rainer Wittmann }
34889358e0fSOliver-Rainer Wittmann
349cdf0e10cSrcweir if (o_pStr)
350cdf0e10cSrcweir {
35189358e0fSOliver-Rainer Wittmann *o_pStr = pAction->GetComment();
35289358e0fSOliver-Rainer Wittmann }
35389358e0fSOliver-Rainer Wittmann if (o_pId)
35489358e0fSOliver-Rainer Wittmann {
35589358e0fSOliver-Rainer Wittmann sal_uInt16 const nId(pAction->GetId());
35689358e0fSOliver-Rainer Wittmann *o_pId = static_cast<SwUndoId>(nId);
357cdf0e10cSrcweir }
358cdf0e10cSrcweir
359cdf0e10cSrcweir return true;
360cdf0e10cSrcweir }
361cdf0e10cSrcweir
362cdf0e10cSrcweir
GetRedoComments() const363cdf0e10cSrcweir SwUndoComments_t UndoManager::GetRedoComments() const
364cdf0e10cSrcweir {
3658218eba2SArmin Le Grand OSL_ENSURE(!SdrUndoManager::IsInListAction(),
366cdf0e10cSrcweir "GetRedoComments() called while in list action?");
367cdf0e10cSrcweir
368cdf0e10cSrcweir SwUndoComments_t ret;
3698218eba2SArmin Le Grand sal_uInt16 const nRedoCount(SdrUndoManager::GetRedoActionCount(TopLevel));
370cdf0e10cSrcweir for (sal_uInt16 n = 0; n < nRedoCount; ++n)
371cdf0e10cSrcweir {
372cdf0e10cSrcweir ::rtl::OUString const comment(
3738218eba2SArmin Le Grand SdrUndoManager::GetRedoActionComment(n, TopLevel));
374cdf0e10cSrcweir ret.push_back(comment);
375cdf0e10cSrcweir }
376cdf0e10cSrcweir
377cdf0e10cSrcweir return ret;
378cdf0e10cSrcweir }
379cdf0e10cSrcweir
380cdf0e10cSrcweir /**************** REPEAT ******************/
381cdf0e10cSrcweir
GetRepeatInfo(::rtl::OUString * const o_pStr) const382cdf0e10cSrcweir SwUndoId UndoManager::GetRepeatInfo(::rtl::OUString *const o_pStr) const
383cdf0e10cSrcweir {
384cdf0e10cSrcweir SwUndoId nRepeatId(UNDO_EMPTY);
385cdf0e10cSrcweir GetLastUndoInfo(o_pStr, & nRepeatId);
386cdf0e10cSrcweir if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
387cdf0e10cSrcweir {
388cdf0e10cSrcweir return nRepeatId;
389cdf0e10cSrcweir }
390cdf0e10cSrcweir if (o_pStr) // not repeatable -> clear comment
391cdf0e10cSrcweir {
392cdf0e10cSrcweir *o_pStr = String();
393cdf0e10cSrcweir }
394cdf0e10cSrcweir return UNDO_EMPTY;
395cdf0e10cSrcweir }
396cdf0e10cSrcweir
RemoveLastUndo()397cdf0e10cSrcweir SwUndo * UndoManager::RemoveLastUndo()
398cdf0e10cSrcweir {
3998218eba2SArmin Le Grand if (SdrUndoManager::GetRedoActionCount(CurrentLevel) ||
4008218eba2SArmin Le Grand SdrUndoManager::GetRedoActionCount(TopLevel))
401cdf0e10cSrcweir {
402cdf0e10cSrcweir OSL_ENSURE(false, "RemoveLastUndoAction(): there are Redo actions?");
403cdf0e10cSrcweir return 0;
404cdf0e10cSrcweir }
4058218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
406cdf0e10cSrcweir {
407cdf0e10cSrcweir OSL_ENSURE(false, "RemoveLastUndoAction(): no Undo actions");
408cdf0e10cSrcweir return 0;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir SfxUndoAction *const pLastUndo(GetUndoAction(0));
4118218eba2SArmin Le Grand SdrUndoManager::RemoveLastUndoAction();
412cdf0e10cSrcweir return dynamic_cast<SwUndo *>(pLastUndo);
413cdf0e10cSrcweir }
414cdf0e10cSrcweir
415cdf0e10cSrcweir // svl::IUndoManager /////////////////////////////////////////////////////
416cdf0e10cSrcweir
EnableUndo(bool bEnable)417cdf0e10cSrcweir void UndoManager::EnableUndo(bool bEnable)
418cdf0e10cSrcweir {
4198218eba2SArmin Le Grand // SdrUndoManager does not have a counter anymore, but reverted to the old behavior of
420cdf0e10cSrcweir // having a simple boolean flag for locking. So, simply forward.
4218218eba2SArmin Le Grand SdrUndoManager::EnableUndo(bEnable);
422cdf0e10cSrcweir }
423cdf0e10cSrcweir
AddUndoAction(SfxUndoAction * pAction,sal_Bool bTryMerge)424cdf0e10cSrcweir void UndoManager::AddUndoAction(SfxUndoAction *pAction, sal_Bool bTryMerge)
425cdf0e10cSrcweir {
426cdf0e10cSrcweir SwUndo *const pUndo( dynamic_cast<SwUndo *>(pAction) );
427cdf0e10cSrcweir if (pUndo)
428cdf0e10cSrcweir {
429cdf0e10cSrcweir if (nsRedlineMode_t::REDLINE_NONE == pUndo->GetRedlineMode())
430cdf0e10cSrcweir {
431cdf0e10cSrcweir pUndo->SetRedlineMode( m_rRedlineAccess.GetRedlineMode() );
432cdf0e10cSrcweir }
433cdf0e10cSrcweir }
4348218eba2SArmin Le Grand SdrUndoManager::AddUndoAction(pAction, bTryMerge);
435cdf0e10cSrcweir // if the undo nodes array is too large, delete some actions
436cdf0e10cSrcweir while (UNDO_ACTION_LIMIT < GetUndoNodes().Count())
437cdf0e10cSrcweir {
438cdf0e10cSrcweir RemoveOldestUndoActions(1);
439cdf0e10cSrcweir }
440cdf0e10cSrcweir }
441cdf0e10cSrcweir
442cdf0e10cSrcweir class CursorGuard
443cdf0e10cSrcweir {
444cdf0e10cSrcweir public:
CursorGuard(SwEditShell & rShell,bool const bSave)445cdf0e10cSrcweir CursorGuard(SwEditShell & rShell, bool const bSave)
446cdf0e10cSrcweir : m_rShell(rShell)
447cdf0e10cSrcweir , m_bSaveCursor(bSave)
448cdf0e10cSrcweir {
449cdf0e10cSrcweir if (m_bSaveCursor)
450cdf0e10cSrcweir {
451cdf0e10cSrcweir m_rShell.Push(); // prevent modification of current cursor
452cdf0e10cSrcweir }
453cdf0e10cSrcweir }
~CursorGuard()454cdf0e10cSrcweir ~CursorGuard()
455cdf0e10cSrcweir {
456cdf0e10cSrcweir if (m_bSaveCursor)
457cdf0e10cSrcweir {
45889358e0fSOliver-Rainer Wittmann m_rShell.Pop( sal_False );
459cdf0e10cSrcweir }
460cdf0e10cSrcweir }
461cdf0e10cSrcweir private:
462cdf0e10cSrcweir SwEditShell & m_rShell;
463cdf0e10cSrcweir bool const m_bSaveCursor;
464cdf0e10cSrcweir };
465cdf0e10cSrcweir
impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)466cdf0e10cSrcweir bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)
467cdf0e10cSrcweir {
468cdf0e10cSrcweir SwDoc & rDoc(*GetUndoNodes().GetDoc());
469cdf0e10cSrcweir
470cdf0e10cSrcweir UnoActionContext c(& rDoc); // exception-safe StartAllAction/EndAllAction
471cdf0e10cSrcweir
472cdf0e10cSrcweir SwEditShell *const pEditShell( rDoc.GetEditShell() );
473cdf0e10cSrcweir
474cdf0e10cSrcweir OSL_ENSURE(pEditShell, "sw::UndoManager needs a SwEditShell!");
475cdf0e10cSrcweir if (!pEditShell)
476cdf0e10cSrcweir {
477cdf0e10cSrcweir throw uno::RuntimeException();
478cdf0e10cSrcweir }
479cdf0e10cSrcweir
480cdf0e10cSrcweir // in case the model has controllers locked, the Undo should not
481cdf0e10cSrcweir // change the view cursors!
482cdf0e10cSrcweir bool const bSaveCursors(pEditShell->CursorsLocked());
48389358e0fSOliver-Rainer Wittmann CursorGuard aCursorGuard(*pEditShell, bSaveCursors);
484cdf0e10cSrcweir if (!bSaveCursors)
485cdf0e10cSrcweir {
486cdf0e10cSrcweir // (in case Undo was called via API) clear the cursors:
487cdf0e10cSrcweir pEditShell->KillPams();
488cdf0e10cSrcweir pEditShell->SetMark();
489cdf0e10cSrcweir pEditShell->ClearMark();
490cdf0e10cSrcweir }
491cdf0e10cSrcweir
492cdf0e10cSrcweir bool bRet(false);
493cdf0e10cSrcweir
494cdf0e10cSrcweir ::sw::UndoRedoContext context(rDoc, *pEditShell);
495cdf0e10cSrcweir
496cdf0e10cSrcweir // N.B. these may throw!
497cdf0e10cSrcweir if (UNDO == undoOrRedo)
498cdf0e10cSrcweir {
4998218eba2SArmin Le Grand bRet = SdrUndoManager::UndoWithContext(context);
500cdf0e10cSrcweir }
501cdf0e10cSrcweir else
502cdf0e10cSrcweir {
5038218eba2SArmin Le Grand bRet = SdrUndoManager::RedoWithContext(context);
504cdf0e10cSrcweir }
505cdf0e10cSrcweir
506cdf0e10cSrcweir if (bRet)
507cdf0e10cSrcweir {
508cdf0e10cSrcweir // if we are at the "last save" position, the document is not modified
5098218eba2SArmin Le Grand if (SdrUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
510cdf0e10cSrcweir {
511cdf0e10cSrcweir m_rState.ResetModified();
512cdf0e10cSrcweir }
513cdf0e10cSrcweir else
514cdf0e10cSrcweir {
515cdf0e10cSrcweir m_rState.SetModified();
516cdf0e10cSrcweir }
517cdf0e10cSrcweir }
518cdf0e10cSrcweir
519cdf0e10cSrcweir pEditShell->HandleUndoRedoContext(context);
520cdf0e10cSrcweir
521cdf0e10cSrcweir return bRet;
522cdf0e10cSrcweir }
523cdf0e10cSrcweir
Undo()524cdf0e10cSrcweir sal_Bool UndoManager::Undo()
525cdf0e10cSrcweir {
5268218eba2SArmin Le Grand if(isTextEditActive())
5278218eba2SArmin Le Grand {
5288218eba2SArmin Le Grand return SdrUndoManager::Undo();
5298218eba2SArmin Le Grand }
5308218eba2SArmin Le Grand else
5318218eba2SArmin Le Grand {
5328218eba2SArmin Le Grand return impl_DoUndoRedo(UNDO);
5338218eba2SArmin Le Grand }
534cdf0e10cSrcweir }
535cdf0e10cSrcweir
Redo()536cdf0e10cSrcweir sal_Bool UndoManager::Redo()
537cdf0e10cSrcweir {
5388218eba2SArmin Le Grand if(isTextEditActive())
5398218eba2SArmin Le Grand {
5408218eba2SArmin Le Grand return SdrUndoManager::Redo();
5418218eba2SArmin Le Grand }
5428218eba2SArmin Le Grand else
5438218eba2SArmin Le Grand {
5448218eba2SArmin Le Grand return impl_DoUndoRedo(REDO);
5458218eba2SArmin Le Grand }
546cdf0e10cSrcweir }
547cdf0e10cSrcweir
5488218eba2SArmin Le Grand /** N.B.: this does _not_ call SdrUndoManager::Repeat because it is not
549cdf0e10cSrcweir possible to wrap a list action around it:
5508218eba2SArmin Le Grand calling EnterListAction here will cause SdrUndoManager::Repeat
551cdf0e10cSrcweir to repeat the list action!
552cdf0e10cSrcweir */
553cdf0e10cSrcweir bool
Repeat(::sw::RepeatContext & rContext,sal_uInt16 const nRepeatCount)554cdf0e10cSrcweir UndoManager::Repeat(::sw::RepeatContext & rContext,
555cdf0e10cSrcweir sal_uInt16 const nRepeatCount)
556cdf0e10cSrcweir {
5578218eba2SArmin Le Grand if (SdrUndoManager::IsInListAction())
558cdf0e10cSrcweir {
559cdf0e10cSrcweir OSL_ENSURE(false, "repeat in open list action???");
560cdf0e10cSrcweir return false;
561cdf0e10cSrcweir }
5628218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(TopLevel))
563cdf0e10cSrcweir {
564cdf0e10cSrcweir return false;
565cdf0e10cSrcweir }
566cdf0e10cSrcweir SfxUndoAction *const pRepeatAction(GetUndoAction(0));
567cdf0e10cSrcweir OSL_ASSERT(pRepeatAction);
568cdf0e10cSrcweir if (!pRepeatAction || !pRepeatAction->CanRepeat(rContext))
569cdf0e10cSrcweir {
570cdf0e10cSrcweir return false;
571cdf0e10cSrcweir }
572cdf0e10cSrcweir
573cdf0e10cSrcweir ::rtl::OUString const comment(pRepeatAction->GetComment());
574cdf0e10cSrcweir ::rtl::OUString const rcomment(pRepeatAction->GetRepeatComment(rContext));
575cdf0e10cSrcweir sal_uInt16 const nId(pRepeatAction->GetId());
576cdf0e10cSrcweir if (DoesUndo())
577cdf0e10cSrcweir {
578cdf0e10cSrcweir EnterListAction(comment, rcomment, nId);
579cdf0e10cSrcweir }
580cdf0e10cSrcweir
581cdf0e10cSrcweir SwPaM *const pFirstCursor(& rContext.GetRepeatPaM());
582cdf0e10cSrcweir do { // iterate over ring
583cdf0e10cSrcweir for (sal_uInt16 nRptCnt = nRepeatCount; nRptCnt > 0; --nRptCnt)
584cdf0e10cSrcweir {
585cdf0e10cSrcweir pRepeatAction->Repeat(rContext);
586cdf0e10cSrcweir }
587cdf0e10cSrcweir rContext.m_bDeleteRepeated = false; // reset for next PaM
588cdf0e10cSrcweir rContext.m_pCurrentPaM =
589cdf0e10cSrcweir static_cast<SwPaM*>(rContext.m_pCurrentPaM->GetNext());
590cdf0e10cSrcweir } while (pFirstCursor != & rContext.GetRepeatPaM());
591cdf0e10cSrcweir
592cdf0e10cSrcweir if (DoesUndo())
593cdf0e10cSrcweir {
594cdf0e10cSrcweir LeaveListAction();
595cdf0e10cSrcweir }
596cdf0e10cSrcweir return true;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir
599cdf0e10cSrcweir } // namespace sw
600