1
0
Fork 0
libreoffice/sw/source/core/undo/unmove.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

305 lines
10 KiB
C++

/* -*- 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.GetNodeIndex())
, m_nDestStartContent(0)
, m_nDestEndContent(0)
, m_nInsPosContent(0)
, m_nMoveDestContent(rMvPos.GetContentIndex())
, m_bJoinNext(false)
, m_bMoveRange(false)
, m_bMoveRedlines(false)
{
// get StartNode from footnotes before delete!
SwDoc& rDoc = rRange.GetDoc();
SwTextNode* pTextNd = rDoc.GetNodes()[ m_nSttNode ]->GetTextNode();
SwTextNode* pEndTextNd = rDoc.GetNodes()[ m_nEndNode ]->GetTextNode();
m_pHistory.reset( new SwHistory );
if( pTextNd )
{
m_pHistory->AddColl(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->AddColl(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.GetNode().GetTextNode();
if (nullptr != pTextNd)
{
m_pHistory->AddColl(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& rDoc, const SwNodeRange& rRg,
const SwNode& rMvPos )
: SwUndo(SwUndoId::MOVE, &rDoc)
, 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?
SwNodeOffset nContentStt = rDoc.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.SetContent( pCNd->Len() );
SwPosition aMkPos( rRg.aStart );
DelContentIndex( aMkPos, aPtPos, DelContentType::Ftn );
if( m_pHistory && !m_pHistory->Count() )
m_pHistory.reset();
}
m_nFootnoteStart = 0;
}
void SwUndoMove::SetDestRange( const SwNode& rStt,
const SwNode& 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.GetNode(),
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.GetNode().GetContentNode();
aPos.SetContent( 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.GetPointNode().IsContentNode() )
aPam.GetPointNode().GetContentNode()->ResetAllAttr();
// the Pam will be dropped now
}
SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
if( m_bJoinNext )
{
{
RemoveIdxRel( aIdx.GetIndex() + 1,
SwPosition( aIdx, 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, m_nEndNode );
rDoc.getIDocumentContentOperations().MoveNodeRange( aRg, aIdx.GetNode(), m_bMoveRedlines
? SwMoveFlags::REDLINES
: SwMoveFlags::DEFAULT );
}
else
{
SwPaM aPam(*rPam.GetPoint());
SetPaM( aPam );
SwPosition aMvPos( aIdx, aIdx.GetNode().GetContentNode(), m_nMoveDestContent );
DelFootnote( aPam );
RemoveIdxFromRange( aPam, false );
aIdx = aPam.Start()->GetNode();
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( *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& rDoc = rRange.GetDoc();
SwNodeOffset nContentStt = rDoc.GetNodes().GetEndOfAutotext().GetIndex();
if( m_nMoveDestNode < nContentStt &&
rRange.GetPoint()->GetNodeIndex() >= 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: */