diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2021-11-28 15:14:45 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2021-11-28 18:03:04 +0100 |
commit | 2408a1ac6131d137704860f5f8b83bb98d62a4d1 (patch) | |
tree | 7ce9f355048b9272a8757adf316c72b2fae8c7db /sw/source/core/doc | |
parent | e2d63449aae4c3e4ffd6e405001ab56fbead5850 (diff) |
Revert "tdf#129183 sw: textboxes in group shapes - part 3"
This reverts commit eabcfb3f18a6944d9ad89cecd3eb3ca7a2259cf3.
Conflicts:
sw/source/core/doc/textboxhelper.cxx
It caused UITest_writer_tests4 to fail in an ASan build with
> ==2987325==ERROR: AddressSanitizer: heap-use-after-free on address 0x6130000e5048 at pc 0x7f20cb3112ac bp 0x7f1e62de92d0 sp 0x7f1e62de92c8
> WRITE of size 8 at 0x6130000e5048 thread T47
> #0 in SwFrameFormat::SetOtherTextBoxFormat(SwTextBoxNode*) at sw/inc/frmfmt.hxx:106:77
> #1 in SwTextBoxNode::~SwTextBoxNode() at sw/source/core/doc/textboxhelper.cxx:1680:30
> #2 in SwFrameFormat::~SwFrameFormat() at sw/source/core/layout/atrfrm.cxx:2564:9
> #3 in SwDrawFrameFormat::~SwDrawFrameFormat() at sw/source/core/layout/atrfrm.cxx:3455:1
> #4 in SwDrawFrameFormat::~SwDrawFrameFormat() at sw/source/core/layout/atrfrm.cxx:3453:1
> #5 in SwFrameFormats::DeleteAndDestroyAll(bool) at sw/source/core/doc/docfmt.cxx:2115:9
> #6 in SwDoc::~SwDoc() at sw/source/core/doc/docnew.cxx:565:28
> #7 in SwDoc::release() at sw/source/core/doc/doc.cxx:118:9
> #8 in rtl::Reference<SwDoc>::clear() at include/rtl/ref.hxx:196:19
> #9 in SwDocShell::RemoveLink() at sw/source/uibase/app/docshini.cxx:444:16
> #10 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:372:5
> #11 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:362:1
> #12 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:362:1
> #13 in SvRefBase::ReleaseRef() at include/tools/ref.hxx:163:29
> #14 in tools::SvRef<SfxObjectShell>::~SvRef() at include/tools/ref.hxx:56:36
> #15 in IMPL_SfxBaseModel_DataContainer::~IMPL_SfxBaseModel_DataContainer() at sfx2/source/doc/sfxbasemodel.cxx:245:5
> #16 in void std::destroy_at<IMPL_SfxBaseModel_DataContainer>(IMPL_SfxBaseModel_DataContainer*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/stl_construct.h:88:15
> #17 in void std::allocator_traits<std::allocator<IMPL_SfxBaseModel_DataContainer> >::destroy<IMPL_SfxBaseModel_DataContainer>(std::allocator<IMPL_SfxBaseModel_DataContainer>&, IMPL_SfxBaseModel_DataContainer*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/alloc_traits.h:537:4
> #18 in std::_Sp_counted_ptr_inplace<IMPL_SfxBaseModel_DataContainer, std::allocator<IMPL_SfxBaseModel_DataContainer>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:528:2
> #19 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:168:6
> #20 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:705:11
> #21 in std::__shared_ptr<IMPL_SfxBaseModel_DataContainer, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:1154:31
> #22 in std::__shared_ptr<IMPL_SfxBaseModel_DataContainer, (__gnu_cxx::_Lock_policy)2>::reset() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:1272:9
> #23 in SfxBaseModel::dispose() at sfx2/source/doc/sfxbasemodel.cxx:757:13
> #24 in SwXTextDocument::dispose() at sw/source/uibase/uno/unotxdoc.cxx:549:19
> #25 in SfxBaseModel::close(unsigned char) at sfx2/source/doc/sfxbasemodel.cxx:1482:5
> #26 in SwXTextDocument::close(unsigned char) at sw/source/uibase/uno/unotxdoc.cxx:562:19
> #27 in SfxBaseModel::dispose() at sfx2/source/doc/sfxbasemodel.cxx:718:13
> #28 in SwXTextDocument::dispose() at sw/source/uibase/uno/unotxdoc.cxx:549:19
> #29 in gcc3::callVirtualMethod(void*, unsigned int, void*, _typelib_TypeDescriptionReference*, bool, unsigned long*, unsigned int, unsigned long*, double*) at bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:77:5
> #30 in cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy*, bridges::cpp_uno::shared::VtableSlot, _typelib_TypeDescriptionReference*, int, _typelib_MethodParameter*, void*, void**, _uno_Any**) at bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx:233:13
> #31 in unoInterfaceProxyDispatch at bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx:413:13
> #32 in binaryurp::IncomingRequest::execute_throw(binaryurp::BinaryAny*, std::__debug::vector<binaryurp::BinaryAny, std::allocator<binaryurp::BinaryAny> >*) const at binaryurp/source/incomingrequest.cxx:235:13
> #33 in binaryurp::IncomingRequest::execute() const at binaryurp/source/incomingrequest.cxx:78:26
> #34 in request at binaryurp/source/reader.cxx:85:9
> #35 in cppu_threadpool::JobQueue::enter(void const*, bool) at cppu/source/threadpool/jobqueue.cxx:100:17
> #36 in cppu_threadpool::ORequestThread::run() at cppu/source/threadpool/thread.cxx:164:31
> #37 in threadFunc at include/osl/thread.hxx:189:15
> #38 in osl_thread_start_Impl(void*) at sal/osl/unx/thread.cxx:264:9
> #39 in start_thread at <null>
> #40 in __GI___clone3 at <null>
>
> 0x6130000e5048 is located 328 bytes inside of 376-byte region [0x6130000e4f00,0x6130000e5078)
> freed by thread T47 here:
> #0 in operator delete(void*, unsigned long) at ~/github.com/llvm/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:164:3
> #1 in SwFlyFrameFormat::~SwFlyFrameFormat() at sw/source/core/layout/atrfrm.cxx:2912:1
> #2 in SwFrameFormats::DeleteAndDestroyAll(bool) at sw/source/core/doc/docfmt.cxx:2115:9
> #3 in SwDoc::~SwDoc() at sw/source/core/doc/docnew.cxx:565:28
> #4 in SwDoc::release() at sw/source/core/doc/doc.cxx:118:9
> #5 in rtl::Reference<SwDoc>::clear() at include/rtl/ref.hxx:196:19
> #6 in SwDocShell::RemoveLink() at sw/source/uibase/app/docshini.cxx:444:16
> #7 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:372:5
> #8 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:362:1
> #9 in SwDocShell::~SwDocShell() at sw/source/uibase/app/docshini.cxx:362:1
> #10 in SvRefBase::ReleaseRef() at include/tools/ref.hxx:163:29
> #11 in tools::SvRef<SfxObjectShell>::~SvRef() at include/tools/ref.hxx:56:36
> #12 in IMPL_SfxBaseModel_DataContainer::~IMPL_SfxBaseModel_DataContainer() at sfx2/source/doc/sfxbasemodel.cxx:245:5
> #13 in void std::destroy_at<IMPL_SfxBaseModel_DataContainer>(IMPL_SfxBaseModel_DataContainer*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/stl_construct.h:88:15
> #14 in void std::allocator_traits<std::allocator<IMPL_SfxBaseModel_DataContainer> >::destroy<IMPL_SfxBaseModel_DataContainer>(std::allocator<IMPL_SfxBaseModel_DataContainer>&, IMPL_SfxBaseModel_DataContainer*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/alloc_traits.h:537:4
> #15 in std::_Sp_counted_ptr_inplace<IMPL_SfxBaseModel_DataContainer, std::allocator<IMPL_SfxBaseModel_DataContainer>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:528:2
> #16 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:168:6
> #17 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:705:11
> #18 in std::__shared_ptr<IMPL_SfxBaseModel_DataContainer, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:1154:31
> #19 in std::__shared_ptr<IMPL_SfxBaseModel_DataContainer, (__gnu_cxx::_Lock_policy)2>::reset() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/shared_ptr_base.h:1272:9
>
> previously allocated by thread T10 here:
> #0 in operator new(unsigned long) at ~/github.com/llvm/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3
> #1 in SwDoc::MakeFlyFrameFormat(rtl::OUString const&, SwFrameFormat*) at sw/source/core/doc/docfmt.cxx:756:33
> #2 in SwDoc::MakeFlySection_(SwPosition const&, SwContentNode const&, RndStdIds, SfxItemSet const*, SwFrameFormat*) at sw/source/core/doc/doclay.cxx:171:33
> #3 in SwDoc::MakeFlySection(RndStdIds, SwPosition const*, SfxItemSet const*, SwFrameFormat*, bool) at sw/source/core/doc/doclay.cxx:337:19
> #4 in SwXFrame::attachToRange(com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&, SwPaM const*) at sw/source/core/unocore/unoframe.cxx:2821:29
> #5 in SwXFrame::attach(com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sw/source/core/unocore/unoframe.cxx:3115:9
> #6 in SwXTextFrame::attach(com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sw/source/core/unocore/unoframe.cxx:3346:15
> #7 in SwXText::insertTextContent(com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&, com::sun::star::uno::Reference<com::sun::star::text::XTextContent> const&, unsigned char) at sw/source/core/unocore/unotext.cxx:615:15
> #8 in SwXText::insertTextContentWithProperties(com::sun::star::uno::Reference<com::sun::star::text::XTextContent> const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sw/source/core/unocore/unotext.cxx:1472:5
> #9 in non-virtual thunk to SwXText::insertTextContentWithProperties(com::sun::star::uno::Reference<com::sun::star::text::XTextContent> const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sw/source/core/unocore/unotext.cxx
> #10 in SwTextBoxHelper::create(SwFrameFormat*, SdrObject*, bool) at sw/source/core/doc/textboxhelper.cxx:100:29
> #11 in SwXShape::setPropertyValue(rtl::OUString const&, com::sun::star::uno::Any const&) at sw/source/core/unocore/unodraw.cxx:1165:25
> #12 in SdXMLShapeContext::SetStyle(bool) at xmloff/source/draw/ximpshap.cxx:701:27
> #13 in SdXMLCustomShapeContext::startFastElement(int, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) at xmloff/source/draw/ximpshap.cxx:3545:5
> #14 in SvXMLImport::startFastElement(int, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) at xmloff/source/core/xmlimp.cxx:805:15
> #15 in (anonymous namespace)::Entity::startElement((anonymous namespace)::Event const*) at sax/source/fastparser/fastparser.cxx:468:27
> #16 in sax_fastparser::FastSaxParserImpl::callbackStartElement(unsigned char const*, unsigned char const*, unsigned char const*, int, unsigned char const**, int, unsigned char const**) at sax/source/fastparser/fastparser.cxx:1304:21
> #17 in (anonymous namespace)::call_callbackStartElement(void*, unsigned char const*, unsigned char const*, unsigned char const*, int, unsigned char const**, int, int, unsigned char const**) at sax/source/fastparser/fastparser.cxx:331:18
> #18 in xmlParseStartTag2 at workdir/UnpackedTarball/libxml2/parser.c:9658:6
> #19 in xmlParseTryOrFinish at workdir/UnpackedTarball/libxml2/parser.c:11453:14
Change-Id: I752190e05fc3c282b75021724527f623f56ee6a6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125977
Tested-by: Jenkins
Tested-by: René Engelhard <rene@debian.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
(cherry picked from commit 4fb7967fb2e67717f79eb87519c1444a82350a83)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125906
Diffstat (limited to 'sw/source/core/doc')
-rw-r--r-- | sw/source/core/doc/DocumentLayoutManager.cxx | 45 | ||||
-rw-r--r-- | sw/source/core/doc/docdraw.cxx | 55 | ||||
-rw-r--r-- | sw/source/core/doc/docfly.cxx | 11 | ||||
-rw-r--r-- | sw/source/core/doc/textboxhelper.cxx | 492 |
4 files changed, 140 insertions, 463 deletions
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index ae49a77183c0..c67e9e05e9a6 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -312,39 +312,7 @@ void DocumentLayoutManager::DelLayoutFormat( SwFrameFormat *pFormat ) } m_rDoc.getIDocumentState().SetModified(); } -#if 0 -// TODO: Replace the textbox part of frameformat copying method to this. -// Now disabled because cause asserts in sw (Node index is still registered in dtor). -// Without this nested group textboxes are not handled correctly. -static void lcl_CopyTextBoxes(SwDoc* pDoc, SwTextBoxNode* pSrcTextBoxes, const SdrObject* pSrcObj, - SwTextBoxNode* pDestTextBoxes, SdrObject* pDestObj, - bool bSetTextFlyAtt, bool bMakeFrames) -{ - auto pSrcChildren = pSrcObj->getChildrenOfSdrObject(); - auto pDestChildren = pDestObj->getChildrenOfSdrObject(); - if (pSrcChildren && pDestChildren) - { - if (pSrcChildren->GetObjCount() == pDestChildren->GetObjCount()) - for (size_t i = 0; i < pSrcChildren->GetObjCount(); ++i) - { - lcl_CopyTextBoxes(pDoc, pSrcTextBoxes, pSrcChildren->GetObj(i), pDestTextBoxes, - pDestChildren->GetObj(i), bSetTextFlyAtt, bMakeFrames); - } - } - else - { - if (auto pSourceTextBoxFormat = pSrcTextBoxes->GetTextBox(pSrcObj)) - { - assert(pSourceTextBoxFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR); - auto pNewTextBoxFormat = pDoc->GetDocumentLayoutManager().CopyLayoutFormat( - *pSourceTextBoxFormat, pSourceTextBoxFormat->GetAnchor(), bSetTextFlyAtt, - bMakeFrames); - pDestTextBoxes->AddTextBox(pDestObj, pNewTextBoxFormat); - pNewTextBoxFormat->SetOtherTextBoxFormat(pDestTextBoxes); - } - } -} -#endif + /** Copies the stated format (pSrc) to pDest and returns pDest. If there's no pDest, it is created. @@ -501,18 +469,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( auto pObj = rSource.FindRealSdrObject(); auto pTextBoxNd = new SwTextBoxNode(pDest); pDest->SetOtherTextBoxFormat(pTextBoxNd); -#if 0 - // TODO: Change the copy algorithm to this. See comment in lcl_CopyTextBoxes for details. - 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; - } - lcl_CopyTextBoxes(&m_rDoc, rSource.GetOtherTextBoxFormat(), rSource.FindRealSdrObject(), - pTextBoxNd, pDest->FindRealSdrObject(), bSetTextFlyAtt, bMakeFrames); -#endif if (pObj) { const bool bIsGroupObj = pObj->getChildrenOfSdrObject(); diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx index 39adffb8b5a0..0aff4b8993ff 100644 --- a/sw/source/core/doc/docdraw.cxx +++ b/sw/source/core/doc/docdraw.cxx @@ -209,7 +209,7 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned(); } - std::unordered_map<const SdrObject*, SwFrameFormat*> vSavedTextBoxes; + std::vector<std::pair<SwFrameFormat*, SdrObject*>> vSavedTextBoxes; // Destroy ContactObjects and formats. for( size_t i = 0; i < rMrkList.GetMarkCount(); ++i ) { @@ -224,13 +224,8 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) "<SwDoc::GroupSelection(..)> - group members have different positioning status!" ); #endif // Before the format will be killed, save its textbox for later use. - if (auto pTxBxNd = pContact->GetFormat()->GetOtherTextBoxFormat()) - { - for (auto& rElem : pTxBxNd->GetTextBoxTable()) - { - vSavedTextBoxes.emplace(rElem); - } - } + if (auto pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pContact->GetFormat(), RES_DRAWFRMFMT, pObj)) + vSavedTextBoxes.push_back(std::pair<SwFrameFormat*, SdrObject*>(pTextBox, pObj)); pFormat = static_cast<SwDrawFrameFormat*>(pContact->GetFormat()); // Deletes itself! @@ -261,8 +256,8 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) auto pTextBoxNode = new SwTextBoxNode(pFormat); for (auto& pTextBoxEntry : vSavedTextBoxes) { - pTextBoxNode->AddTextBox(const_cast<SdrObject*>(pTextBoxEntry.first), pTextBoxEntry.second); - pTextBoxEntry.second->SetOtherTextBoxFormat(pTextBoxNode); + pTextBoxNode->AddTextBox(pTextBoxEntry.second, pTextBoxEntry.first); + pTextBoxEntry.first->SetOtherTextBoxFormat(pTextBoxNode); } pFormat->SetOtherTextBoxFormat(pTextBoxNode); vSavedTextBoxes.clear(); @@ -304,27 +299,6 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) return pNewContact; } -static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, SwTextBoxNode* pTextBoxNode, - SdrObject* pSourceObjs) -{ - if (auto pChildrenObjs = pSourceObjs->getChildrenOfSdrObject()) - for (size_t i = 0; i < pChildrenObjs->GetObjCount(); ++i) - lcl_CollectTextBoxesForSubGroupObj(pTargetFormat, pTextBoxNode, pChildrenObjs->GetObj(i)); - else - { - if (auto pTextBox = pTextBoxNode->GetTextBox(pSourceObjs)) - { - if (!pTargetFormat->GetOtherTextBoxFormat()) - { - pTargetFormat->SetOtherTextBoxFormat(new SwTextBoxNode(pTargetFormat)); - } - - pTargetFormat->GetOtherTextBoxFormat()->AddTextBox(pSourceObjs, pTextBox); - pTextBox->SetOtherTextBoxFormat(pTargetFormat->GetOtherTextBoxFormat()); - } - } -} - void SwDoc::UnGroupSelection( SdrView& rDrawView ) { bool const bUndo = GetIDocumentUndoRedo().DoesUndo(); @@ -375,22 +349,13 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView ) pFormat->SetFormatAttr( aAnch ); if (pTextBoxNode) - { - if (!pSubObj->getChildrenOfSdrObject()) - { - if (auto pTextBoxFormat = pTextBoxNode->GetTextBox(pSubObj)) - { - auto pNewTextBoxNode = new SwTextBoxNode(pFormat); - pNewTextBoxNode->AddTextBox(pSubObj, pTextBoxFormat); - pFormat->SetOtherTextBoxFormat(pNewTextBoxNode); - pTextBoxFormat->SetOtherTextBoxFormat(pNewTextBoxNode); - }; - } - else + if (auto pTextBoxFormat = pTextBoxNode->GetTextBox(pSubObj)) { - lcl_CollectTextBoxesForSubGroupObj(pFormat, pTextBoxNode, pSubObj); + auto pNewTextBoxNode = new SwTextBoxNode(pFormat); + pNewTextBoxNode->AddTextBox(pSubObj, pTextBoxFormat); + pFormat->SetOtherTextBoxFormat(pNewTextBoxNode); + pTextBoxFormat->SetOtherTextBoxFormat(pNewTextBoxNode); } - } // #i36010# - set layout direction of the position pFormat->SetPositionLayoutDir( diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx index 16365ebbbfec..6b73f1f756b5 100644 --- a/sw/source/core/doc/docfly.cxx +++ b/sw/source/core/doc/docfly.cxx @@ -577,6 +577,8 @@ bool SwDoc::SetFlyFrameAttr( SwFrameFormat& rFlyFormat, SfxItemSet& rSet ) getIDocumentState().SetModified(); + //SwTextBoxHelper::syncFlyFrameAttr(rFlyFormat, rSet); + return bRet; } @@ -918,9 +920,12 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList, pNd->InsertItem( aFormat, aPos.nContent.GetIndex(), 0 ); // Has a textbox attached to the format? Sync it as well! - SwTextBoxHelper::syncFlyFrameAttr(*pContact->GetFormat(), - pContact->GetFormat()->GetAttrSet(), pObj); - + if (SwTextBoxHelper::getOtherTextBoxFormat(pContact->GetFormat(), + RES_DRAWFRMFMT)) + { + SwTextBoxHelper::syncFlyFrameAttr(*pContact->GetFormat(), + pContact->GetFormat()->GetAttrSet(), pObj); + } } break; default: diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 3fc5c4a56313..418c69927228 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -187,8 +187,7 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)), pObject); if (bIsGroupObj) - handleTextBoxGroup( - pShape, SwTextBoxHelper::GroupTextBoxActionType::POSITION_SIZE_AND_ANCHOR_CHANGE); + doTextBoxPositioning(pShape, pObject); // Check if the shape had text before and move it to the new textframe if (!bCopyText || sCopyableText.isEmpty()) @@ -208,156 +207,18 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo } } -void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, - uno::Reference<text::XTextFrame> xNew) -{ - // Do not set invalid data - assert(pShapeFormat && pObj && xNew); - // Firstly find the format of the new textbox. - SwFrameFormat* pFormat = nullptr; - if (auto pTextFrame = dynamic_cast<SwXTextFrame*>(xNew.get())) - pFormat = pTextFrame->GetFrameFormat(); - if (!pFormat) - return; - std::vector<std::pair<beans::Property, uno::Any>> aOldProps; - // If there is a format, check if the shape already has a textbox assigned to. - if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat()) - { - // If it has a texbox, destroy it. - if (pTextBoxNode->GetTextBox(pObj)) - { - auto xOldFrame - = pObj->getUnoShape()->queryInterface(cppu::UnoType<text::XTextRange>::get()); - if (xOldFrame.hasValue()) - { - uno::Reference<beans::XPropertySet> xOldprops(xOldFrame, uno::UNO_QUERY); - uno::Reference<beans::XPropertyState> xOldPropStates(xOldFrame, uno::UNO_QUERY); - for (auto& rProp : xOldprops->getPropertySetInfo()->getProperties()) - { - try - { - if (xOldPropStates->getPropertyState(rProp.Name) - == beans::PropertyState::PropertyState_DIRECT_VALUE) - aOldProps.push_back( - std::pair(rProp, xOldprops->getPropertyValue(rProp.Name))); - } - catch (...) - { - } - } - } - destroy(pShapeFormat, pObj); - } - // And set the new one. - pTextBoxNode->AddTextBox(pObj, pFormat); - pFormat->SetOtherTextBoxFormat(pTextBoxNode); - } - else - { - // If the shape do not have a texbox node and textbox, - // create that for the shape. - auto* pTextBox = new SwTextBoxNode(pShapeFormat); - pTextBox->AddTextBox(pObj, pFormat); - pShapeFormat->SetOtherTextBoxFormat(pTextBox); - pFormat->SetOtherTextBoxFormat(pTextBox); - } - - // Initialize its properties - uno::Reference<beans::XPropertySet> xPropertySet(xNew, uno::UNO_QUERY); - uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2()); - xPropertySet->setPropertyValue(UNO_NAME_TOP_BORDER, aEmptyBorder); - xPropertySet->setPropertyValue(UNO_NAME_BOTTOM_BORDER, aEmptyBorder); - xPropertySet->setPropertyValue(UNO_NAME_LEFT_BORDER, aEmptyBorder); - xPropertySet->setPropertyValue(UNO_NAME_RIGHT_BORDER, aEmptyBorder); - xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(sal_Int32(100))); - xPropertySet->setPropertyValue(UNO_NAME_SIZE_TYPE, uno::makeAny(text::SizeType::FIX)); - xPropertySet->setPropertyValue(UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGH)); - // Add a new name to it - uno::Reference<container::XNamed> xNamed(xNew, uno::UNO_QUERY); - xNamed->setName(pShapeFormat->GetDoc()->GetUniqueFrameName()); - // And sync. properties. - uno::Reference<drawing::XShape> xShape(pObj->getUnoShape(), uno::UNO_QUERY); - syncProperty(pShapeFormat, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::makeAny(xShape->getSize()), - pObj); - - uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY); - syncProperty(pShapeFormat, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, - xShapePropertySet->getPropertyValue(UNO_NAME_ANCHOR_TYPE), pObj); - syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, - xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT), pObj); - syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_RELATION, - xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION), pObj); - syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT, - xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT), pObj); - syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_RELATION, - xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION), pObj); - syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_POSITION, - xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION), pObj); - syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, - xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION), pObj); - syncProperty(pShapeFormat, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, - xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT), pObj); - - drawing::TextVerticalAdjust aVertAdj = drawing::TextVerticalAdjust_CENTER; - - if ((uno::Reference<beans::XPropertyState>(xShape, uno::UNO_QUERY_THROW)) - ->getPropertyState(UNO_NAME_TEXT_VERT_ADJUST) - != beans::PropertyState::PropertyState_DEFAULT_VALUE) - { - aVertAdj = xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST) - .get<drawing::TextVerticalAdjust>(); - } - - xPropertySet->setPropertyValue(UNO_NAME_TEXT_VERT_ADJUST, uno::makeAny(aVertAdj)); - text::WritingMode eMode; - if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= eMode) - syncProperty(pShapeFormat, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)), pObj); - if (aOldProps.size()) - { - for (auto& rProp : aOldProps) - { - try - { - xPropertySet->setPropertyValue(rProp.first.Name, rProp.second); - } - catch (...) - { - } - } - } - if (pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE - && pFormat->GetAnchor().GetPageNum() == 0) - { - pFormat->SetFormatAttr(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1)); - } - // Do sync for the new textframe. - handleTextBoxGroup(pShapeFormat, GroupTextBoxActionType::POSITION_SIZE_AND_ANCHOR_CHANGE); -} - void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* pObject) { - assert(pShape && pObject); - // If a TextBox was enabled previously - auto pTextBoxNode = pShape->GetOtherTextBoxFormat(); - if (!pTextBoxNode) - { - SAL_WARN("sw.core", "SwTextBoxHelper::destroy: No TextBoxNode!"); - return; - } - - if (auto pFormat = pTextBoxNode->GetTextBox(pObject)) + auto pTextBox = pShape->GetOtherTextBoxFormat(); + if (pTextBox && pTextBox->IsTextBoxActive(pObject)) { // Unlink the TextBox's text range from the original shape. - pTextBoxNode->DelTextBox(pObject); - pFormat->SetOtherTextBoxFormat(nullptr); + pTextBox->SetTextBoxInactive(pObject); // Delete the associated TextFrame. - pFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(pFormat); - return; + pTextBox->DelTextBox(pObject); } - - SAL_WARN("sw.core", "SwTextBoxHelper::destroy: No TextBox to destroy!"); } bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType, @@ -372,9 +233,6 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType, if (!pTextBox) return false; - if (!pTextBox->GetTextBoxCount()) - return false; - if (nType == RES_DRAWFRMFMT) { if (pObject) @@ -475,12 +333,6 @@ sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject) void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough) { - if (!pTextBox->GetOtherTextBoxFormat()) - { - SAL_WARN("sw.core", "SwTextBoxHelper::getShapeWrapThrough: No TextBoxNode!"); - return; - } - SwFrameFormat* pShape = SwTextBoxHelper::getOtherTextBoxFormat(pTextBox, RES_FLYFRMFMT); if (pShape) rWrapThrough = pShape->GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH; @@ -515,8 +367,7 @@ SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XS return nullptr; SwFrameFormat* pFormat = pShape->GetFrameFormat(); - return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT, - SdrObject::getSdrObjectFromXShape(xShape)); + return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT); } uno::Reference<text::XTextFrame> @@ -537,49 +388,33 @@ SwTextBoxHelper::getUnoTextFrame(uno::Reference<drawing::XShape> const& xShape) return {}; } -uno::Any SwTextBoxHelper::queryInterface(const SwFrameFormat* pShape, const uno::Type& rType, - SdrObject* pObj) +template <typename T> static void lcl_queryInterface(const SwFrameFormat* pShape, uno::Any& rAny) { - if (!pShape) - return {}; - - if (!pShape->GetOtherTextBoxFormat()) + if (SwFrameFormat* pFormat = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { - SAL_WARN("sw.core", "SwTextBoxHelper::queryInterface: No TextBoxNode!"); - return {}; - } - - SwFrameFormat* pFormat = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj); - - if (!pFormat) - { - SAL_WARN("sw.core", "SwTextBoxHelper::queryInterface: No TextBox!"); - return {}; + uno::Reference<T> const xInterface( + SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); + rAny <<= xInterface; } +} +uno::Any SwTextBoxHelper::queryInterface(const SwFrameFormat* pShape, const uno::Type& rType) +{ uno::Any aRet; if (rType == cppu::UnoType<css::text::XTextAppend>::get()) { - uno::Reference<css::text::XTextAppend> const xInterface( - SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY_THROW); - aRet <<= xInterface; + lcl_queryInterface<text::XTextAppend>(pShape, aRet); } else if (rType == cppu::UnoType<css::text::XText>::get()) { - uno::Reference<css::text::XText> const xInterface( - SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY_THROW); - aRet <<= xInterface; + lcl_queryInterface<text::XText>(pShape, aRet); } else if (rType == cppu::UnoType<css::text::XTextRange>::get()) { - uno::Reference<css::text::XTextRange> const xInterface( - SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY_THROW); - aRet <<= xInterface; + lcl_queryInterface<text::XTextRange>(pShape, aRet); } - assert(aRet.hasValue()); - return aRet; } @@ -1073,51 +908,6 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame } } -void SwTextBoxHelper::handleTextBoxGroup(SwFrameFormat* pGroupShapeFormat, - GroupTextBoxActionType eActionType, - SdrObject* pGroupObject) -{ - if (!pGroupShapeFormat) - return; - - SdrObject* pMasterObj = nullptr; - if (!pGroupObject) - pMasterObj = pGroupShapeFormat->FindRealSdrObject(); - else - pMasterObj = pGroupObject; - - if (auto pChildrenObjs = pMasterObj->getChildrenOfSdrObject()) - { - for (size_t i = 0; i < pChildrenObjs->GetObjCount(); ++i) - handleTextBoxGroup(pGroupShapeFormat, eActionType, pChildrenObjs->GetObj(i)); - } - else - { - switch (eActionType) - { - case GroupTextBoxActionType::POSITION_SIZE_AND_ANCHOR_CHANGE: - { - changeAnchor(pGroupShapeFormat, pMasterObj); - setTextBoxSize(pGroupShapeFormat, pMasterObj); - break; - } - case GroupTextBoxActionType::Z_ORDER_CHANGE: - { - DoTextBoxZOrderCorrection(pGroupShapeFormat, pMasterObj); - break; - } - case GroupTextBoxActionType::DELETE: - { - destroy(pGroupShapeFormat, pMasterObj); - break; - } - default: - SAL_WARN("sw.core", "SwTextBoxHelper::handleTextBoxGroup: Unknown Action!"); - break; - } - } -} - text::TextContentAnchorType SwTextBoxHelper::mapAnchorType(const RndStdIds& rAnchorID) { text::TextContentAnchorType aAnchorType; @@ -1276,6 +1066,7 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& if (aTextBoxSet.Count()) pFormat->SetFormatAttr(aTextBoxSet); + //pFormat->GetDoc()->SetFlyFrameAttr(*pFormat, aTextBoxSet); DoTextBoxZOrderCorrection(&rShape, pObj); } @@ -1323,11 +1114,12 @@ void SwTextBoxHelper::updateTextBoxMargin(SdrObject* pObj) DoTextBoxZOrderCorrection(pParentFormat, pObj); } -bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* pShape, SdrObject* pObj) +bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* pShape) { - if (isTextBoxShapeHasValidTextFrame(pShape, pObj)) + OUString sErrMsg; + if (isTextBoxShapeHasValidTextFrame(pShape)) { - if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); if (auto xFrame = SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat)) @@ -1340,77 +1132,53 @@ bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* pShape, SdrObject* pObj) } catch (uno::Exception& e) { - SAL_WARN("sw.core", - "SwTextBoxHelper::setWrapThrough: Exception caught: " << e.Message); + sErrMsg = "Exception caught: " + e.Message; } else - SAL_WARN("sw.core", "SwTextBoxHelper::setWrapThrough: No XTextFrame!"); + sErrMsg = "No XTextFrame!"; } else - SAL_WARN("sw.core", "SwTextBoxHelper::setWrapThrough: No Other TextBox Format!"); + sErrMsg = "No Other TextBox Format!"; } else - SAL_WARN("sw.core", "SwTextBoxHelper::setWrapThrough: Not a Valid TextBox object!"); + sErrMsg = "Not a Valid TextBox object!"; + SAL_WARN("sw.core", "SwTextBoxHelper::setWrapThrough: " << sErrMsg); return false; } bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { - // Get the desired textbox from the shape if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) { - // Collect the anchors const SwFormatAnchor& rOldAnch = pFormat->GetAnchor(); const SwFormatAnchor& rNewAnch = pShape->GetAnchor(); - // Collect the anchor positions (in the text) const auto pOldCnt = rOldAnch.GetContentAnchor(); const auto pNewCnt = rNewAnch.GetContentAnchor(); - // Collect the relative anchor points const uno::Any aShapeHorRelOrient = uno::makeAny(pShape->GetHoriOrient().GetRelationOrient()); - const uno::Any aShapeVertRelOrient - = uno::makeAny(pShape->GetVertOrient().GetRelationOrient()); - // Get the new page number. If this is 0 increase it to 1! - // (0 is invalid page) - const sal_uInt16 nPageNum = rNewAnch.GetPageNum() ? rNewAnch.GetPageNum() : 1; - - // If anchor is different, sync needed - if (isAnchorTypeDifferent(pShape, pObj) || (pObj && pObj != pShape->FindRealSdrObject())) + if (isAnchorTypeDifferent(pShape) || (pObj && pObj != pShape->FindRealSdrObject())) { try { - // Disable undo for the sync ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); - // Get the properties of the textframe uno::Reference<beans::XPropertySet> const xPropertySet( SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); - - // Anchoring situations: - - // First: - // the old anchor is in the text (namely inline or at_char/para) and, - // the new one will be at_page if (pOldCnt && rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && rNewAnch.GetPageNum()) { uno::Any aValue(text::TextContentAnchorType_AT_PAGE); xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, - aShapeVertRelOrient); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, uno::Any(nPageNum)); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, + uno::Any(rNewAnch.GetPageNum())); } - // Second: - // The reverse of the previous one: Old one at page, new at-text. else if (rOldAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && pNewCnt) { - // If the new at-text anchor is inline, the textbox can not be inline too, - // so change it to at_char and make its position according to the shape. if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) { uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); @@ -1423,28 +1191,17 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) aPos.SetAnchor(pNewCnt); pFormat->SetFormatAttr(aPos); } - // Else, copy the anchor of the shape to the frame. Correct pagenum if needed. else { uno::Any aValue(mapAnchorType(rNewAnch.GetAnchorId())); xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, - aShapeVertRelOrient); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE - && !rNewAnch.GetPageNum()) - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, - uno::Any(sal_uInt16(1))); - pFormat->SetFormatAttr(rNewAnch); } } - // Third: - // At-text anchor changes to at-text. (Only the type changes) else { - // Special treatment for inline case. if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) { uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); @@ -1457,19 +1214,10 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) aPos.SetAnchor(pNewCnt); pFormat->SetFormatAttr(aPos); } - // Else, just copy the anchor. else { xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, - aShapeVertRelOrient); - - if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE - && !rNewAnch.GetPageNum()) - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, - uno::Any(sal_uInt16(1))); - pFormat->SetFormatAttr(pShape->GetAnchor()); } } @@ -1505,12 +1253,6 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb SwFormatVertOrient aNewVOri(pFormat->GetVertOrient()); aNewVOri.SetPos(aRect.Top() + pShape->GetVertOrient().GetPos()); - if (bIsGroupObj) - { - aNewHOri.SetPos(aNewHOri.GetPos() + pObj->GetRelativePos().getX()); - aNewVOri.SetPos(aNewVOri.GetPos() + pObj->GetRelativePos().getY()); - } - // tdf#140598: Do not apply wrong rectangle position. if (aRect.TopLeft() != Point(0, 0)) { @@ -1530,11 +1272,11 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb { SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient()); aNewHOri.SetPos( - ((bIsGroupObj && pObj) ? pObj->GetRelativePos().getX() : aNewHOri.GetPos()) + (bIsGroupObj && pObj ? pObj->GetRelativePos().getX() : aNewHOri.GetPos()) + aRect.Left()); SwFormatVertOrient aNewVOri(pShape->GetVertOrient()); aNewVOri.SetPos( - ((bIsGroupObj && pObj) ? pObj->GetRelativePos().getY() : aNewVOri.GetPos()) + (bIsGroupObj && pObj ? pObj->GetRelativePos().getY() : aNewVOri.GetPos()) + aRect.Top()); pFormat->SetFormatAttr(aNewHOri); @@ -1549,31 +1291,12 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb return false; } -bool SwTextBoxHelper::setTextBoxSize(const SwFrameFormat* pShape, SdrObject* pObj) -{ - if (!pShape || !pObj) - return false; - - if (auto pTBox = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) - { - const auto& rSize = getTextRectangle(pObj, false).GetSize(); - if (!rSize.IsEmpty()) - { - SwFormatFrameSize aSizeFormatItem = pTBox->GetFrameSize(); - aSizeFormatItem.SetSize(rSize); - return pTBox->SetFormatAttr(aSizeFormatItem); - } - } - return false; -} - -std::optional<bool> SwTextBoxHelper::isAnchorTypeDifferent(const SwFrameFormat* pShape, - SdrObject* pObj) +std::optional<bool> SwTextBoxHelper::isAnchorTypeDifferent(const SwFrameFormat* pShape) { std::optional<bool> bRet; - if (isTextBoxShapeHasValidTextFrame(pShape, pObj)) + if (isTextBoxShapeHasValidTextFrame(pShape)) { - if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) bRet = (pFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AT_CHAR @@ -1585,21 +1308,20 @@ std::optional<bool> SwTextBoxHelper::isAnchorTypeDifferent(const SwFrameFormat* return bRet; } -bool SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(const SwFrameFormat* pShape, SdrObject* pObj) +bool SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(const SwFrameFormat* pShape) { if (pShape && pShape->Which() == RES_DRAWFRMFMT) - if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) if (pFormat && pFormat->Which() == RES_FLYFRMFMT) return true; else - SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: Shape does " - "not have valid textframe!"); + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: " + "Shape does not have valid textframe!"); else - SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: Shape does not " - "have associated frame!"); + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: " + "Shape does not have associated frame!"); else - SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: No valid shape"); - + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: Not valid shape!"); return false; } @@ -1607,6 +1329,9 @@ bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const Sdr { // TODO: do this with group shape textboxes. SdrObject* pShpObj = nullptr; + //if (pObj) + // pShpObj = pObj; + //else pShpObj = pShape->FindRealSdrObject(); if (pShpObj) @@ -1640,53 +1365,39 @@ bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const Sdr break; ++nIterator; if (nIterator > 300) - { break; // Do not run to infinity - } } pPage->RecalcObjOrdNums(); return true; // Success } - SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): No Valid Draw model " - "for SdrObject for the shape!"); + SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): " + "No Valid Draw model for SdrObject for the shape!"); } - SAL_WARN("sw.core", - "SwTextBoxHelper::DoTextBoxZOrderCorrection(): No Valid SdrObject for the frame!"); + SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): " + "No Valid SdrObject for the frame!"); } - SAL_WARN("sw.core", - "SwTextBoxHelper::DoTextBoxZOrderCorrection(): No Valid SdrObject for the shape!"); + SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): " + "No Valid SdrObject for the shape!"); return false; } -// SwTextBoxNode class: - SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape) { assert(pOwnerShape); assert(pOwnerShape->Which() == RES_DRAWFRMFMT); m_pOwnerShapeFormat = pOwnerShape; - if (!m_pTextBoxTable.empty()) - m_pTextBoxTable.clear(); + if (!m_pTextBoxes.empty()) + m_pTextBoxes.clear(); } SwTextBoxNode::~SwTextBoxNode() { - if (m_pTextBoxTable.size()) - { - for (auto& rTextBox : m_pTextBoxTable) - { - rTextBox.second->SetOtherTextBoxFormat(nullptr); - rTextBox.second = nullptr; - } - m_pTextBoxTable.clear(); - } + m_pTextBoxes.clear(); if (m_pOwnerShapeFormat && m_pOwnerShapeFormat->GetOtherTextBoxFormat()) m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr); - - m_pOwnerShapeFormat = nullptr; } void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBox) @@ -1696,63 +1407,102 @@ void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBo assert(pDrawObject); - if (!m_pTextBoxTable.count(pDrawObject)) - { - m_pTextBoxTable.emplace(pDrawObject, pNewTextBox); - } - else - { - m_pTextBoxTable[pDrawObject] = pNewTextBox; - } + SwTextBoxElement aElem; + aElem.m_bIsActive = true; + aElem.m_pDrawObject = pDrawObject; + aElem.m_pTextBoxFormat = pNewTextBox; auto pSwFlyDraw = dynamic_cast<SwFlyDrawObj*>(pDrawObject); if (pSwFlyDraw) { pSwFlyDraw->SetTextBox(true); } + m_pTextBoxes.push_back(aElem); } void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject) { assert(pDrawObject); - auto pObj = const_cast<SdrObject*>(pDrawObject); - - if (m_pTextBoxTable.empty()) + if (m_pTextBoxes.empty()) return; - if (m_pTextBoxTable.count(pObj)) + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end();) { - m_pTextBoxTable[pObj]->SetOtherTextBoxFormat(nullptr); - m_pTextBoxTable.erase(pObj); + if (it->m_pDrawObject == pDrawObject) + { + m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( + it->m_pTextBoxFormat); + it = m_pTextBoxes.erase(it); + break; + } + ++it; } } -void SwTextBoxNode::DelTextBox(SwFrameFormat* pTextBox) +SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const { - if (!pTextBox || m_pTextBoxTable.empty()) - return; + assert(pDrawObject); + if (!m_pTextBoxes.empty()) + { + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) + { + if (it->m_pDrawObject == pDrawObject) + { + return it->m_pTextBoxFormat; + } + } + } + return nullptr; +} - for (auto it = m_pTextBoxTable.begin(); it != m_pTextBoxTable.end(); ++it) - if (it->second == pTextBox) +bool SwTextBoxNode::IsTextBoxActive(const SdrObject* pDrawObject) const +{ + assert(pDrawObject); + + if (!m_pTextBoxes.empty()) + { + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) { - it->second->SetOtherTextBoxFormat(nullptr); - m_pTextBoxTable.erase(it->first); - break; + if (it->m_pDrawObject == pDrawObject) + { + return it->m_bIsActive; + } } + } + return false; } -SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const +void SwTextBoxNode::SetTextBoxActive(const SdrObject* pDrawObject) { assert(pDrawObject); - if (!m_pTextBoxTable.empty()) + + if (!m_pTextBoxes.empty()) { - if (m_pTextBoxTable.count(pDrawObject)) + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) { - return m_pTextBoxTable.at(pDrawObject); + if (it->m_pDrawObject == pDrawObject) + { + it->m_bIsActive = true; + } + } + } +} + +void SwTextBoxNode::SetTextBoxInactive(const SdrObject* pDrawObject) +{ + assert(pDrawObject); + + if (!m_pTextBoxes.empty()) + { + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) + { + if (it->m_pDrawObject == pDrawObject) + { + it->m_bIsActive = false; + } } } - return nullptr; } -bool SwTextBoxNode::IsGroupTextBoxShape() const { return m_pTextBoxTable.size() > 1; } +bool SwTextBoxNode::IsGroupTextBox() const { return m_pTextBoxes.size() > 1; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |