summaryrefslogtreecommitdiff
path: root/sw/source/core/doc/DocumentLayoutManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/DocumentLayoutManager.cxx')
-rw-r--r--sw/source/core/doc/DocumentLayoutManager.cxx111
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;
}