summaryrefslogtreecommitdiffstats
path: root/sw/source/core/undo/unmove.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/core/undo/unmove.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/undo/unmove.cxx')
-rw-r--r--sw/source/core/undo/unmove.cxx308
1 files changed, 308 insertions, 0 deletions
diff --git a/sw/source/core/undo/unmove.cxx b/sw/source/core/undo/unmove.cxx
new file mode 100644
index 000000000..6888d477f
--- /dev/null
+++ b/sw/source/core/undo/unmove.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <UndoSplitMove.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <swundo.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+
+// MOVE
+SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
+ : SwUndo( SwUndoId::MOVE, rRange.GetDoc() )
+ , SwUndRng( rRange )
+ , m_nDestStartNode(0)
+ , m_nDestEndNode(0)
+ , m_nInsPosNode(0)
+ , m_nMoveDestNode(rMvPos.nNode.GetIndex())
+ , m_nDestStartContent(0)
+ , m_nDestEndContent(0)
+ , m_nInsPosContent(0)
+ , m_nMoveDestContent(rMvPos.nContent.GetIndex())
+ , m_bJoinNext(false)
+ , m_bMoveRange(false)
+ , m_bMoveRedlines(false)
+{
+ // get StartNode from footnotes before delete!
+ SwDoc* pDoc = rRange.GetDoc();
+ SwTextNode* pTextNd = pDoc->GetNodes()[ m_nSttNode ]->GetTextNode();
+ SwTextNode* pEndTextNd = pDoc->GetNodes()[ m_nEndNode ]->GetTextNode();
+
+ m_pHistory.reset( new SwHistory );
+
+ if( pTextNd )
+ {
+ m_pHistory->Add( pTextNd->GetTextColl(), m_nSttNode, SwNodeType::Text );
+ if ( pTextNd->GetpSwpHints() )
+ {
+ m_pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nSttNode,
+ 0, pTextNd->GetText().getLength(), false );
+ }
+ if( pTextNd->HasSwAttrSet() )
+ m_pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nSttNode );
+ }
+ if( pEndTextNd && pEndTextNd != pTextNd )
+ {
+ m_pHistory->Add( pEndTextNd->GetTextColl(), m_nEndNode, SwNodeType::Text );
+ if ( pEndTextNd->GetpSwpHints() )
+ {
+ m_pHistory->CopyAttr( pEndTextNd->GetpSwpHints(), m_nEndNode,
+ 0, pEndTextNd->GetText().getLength(), false );
+ }
+ if( pEndTextNd->HasSwAttrSet() )
+ m_pHistory->CopyFormatAttr( *pEndTextNd->GetpSwAttrSet(), m_nEndNode );
+ }
+
+ pTextNd = rMvPos.nNode.GetNode().GetTextNode();
+ if (nullptr != pTextNd)
+ {
+ m_pHistory->Add( pTextNd->GetTextColl(), m_nMoveDestNode, SwNodeType::Text );
+ if ( pTextNd->GetpSwpHints() )
+ {
+ m_pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nMoveDestNode,
+ 0, pTextNd->GetText().getLength(), false );
+ }
+ if( pTextNd->HasSwAttrSet() )
+ m_pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nMoveDestNode );
+ }
+
+ m_nFootnoteStart = m_pHistory->Count();
+ DelFootnote( rRange );
+
+ if( m_pHistory && !m_pHistory->Count() )
+ m_pHistory.reset();
+}
+
+SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
+ const SwNodeIndex& rMvPos )
+ : SwUndo(SwUndoId::MOVE, pDoc)
+ , m_nDestStartNode(0)
+ , m_nDestEndNode(0)
+ , m_nInsPosNode(0)
+ , m_nMoveDestNode(rMvPos.GetIndex())
+ , m_nDestStartContent(0)
+ , m_nDestEndContent(0)
+ , m_nInsPosContent(0)
+ , m_bMoveRedlines(false)
+{
+ m_bMoveRange = true;
+ m_bJoinNext = false;
+
+ m_nSttContent = m_nEndContent = m_nMoveDestContent = COMPLETE_STRING;
+
+ m_nSttNode = rRg.aStart.GetIndex();
+ m_nEndNode = rRg.aEnd.GetIndex();
+
+// DelFootnote( rRange );
+// FIXME: duplication of the method body of DelFootnote below
+
+ // is the current move from ContentArea into the special section?
+ sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( m_nMoveDestNode < nContentStt && rRg.aStart.GetIndex() > nContentStt )
+ {
+ // delete all footnotes since they are undesired there
+ SwPosition aPtPos( rRg.aEnd );
+ SwContentNode* pCNd = rRg.aEnd.GetNode().GetContentNode();
+ if( pCNd )
+ aPtPos.nContent.Assign( pCNd, pCNd->Len() );
+ SwPosition aMkPos( rRg.aStart );
+ if( nullptr != ( pCNd = aMkPos.nNode.GetNode().GetContentNode() ))
+ aMkPos.nContent.Assign( pCNd, 0 );
+
+ DelContentIndex( aMkPos, aPtPos, DelContentType::Ftn );
+
+ if( m_pHistory && !m_pHistory->Count() )
+ m_pHistory.reset();
+ }
+
+ m_nFootnoteStart = 0;
+}
+
+void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ const SwNodeIndex& rInsPos )
+{
+ m_nDestStartNode = rStt.GetIndex();
+ m_nDestEndNode = rEnd.GetIndex();
+ if( m_nDestStartNode > m_nDestEndNode )
+ {
+ m_nDestStartNode = m_nDestEndNode;
+ m_nDestEndNode = rStt.GetIndex();
+ }
+ m_nInsPosNode = rInsPos.GetIndex();
+
+ m_nDestStartContent = m_nDestEndContent = m_nInsPosContent = COMPLETE_STRING;
+}
+
+void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ // Block so that we can jump out of it
+ do {
+ // create index position and section based on the existing values
+ SwNodeIndex aIdx( pDoc->GetNodes(), m_nDestStartNode );
+
+ if( m_bMoveRange )
+ {
+ // only a move with SwRange
+ SwNodeRange aRg( aIdx, aIdx );
+ aRg.aEnd = m_nDestEndNode;
+ aIdx = m_nInsPosNode;
+ bool bSuccess = pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aIdx,
+ SwMoveFlags::DEFAULT );
+ if (!bSuccess)
+ break;
+ }
+ else
+ {
+ SwPaM aPam( aIdx.GetNode(), m_nDestStartContent,
+ *pDoc->GetNodes()[ m_nDestEndNode ], m_nDestEndContent );
+
+ // #i17764# if redlines are to be moved, we may not remove them
+ // before pDoc->Move gets a chance to handle them
+ if( ! m_bMoveRedlines )
+ RemoveIdxFromRange( aPam, false );
+
+ SwPosition aPos( *pDoc->GetNodes()[ m_nInsPosNode] );
+ SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode();
+ aPos.nContent.Assign( pCNd, m_nInsPosContent );
+
+ if( pCNd->HasSwAttrSet() )
+ pCNd->ResetAllAttr();
+
+ if( pCNd->IsTextNode() && static_cast<SwTextNode*>(pCNd)->GetpSwpHints() )
+ static_cast<SwTextNode*>(pCNd)->ClearSwpHintsArr( false );
+
+ // first delete all attributes at InsertPos
+ const bool bSuccess = pDoc->getIDocumentContentOperations().MoveRange( aPam, aPos, m_bMoveRedlines
+ ? SwMoveFlags::REDLINES
+ : SwMoveFlags::DEFAULT );
+ if (!bSuccess)
+ break;
+
+ aPam.Exchange();
+ aPam.DeleteMark();
+ if( aPam.GetNode().IsContentNode() )
+ aPam.GetNode().GetContentNode()->ResetAllAttr();
+ // the Pam will be dropped now
+ }
+
+ SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
+ if( m_bJoinNext )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex(pTextNd, pTextNd->GetText().getLength())));
+ }
+ // Are there any Pams in the next TextNode?
+ pTextNd->JoinNext();
+ }
+
+ } while( false );
+
+ if( m_pHistory )
+ {
+ if( m_nFootnoteStart != m_pHistory->Count() )
+ m_pHistory->Rollback( pDoc, m_nFootnoteStart );
+ m_pHistory->TmpRollback( pDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+ }
+
+ // set the cursor onto Undo area
+ if( !m_bMoveRange )
+ {
+ AddUndoRedoPaM(rContext);
+ }
+}
+
+void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM& rPam = AddUndoRedoPaM(rContext);
+ SwDoc& rDoc = rContext.GetDoc();
+
+ SwNodes& rNds = rDoc.GetNodes();
+ SwNodeIndex aIdx( rNds, m_nMoveDestNode );
+
+ if( m_bMoveRange )
+ {
+ // only a move with SwRange
+ SwNodeRange aRg( rNds, m_nSttNode, rNds, m_nEndNode );
+ rDoc.getIDocumentContentOperations().MoveNodeRange( aRg, aIdx, m_bMoveRedlines
+ ? SwMoveFlags::REDLINES
+ : SwMoveFlags::DEFAULT );
+ }
+ else
+ {
+ SwPaM aPam(*rPam.GetPoint());
+ SetPaM( aPam );
+ SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetContentNode(),
+ m_nMoveDestContent ));
+
+ DelFootnote( aPam );
+ RemoveIdxFromRange( aPam, false );
+
+ aIdx = aPam.Start()->nNode;
+ bool bJoinText = aIdx.GetNode().IsTextNode();
+
+ --aIdx;
+ rDoc.getIDocumentContentOperations().MoveRange( aPam, aMvPos,
+ SwMoveFlags::DEFAULT );
+
+ if( m_nSttNode != m_nEndNode && bJoinText )
+ {
+ ++aIdx;
+ SwTextNode * pTextNd = aIdx.GetNode().GetTextNode();
+ if( pTextNd && pTextNd->CanJoinNext() )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex(pTextNd, pTextNd->GetText().getLength())));
+ }
+ pTextNd->JoinNext();
+ }
+ }
+ *rPam.GetPoint() = *aPam.GetPoint();
+ rPam.SetMark();
+ *rPam.GetMark() = *aPam.GetMark();
+ }
+}
+
+void SwUndoMove::DelFootnote( const SwPaM& rRange )
+{
+ // is the current move from ContentArea into the special section?
+ SwDoc* pDoc = rRange.GetDoc();
+ sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( m_nMoveDestNode < nContentStt &&
+ rRange.GetPoint()->nNode.GetIndex() >= nContentStt )
+ {
+ // delete all footnotes since they are undesired there
+ DelContentIndex( *rRange.GetMark(), *rRange.GetPoint(),
+ DelContentType::Ftn );
+
+ if( m_pHistory && !m_pHistory->Count() )
+ {
+ m_pHistory.reset();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */