diff options
Diffstat (limited to 'sw/source/core/doc/DocumentLayoutManager.cxx')
-rw-r--r-- | sw/source/core/doc/DocumentLayoutManager.cxx | 111 |
1 files changed, 43 insertions, 68 deletions
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index d4a92a09a69c..dc2b34977173 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -41,7 +41,9 @@ #include <frameformats.hxx> #include <com/sun/star/embed/EmbedStates.hpp> #include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> #include <osl/diagnose.h> +#include <vcl/scheduler.hxx> using namespace ::com::sun::star; @@ -130,12 +132,12 @@ SwFrameFormat *DocumentLayoutManager::MakeLayoutFormat( RndStdIds eRequest, cons (bHeader ? "Right header" : "Right footer"), m_rDoc.GetDfltFrameFormat() ); - SwNodeIndex aTmpIdx( m_rDoc.GetNodes().GetEndOfAutotext() ); + const SwNode& rEndOfAutotext( m_rDoc.GetNodes().GetEndOfAutotext() ); SwStartNode* pSttNd = m_rDoc.GetNodes().MakeTextSection - ( aTmpIdx, + ( rEndOfAutotext, bHeader ? SwHeaderStartNode : SwFooterStartNode, - m_rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(static_cast<sal_uInt16>( bHeader + m_rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(o3tl::narrowing<sal_uInt16>( bHeader ? ( eRequest == RndStdIds::HEADERL ? RES_POOLCOLL_HEADERL : eRequest == RndStdIds::HEADERR @@ -164,7 +166,7 @@ SwFrameFormat *DocumentLayoutManager::MakeLayoutFormat( RndStdIds eRequest, cons if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { m_rDoc.GetIDocumentUndoRedo().AppendUndo( - std::make_unique<SwUndoInsLayFormat>(pFormat, 0, 0)); + std::make_unique<SwUndoInsLayFormat>(pFormat, SwNodeOffset(0), 0)); } } break; @@ -190,6 +192,9 @@ SwFrameFormat *DocumentLayoutManager::MakeLayoutFormat( RndStdIds eRequest, cons /// Deletes the denoted format and its content. void DocumentLayoutManager::DelLayoutFormat( SwFrameFormat *pFormat ) { + // Do not paint, until the destruction is complete. Paint may access the layout and nodes + // while it's in inconsistent state, and crash. + Scheduler::IdlesLockGuard g; // A chain of frames needs to be merged, if necessary, // so that the Frame's contents are adjusted accordingly before we destroy the Frames. const SwFormatChain &rChain = pFormat->GetChain(); @@ -247,20 +252,19 @@ void DocumentLayoutManager::DelLayoutFormat( SwFrameFormat *pFormat ) pContentIdx = pFormat->GetContent().GetContentIdx(); if (pContentIdx) { - const SwFrameFormats* pTable = pFormat->GetDoc()->GetSpzFrameFormats(); - if ( pTable ) + sw::SpzFrameFormats* pSpzs = pFormat->GetDoc()->GetSpzFrameFormats(); + if ( pSpzs ) { std::vector<SwFrameFormat*> aToDeleteFrameFormats; - const sal_uLong nNodeIdxOfFlyFormat( pContentIdx->GetIndex() ); + const SwNodeOffset nNodeIdxOfFlyFormat( pContentIdx->GetIndex() ); - for ( size_t i = 0; i < pTable->size(); ++i ) + for(sw::SpzFrameFormat* pSpz: *pSpzs) { - SwFrameFormat* pTmpFormat = (*pTable)[i]; - const SwFormatAnchor &rAnch = pTmpFormat->GetAnchor(); + const SwFormatAnchor &rAnch = pSpz->GetAnchor(); if ( rAnch.GetAnchorId() == RndStdIds::FLY_AT_FLY && - rAnch.GetContentAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFormat ) + rAnch.GetAnchorNode()->GetIndex() == nNodeIdxOfFlyFormat ) { - aToDeleteFrameFormats.push_back( pTmpFormat ); + aToDeleteFrameFormats.push_back(pSpz); } } @@ -286,23 +290,21 @@ void DocumentLayoutManager::DelLayoutFormat( SwFrameFormat *pFormat ) // Delete the character for FlyFrames anchored as char (if necessary) const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); - if ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetContentAnchor()) + if ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetAnchorNode()) { - const SwPosition* pPos = rAnchor.GetContentAnchor(); - SwTextNode *pTextNd = pPos->nNode.GetNode().GetTextNode(); + SwTextNode *pTextNd = rAnchor.GetAnchorNode()->GetTextNode(); // attribute is still in text node, delete it if ( pTextNd ) { SwTextFlyCnt* const pAttr = static_cast<SwTextFlyCnt*>( - pTextNd->GetTextAttrForCharAt( pPos->nContent.GetIndex(), + pTextNd->GetTextAttrForCharAt( rAnchor.GetAnchorContentOffset(), RES_TXTATR_FLYCNT )); if ( pAttr && (pAttr->GetFlyCnt().GetFrameFormat() == pFormat) ) { // don't delete, set pointer to 0 const_cast<SwFormatFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFormat(); - SwIndex aIdx( pPos->nContent ); - pTextNd->EraseText( aIdx, 1 ); + pTextNd->EraseText( *rAnchor.GetContentAnchor(), 1 ); } } } @@ -335,15 +337,16 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( // 2) anchored in a header/footer // 3) anchored (to paragraph?) bool bMayNotCopy = false; + const SwNode* pCAnchor = rNewAnchor.GetAnchorNode(); + bool bInHeaderFooter = pCAnchor && m_rDoc.IsInHeaderFooter(*pCAnchor); if(bDraw) { - const auto pCAnchor = rNewAnchor.GetContentAnchor(); bool bCheckControlLayer = false; rSource.CallSwClientNotify(sw::CheckDrawFrameFormatLayerHint(&bCheckControlLayer)); bMayNotCopy = bCheckControlLayer && ((RndStdIds::FLY_AT_PARA == rNewAnchor.GetAnchorId()) || (RndStdIds::FLY_AT_FLY == rNewAnchor.GetAnchorId()) || (RndStdIds::FLY_AT_CHAR == rNewAnchor.GetAnchorId())) && - pCAnchor && m_rDoc.IsInHeaderFooter(pCAnchor->nNode); + bInHeaderFooter; } // just return if we can't copy this @@ -379,14 +382,13 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( { // Duplicate the content. const SwNode& rCSttNd = rSource.GetContent().GetContentIdx()->GetNode(); - SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() ); + SwNodeRange aRg( rCSttNd, SwNodeOffset(1), *rCSttNd.EndOfSectionNode() ); - SwNodeIndex aIdx( m_rDoc.GetNodes().GetEndOfAutotext() ); - SwStartNode* pSttNd = SwNodes::MakeEmptySection( aIdx, SwFlyStartNode ); + SwStartNode* pSttNd = SwNodes::MakeEmptySection( m_rDoc.GetNodes().GetEndOfAutotext(), SwFlyStartNode ); // Set the Anchor/ContentIndex first. // Within the copying part, we can access the values (DrawFormat in Headers and Footers) - aIdx = *pSttNd; + SwNodeIndex aIdx( *pSttNd ); SwFormatContent aAttr( rSource.GetContent() ); aAttr.SetNewContentIdx( &aIdx ); pDest->SetFormatAttr( aAttr ); @@ -394,30 +396,30 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( if( !m_rDoc.IsCopyIsMove() || &m_rDoc != pSrcDoc ) { - if( m_rDoc.IsInReading() || m_rDoc.IsInMailMerge() ) - pDest->SetName( OUString() ); + if( (m_rDoc.IsInReading() && !bInHeaderFooter) || m_rDoc.IsInMailMerge() ) + pDest->SetFormatName( OUString() ); else { // Test first if the name is already taken, if so generate a new one. SwNodeType nNdTyp = aRg.aStart.GetNode().GetNodeType(); OUString sOld( pDest->GetName() ); - pDest->SetName( OUString() ); + pDest->SetFormatName( OUString() ); if( m_rDoc.FindFlyByName( sOld, nNdTyp ) ) // found one switch( nNdTyp ) { - case SwNodeType::Grf: sOld = m_rDoc.GetUniqueGrfName(); break; + case SwNodeType::Grf: sOld = m_rDoc.GetUniqueGrfName(sOld); break; case SwNodeType::Ole: sOld = m_rDoc.GetUniqueOLEName(); break; default: sOld = m_rDoc.GetUniqueFrameName(); break; } - pDest->SetName( sOld ); + pDest->SetFormatName( sOld ); } } if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsLayFormat>(pDest,0,0)); + m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsLayFormat>(pDest,SwNodeOffset(0),0)); } // Make sure that FlyFrames in FlyFrames are copied @@ -427,7 +429,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( //contact object itself. They should be managed by SwUndoInsLayFormat. const ::sw::DrawUndoGuard drawUndoGuard(m_rDoc.GetIDocumentUndoRedo()); - pSrcDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly(aRg, aIdx, nullptr, false, true, true); + pSrcDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly(aRg, aIdx.GetNode(), nullptr, false, true, true); } else { @@ -447,61 +449,34 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsLayFormat>(pDest,0,0)); + m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsLayFormat>(pDest,SwNodeOffset(0),0)); } } if (bSetTextFlyAtt && (RndStdIds::FLY_AS_CHAR == rNewAnchor.GetAnchorId())) { - const SwPosition* pPos = rNewAnchor.GetContentAnchor(); + SwNode* pAnchorNode = rNewAnchor.GetAnchorNode(); SwFormatFlyCnt aFormat( pDest ); - pPos->nNode.GetNode().GetTextNode()->InsertItem( - aFormat, pPos->nContent.GetIndex(), 0 ); + assert(pAnchorNode->GetTextNode() && "sw.core: text node expected"); + if (SwTextNode *pTextNd = pAnchorNode->GetTextNode()) + pTextNd->InsertItem( aFormat, rNewAnchor.GetAnchorContentOffset(), 0 ); } if( bMakeFrames ) pDest->MakeFrames(); - // If the draw format has a TextBox, then copy its fly format as well. - if (SwFrameFormat* pSourceTextBox = SwTextBoxHelper::getOtherTextBoxFormat(&rSource, RES_DRAWFRMFMT)) - { - SwFormatAnchor boxAnchor(rNewAnchor); - if (RndStdIds::FLY_AS_CHAR == boxAnchor.GetAnchorId()) - { - // AS_CHAR *must not* be set on textbox fly-frame - boxAnchor.SetType(RndStdIds::FLY_AT_CHAR); - } - // presumably these anchors are supported though not sure - assert(RndStdIds::FLY_AT_CHAR == boxAnchor.GetAnchorId() || RndStdIds::FLY_AT_PARA == boxAnchor.GetAnchorId() - || boxAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE); - - if (!bMakeFrames && rNewAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) - { - // If the draw format is as-char, then it will be copied with bMakeFrames=false, but - // doing the same for the fly format would result in not making fly frames at all. - bMakeFrames = true; - } - - SwFrameFormat* pDestTextBox = CopyLayoutFormat(*pSourceTextBox, - boxAnchor, bSetTextFlyAtt, bMakeFrames); - SwAttrSet aSet(pDest->GetAttrSet()); - SwFormatContent aContent(pDestTextBox->GetContent().GetContentIdx()->GetNode().GetStartNode()); - aSet.Put(aContent); - pDest->SetFormatAttr(aSet); - - // Link FLY and DRAW formats, so it becomes a text box - pDest->SetOtherTextBoxFormat(pDestTextBox); - pDestTextBox->SetOtherTextBoxFormat(pDest); - } - if (pDest->GetName().isEmpty()) { // Format name should have unique name. Let's use object name as a fallback SdrObject *pObj = pDest->FindSdrObject(); if (pObj) - pDest->SetName(pObj->GetName()); + pDest->SetFormatName(pObj->GetName()); } + // If the draw format has a TextBox, then copy its fly format as well. + if (const auto& pTextBoxes = rSource.GetOtherTextBoxFormats()) + pTextBoxes->Clone(&m_rDoc, rNewAnchor, pDest, bSetTextFlyAtt, bMakeFrames); + return pDest; } |