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
10efeef26fSAndrew Rist *
11efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist *
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.
19efeef26fSAndrew Rist *
20efeef26fSAndrew Rist *************************************************************/
21efeef26fSAndrew Rist
22efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <UndoManager.hxx>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include <unotools/undoopt.hxx>
30cdf0e10cSrcweir
31cdf0e10cSrcweir #include <vcl/wrkwin.hxx>
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include <svx/svdmodel.hxx>
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include <swmodule.hxx>
36cdf0e10cSrcweir #include <doc.hxx>
37cdf0e10cSrcweir #include <ndarr.hxx>
38cdf0e10cSrcweir #include <pam.hxx>
39cdf0e10cSrcweir #include <ndtxt.hxx>
40cdf0e10cSrcweir #include <swundo.hxx>
41cdf0e10cSrcweir #include <UndoCore.hxx>
42cdf0e10cSrcweir #include <rolbck.hxx>
43cdf0e10cSrcweir #include <undo.hrc>
44cdf0e10cSrcweir #include <editsh.hxx>
45cdf0e10cSrcweir #include <unobaseclass.hxx>
46cdf0e10cSrcweir #include <limits>
47cdf0e10cSrcweir
48cdf0e10cSrcweir #include <limits>
49cdf0e10cSrcweir
50cdf0e10cSrcweir using namespace ::com::sun::star;
51cdf0e10cSrcweir
52cdf0e10cSrcweir
53cdf0e10cSrcweir // the undo array should never grow beyond this limit:
54cdf0e10cSrcweir #define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
55cdf0e10cSrcweir
56cdf0e10cSrcweir
57cdf0e10cSrcweir // UndoManager ///////////////////////////////////////////////////////////
58cdf0e10cSrcweir
59cdf0e10cSrcweir namespace sw {
60cdf0e10cSrcweir
UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,IDocumentDrawModelAccess & rDrawModelAccess,IDocumentRedlineAccess & rRedlineAccess,IDocumentState & rState)61cdf0e10cSrcweir UndoManager::UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
62cdf0e10cSrcweir IDocumentDrawModelAccess & rDrawModelAccess,
63cdf0e10cSrcweir IDocumentRedlineAccess & rRedlineAccess,
64cdf0e10cSrcweir IDocumentState & rState)
65cdf0e10cSrcweir : m_rDrawModelAccess(rDrawModelAccess)
66cdf0e10cSrcweir , m_rRedlineAccess(rRedlineAccess)
67cdf0e10cSrcweir , m_rState(rState)
68cdf0e10cSrcweir , m_pUndoNodes(pUndoNodes)
69cdf0e10cSrcweir , m_bGroupUndo(true)
70cdf0e10cSrcweir , m_bDrawUndo(true)
71cdf0e10cSrcweir , m_bLockUndoNoModifiedPosition(false)
72cdf0e10cSrcweir , m_UndoSaveMark(MARK_INVALID)
73cdf0e10cSrcweir {
74cdf0e10cSrcweir OSL_ASSERT(m_pUndoNodes.get());
75cdf0e10cSrcweir // writer expects it to be disabled initially
76cdf0e10cSrcweir // Undo is enabled by SwEditShell constructor
778218eba2SArmin Le Grand SdrUndoManager::EnableUndo(false);
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
GetUndoNodes() const80cdf0e10cSrcweir SwNodes const& UndoManager::GetUndoNodes() const
81cdf0e10cSrcweir {
82cdf0e10cSrcweir return *m_pUndoNodes;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir
GetUndoNodes()85cdf0e10cSrcweir SwNodes & UndoManager::GetUndoNodes()
86cdf0e10cSrcweir {
87cdf0e10cSrcweir return *m_pUndoNodes;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir
IsUndoNodes(SwNodes const & rNodes) const90cdf0e10cSrcweir bool UndoManager::IsUndoNodes(SwNodes const& rNodes) const
91cdf0e10cSrcweir {
92cdf0e10cSrcweir return & rNodes == m_pUndoNodes.get();
93cdf0e10cSrcweir }
94cdf0e10cSrcweir
DoUndo(bool const bDoUndo)95cdf0e10cSrcweir void UndoManager::DoUndo(bool const bDoUndo)
96cdf0e10cSrcweir {
978218eba2SArmin Le Grand if(!isTextEditActive())
98cdf0e10cSrcweir {
998218eba2SArmin Le Grand EnableUndo(bDoUndo);
1008218eba2SArmin Le Grand
1018218eba2SArmin Le Grand SdrModel *const pSdrModel = m_rDrawModelAccess.GetDrawModel();
1028218eba2SArmin Le Grand if( pSdrModel )
1038218eba2SArmin Le Grand {
1048218eba2SArmin Le Grand pSdrModel->EnableUndo(bDoUndo);
1058218eba2SArmin Le Grand }
106cdf0e10cSrcweir }
107cdf0e10cSrcweir }
108cdf0e10cSrcweir
DoesUndo() const109cdf0e10cSrcweir bool UndoManager::DoesUndo() const
110cdf0e10cSrcweir {
1118218eba2SArmin Le Grand if(isTextEditActive())
1128218eba2SArmin Le Grand {
1138218eba2SArmin Le Grand return false;
1148218eba2SArmin Le Grand }
1158218eba2SArmin Le Grand else
1168218eba2SArmin Le Grand {
1178218eba2SArmin Le Grand return IsUndoEnabled();
1188218eba2SArmin Le Grand }
119cdf0e10cSrcweir }
120cdf0e10cSrcweir
DoGroupUndo(bool const bDoUndo)121cdf0e10cSrcweir void UndoManager::DoGroupUndo(bool const bDoUndo)
122cdf0e10cSrcweir {
123cdf0e10cSrcweir m_bGroupUndo = bDoUndo;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir
DoesGroupUndo() const126cdf0e10cSrcweir bool UndoManager::DoesGroupUndo() const
127cdf0e10cSrcweir {
128cdf0e10cSrcweir return m_bGroupUndo;
129cdf0e10cSrcweir }
130cdf0e10cSrcweir
DoDrawUndo(bool const bDoUndo)131cdf0e10cSrcweir void UndoManager::DoDrawUndo(bool const bDoUndo)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir m_bDrawUndo = bDoUndo;
134cdf0e10cSrcweir }
135cdf0e10cSrcweir
DoesDrawUndo() const136cdf0e10cSrcweir bool UndoManager::DoesDrawUndo() const
137cdf0e10cSrcweir {
138cdf0e10cSrcweir return m_bDrawUndo;
139cdf0e10cSrcweir }
140cdf0e10cSrcweir
141cdf0e10cSrcweir
IsUndoNoResetModified() const142cdf0e10cSrcweir bool UndoManager::IsUndoNoResetModified() const
143cdf0e10cSrcweir {
144cdf0e10cSrcweir return MARK_INVALID == m_UndoSaveMark;
145cdf0e10cSrcweir }
146cdf0e10cSrcweir
SetUndoNoResetModified()147cdf0e10cSrcweir void UndoManager::SetUndoNoResetModified()
148cdf0e10cSrcweir {
149cdf0e10cSrcweir if (MARK_INVALID != m_UndoSaveMark)
150cdf0e10cSrcweir {
151cdf0e10cSrcweir RemoveMark(m_UndoSaveMark);
152cdf0e10cSrcweir m_UndoSaveMark = MARK_INVALID;
153cdf0e10cSrcweir }
154cdf0e10cSrcweir }
155cdf0e10cSrcweir
SetUndoNoModifiedPosition()156cdf0e10cSrcweir void UndoManager::SetUndoNoModifiedPosition()
157cdf0e10cSrcweir {
158cdf0e10cSrcweir if (!m_bLockUndoNoModifiedPosition)
159cdf0e10cSrcweir {
160cdf0e10cSrcweir m_UndoSaveMark = MarkTopUndoAction();
161cdf0e10cSrcweir }
162cdf0e10cSrcweir }
163cdf0e10cSrcweir
LockUndoNoModifiedPosition()164cdf0e10cSrcweir void UndoManager::LockUndoNoModifiedPosition()
165cdf0e10cSrcweir {
166cdf0e10cSrcweir m_bLockUndoNoModifiedPosition = true;
167cdf0e10cSrcweir }
168cdf0e10cSrcweir
UnLockUndoNoModifiedPosition()169cdf0e10cSrcweir void UndoManager::UnLockUndoNoModifiedPosition()
170cdf0e10cSrcweir {
171cdf0e10cSrcweir m_bLockUndoNoModifiedPosition = false;
172cdf0e10cSrcweir }
173cdf0e10cSrcweir
174cdf0e10cSrcweir
GetLastUndo()175cdf0e10cSrcweir SwUndo* UndoManager::GetLastUndo()
176cdf0e10cSrcweir {
1778218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
178cdf0e10cSrcweir {
179cdf0e10cSrcweir return 0;
180cdf0e10cSrcweir }
1818218eba2SArmin Le Grand SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
182cdf0e10cSrcweir return dynamic_cast<SwUndo*>(pAction);
183cdf0e10cSrcweir }
184cdf0e10cSrcweir
AppendUndo(SwUndo * const pUndo)185cdf0e10cSrcweir void UndoManager::AppendUndo(SwUndo *const pUndo)
186cdf0e10cSrcweir {
187cdf0e10cSrcweir AddUndoAction(pUndo);
188cdf0e10cSrcweir }
189cdf0e10cSrcweir
ClearRedo()190cdf0e10cSrcweir void UndoManager::ClearRedo()
191cdf0e10cSrcweir {
1928218eba2SArmin Le Grand return SdrUndoManager::ImplClearRedo_NoLock(TopLevel);
193cdf0e10cSrcweir }
194cdf0e10cSrcweir
DelAllUndoObj()195cdf0e10cSrcweir void UndoManager::DelAllUndoObj()
196cdf0e10cSrcweir {
197cdf0e10cSrcweir ::sw::UndoGuard const undoGuard(*this);
198cdf0e10cSrcweir
1998218eba2SArmin Le Grand SdrUndoManager::ClearAllLevels();
200cdf0e10cSrcweir
201cdf0e10cSrcweir m_UndoSaveMark = MARK_INVALID;
202cdf0e10cSrcweir }
203cdf0e10cSrcweir
204cdf0e10cSrcweir
205cdf0e10cSrcweir /**************** UNDO ******************/
206cdf0e10cSrcweir
207cdf0e10cSrcweir SwUndoId
StartUndo(SwUndoId const i_eUndoId,SwRewriter const * const pRewriter)208cdf0e10cSrcweir UndoManager::StartUndo(SwUndoId const i_eUndoId,
209cdf0e10cSrcweir SwRewriter const*const pRewriter)
210cdf0e10cSrcweir {
211cdf0e10cSrcweir if (!IsUndoEnabled())
212cdf0e10cSrcweir {
213cdf0e10cSrcweir return UNDO_EMPTY;
214cdf0e10cSrcweir }
215cdf0e10cSrcweir
216cdf0e10cSrcweir SwUndoId const eUndoId( (0 == i_eUndoId) ? UNDO_START : i_eUndoId );
217cdf0e10cSrcweir
218cdf0e10cSrcweir OSL_ASSERT(UNDO_END != eUndoId);
219cdf0e10cSrcweir String comment( (UNDO_START == eUndoId)
220cdf0e10cSrcweir ? String("??", RTL_TEXTENCODING_ASCII_US)
221cdf0e10cSrcweir : String(SW_RES(UNDO_BASE + eUndoId)) );
222cdf0e10cSrcweir if (pRewriter)
223cdf0e10cSrcweir {
224cdf0e10cSrcweir OSL_ASSERT(UNDO_START != eUndoId);
225cdf0e10cSrcweir comment = pRewriter->Apply(comment);
226cdf0e10cSrcweir }
227cdf0e10cSrcweir
2288218eba2SArmin Le Grand SdrUndoManager::EnterListAction(comment, comment, eUndoId);
229cdf0e10cSrcweir
230cdf0e10cSrcweir return eUndoId;
231cdf0e10cSrcweir }
232cdf0e10cSrcweir
233cdf0e10cSrcweir
234cdf0e10cSrcweir SwUndoId
EndUndo(SwUndoId const i_eUndoId,SwRewriter const * const pRewriter)235cdf0e10cSrcweir UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
236cdf0e10cSrcweir {
237cdf0e10cSrcweir if (!IsUndoEnabled())
238cdf0e10cSrcweir {
239cdf0e10cSrcweir return UNDO_EMPTY;
240cdf0e10cSrcweir }
241cdf0e10cSrcweir
242cdf0e10cSrcweir SwUndoId const eUndoId( ((0 == i_eUndoId) || (UNDO_START == i_eUndoId))
243cdf0e10cSrcweir ? UNDO_END : i_eUndoId );
244cdf0e10cSrcweir OSL_ENSURE(!((UNDO_END == eUndoId) && pRewriter),
245cdf0e10cSrcweir "EndUndo(): no Undo ID, but rewriter given?");
246cdf0e10cSrcweir
247cdf0e10cSrcweir SfxUndoAction *const pLastUndo(
2488218eba2SArmin Le Grand (0 == SdrUndoManager::GetUndoActionCount(CurrentLevel))
2498218eba2SArmin Le Grand ? 0 : SdrUndoManager::GetUndoAction(0) );
250cdf0e10cSrcweir
251cdf0e10cSrcweir int const nCount = LeaveListAction();
252cdf0e10cSrcweir
253cdf0e10cSrcweir if (nCount) // otherwise: empty list action not inserted!
254cdf0e10cSrcweir {
255cdf0e10cSrcweir OSL_ASSERT(pLastUndo);
256cdf0e10cSrcweir OSL_ASSERT(UNDO_START != eUndoId);
2578218eba2SArmin Le Grand SfxUndoAction *const pUndoAction(SdrUndoManager::GetUndoAction(0));
258cdf0e10cSrcweir SfxListUndoAction *const pListAction(
259cdf0e10cSrcweir dynamic_cast<SfxListUndoAction*>(pUndoAction));
260cdf0e10cSrcweir OSL_ASSERT(pListAction);
261cdf0e10cSrcweir if (pListAction)
262cdf0e10cSrcweir {
263cdf0e10cSrcweir if (UNDO_END != eUndoId)
264cdf0e10cSrcweir {
265cdf0e10cSrcweir OSL_ENSURE(pListAction->GetId() == eUndoId,
266cdf0e10cSrcweir "EndUndo(): given ID different from StartUndo()");
267cdf0e10cSrcweir // comment set by caller of EndUndo
268cdf0e10cSrcweir String comment = String(SW_RES(UNDO_BASE + eUndoId));
269cdf0e10cSrcweir if (pRewriter)
270cdf0e10cSrcweir {
271cdf0e10cSrcweir comment = pRewriter->Apply(comment);
272cdf0e10cSrcweir }
273cdf0e10cSrcweir pListAction->SetComment(comment);
274cdf0e10cSrcweir }
275cdf0e10cSrcweir else if ((UNDO_START != pListAction->GetId()))
276cdf0e10cSrcweir {
277cdf0e10cSrcweir // comment set by caller of StartUndo: nothing to do here
278cdf0e10cSrcweir }
279cdf0e10cSrcweir else if (pLastUndo)
280cdf0e10cSrcweir {
281cdf0e10cSrcweir // comment was not set at StartUndo or EndUndo:
282cdf0e10cSrcweir // take comment of last contained action
283cdf0e10cSrcweir // (note that this works recursively, i.e. the last contained
284cdf0e10cSrcweir // action may be a list action created by StartUndo/EndUndo)
285cdf0e10cSrcweir String const comment(pLastUndo->GetComment());
286cdf0e10cSrcweir pListAction->SetComment(comment);
287cdf0e10cSrcweir }
288cdf0e10cSrcweir else
289cdf0e10cSrcweir {
290cdf0e10cSrcweir OSL_ENSURE(false, "EndUndo(): no comment?");
291cdf0e10cSrcweir }
292cdf0e10cSrcweir }
293cdf0e10cSrcweir }
294cdf0e10cSrcweir
295cdf0e10cSrcweir return eUndoId;
296cdf0e10cSrcweir }
297cdf0e10cSrcweir
298cdf0e10cSrcweir bool
GetLastUndoInfo(::rtl::OUString * const o_pStr,SwUndoId * const o_pId) const299cdf0e10cSrcweir UndoManager::GetLastUndoInfo(
300cdf0e10cSrcweir ::rtl::OUString *const o_pStr, SwUndoId *const o_pId) const
301cdf0e10cSrcweir {
302cdf0e10cSrcweir // this is actually expected to work on the current level,
303cdf0e10cSrcweir // but that was really not obvious from the previous implementation...
3048218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
305cdf0e10cSrcweir {
306cdf0e10cSrcweir return false;
307cdf0e10cSrcweir }
308cdf0e10cSrcweir
3098218eba2SArmin Le Grand SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction(0) );
310cdf0e10cSrcweir
311cdf0e10cSrcweir if (o_pStr)
312cdf0e10cSrcweir {
313cdf0e10cSrcweir *o_pStr = pAction->GetComment();
314cdf0e10cSrcweir }
315cdf0e10cSrcweir if (o_pId)
316cdf0e10cSrcweir {
317cdf0e10cSrcweir sal_uInt16 const nId(pAction->GetId());
318cdf0e10cSrcweir *o_pId = static_cast<SwUndoId>(nId);
319cdf0e10cSrcweir }
320cdf0e10cSrcweir
321cdf0e10cSrcweir return true;
322cdf0e10cSrcweir }
323cdf0e10cSrcweir
GetUndoComments() const324cdf0e10cSrcweir SwUndoComments_t UndoManager::GetUndoComments() const
325cdf0e10cSrcweir {
3268218eba2SArmin Le Grand OSL_ENSURE(!SdrUndoManager::IsInListAction(),
327cdf0e10cSrcweir "GetUndoComments() called while in list action?");
328cdf0e10cSrcweir
329cdf0e10cSrcweir SwUndoComments_t ret;
3308218eba2SArmin Le Grand sal_uInt16 const nUndoCount(SdrUndoManager::GetUndoActionCount(TopLevel));
331cdf0e10cSrcweir for (sal_uInt16 n = 0; n < nUndoCount; ++n)
332cdf0e10cSrcweir {
333cdf0e10cSrcweir ::rtl::OUString const comment(
3348218eba2SArmin Le Grand SdrUndoManager::GetUndoActionComment(n, TopLevel));
335cdf0e10cSrcweir ret.push_back(comment);
336cdf0e10cSrcweir }
337cdf0e10cSrcweir
338cdf0e10cSrcweir return ret;
339cdf0e10cSrcweir }
340cdf0e10cSrcweir
341cdf0e10cSrcweir
342cdf0e10cSrcweir /**************** REDO ******************/
343cdf0e10cSrcweir
GetFirstRedoInfo(::rtl::OUString * const o_pStr,SwUndoId * const o_pId) const344*89358e0fSOliver-Rainer Wittmann bool UndoManager::GetFirstRedoInfo(::rtl::OUString *const o_pStr,
345*89358e0fSOliver-Rainer Wittmann SwUndoId *const o_pId) const
346cdf0e10cSrcweir {
3478218eba2SArmin Le Grand if (!SdrUndoManager::GetRedoActionCount(CurrentLevel))
348cdf0e10cSrcweir {
349cdf0e10cSrcweir return false;
350cdf0e10cSrcweir }
351cdf0e10cSrcweir
352*89358e0fSOliver-Rainer Wittmann SfxUndoAction *const pAction( SdrUndoManager::GetRedoAction(0, CurrentLevel) );
353*89358e0fSOliver-Rainer Wittmann if ( pAction == NULL )
354*89358e0fSOliver-Rainer Wittmann {
355*89358e0fSOliver-Rainer Wittmann return false;
356*89358e0fSOliver-Rainer Wittmann }
357*89358e0fSOliver-Rainer Wittmann
358cdf0e10cSrcweir if (o_pStr)
359cdf0e10cSrcweir {
360*89358e0fSOliver-Rainer Wittmann *o_pStr = pAction->GetComment();
361*89358e0fSOliver-Rainer Wittmann }
362*89358e0fSOliver-Rainer Wittmann if (o_pId)
363*89358e0fSOliver-Rainer Wittmann {
364*89358e0fSOliver-Rainer Wittmann sal_uInt16 const nId(pAction->GetId());
365*89358e0fSOliver-Rainer Wittmann *o_pId = static_cast<SwUndoId>(nId);
366cdf0e10cSrcweir }
367cdf0e10cSrcweir
368cdf0e10cSrcweir return true;
369cdf0e10cSrcweir }
370cdf0e10cSrcweir
371cdf0e10cSrcweir
GetRedoComments() const372cdf0e10cSrcweir SwUndoComments_t UndoManager::GetRedoComments() const
373cdf0e10cSrcweir {
3748218eba2SArmin Le Grand OSL_ENSURE(!SdrUndoManager::IsInListAction(),
375cdf0e10cSrcweir "GetRedoComments() called while in list action?");
376cdf0e10cSrcweir
377cdf0e10cSrcweir SwUndoComments_t ret;
3788218eba2SArmin Le Grand sal_uInt16 const nRedoCount(SdrUndoManager::GetRedoActionCount(TopLevel));
379cdf0e10cSrcweir for (sal_uInt16 n = 0; n < nRedoCount; ++n)
380cdf0e10cSrcweir {
381cdf0e10cSrcweir ::rtl::OUString const comment(
3828218eba2SArmin Le Grand SdrUndoManager::GetRedoActionComment(n, TopLevel));
383cdf0e10cSrcweir ret.push_back(comment);
384cdf0e10cSrcweir }
385cdf0e10cSrcweir
386cdf0e10cSrcweir return ret;
387cdf0e10cSrcweir }
388cdf0e10cSrcweir
389cdf0e10cSrcweir /**************** REPEAT ******************/
390cdf0e10cSrcweir
GetRepeatInfo(::rtl::OUString * const o_pStr) const391cdf0e10cSrcweir SwUndoId UndoManager::GetRepeatInfo(::rtl::OUString *const o_pStr) const
392cdf0e10cSrcweir {
393cdf0e10cSrcweir SwUndoId nRepeatId(UNDO_EMPTY);
394cdf0e10cSrcweir GetLastUndoInfo(o_pStr, & nRepeatId);
395cdf0e10cSrcweir if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
396cdf0e10cSrcweir {
397cdf0e10cSrcweir return nRepeatId;
398cdf0e10cSrcweir }
399cdf0e10cSrcweir if (o_pStr) // not repeatable -> clear comment
400cdf0e10cSrcweir {
401cdf0e10cSrcweir *o_pStr = String();
402cdf0e10cSrcweir }
403cdf0e10cSrcweir return UNDO_EMPTY;
404cdf0e10cSrcweir }
405cdf0e10cSrcweir
RemoveLastUndo()406cdf0e10cSrcweir SwUndo * UndoManager::RemoveLastUndo()
407cdf0e10cSrcweir {
4088218eba2SArmin Le Grand if (SdrUndoManager::GetRedoActionCount(CurrentLevel) ||
4098218eba2SArmin Le Grand SdrUndoManager::GetRedoActionCount(TopLevel))
410cdf0e10cSrcweir {
411cdf0e10cSrcweir OSL_ENSURE(false, "RemoveLastUndoAction(): there are Redo actions?");
412cdf0e10cSrcweir return 0;
413cdf0e10cSrcweir }
4148218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(CurrentLevel))
415cdf0e10cSrcweir {
416cdf0e10cSrcweir OSL_ENSURE(false, "RemoveLastUndoAction(): no Undo actions");
417cdf0e10cSrcweir return 0;
418cdf0e10cSrcweir }
419cdf0e10cSrcweir SfxUndoAction *const pLastUndo(GetUndoAction(0));
4208218eba2SArmin Le Grand SdrUndoManager::RemoveLastUndoAction();
421cdf0e10cSrcweir return dynamic_cast<SwUndo *>(pLastUndo);
422cdf0e10cSrcweir }
423cdf0e10cSrcweir
424cdf0e10cSrcweir // svl::IUndoManager /////////////////////////////////////////////////////
425cdf0e10cSrcweir
EnableUndo(bool bEnable)426cdf0e10cSrcweir void UndoManager::EnableUndo(bool bEnable)
427cdf0e10cSrcweir {
4288218eba2SArmin Le Grand // SdrUndoManager does not have a counter anymore, but reverted to the old behavior of
429cdf0e10cSrcweir // having a simple boolean flag for locking. So, simply forward.
4308218eba2SArmin Le Grand SdrUndoManager::EnableUndo(bEnable);
431cdf0e10cSrcweir }
432cdf0e10cSrcweir
AddUndoAction(SfxUndoAction * pAction,sal_Bool bTryMerge)433cdf0e10cSrcweir void UndoManager::AddUndoAction(SfxUndoAction *pAction, sal_Bool bTryMerge)
434cdf0e10cSrcweir {
435cdf0e10cSrcweir SwUndo *const pUndo( dynamic_cast<SwUndo *>(pAction) );
436cdf0e10cSrcweir if (pUndo)
437cdf0e10cSrcweir {
438cdf0e10cSrcweir if (nsRedlineMode_t::REDLINE_NONE == pUndo->GetRedlineMode())
439cdf0e10cSrcweir {
440cdf0e10cSrcweir pUndo->SetRedlineMode( m_rRedlineAccess.GetRedlineMode() );
441cdf0e10cSrcweir }
442cdf0e10cSrcweir }
4438218eba2SArmin Le Grand SdrUndoManager::AddUndoAction(pAction, bTryMerge);
444cdf0e10cSrcweir // if the undo nodes array is too large, delete some actions
445cdf0e10cSrcweir while (UNDO_ACTION_LIMIT < GetUndoNodes().Count())
446cdf0e10cSrcweir {
447cdf0e10cSrcweir RemoveOldestUndoActions(1);
448cdf0e10cSrcweir }
449cdf0e10cSrcweir }
450cdf0e10cSrcweir
451cdf0e10cSrcweir class CursorGuard
452cdf0e10cSrcweir {
453cdf0e10cSrcweir public:
CursorGuard(SwEditShell & rShell,bool const bSave)454cdf0e10cSrcweir CursorGuard(SwEditShell & rShell, bool const bSave)
455cdf0e10cSrcweir : m_rShell(rShell)
456cdf0e10cSrcweir , m_bSaveCursor(bSave)
457cdf0e10cSrcweir {
458cdf0e10cSrcweir if (m_bSaveCursor)
459cdf0e10cSrcweir {
460cdf0e10cSrcweir m_rShell.Push(); // prevent modification of current cursor
461cdf0e10cSrcweir }
462cdf0e10cSrcweir }
~CursorGuard()463cdf0e10cSrcweir ~CursorGuard()
464cdf0e10cSrcweir {
465cdf0e10cSrcweir if (m_bSaveCursor)
466cdf0e10cSrcweir {
467*89358e0fSOliver-Rainer Wittmann m_rShell.Pop( sal_False );
468cdf0e10cSrcweir }
469cdf0e10cSrcweir }
470cdf0e10cSrcweir private:
471cdf0e10cSrcweir SwEditShell & m_rShell;
472cdf0e10cSrcweir bool const m_bSaveCursor;
473cdf0e10cSrcweir };
474cdf0e10cSrcweir
impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)475cdf0e10cSrcweir bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)
476cdf0e10cSrcweir {
477cdf0e10cSrcweir SwDoc & rDoc(*GetUndoNodes().GetDoc());
478cdf0e10cSrcweir
479cdf0e10cSrcweir UnoActionContext c(& rDoc); // exception-safe StartAllAction/EndAllAction
480cdf0e10cSrcweir
481cdf0e10cSrcweir SwEditShell *const pEditShell( rDoc.GetEditShell() );
482cdf0e10cSrcweir
483cdf0e10cSrcweir OSL_ENSURE(pEditShell, "sw::UndoManager needs a SwEditShell!");
484cdf0e10cSrcweir if (!pEditShell)
485cdf0e10cSrcweir {
486cdf0e10cSrcweir throw uno::RuntimeException();
487cdf0e10cSrcweir }
488cdf0e10cSrcweir
489cdf0e10cSrcweir // in case the model has controllers locked, the Undo should not
490cdf0e10cSrcweir // change the view cursors!
491cdf0e10cSrcweir bool const bSaveCursors(pEditShell->CursorsLocked());
492*89358e0fSOliver-Rainer Wittmann CursorGuard aCursorGuard(*pEditShell, bSaveCursors);
493cdf0e10cSrcweir if (!bSaveCursors)
494cdf0e10cSrcweir {
495cdf0e10cSrcweir // (in case Undo was called via API) clear the cursors:
496cdf0e10cSrcweir pEditShell->KillPams();
497cdf0e10cSrcweir pEditShell->SetMark();
498cdf0e10cSrcweir pEditShell->ClearMark();
499cdf0e10cSrcweir }
500cdf0e10cSrcweir
501cdf0e10cSrcweir bool bRet(false);
502cdf0e10cSrcweir
503cdf0e10cSrcweir ::sw::UndoRedoContext context(rDoc, *pEditShell);
504cdf0e10cSrcweir
505cdf0e10cSrcweir // N.B. these may throw!
506cdf0e10cSrcweir if (UNDO == undoOrRedo)
507cdf0e10cSrcweir {
5088218eba2SArmin Le Grand bRet = SdrUndoManager::UndoWithContext(context);
509cdf0e10cSrcweir }
510cdf0e10cSrcweir else
511cdf0e10cSrcweir {
5128218eba2SArmin Le Grand bRet = SdrUndoManager::RedoWithContext(context);
513cdf0e10cSrcweir }
514cdf0e10cSrcweir
515cdf0e10cSrcweir if (bRet)
516cdf0e10cSrcweir {
517cdf0e10cSrcweir // if we are at the "last save" position, the document is not modified
5188218eba2SArmin Le Grand if (SdrUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
519cdf0e10cSrcweir {
520cdf0e10cSrcweir m_rState.ResetModified();
521cdf0e10cSrcweir }
522cdf0e10cSrcweir else
523cdf0e10cSrcweir {
524cdf0e10cSrcweir m_rState.SetModified();
525cdf0e10cSrcweir }
526cdf0e10cSrcweir }
527cdf0e10cSrcweir
528cdf0e10cSrcweir pEditShell->HandleUndoRedoContext(context);
529cdf0e10cSrcweir
530cdf0e10cSrcweir return bRet;
531cdf0e10cSrcweir }
532cdf0e10cSrcweir
Undo()533cdf0e10cSrcweir sal_Bool UndoManager::Undo()
534cdf0e10cSrcweir {
5358218eba2SArmin Le Grand if(isTextEditActive())
5368218eba2SArmin Le Grand {
5378218eba2SArmin Le Grand return SdrUndoManager::Undo();
5388218eba2SArmin Le Grand }
5398218eba2SArmin Le Grand else
5408218eba2SArmin Le Grand {
5418218eba2SArmin Le Grand return impl_DoUndoRedo(UNDO);
5428218eba2SArmin Le Grand }
543cdf0e10cSrcweir }
544cdf0e10cSrcweir
Redo()545cdf0e10cSrcweir sal_Bool UndoManager::Redo()
546cdf0e10cSrcweir {
5478218eba2SArmin Le Grand if(isTextEditActive())
5488218eba2SArmin Le Grand {
5498218eba2SArmin Le Grand return SdrUndoManager::Redo();
5508218eba2SArmin Le Grand }
5518218eba2SArmin Le Grand else
5528218eba2SArmin Le Grand {
5538218eba2SArmin Le Grand return impl_DoUndoRedo(REDO);
5548218eba2SArmin Le Grand }
555cdf0e10cSrcweir }
556cdf0e10cSrcweir
5578218eba2SArmin Le Grand /** N.B.: this does _not_ call SdrUndoManager::Repeat because it is not
558cdf0e10cSrcweir possible to wrap a list action around it:
5598218eba2SArmin Le Grand calling EnterListAction here will cause SdrUndoManager::Repeat
560cdf0e10cSrcweir to repeat the list action!
561cdf0e10cSrcweir */
562cdf0e10cSrcweir bool
Repeat(::sw::RepeatContext & rContext,sal_uInt16 const nRepeatCount)563cdf0e10cSrcweir UndoManager::Repeat(::sw::RepeatContext & rContext,
564cdf0e10cSrcweir sal_uInt16 const nRepeatCount)
565cdf0e10cSrcweir {
5668218eba2SArmin Le Grand if (SdrUndoManager::IsInListAction())
567cdf0e10cSrcweir {
568cdf0e10cSrcweir OSL_ENSURE(false, "repeat in open list action???");
569cdf0e10cSrcweir return false;
570cdf0e10cSrcweir }
5718218eba2SArmin Le Grand if (!SdrUndoManager::GetUndoActionCount(TopLevel))
572cdf0e10cSrcweir {
573cdf0e10cSrcweir return false;
574cdf0e10cSrcweir }
575cdf0e10cSrcweir SfxUndoAction *const pRepeatAction(GetUndoAction(0));
576cdf0e10cSrcweir OSL_ASSERT(pRepeatAction);
577cdf0e10cSrcweir if (!pRepeatAction || !pRepeatAction->CanRepeat(rContext))
578cdf0e10cSrcweir {
579cdf0e10cSrcweir return false;
580cdf0e10cSrcweir }
581cdf0e10cSrcweir
582cdf0e10cSrcweir ::rtl::OUString const comment(pRepeatAction->GetComment());
583cdf0e10cSrcweir ::rtl::OUString const rcomment(pRepeatAction->GetRepeatComment(rContext));
584cdf0e10cSrcweir sal_uInt16 const nId(pRepeatAction->GetId());
585cdf0e10cSrcweir if (DoesUndo())
586cdf0e10cSrcweir {
587cdf0e10cSrcweir EnterListAction(comment, rcomment, nId);
588cdf0e10cSrcweir }
589cdf0e10cSrcweir
590cdf0e10cSrcweir SwPaM *const pFirstCursor(& rContext.GetRepeatPaM());
591cdf0e10cSrcweir do { // iterate over ring
592cdf0e10cSrcweir for (sal_uInt16 nRptCnt = nRepeatCount; nRptCnt > 0; --nRptCnt)
593cdf0e10cSrcweir {
594cdf0e10cSrcweir pRepeatAction->Repeat(rContext);
595cdf0e10cSrcweir }
596cdf0e10cSrcweir rContext.m_bDeleteRepeated = false; // reset for next PaM
597cdf0e10cSrcweir rContext.m_pCurrentPaM =
598cdf0e10cSrcweir static_cast<SwPaM*>(rContext.m_pCurrentPaM->GetNext());
599cdf0e10cSrcweir } while (pFirstCursor != & rContext.GetRepeatPaM());
600cdf0e10cSrcweir
601cdf0e10cSrcweir if (DoesUndo())
602cdf0e10cSrcweir {
603cdf0e10cSrcweir LeaveListAction();
604cdf0e10cSrcweir }
605cdf0e10cSrcweir return true;
606cdf0e10cSrcweir }
607cdf0e10cSrcweir
608cdf0e10cSrcweir } // namespace sw
609cdf0e10cSrcweir
610