sw/inc/anchoredobject.hxx | 1 sw/source/core/doc/docdraw.cxx | 17 ++- sw/source/core/draw/dview.cxx | 19 ++-- sw/source/core/frmedt/feshview.cxx | 36 ++++--- sw/source/core/layout/anchoredobject.cxx | 134 ++++++++++++++++------------- sw/source/core/layout/flylay.cxx | 113 ++++++++++++------------ sw/source/core/layout/frmtool.cxx | 6 - sw/source/core/layout/sortedobjs.cxx | 4 sw/source/core/text/txtfly.cxx | 143 ++++++++++++++++--------------- sw/source/uibase/docvw/edtwin.cxx | 28 +++--- sw/source/uibase/shells/drwbassh.cxx | 16 ++- 11 files changed, 288 insertions(+), 229 deletions(-)
New commits: commit a72dad4e4c0d41b61e453919401fcefc8e5e9b43 Author: Matt K <matt...@gmail.com> AuthorDate: Thu Jan 11 20:37:01 2024 -0600 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Mon Jan 15 13:01:00 2024 +0100 tdf#132810 Prevent crashes with gallery objects The problem is the formats for the gallery objects may be non-existent but the code attempts to use them anyway, causing crashes. The fix is to check for the existence of the proper format objects before using them, so as to prevent the crashes. I tested creating/deleting multiple objects with multiple rounds of undo/redo and believe this change to cover all the crashes that can occur (there were several). Change-Id: I9d5d704eaa381be861ac1758ad58269706437a27 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161950 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162078 diff --git a/sw/inc/anchoredobject.hxx b/sw/inc/anchoredobject.hxx index 19cd2e75802b..9af198425714 100644 --- a/sw/inc/anchoredobject.hxx +++ b/sw/inc/anchoredobject.hxx @@ -318,6 +318,7 @@ class SW_DLLPUBLIC SwAnchoredObject void SetCurrRelPos( Point _aRelPos ); // accessors to the format + bool HasFrameFormat() const; virtual SwFrameFormat& GetFrameFormat() = 0; virtual const SwFrameFormat& GetFrameFormat() const = 0; diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx index aecbe2ac824f..521ca2b0ba15 100644 --- a/sw/source/core/doc/docdraw.cxx +++ b/sw/source/core/doc/docdraw.cxx @@ -463,14 +463,17 @@ bool SwDoc::DeleteSelection( SwDrawView& rDrawView ) SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); if( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) { - SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj)); - SwDrawFrameFormat *pFrameFormat = static_cast<SwDrawFrameFormat*>(pC->GetFormat()); - if( pFrameFormat && - RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId() ) + if (SwDrawContact* pC = static_cast<SwDrawContact*>(GetUserCall(pObj))) { - rDrawView.MarkObj( pObj, rDrawView.Imp().GetPageView(), true ); - --i; - getIDocumentLayoutAccess().DelLayoutFormat( pFrameFormat ); + SwDrawFrameFormat* pFrameFormat + = static_cast<SwDrawFrameFormat*>(pC->GetFormat()); + if (pFrameFormat + && RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()) + { + rDrawView.MarkObj(pObj, rDrawView.Imp().GetPageView(), true); + --i; + getIDocumentLayoutAccess().DelLayoutFormat(pFrameFormat); + } } } } diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx index 9d704647c30e..2bd1acaf3db3 100644 --- a/sw/source/core/draw/dview.cxx +++ b/sw/source/core/draw/dview.cxx @@ -977,16 +977,19 @@ void SwDrawView::DeleteMarked() { SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj(); SwContact* pContact = GetUserCall(pObject); - SwFrameFormat* pFormat = pContact->GetFormat(); - if (pObject->getChildrenOfSdrObject()) + if (pContact) { - auto pChildTextBoxes = SwTextBoxHelper::CollectTextBoxes(pObject, pFormat); - for (auto& rChildTextBox : pChildTextBoxes) - aTextBoxesToDelete.push_back(rChildTextBox); - } - else - if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT)) + SwFrameFormat* pFormat = pContact->GetFormat(); + if (pObject->getChildrenOfSdrObject()) + { + auto pChildTextBoxes = SwTextBoxHelper::CollectTextBoxes(pObject, pFormat); + for (auto& rChildTextBox : pChildTextBoxes) + aTextBoxesToDelete.push_back(rChildTextBox); + } + else if (SwFrameFormat* pTextBox + = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT)) aTextBoxesToDelete.push_back(pTextBox); + } } if ( pDoc->DeleteSelection( *this ) ) diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx index 9a18e7934c03..30e448dec8e3 100644 --- a/sw/source/core/frmedt/feshview.cxx +++ b/sw/source/core/frmedt/feshview.cxx @@ -2221,14 +2221,16 @@ RndStdIds SwFEShell::GetAnchorId() const nRet = RndStdIds::UNKNOWN; break; } - SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj)); - RndStdIds nId = pContact->GetFormat()->GetAnchor().GetAnchorId(); - if ( nRet == RndStdIds(SHRT_MAX) ) - nRet = nId; - else if ( nRet != nId ) + if (SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj))) { - nRet = RndStdIds::UNKNOWN; - break; + RndStdIds nId = pContact->GetFormat()->GetAnchor().GetAnchorId(); + if (nRet == RndStdIds(SHRT_MAX)) + nRet = nId; + else if (nRet != nId) + { + nRet = RndStdIds::UNKNOWN; + break; + } } } } @@ -3152,17 +3154,19 @@ Color SwFEShell::GetShapeBackground() const OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr, "wrong usage of SwFEShell::GetShapeBackground - selected object is not a drawing object!"); if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr ) { - // determine page frame of the frame the shape is anchored. - const SwFrame* pAnchorFrame = - static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj ); - OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at shape!"); - if ( pAnchorFrame ) + if (SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall(pSdrObj))) { - const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame(); - OSL_ENSURE( pPageFrame, "inconsistent model - no page!"); - if ( pPageFrame ) + // determine page frame of the frame the shape is anchored. + const SwFrame * pAnchorFrame = pDrawContact->GetAnchorFrame(pSdrObj); + OSL_ENSURE(pAnchorFrame, "inconsistent model - no anchor at shape!"); + if (pAnchorFrame) { - aRetColor = pPageFrame->GetDrawBackgroundColor(); + const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame(); + OSL_ENSURE(pPageFrame, "inconsistent model - no page!"); + if (pPageFrame) + { + aRetColor = pPageFrame->GetDrawBackgroundColor(); + } } } } diff --git a/sw/source/core/layout/anchoredobject.cxx b/sw/source/core/layout/anchoredobject.cxx index 42e7dd39fcd2..fe959a688723 100644 --- a/sw/source/core/layout/anchoredobject.cxx +++ b/sw/source/core/layout/anchoredobject.cxx @@ -32,6 +32,7 @@ #include <layouter.hxx> #include <osl/diagnose.h> #include <flyfrms.hxx> +#include <dcontact.hxx> using namespace ::com::sun::star; @@ -98,6 +99,8 @@ void SwAnchoredObject::ClearVertPosOrientFrame() } } +bool SwAnchoredObject::HasFrameFormat() const { return GetUserCall(GetDrawObj()); } + SwAnchoredObject::~SwAnchoredObject() { ClearVertPosOrientFrame(); @@ -408,29 +411,33 @@ bool SwAnchoredObject::ConsiderObjWrapInfluenceOnObjPos() const { bool bRet( false ); - const SwFrameFormat& rObjFormat = GetFrameFormat(); - - // --> #i3317# - add condition <IsTmpConsiderWrapInfluence()> - // --> #i55204# - // - correction: wrapping style influence has been considered, if condition - // <IsTmpConsiderWrapInfluence()> is hold, regardless of its anchor type - // or its wrapping style. - if ( IsTmpConsiderWrapInfluence() ) + if (HasFrameFormat()) { - bRet = true; - } - else if ( rObjFormat.getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) ) - { - const SwFormatAnchor& rAnchor = rObjFormat.GetAnchor(); - if ( ((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR) || - (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)) && - rObjFormat.GetSurround().GetSurround() != css::text::WrapTextMode_THROUGH ) + const SwFrameFormat& rObjFormat = GetFrameFormat(); + + // --> #i3317# - add condition <IsTmpConsiderWrapInfluence()> + // --> #i55204# + // - correction: wrapping style influence has been considered, if condition + // <IsTmpConsiderWrapInfluence()> is hold, regardless of its anchor type + // or its wrapping style. + if (IsTmpConsiderWrapInfluence()) { - // --> #i34520# - text also wraps around anchored - // objects in the layer Hell - see the text formatting. - // Thus, it hasn't to be checked here. bRet = true; } + else if (rObjFormat.getIDocumentSettingAccess().get( + DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION)) + { + const SwFormatAnchor& rAnchor = rObjFormat.GetAnchor(); + if (((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR) + || (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)) + && rObjFormat.GetSurround().GetSurround() != css::text::WrapTextMode_THROUGH) + { + // --> #i34520# - text also wraps around anchored + // objects in the layer Hell - see the text formatting. + // Thus, it hasn't to be checked here. + bRet = true; + } + } } return bRet; @@ -567,18 +574,23 @@ const SwRect& SwAnchoredObject::GetObjRectWithSpaces() const if ( !mbObjRectWithSpacesValid ) { maObjRectWithSpaces = GetObjBoundRect(); - const SwFrameFormat& rFormat = GetFrameFormat(); - const SvxULSpaceItem& rUL = rFormat.GetULSpace(); - const SvxLRSpaceItem& rLR = rFormat.GetLRSpace(); + if (HasFrameFormat()) { - maObjRectWithSpaces.Top ( std::max( maObjRectWithSpaces.Top() - tools::Long(rUL.GetUpper()), tools::Long(0) )); - maObjRectWithSpaces.Left( std::max( maObjRectWithSpaces.Left()- rLR.GetLeft(), tools::Long(0) )); - maObjRectWithSpaces.AddHeight(rUL.GetLower() ); - maObjRectWithSpaces.AddWidth(rLR.GetRight() ); - } + const SwFrameFormat& rFormat = GetFrameFormat(); + const SvxULSpaceItem& rUL = rFormat.GetULSpace(); + const SvxLRSpaceItem& rLR = rFormat.GetLRSpace(); + { + maObjRectWithSpaces.Top(std::max( + maObjRectWithSpaces.Top() - tools::Long(rUL.GetUpper()), tools::Long(0))); + maObjRectWithSpaces.Left( + std::max(maObjRectWithSpaces.Left() - rLR.GetLeft(), tools::Long(0))); + maObjRectWithSpaces.AddHeight(rUL.GetLower()); + maObjRectWithSpaces.AddWidth(rLR.GetRight()); + } - mbObjRectWithSpacesValid = true; - maLastObjRect = GetObjRect(); + mbObjRectWithSpacesValid = true; + maLastObjRect = GetObjRect(); + } } return maObjRectWithSpaces; @@ -709,39 +721,43 @@ SwTextFrame* SwAnchoredObject::FindAnchorCharFrame() // --> #i44339# - check, if anchor frame exists. if ( mpAnchorFrame ) { - const SwFormatAnchor& rAnch = GetFrameFormat().GetAnchor(); - if ((rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) || - (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)) + if (HasFrameFormat()) { - SwTextFrame *const pFrame(static_cast<SwTextFrame*>(AnchorFrame())); - TextFrameIndex const nOffset(pFrame->MapModelToViewPos(*rAnch.GetContentAnchor())); - pAnchorCharFrame = &pFrame->GetFrameAtOfst(nOffset); - } - else if (SwFlyFrame* pFlyFrame = DynCastFlyFrame()) - { - // See if this fly is split. If so, then the anchor is also split. All anchors are - // empty, except the last follow. - if (pFlyFrame->IsFlySplitAllowed()) + const SwFormatAnchor& rAnch = GetFrameFormat().GetAnchor(); + if ((rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) + || (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)) { - auto pFlyAtContentFrame = static_cast<SwFlyAtContentFrame*>(pFlyFrame); - SwFlyAtContentFrame* pFly = pFlyAtContentFrame; - SwTextFrame* pAnchor = static_cast<SwTextFrame*>(AnchorFrame()); - // If we have to jump back N frames to find the master fly, then we have to step N - // frames from the master anchor to reach the correct follow anchor. - while (pFly->GetPrecede()) + SwTextFrame* const pFrame(static_cast<SwTextFrame*>(AnchorFrame())); + TextFrameIndex const nOffset(pFrame->MapModelToViewPos(*rAnch.GetContentAnchor())); + pAnchorCharFrame = &pFrame->GetFrameAtOfst(nOffset); + } + else if (SwFlyFrame* pFlyFrame = DynCastFlyFrame()) + { + // See if this fly is split. If so, then the anchor is also split. All anchors are + // empty, except the last follow. + if (pFlyFrame->IsFlySplitAllowed()) { - pFly = pFly->GetPrecede(); - if (!pAnchor) + auto pFlyAtContentFrame = static_cast<SwFlyAtContentFrame*>(pFlyFrame); + SwFlyAtContentFrame* pFly = pFlyAtContentFrame; + SwTextFrame* pAnchor = static_cast<SwTextFrame*>(AnchorFrame()); + // If we have to jump back N frames to find the master fly, then we have to step N + // frames from the master anchor to reach the correct follow anchor. + while (pFly->GetPrecede()) { - SAL_WARN("sw.layout", "SwAnchoredObject::FindAnchorCharFrame: fly chain " - "length is longer then anchor chain length"); - break; + pFly = pFly->GetPrecede(); + if (!pAnchor) + { + SAL_WARN("sw.layout", + "SwAnchoredObject::FindAnchorCharFrame: fly chain " + "length is longer then anchor chain length"); + break; + } + pAnchor = pAnchor->GetFollow(); + } + if (pAnchor) + { + pAnchorCharFrame = pAnchor; } - pAnchor = pAnchor->GetFollow(); - } - if (pAnchor) - { - pAnchorCharFrame = pAnchor; } } } @@ -758,7 +774,9 @@ SwTextFrame* SwAnchoredObject::FindAnchorCharFrame() */ bool SwAnchoredObject::IsFormatPossible() const { - return GetFrameFormat().GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetDrawObj()->GetLayer() ); + if (HasFrameFormat()) + return GetFrameFormat().GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetDrawObj()->GetLayer() ); + return false; } bool SwAnchoredObject::IsDraggingOffPageAllowed(const SwFrameFormat* pFrameFormat) diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 457a0d41bbf3..66e27adb8f47 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -1140,8 +1140,9 @@ void SwPageFrame::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj ) } if ( GetUpper() ) { - if (RndStdIds::FLY_AS_CHAR != - _rToRemoveObj.GetFrameFormat().GetAnchor().GetAnchorId()) + if (_rToRemoveObj.HasFrameFormat() + && RndStdIds::FLY_AS_CHAR + != _rToRemoveObj.GetFrameFormat().GetAnchor().GetAnchorId()) { static_cast<SwRootFrame*>(GetUpper())->SetSuperfluous(); InvalidatePage(); @@ -1454,63 +1455,67 @@ bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, bool bMove ) } else { - const SwDrawContact *pC = static_cast<const SwDrawContact*>(GetUserCall(pSdrObj)); - const SwFrameFormat *pFormat = pC->GetFormat(); - const SwFormatAnchor &rAnch = pFormat->GetAnchor(); - if ( RndStdIds::FLY_AS_CHAR == rAnch.GetAnchorId() ) + if (const SwDrawContact* pC = static_cast<const SwDrawContact*>(GetUserCall(pSdrObj))) { - const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); - if( !pAnchorFrame ) + const SwFrameFormat* pFormat = pC->GetFormat(); + const SwFormatAnchor& rAnch = pFormat->GetAnchor(); + if (RndStdIds::FLY_AS_CHAR == rAnch.GetAnchorId()) { - OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." ); - const_cast<SwDrawContact*>(pC)->ConnectToLayout(); - pAnchorFrame = pC->GetAnchorFrame(); - } - const SwFrame* pUp = pAnchorFrame->GetUpper(); - rRect = pUp->getFramePrintArea(); - rRect += pUp->getFrameArea().Pos(); - SwRectFnSet aRectFnSet(pAnchorFrame); - tools::Long nHeight = (9*aRectFnSet.GetHeight(rRect))/10; - tools::Long nTop; - const SvxULSpaceItem &rUL = pFormat->GetULSpace(); - SwRect aSnapRect( pSdrObj->GetSnapRect() ); - tools::Long nTmpH = 0; - if( bMove ) - { - nTop = aRectFnSet.YInc( aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().X() : - pSdrObj->GetAnchorPos().Y(), -nHeight ); - tools::Long nWidth = aRectFnSet.GetWidth(aSnapRect); - aRectFnSet.SetLeftAndWidth( rRect, aRectFnSet.IsVert() ? - pSdrObj->GetAnchorPos().Y() : - pSdrObj->GetAnchorPos().X(), nWidth ); - } - else - { - // #i26791# - value of <nTmpH> is needed to - // calculate value of <nTop>. - nTmpH = aRectFnSet.IsVert() ? pSdrObj->GetCurrentBoundRect().GetWidth() : - pSdrObj->GetCurrentBoundRect().GetHeight(); - nTop = aRectFnSet.YInc( aRectFnSet.GetTop(aSnapRect), - rUL.GetLower() + nTmpH - nHeight ); - } - nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper(); - aRectFnSet.SetTopAndHeight( rRect, nTop, nHeight ); - } - else - { - // restrict clip rectangle for drawing - // objects in header/footer to the page frame. - // #i26791# - const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); - if ( pAnchorFrame && pAnchorFrame->FindFooterOrHeader() ) - { - // clip frame is the page frame the header/footer is on. - const SwFrame* pClipFrame = pAnchorFrame->FindPageFrame(); - rRect = pClipFrame->getFrameArea(); + const SwFrame* pAnchorFrame = pC->GetAnchorFrame(pSdrObj); + if (!pAnchorFrame) + { + OSL_FAIL("<::CalcClipRect(..)> - missing anchor frame."); + const_cast<SwDrawContact*>(pC)->ConnectToLayout(); + pAnchorFrame = pC->GetAnchorFrame(); + } + const SwFrame* pUp = pAnchorFrame->GetUpper(); + rRect = pUp->getFramePrintArea(); + rRect += pUp->getFrameArea().Pos(); + SwRectFnSet aRectFnSet(pAnchorFrame); + tools::Long nHeight = (9 * aRectFnSet.GetHeight(rRect)) / 10; + tools::Long nTop; + const SvxULSpaceItem& rUL = pFormat->GetULSpace(); + SwRect aSnapRect(pSdrObj->GetSnapRect()); + tools::Long nTmpH = 0; + if (bMove) + { + nTop = aRectFnSet.YInc(aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().X() + : pSdrObj->GetAnchorPos().Y(), + -nHeight); + tools::Long nWidth = aRectFnSet.GetWidth(aSnapRect); + aRectFnSet.SetLeftAndWidth(rRect, + aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().Y() + : pSdrObj->GetAnchorPos().X(), + nWidth); + } + else + { + // #i26791# - value of <nTmpH> is needed to + // calculate value of <nTop>. + nTmpH = aRectFnSet.IsVert() ? pSdrObj->GetCurrentBoundRect().GetWidth() + : pSdrObj->GetCurrentBoundRect().GetHeight(); + nTop = aRectFnSet.YInc(aRectFnSet.GetTop(aSnapRect), + rUL.GetLower() + nTmpH - nHeight); + } + nHeight = 2 * nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper(); + aRectFnSet.SetTopAndHeight(rRect, nTop, nHeight); } else { - bRet = false; + // restrict clip rectangle for drawing + // objects in header/footer to the page frame. + // #i26791# + const SwFrame* pAnchorFrame = pC->GetAnchorFrame(pSdrObj); + if (pAnchorFrame && pAnchorFrame->FindFooterOrHeader()) + { + // clip frame is the page frame the header/footer is on. + const SwFrame* pClipFrame = pAnchorFrame->FindPageFrame(); + rRect = pClipFrame->getFrameArea(); + } + else + { + bRet = false; + } } } } diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index c3fa35fcdc7b..c4dbb28f0073 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -3404,8 +3404,10 @@ void Notify_Background( const SdrObject* pObj, else { pFlyFrame = nullptr; - pAnchor = const_cast<SwFrame*>( - GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrame() ); + if (SwDrawContact* pC = static_cast<SwDrawContact*>(GetUserCall(pObj))) + pAnchor = const_cast<SwFrame*>(pC->GetAnchoredObj(pObj)->GetAnchorFrame()); + else + return; } if( PrepareHint::FlyFrameLeave != eHint && pAnchor->IsInFly() ) pArea = pAnchor->FindFlyFrame(); diff --git a/sw/source/core/layout/sortedobjs.cxx b/sw/source/core/layout/sortedobjs.cxx index ce581bb663ef..1e5f1aa293be 100644 --- a/sw/source/core/layout/sortedobjs.cxx +++ b/sw/source/core/layout/sortedobjs.cxx @@ -78,10 +78,14 @@ struct ObjAnchorOrder const SwAnchoredObject* _pNewAnchoredObj ) { // get attributes of listed object + if (!_pListedAnchoredObj->HasFrameFormat()) + return false; const SwFrameFormat& rFormatListed = _pListedAnchoredObj->GetFrameFormat(); const SwFormatAnchor* pAnchorListed = &(rFormatListed.GetAnchor()); // get attributes of new object + if (!_pNewAnchoredObj->HasFrameFormat()) + return false; const SwFrameFormat& rFormatNew = _pNewAnchoredObj->GetFrameFormat(); const SwFormatAnchor* pAnchorNew = &(rFormatNew.GetAnchor()); diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx index ff5566f537ac..6d25e4c96581 100644 --- a/sw/source/core/text/txtfly.cxx +++ b/sw/source/core/text/txtfly.cxx @@ -768,78 +768,85 @@ bool SwTextFly::GetTop( const SwAnchoredObject* _pAnchoredObj, if ( bEvade ) { // #i26945# - const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor(); - OSL_ENSURE( RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId(), - "Don't call GetTop with a FlyInContentFrame" ); - if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) - return true; // We always avoid page anchored ones - - // If Flys anchored at paragraph are caught in a FlyCnt, then - // their influence ends at the borders of the FlyCnt! - // If we are currently formatting the text of the FlyCnt, then - // it has to get out of the way of the Frame anchored at paragraph! - // m_pCurrFrame is the anchor of pNew? - // #i26945# - const SwFrame* pTmp = _pAnchoredObj->GetAnchorFrame(); - if (pTmp == m_pCurrFrame) - return true; - if( pTmp->IsTextFrame() && ( pTmp->IsInFly() || pTmp->IsInFootnote() ) ) + if (_pAnchoredObj->HasFrameFormat()) { + const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor(); + OSL_ENSURE(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId(), + "Don't call GetTop with a FlyInContentFrame"); + if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) + return true; // We always avoid page anchored ones + + // If Flys anchored at paragraph are caught in a FlyCnt, then + // their influence ends at the borders of the FlyCnt! + // If we are currently formatting the text of the FlyCnt, then + // it has to get out of the way of the Frame anchored at paragraph! + // m_pCurrFrame is the anchor of pNew? // #i26945# - Point aPos = _pAnchoredObj->GetObjRect().Pos(); - pTmp = GetVirtualUpper( pTmp, aPos ); - } - // #i26945# - // If <pTmp> is a text frame inside a table, take the upper - // of the anchor frame, which contains the anchor position. - else if ( pTmp->IsTextFrame() && pTmp->IsInTab() ) - { - pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj) - ->GetAnchorFrameContainingAnchPos()->GetUpper(); - } - // #i28701# - consider all objects in same context, - // if wrapping style is considered on object positioning. - // Thus, text will wrap around negative positioned objects. - // #i3317# - remove condition on checking, - // if wrappings style is considered on object positioning. - // Thus, text is wrapping around negative positioned objects. - // #i35640# - no consideration of negative - // positioned objects, if wrapping style isn't considered on - // object position and former text wrapping is applied. - // This condition is typically for documents imported from the - // OpenOffice.org file format. - const IDocumentSettingAccess* pIDSA = &m_pCurrFrame->GetDoc().getIDocumentSettingAccess(); - if ( ( pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) || - !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) ) && - ::FindContext( pTmp, SwFrameType::None ) == ::FindContext(m_pCurrFrame, SwFrameType::None)) - { - return true; - } - - const SwFrame* pHeader = nullptr; - if (m_pCurrFrame->GetNext() != pTmp && - (IsFrameInSameContext( pTmp, m_pCurrFrame ) || - // #i13832#, #i24135# wrap around objects in page header - ( !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) && - nullptr != ( pHeader = pTmp->FindFooterOrHeader() ) && - m_pCurrFrame->IsInDocBody()))) - { - if( pHeader || RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId() ) + const SwFrame* pTmp = _pAnchoredObj->GetAnchorFrame(); + if (pTmp == m_pCurrFrame) return true; - - // Compare indices: - // The Index of the other is retrieved from the anchor attr. - SwNodeOffset nTmpIndex = rNewA.GetAnchorNode()->GetIndex(); - // Now check whether the current paragraph is before the anchor - // of the displaced object in the text, then we don't have to - // get out of its way. - // If possible determine Index via SwFormatAnchor because - // otherwise it's quite expensive. - if (NODE_OFFSET_MAX == m_nCurrFrameNodeIndex) - m_nCurrFrameNodeIndex = m_pCurrFrame->GetTextNodeFirst()->GetIndex(); - - if (FrameContainsNode(*m_pCurrFrame, nTmpIndex) || nTmpIndex < m_nCurrFrameNodeIndex) + if (pTmp->IsTextFrame() && (pTmp->IsInFly() || pTmp->IsInFootnote())) + { + // #i26945# + Point aPos = _pAnchoredObj->GetObjRect().Pos(); + pTmp = GetVirtualUpper(pTmp, aPos); + } + // #i26945# + // If <pTmp> is a text frame inside a table, take the upper + // of the anchor frame, which contains the anchor position. + else if (pTmp->IsTextFrame() && pTmp->IsInTab()) + { + pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj) + ->GetAnchorFrameContainingAnchPos() + ->GetUpper(); + } + // #i28701# - consider all objects in same context, + // if wrapping style is considered on object positioning. + // Thus, text will wrap around negative positioned objects. + // #i3317# - remove condition on checking, + // if wrappings style is considered on object positioning. + // Thus, text is wrapping around negative positioned objects. + // #i35640# - no consideration of negative + // positioned objects, if wrapping style isn't considered on + // object position and former text wrapping is applied. + // This condition is typically for documents imported from the + // OpenOffice.org file format. + const IDocumentSettingAccess* pIDSA + = &m_pCurrFrame->GetDoc().getIDocumentSettingAccess(); + if ((pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) + || !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING)) + && ::FindContext(pTmp, SwFrameType::None) + == ::FindContext(m_pCurrFrame, SwFrameType::None)) + { return true; + } + + const SwFrame* pHeader = nullptr; + if (m_pCurrFrame->GetNext() != pTmp + && (IsFrameInSameContext(pTmp, m_pCurrFrame) || + // #i13832#, #i24135# wrap around objects in page header + (!pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) + && nullptr != (pHeader = pTmp->FindFooterOrHeader()) + && m_pCurrFrame->IsInDocBody()))) + { + if (pHeader || RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId()) + return true; + + // Compare indices: + // The Index of the other is retrieved from the anchor attr. + SwNodeOffset nTmpIndex = rNewA.GetAnchorNode()->GetIndex(); + // Now check whether the current paragraph is before the anchor + // of the displaced object in the text, then we don't have to + // get out of its way. + // If possible determine Index via SwFormatAnchor because + // otherwise it's quite expensive. + if (NODE_OFFSET_MAX == m_nCurrFrameNodeIndex) + m_nCurrFrameNodeIndex = m_pCurrFrame->GetTextNodeFirst()->GetIndex(); + + if (FrameContainsNode(*m_pCurrFrame, nTmpIndex) + || nTmpIndex < m_nCurrFrameNodeIndex) + return true; + } } } } diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 322928eb4ead..d2c3f0e865d7 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -4662,19 +4662,23 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt) SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr; if (pObj) { - SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat(); - SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT); - if (!pShapeFormat) + if (SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj))) { - pSdrView->UnmarkAllObj(); - pSdrView->MarkObj(pObj,pPV); - } - else - { - // If the fly frame is a textbox of a shape, then select the shape instead. - SdrObject* pShape = pShapeFormat->FindSdrObject(); - pSdrView->UnmarkAllObj(); - pSdrView->MarkObj(pShape, pPV); + SwFrameFormat* pFormat = pContact->GetFormat(); + SwFrameFormat* pShapeFormat + = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT); + if (!pShapeFormat) + { + pSdrView->UnmarkAllObj(); + pSdrView->MarkObj(pObj, pPV); + } + else + { + // If the fly frame is a textbox of a shape, then select the shape instead. + SdrObject* pShape = pShapeFormat->FindSdrObject(); + pSdrView->UnmarkAllObj(); + pSdrView->MarkObj(pShape, pPV); + } } } } diff --git a/sw/source/uibase/shells/drwbassh.cxx b/sw/source/uibase/shells/drwbassh.cxx index a5a63a66343d..d5eec2132093 100644 --- a/sw/source/uibase/shells/drwbassh.cxx +++ b/sw/source/uibase/shells/drwbassh.cxx @@ -836,8 +836,12 @@ void SwDrawBaseShell::GetState(SfxItemSet& rSet) SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); SwFrameFormat* pFrameFormat = FindFrameFormat(pObj); - SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT)); - rSet.Put(SfxBoolItem(nWhich, aHOrient.GetHoriOrient() == nHoriOrient)); + if (pFrameFormat) + { + SwFormatHoriOrient aHOrient( + pFrameFormat->GetFormatAttr(RES_HORI_ORIENT)); + rSet.Put(SfxBoolItem(nWhich, aHOrient.GetHoriOrient() == nHoriOrient)); + } } if (bVert && !bDisableThis && rMarkList.GetMarkCount() == 1) @@ -860,8 +864,12 @@ void SwDrawBaseShell::GetState(SfxItemSet& rSet) SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); SwFrameFormat* pFrameFormat = FindFrameFormat(pObj); - SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT)); - rSet.Put(SfxBoolItem(nWhich, aVOrient.GetVertOrient() == nVertOrient)); + if (pFrameFormat) + { + SwFormatVertOrient aVOrient( + pFrameFormat->GetFormatAttr(RES_VERT_ORIENT)); + rSet.Put(SfxBoolItem(nWhich, aVOrient.GetVertOrient() == nVertOrient)); + } } } break;