android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / undo / docundo.cxx
bloba9efc248259a1f669fd731b926793c892f16732d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <UndoManager.hxx>
22 #include <libxml/xmlwriter.h>
24 #include <doc.hxx>
25 #include <docsh.hxx>
26 #include <utility>
27 #include <view.hxx>
28 #include <drawdoc.hxx>
29 #include <ndarr.hxx>
30 #include <pam.hxx>
31 #include <swundo.hxx>
32 #include <UndoCore.hxx>
33 #include <editsh.hxx>
34 #include <unobaseclass.hxx>
35 #include <IDocumentDrawModelAccess.hxx>
36 #include <IDocumentRedlineAccess.hxx>
37 #include <IDocumentState.hxx>
38 #include <comphelper/lok.hxx>
39 #include <assert.h>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <osl/diagnose.h>
44 #include <o3tl/temporary.hxx>
46 #include <UndoInsert.hxx>
48 using namespace ::com::sun::star;
50 // the undo array should never grow beyond this limit:
51 #define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
53 namespace sw {
55 UndoManager::UndoManager(std::shared_ptr<SwNodes> xUndoNodes,
56 IDocumentDrawModelAccess & rDrawModelAccess,
57 IDocumentRedlineAccess & rRedlineAccess,
58 IDocumentState & rState)
59 : m_rDrawModelAccess(rDrawModelAccess)
60 , m_rRedlineAccess(rRedlineAccess)
61 , m_rState(rState)
62 , m_xUndoNodes(std::move(xUndoNodes))
63 , m_bGroupUndo(true)
64 , m_bDrawUndo(true)
65 , m_bRepair(false)
66 , m_bLockUndoNoModifiedPosition(false)
67 , m_isAddWithIgnoreRepeat(false)
68 , m_UndoSaveMark(MARK_INVALID)
69 , m_pDocShell(nullptr)
70 , m_pView(nullptr)
72 assert(bool(m_xUndoNodes));
73 // writer expects it to be disabled initially
74 // Undo is enabled by SwEditShell constructor
75 SdrUndoManager::EnableUndo(false);
78 SwNodes const& UndoManager::GetUndoNodes() const
80 return *m_xUndoNodes;
83 SwNodes & UndoManager::GetUndoNodes()
85 return *m_xUndoNodes;
88 bool UndoManager::IsUndoNodes(SwNodes const& rNodes) const
90 return & rNodes == m_xUndoNodes.get();
93 void UndoManager::SetDocShell(SwDocShell* pDocShell)
95 m_pDocShell = pDocShell;
98 void UndoManager::SetView(SwView* pView)
100 m_pView = pView;
103 size_t UndoManager::GetUndoActionCount(const bool bCurrentLevel) const
105 size_t nRet = SdrUndoManager::GetUndoActionCount(bCurrentLevel);
106 if (!comphelper::LibreOfficeKit::isActive() || !m_pView)
107 return nRet;
109 if (!nRet || !SdrUndoManager::GetUndoActionCount())
110 return nRet;
112 const SfxUndoAction* pAction = SdrUndoManager::GetUndoAction();
113 if (!pAction)
114 return nRet;
116 if (!m_bRepair)
118 // If another view created the last undo action, prevent undoing it from this view.
119 ViewShellId nViewShellId = m_pView->GetViewShellId();
120 if (pAction->GetViewShellId() != nViewShellId)
121 nRet = 0;
124 return nRet;
127 size_t UndoManager::GetRedoActionCount(const bool bCurrentLevel) const
129 size_t nRet = SdrUndoManager::GetRedoActionCount(bCurrentLevel);
130 if (!comphelper::LibreOfficeKit::isActive() || !m_pView)
131 return nRet;
133 if (!nRet || !SdrUndoManager::GetRedoActionCount())
134 return nRet;
136 const SfxUndoAction* pAction = SdrUndoManager::GetRedoAction();
137 if (!pAction)
138 return nRet;
140 if (!m_bRepair)
142 // If another view created the first redo action, prevent redoing it from this view.
143 ViewShellId nViewShellId = m_pView->GetViewShellId();
144 if (pAction->GetViewShellId() != nViewShellId)
145 nRet = 0;
148 return nRet;
151 void UndoManager::DoUndo(bool const bDoUndo)
153 if(!isTextEditActive())
155 EnableUndo(bDoUndo);
157 SwDrawModel*const pSdrModel = m_rDrawModelAccess.GetDrawModel();
158 if( pSdrModel )
160 pSdrModel->EnableUndo(bDoUndo);
165 bool UndoManager::DoesUndo() const
167 if(isTextEditActive())
169 return false;
171 else
173 return IsUndoEnabled();
177 void UndoManager::DoGroupUndo(bool const bDoUndo)
179 m_bGroupUndo = bDoUndo;
182 bool UndoManager::DoesGroupUndo() const
184 return m_bGroupUndo;
187 void UndoManager::DoDrawUndo(bool const bDoUndo)
189 m_bDrawUndo = bDoUndo;
192 bool UndoManager::DoesDrawUndo() const
194 return m_bDrawUndo;
197 void UndoManager::DoRepair(bool bRepair)
199 m_bRepair = bRepair;
202 bool UndoManager::DoesRepair() const
204 return m_bRepair;
207 bool UndoManager::IsUndoNoResetModified() const
209 return MARK_INVALID == m_UndoSaveMark;
212 void UndoManager::SetUndoNoResetModified()
214 if (MARK_INVALID != m_UndoSaveMark)
216 RemoveMark(m_UndoSaveMark);
217 m_UndoSaveMark = MARK_INVALID;
221 void UndoManager::SetUndoNoModifiedPosition()
223 if (!m_bLockUndoNoModifiedPosition)
225 m_UndoSaveMark = MarkTopUndoAction();
229 void UndoManager::LockUndoNoModifiedPosition()
231 m_bLockUndoNoModifiedPosition = true;
234 void UndoManager::UnLockUndoNoModifiedPosition()
236 m_bLockUndoNoModifiedPosition = false;
239 SwUndo* UndoManager::GetLastUndo()
241 if (!SdrUndoManager::GetUndoActionCount())
243 return nullptr;
245 SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction() );
246 return dynamic_cast<SwUndo*>(pAction);
249 void UndoManager::AppendUndo(std::unique_ptr<SwUndo> pUndo)
251 AddUndoAction(std::move(pUndo));
254 void UndoManager::ClearRedo()
256 return SdrUndoManager::ImplClearRedo_NoLock(TopLevel);
259 void UndoManager::DelAllUndoObj()
261 ::sw::UndoGuard const undoGuard(*this);
263 SdrUndoManager::ClearAllLevels();
265 m_UndoSaveMark = MARK_INVALID;
268 SwUndoId
269 UndoManager::StartUndo(SwUndoId const i_eUndoId,
270 SwRewriter const*const pRewriter)
272 if (!IsUndoEnabled())
274 return SwUndoId::EMPTY;
277 SwUndoId const eUndoId( (i_eUndoId == SwUndoId::EMPTY) ? SwUndoId::START : i_eUndoId );
279 assert(SwUndoId::END != eUndoId);
280 OUString comment( (SwUndoId::START == eUndoId)
281 ? OUString("??")
282 : GetUndoComment(eUndoId) );
283 if (pRewriter)
285 assert(SwUndoId::START != eUndoId);
286 comment = pRewriter->Apply(comment);
289 ViewShellId nViewShellId(-1);
290 if (m_pDocShell)
292 if (const SwView* pView = m_pDocShell->GetView())
293 nViewShellId = pView->GetViewShellId();
295 SdrUndoManager::EnterListAction(comment, comment, static_cast<sal_uInt16>(eUndoId), nViewShellId);
297 return eUndoId;
300 SwUndoId
301 UndoManager::EndUndo(SwUndoId eUndoId, SwRewriter const*const pRewriter)
303 if (!IsUndoEnabled())
305 return SwUndoId::EMPTY;
308 if ((eUndoId == SwUndoId::EMPTY) || (SwUndoId::START == eUndoId))
309 eUndoId = SwUndoId::END;
310 OSL_ENSURE(!((SwUndoId::END == eUndoId) && pRewriter),
311 "EndUndo(): no Undo ID, but rewriter given?");
313 SfxUndoAction *const pLastUndo(
314 (0 == SdrUndoManager::GetUndoActionCount())
315 ? nullptr : SdrUndoManager::GetUndoAction() );
317 int const nCount = LeaveListAction();
319 if (nCount) // otherwise: empty list action not inserted!
321 assert(pLastUndo);
322 assert(SwUndoId::START != eUndoId);
323 auto pListAction = dynamic_cast<SfxListUndoAction*>(SdrUndoManager::GetUndoAction());
324 assert(pListAction);
325 if (SwUndoId::END != eUndoId)
327 OSL_ENSURE(static_cast<SwUndoId>(pListAction->GetId()) == eUndoId,
328 "EndUndo(): given ID different from StartUndo()");
329 // comment set by caller of EndUndo
330 OUString comment = GetUndoComment(eUndoId);
331 if (pRewriter)
333 comment = pRewriter->Apply(comment);
335 pListAction->SetComment(comment);
337 else if (SwUndoId::START != static_cast<SwUndoId>(pListAction->GetId()))
339 // comment set by caller of StartUndo: nothing to do here
341 else if (pLastUndo)
343 // comment was not set at StartUndo or EndUndo:
344 // take comment of last contained action
345 // (note that this works recursively, i.e. the last contained
346 // action may be a list action created by StartUndo/EndUndo)
347 OUString const comment(pLastUndo->GetComment());
348 pListAction->SetComment(comment);
350 else
352 OSL_ENSURE(false, "EndUndo(): no comment?");
356 return eUndoId;
360 * Checks if the topmost undo action owned by pView is independent from the topmost action undo
361 * action.
363 bool UndoManager::IsViewUndoActionIndependent(const SwView* pView, sal_uInt16& rOffset) const
365 if (GetUndoActionCount() <= 1)
367 // Single or less undo, owned by another view.
368 return false;
371 if (!pView)
373 return false;
376 // Last undo action that doesn't belong to the view.
377 const SfxUndoAction* pTopAction = GetUndoAction();
379 ViewShellId nViewId = pView->GetViewShellId();
381 // Earlier undo action that belongs to the view, but is not the top one.
382 const SfxUndoAction* pViewAction = nullptr;
383 size_t nOffset = 0;
384 for (size_t i = 0; i < GetUndoActionCount(); ++i)
386 const SfxUndoAction* pAction = GetUndoAction(i);
387 if (pAction->GetViewShellId() == nViewId)
389 pViewAction = pAction;
390 nOffset = i;
391 break;
395 if (!pViewAction)
397 // Found no earlier undo action that belongs to the view.
398 return false;
401 auto pTopSwAction = dynamic_cast<const SwUndo*>(pTopAction);
402 if (!pTopSwAction || pTopSwAction->GetId() != SwUndoId::TYPING)
404 return false;
407 auto pViewSwAction = dynamic_cast<const SwUndo*>(pViewAction);
408 if (!pViewSwAction || pViewSwAction->GetId() != SwUndoId::TYPING)
410 return false;
413 const auto& rTopInsert = *static_cast<const SwUndoInsert*>(pTopSwAction);
414 const auto& rViewInsert = *static_cast<const SwUndoInsert*>(pViewSwAction);
416 for (size_t i = 0; i < GetRedoActionCount(); ++i)
418 auto pRedoAction = dynamic_cast<const SwUndo*>(GetRedoAction(i));
419 if (!pRedoAction || pRedoAction->GetId() != SwUndoId::TYPING)
421 return false;
424 const auto& rRedoInsert = *static_cast<const SwUndoInsert*>(pRedoAction);
425 if (!rViewInsert.IsIndependent(rRedoInsert) && rRedoInsert.GetViewShellId() != nViewId)
427 // Dependent redo action and owned by another view.
428 return false;
432 if (!rViewInsert.IsIndependent(rTopInsert))
434 return false;
437 rOffset = nOffset;
438 return true;
441 bool
442 UndoManager::GetLastUndoInfo(
443 OUString *const o_pStr, SwUndoId *const o_pId, const SwView* pView) const
445 // this is actually expected to work on the current level,
446 // but that was really not obvious from the previous implementation...
447 if (!SdrUndoManager::GetUndoActionCount())
449 return false;
452 SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction() );
454 if (comphelper::LibreOfficeKit::isActive() && !m_bRepair)
456 // If another view created the undo action, prevent undoing it from this view.
457 ViewShellId nViewShellId = pView ? pView->GetViewShellId() : m_pDocShell->GetView()->GetViewShellId();
458 // Unless we know that the other view's undo action is independent from us.
459 if (pAction->GetViewShellId() != nViewShellId
460 && !IsViewUndoActionIndependent(pView, o3tl::temporary(sal_uInt16())))
462 if (o_pId)
464 *o_pId = SwUndoId::CONFLICT;
466 return false;
470 if (o_pStr)
472 *o_pStr = pAction->GetComment();
474 if (o_pId)
476 if (auto pListAction = dynamic_cast<const SfxListUndoAction*>(pAction))
477 *o_pId = static_cast<SwUndoId>(pListAction->GetId());
478 else if (auto pSwAction = dynamic_cast<const SwUndo*>(pAction))
479 *o_pId = pSwAction->GetId();
480 else
481 *o_pId = SwUndoId::EMPTY;
484 return true;
487 SwUndoComments_t UndoManager::GetUndoComments() const
489 OSL_ENSURE(!SdrUndoManager::IsInListAction(),
490 "GetUndoComments() called while in list action?");
492 SwUndoComments_t ret;
493 const size_t nUndoCount(SdrUndoManager::GetUndoActionCount(TopLevel));
494 for (size_t n = 0; n < nUndoCount; ++n)
496 OUString const comment(
497 SdrUndoManager::GetUndoActionComment(n, TopLevel));
498 ret.push_back(comment);
501 return ret;
504 bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr,
505 SwUndoId *const o_pId,
506 const SwView* pView) const
508 if (!SdrUndoManager::GetRedoActionCount())
510 return false;
513 SfxUndoAction *const pAction( SdrUndoManager::GetRedoAction() );
514 if ( pAction == nullptr )
516 return false;
519 if (comphelper::LibreOfficeKit::isActive() && !m_bRepair)
521 // If another view created the undo action, prevent redoing it from this view.
522 ViewShellId nViewShellId = pView ? pView->GetViewShellId() : m_pDocShell->GetView()->GetViewShellId();
523 if (pAction->GetViewShellId() != nViewShellId)
525 if (o_pId)
527 *o_pId = SwUndoId::CONFLICT;
529 return false;
533 if (o_pStr)
535 *o_pStr = pAction->GetComment();
537 if (o_pId)
539 if (auto pListAction = dynamic_cast<const SfxListUndoAction*>(pAction))
540 *o_pId = static_cast<SwUndoId>(pListAction->GetId());
541 else if (auto pSwAction = dynamic_cast<const SwUndo*>(pAction))
542 *o_pId = pSwAction->GetId();
543 else
544 *o_pId = SwUndoId::EMPTY;
547 return true;
550 SwUndoComments_t UndoManager::GetRedoComments() const
552 OSL_ENSURE(!SdrUndoManager::IsInListAction(),
553 "GetRedoComments() called while in list action?");
555 SwUndoComments_t ret;
556 const size_t nRedoCount(SdrUndoManager::GetRedoActionCount(TopLevel));
557 for (size_t n = 0; n < nRedoCount; ++n)
559 OUString const comment(
560 SdrUndoManager::GetRedoActionComment(n, TopLevel));
561 ret.push_back(comment);
564 return ret;
567 SwUndoId UndoManager::GetRepeatInfo(OUString *const o_pStr) const
569 SwUndoId nRepeatId(SwUndoId::EMPTY);
570 GetLastUndoInfo(o_pStr, & nRepeatId);
571 if( SwUndoId::REPEAT_START <= nRepeatId && SwUndoId::REPEAT_END > nRepeatId )
573 return nRepeatId;
575 if (o_pStr) // not repeatable -> clear comment
577 o_pStr->clear();
579 return SwUndoId::EMPTY;
582 SwUndo * UndoManager::RemoveLastUndo()
584 if (SdrUndoManager::GetRedoActionCount() ||
585 SdrUndoManager::GetRedoActionCount(TopLevel))
587 OSL_ENSURE(false, "RemoveLastUndoAction(): there are Redo actions?");
588 return nullptr;
590 if (!SdrUndoManager::GetUndoActionCount())
592 OSL_ENSURE(false, "RemoveLastUndoAction(): no Undo actions");
593 return nullptr;
595 SfxUndoAction *const pLastUndo(GetUndoAction());
596 SdrUndoManager::RemoveLastUndoAction();
597 return dynamic_cast<SwUndo *>(pLastUndo);
600 // SfxUndoManager
602 void UndoManager::AddUndoAction(std::unique_ptr<SfxUndoAction> pAction, bool bTryMerge)
604 SwUndo *const pUndo( dynamic_cast<SwUndo *>(pAction.get()) );
605 if (pUndo)
607 if (RedlineFlags::NONE == pUndo->GetRedlineFlags())
609 pUndo->SetRedlineFlags( m_rRedlineAccess.GetRedlineFlags() );
611 if (m_isAddWithIgnoreRepeat)
613 pUndo->IgnoreRepeat();
616 SdrUndoManager::AddUndoAction(std::move(pAction), bTryMerge);
617 if (m_pDocShell)
619 SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( m_pDocShell );
620 while ( pViewFrame )
622 pViewFrame->GetBindings().Invalidate( SID_UNDO );
623 pViewFrame->GetBindings().Invalidate( SID_REDO );
624 pViewFrame = SfxViewFrame::GetNext( *pViewFrame, m_pDocShell );
628 // if the undo nodes array is too large, delete some actions
629 while (UNDO_ACTION_LIMIT < sal_Int32(GetUndoNodes().Count()))
631 RemoveOldestUndoAction();
635 namespace {
637 class CursorGuard
639 public:
640 CursorGuard(SwEditShell & rShell, bool const bSave)
641 : m_rShell(rShell)
642 , m_bSaveCursor(bSave)
644 if (m_bSaveCursor)
646 m_rShell.Push(); // prevent modification of current cursor
649 ~CursorGuard() COVERITY_NOEXCEPT_FALSE
651 if (m_bSaveCursor)
653 m_rShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
656 private:
657 SwEditShell & m_rShell;
658 bool const m_bSaveCursor;
663 bool UndoManager::impl_DoUndoRedo(UndoOrRedoType undoOrRedo, size_t nUndoOffset)
665 SwDoc & rDoc(GetUndoNodes().GetDoc());
667 UnoActionContext c(& rDoc); // exception-safe StartAllAction/EndAllAction
669 SwEditShell *const pEditShell(rDoc.GetEditShell());
670 OSL_ENSURE(pEditShell, "sw::UndoManager needs a SwEditShell!");
671 if (!pEditShell)
673 throw uno::RuntimeException();
676 // in case the model has controllers locked, the Undo should not
677 // change the view cursors!
678 bool const bSaveCursors(pEditShell->CursorsLocked());
679 CursorGuard aCursorGuard(*pEditShell, bSaveCursors);
680 if (!bSaveCursors)
682 // (in case Undo was called via API) clear the cursors:
683 pEditShell->KillPams();
684 pEditShell->SetMark();
685 pEditShell->ClearMark();
688 bool bRet(false);
690 ::sw::UndoRedoContext context(rDoc, *pEditShell);
691 context.SetUndoOffset(nUndoOffset);
693 // N.B. these may throw!
694 if (UndoOrRedoType::Undo == undoOrRedo)
696 bRet = SdrUndoManager::UndoWithContext(context);
698 else
700 bRet = SdrUndoManager::RedoWithContext(context);
703 if (bRet)
705 // if we are at the "last save" position, the document is not modified
706 if (SdrUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
708 m_rState.ResetModified();
710 else
712 m_rState.SetModified();
716 pEditShell->HandleUndoRedoContext(context);
718 return bRet;
721 bool UndoManager::Undo() { return UndoWithOffset(0); }
723 bool UndoManager::UndoWithOffset(size_t nUndoOffset)
725 if(isTextEditActive())
727 return SdrUndoManager::Undo();
729 else
731 return impl_DoUndoRedo(UndoOrRedoType::Undo, nUndoOffset);
735 bool UndoManager::Redo()
737 if(isTextEditActive())
739 return SdrUndoManager::Redo();
741 else
743 return impl_DoUndoRedo(UndoOrRedoType::Redo, /*nUndoOffset=*/0);
747 void UndoManager::dumpAsXml(xmlTextWriterPtr pWriter) const
749 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("swUndoManager"));
750 SdrUndoManager::dumpAsXml(pWriter);
752 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_xUndoNodes"));
753 m_xUndoNodes->dumpAsXml(pWriter);
754 (void)xmlTextWriterEndElement(pWriter);
756 (void)xmlTextWriterEndElement(pWriter);
759 void UndoManager::EmptyActionsChanged()
761 if (m_pDocShell)
763 m_pDocShell->Broadcast(SfxHint(SfxHintId::DocumentRepair));
767 /** N.B.: this does _not_ call SdrUndoManager::Repeat because it is not
768 possible to wrap a list action around it:
769 calling EnterListAction here will cause SdrUndoManager::Repeat
770 to repeat the list action!
772 bool UndoManager::Repeat(::sw::RepeatContext & rContext,
773 sal_uInt16 const nRepeatCount)
775 if (SdrUndoManager::IsInListAction())
777 OSL_ENSURE(false, "repeat in open list action???");
778 return false;
780 if (!SdrUndoManager::GetUndoActionCount(TopLevel))
782 return false;
784 SfxUndoAction *const pRepeatAction(GetUndoAction());
785 assert(pRepeatAction);
786 if (!pRepeatAction->CanRepeat(rContext))
788 return false;
791 OUString const comment(pRepeatAction->GetComment());
792 OUString const rcomment(pRepeatAction->GetRepeatComment(rContext));
793 SwUndoId nId;
794 if (auto const* const pSwAction = dynamic_cast<SwUndo*>(pRepeatAction))
795 nId = pSwAction->GetId();
796 else if (auto const* const pListAction = dynamic_cast<SfxListUndoAction*>(pRepeatAction))
797 nId = static_cast<SwUndoId>(pListAction->GetId());
798 else
799 return false;
800 if (DoesUndo())
802 ViewShellId nViewShellId(-1);
803 if (m_pDocShell)
805 if (const SwView* pView = m_pDocShell->GetView())
806 nViewShellId = pView->GetViewShellId();
808 EnterListAction(comment, rcomment, static_cast<sal_uInt16>(nId), nViewShellId);
811 SwPaM* pTmp = rContext.m_pCurrentPaM;
812 for(SwPaM& rPaM : rContext.GetRepeatPaM().GetRingContainer())
813 { // iterate over ring
814 rContext.m_pCurrentPaM = &rPaM;
815 if (DoesUndo() && & rPaM != pTmp)
817 m_isAddWithIgnoreRepeat = true;
819 for (sal_uInt16 nRptCnt = nRepeatCount; nRptCnt > 0; --nRptCnt)
821 pRepeatAction->Repeat(rContext);
823 if (DoesUndo() && & rPaM != pTmp)
825 m_isAddWithIgnoreRepeat = false;
827 rContext.m_bDeleteRepeated = false; // reset for next PaM
829 rContext.m_pCurrentPaM = pTmp;
831 if (DoesUndo())
833 LeaveListAction();
835 return true;
838 } // namespace sw
840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */