/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam ) : SwUndo( nUndoId ), SwUndRng( rPam ), pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ), bSttWasTxtNd( true ), nNdDiff( 0 ), nSetPos( 0 ) { pHistory = new SwHistory; SwDoc* pDoc = (SwDoc*)rPam.GetDoc(); SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode(); if( pTxtNd ) { pTxtFmtColl = pTxtNd->GetTxtColl(); pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode, 0, pTxtNd->GetTxt().getLength(), false ); if( pTxtNd->HasSwAttrSet() ) pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode ); if( !nSttCntnt ) // than take the Flys along { const size_t nArrLen = pDoc->GetSpzFrmFmts()->size(); for( size_t n = 0; n < nArrLen; ++n ) { SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n]; SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor(); const SwPosition* pAPos = pAnchor->GetCntntAnchor(); if (pAPos && (pAnchor->GetAnchorId() == FLY_AT_PARA) && nSttNode == pAPos->nNode.GetIndex() ) { if( !pFrmFmts ) pFrmFmts = new std::vector; pFrmFmts->push_back( pFmt ); } } } } // consider Redline if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() ) { pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->getIDocumentRedlineAccess().GetRedlineAuthor() ); SetRedlineMode( pDoc->getIDocumentRedlineAccess().GetRedlineMode() ); } } // set destination after reading input void SwUndoInserts::SetInsertRange( const SwPaM& rPam, bool bScanFlys, bool bSttIsTxtNd ) { const SwPosition* pTmpPos = rPam.End(); nEndNode = pTmpPos->nNode.GetIndex(); nEndCntnt = pTmpPos->nContent.GetIndex(); if( rPam.HasMark() ) { if( pTmpPos == rPam.GetPoint() ) pTmpPos = rPam.GetMark(); else pTmpPos = rPam.GetPoint(); nSttNode = pTmpPos->nNode.GetIndex(); nSttCntnt = pTmpPos->nContent.GetIndex(); if( !bSttIsTxtNd ) // if a table selection is added ... { ++nSttNode; // ... than the CopyPam is not fully correct bSttWasTxtNd = false; } } if( bScanFlys && !nSttCntnt ) { // than collect all new Flys SwDoc* pDoc = (SwDoc*)rPam.GetDoc(); const size_t nArrLen = pDoc->GetSpzFrmFmts()->size(); for( size_t n = 0; n < nArrLen; ++n ) { SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n]; SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor(); SwPosition const*const pAPos = pAnchor->GetCntntAnchor(); if (pAPos && (pAnchor->GetAnchorId() == FLY_AT_PARA) && nSttNode == pAPos->nNode.GetIndex() ) { std::vector::iterator it; if( !pFrmFmts || pFrmFmts->end() == ( it = std::find( pFrmFmts->begin(), pFrmFmts->end(), pFmt ) ) ) { ::boost::shared_ptr const pFlyUndo( new SwUndoInsLayFmt(pFmt, 0, 0)); m_FlyUndos.push_back(pFlyUndo); } else pFrmFmts->erase( it ); } } delete pFrmFmts, pFrmFmts = 0; } } SwUndoInserts::~SwUndoInserts() { if (m_pUndoNodeIndex) // delete also the section from UndoNodes array { // Insert saves content in IconSection SwNodes& rUNds = m_pUndoNodeIndex->GetNodes(); rUNds.Delete(*m_pUndoNodeIndex, rUNds.GetEndOfExtras().GetIndex() - m_pUndoNodeIndex->GetIndex()); m_pUndoNodeIndex.reset(); } delete pFrmFmts; delete pRedlData; } void SwUndoInserts::UndoImpl(::sw::UndoRedoContext & rContext) { SwDoc *const pDoc = & rContext.GetDoc(); SwPaM *const pPam = & AddUndoRedoPaM(rContext); if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) pDoc->getIDocumentRedlineAccess().DeleteRedline( *pPam, true, USHRT_MAX ); // if Point and Mark are different text nodes so a JoinNext has to be done bool bJoinNext = nSttNode != nEndNode && pPam->GetMark()->nNode.GetNode().GetTxtNode() && pPam->GetPoint()->nNode.GetNode().GetTxtNode(); // Is there any content? (loading from template does not have content) if( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) { if( nSttNode != nEndNode ) { SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode(); if (pTxtNd && pTxtNd->GetTxt().getLength() == nEndCntnt) pLastNdColl = pTxtNd->GetTxtColl(); } RemoveIdxFromRange( *pPam, false ); SetPaM(*pPam); // are there Footnotes or CntntFlyFrames in text? nSetPos = pHistory->Count(); nNdDiff = pPam->GetMark()->nNode.GetIndex(); DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() ); nNdDiff -= pPam->GetMark()->nNode.GetIndex(); if( *pPam->GetPoint() != *pPam->GetMark() ) { m_pUndoNodeIndex.reset( new SwNodeIndex(pDoc->GetNodes().GetEndOfContent())); MoveToUndoNds(*pPam, m_pUndoNodeIndex.get()); if( !bSttWasTxtNd ) pPam->Move( fnMoveBackward, fnGoCntnt ); } } if (m_FlyUndos.size()) { sal_uLong nTmp = pPam->GetPoint()->nNode.GetIndex(); for (size_t n = m_FlyUndos.size(); 0 < n; --n) { m_FlyUndos[ n-1 ]->UndoImpl(rContext); } nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex(); } SwNodeIndex& rIdx = pPam->GetPoint()->nNode; SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode(); if( pTxtNode ) { if( !pTxtFmtColl ) // if 0 than it's no TextNode -> delete { SwNodeIndex aDelIdx( rIdx ); ++rIdx; SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode(); pPam->GetPoint()->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 ); pPam->SetMark(); pPam->DeleteMark(); RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() ); pDoc->GetNodes().Delete( aDelIdx, 1 ); } else { if( bJoinNext && pTxtNode->CanJoinNext()) { { RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx, SwIndex( pTxtNode, pTxtNode->GetTxt().getLength() ))); } pTxtNode->JoinNext(); } // reset all text attributes in the paragraph! pTxtNode->RstTxtAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(), 0, 0, true ); pTxtNode->ResetAllAttr(); if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl )) pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl ); pHistory->SetTmpEnd( nSetPos ); pHistory->TmpRollback( pDoc, 0, false ); } } } void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext) { // position cursor onto REDO section SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); SwDoc* pDoc = pPam->GetDoc(); pPam->DeleteMark(); pPam->GetPoint()->nNode = nSttNode - nNdDiff; SwCntntNode* pCNd = pPam->GetCntntNode(); pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt ); SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl; if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() ) pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl(); pHistory->SetTmpEnd( nSetPos ); // retrieve start position for rollback if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && m_pUndoNodeIndex) { const bool bMvBkwrd = MovePtBackward( *pPam ); // re-insert content again (first detach m_pUndoNodeIndex!) sal_uLong const nMvNd = m_pUndoNodeIndex->GetIndex(); m_pUndoNodeIndex.reset(); MoveFromUndoNds(*pDoc, nMvNd, *pPam->GetMark()); if( bSttWasTxtNd ) MovePtForward( *pPam, bMvBkwrd ); pPam->Exchange(); } if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl )) { SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode(); if( pTxtNd ) pTxtNd->ChgFmtColl( pTxtFmtColl ); } pTxtFmtColl = pSavTxtFmtColl; if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) && pPam->GetPoint()->nNode != pPam->GetMark()->nNode ) { SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode(); if( pTxtNd ) pTxtNd->ChgFmtColl( pLastNdColl ); } for (size_t n = m_FlyUndos.size(); 0 < n; --n) { m_FlyUndos[ n-1 ]->RedoImpl(rContext); } pHistory->Rollback( pDoc, nSetPos ); if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) { RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode(); pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE )); pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *pRedlData, *pPam ), true); pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld ); } else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) && !pDoc->getIDocumentRedlineAccess().GetRedlineTbl().empty() ) pDoc->getIDocumentRedlineAccess().SplitRedline( *pPam ); } void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext) { SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() ); SetPaM( aPam ); SwPaM & rRepeatPaM( rContext.GetRepeatPaM() ); aPam.GetDoc()->getIDocumentContentOperations().CopyRange( aPam, *rRepeatPaM.GetPoint(), false ); } SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam ) : SwUndoInserts( UNDO_INSDOKUMENT, rPam ) { } SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam ) : SwUndoInserts( UNDO_COPY, rPam ) { } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */