diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/core/undo/unmove.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-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.cxx | 308 |
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: */ |