xref: /aoo41x/main/sw/source/core/undo/docundo.cxx (revision 89358e0f)
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