dev/null |binary sw/inc/textboxhelper.hxx | 40 -- sw/qa/extras/layout/layout.cxx | 5 sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 6 sw/source/core/doc/docfly.cxx | 7 sw/source/core/doc/textboxhelper.cxx | 310 +++++++--------------- sw/source/core/edit/edundo.cxx | 9 sw/source/core/layout/atrfrm.cxx | 9 sw/source/core/text/porfly.cxx | 7 sw/source/core/undo/undobj1.cxx | 12 sw/source/core/unocore/unodraw.cxx | 22 - sw/source/core/unocore/unotext.cxx | 23 - writerfilter/source/dmapper/DomainMapper_Impl.cxx | 27 - 13 files changed, 128 insertions(+), 349 deletions(-)
New commits: commit 71dfe14a10335099624296ae22e74096ba70a7a9 Author: Justin Luth <[email protected]> AuthorDate: Wed Apr 12 08:02:46 2023 -0400 Commit: Andras Timar <[email protected]> CommitDate: Wed Apr 12 21:32:04 2023 +0200 Revert "tdf#148687 tdf#149173 tdf#149546 sw: fix crash with textboxes" This reverts commit 05eaee071ba6eb93ccc4da31b11ee01d102a960c. It was added for T38690 and removed for T41585 Change-Id: Ia50f6bff6e7f15dd7d5f28795fdfe9df7ad048ad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150287 Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index 991b4a5c77f5..b0ab5618b466 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -180,9 +180,6 @@ public: /// vector filled with the textboxes. static std::vector<SwFrameFormat*> CollectTextBoxes(SdrObject* pGroupObject, SwFrameFormat* pFormat); - - // Compares the anchor of the first and second given formats, and decides whether sync needed. - static bool isAnchorSyncNeeded(const SwFrameFormat* pFirst, const SwFrameFormat* pSecond); }; /// Textboxes are basically textframe + shape pairs. This means one shape has one frame. @@ -191,8 +188,6 @@ public: /// it can have multiple textboxes. class SwTextBoxNode { - friend class SwTextBoxLockGuard; - // One TextBox-entry struct SwTextBoxElement { @@ -200,6 +195,8 @@ class SwTextBoxNode SwFrameFormat* m_pTextBoxFormat; // The Draw object where the textbox belongs to SdrObject* m_pDrawObject; + // This is for indicating if the textbox is in special case: for example during undo. + bool m_bIsActive; }; // This vector stores the textboxes what belongs to this node @@ -208,12 +205,8 @@ class SwTextBoxNode // (and the textboxes) SwFrameFormat* m_pOwnerShapeFormat; - // Prevents oscillating during recursive clone calling. mutable bool m_bIsCloningInProgress; - // Protection against looping - bool m_bLock; - public: // Not needed. SwTextBoxNode() = delete; @@ -246,24 +239,22 @@ public: // to the given shape (pDrawObject) SwFrameFormat* GetTextBox(const SdrObject* pDrawObject) const; - // Clears all textboxes of this node from the doc and also from here. - void ClearAll(); + // Is this textbox has special state, undo for example? + bool IsTextBoxActive(const SdrObject* pDrawObject) const; + + // Setters for the state flag. + void SetTextBoxInactive(const SdrObject* pDrawObject); + void SetTextBoxActive(const SdrObject* pDrawObject); // If this is a group shape, that returns true. bool IsGroupTextBox() const; - // This returns with the shape what this class belongs to. SwFrameFormat* GetOwnerShape() { return m_pOwnerShapeFormat; }; - // This will give the current number of textboxes. size_t GetTextBoxCount() const { return m_pTextBoxes.size(); }; - // Returns with a const collection of textboxes owned by this node. std::map<SdrObject*, SwFrameFormat*> GetAllTextBoxes() const; - // Does the copy, and assign of all textboxes of this node to the given format. - // Important: The given format has to be a shape-format, and must have same structure - // as the owner shape has. If the structure different, the cloning will be aborted. void Clone(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, bool bSetAttr, bool bMakeFrame) const; @@ -273,21 +264,6 @@ private: bool bMakeFrame) const; }; -// Helper class for preventing unwanted sync calls. -class SwTextBoxLockGuard -{ - SwTextBoxNode& m_rTextBoxes; - -public: - SwTextBoxLockGuard(SwTextBoxNode& rTextBoxes) - : m_rTextBoxes(rTextBoxes) - { - m_rTextBoxes.m_bLock = true; - } - - ~SwTextBoxLockGuard() { m_rTextBoxes.m_bLock = false; } -}; - #endif // INCLUDED_SW_INC_TEXTBOXHELPER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 2d57ba8642e2..08e33c87980c 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2560,16 +2560,11 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testForcepoint103) createSwWebDoc(DATA_DIRECTORY, "forcepoint103.html"); } -// FIXME: The font substitution of the bugdoc causes crash in Linux builds, -// in addition this example file originally was a docx so check system type -// until that issue is not fixed: -#ifndef SAL_UNX //just care it doesn't crash/assert CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf147485Forcepoint) { createSwDoc(DATA_DIRECTORY, "tdf147485-forcepoint.doc"); } -#endif CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf118058) { diff --git a/sw/qa/extras/ooxmlexport/data/tdf149546.docx b/sw/qa/extras/ooxmlexport/data/tdf149546.docx deleted file mode 100644 index 2811ec1898b4..000000000000 Binary files a/sw/qa/extras/ooxmlexport/data/tdf149546.docx and /dev/null differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index ae386767c584..d3feaf95f720 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -849,12 +849,6 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testTdf147485) load(DATA_DIRECTORY, "Tdf147485.docx"); } -CPPUNIT_TEST_FIXTURE(SwModelTestBase, testTdf149546) -{ - // Before the fix this was impossible. - load(DATA_DIRECTORY, "tdf149546.docx"); -} - CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField) { // Create an in-memory empty document with a user field. diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx index 6dfc19c48f2d..db9518b2cecd 100644 --- a/sw/source/core/doc/docfly.cxx +++ b/sw/source/core/doc/docfly.cxx @@ -920,10 +920,11 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList, pNd->InsertItem( aFormat, aPos.nContent.GetIndex(), 0 ); // Has a textbox attached to the format? Sync it as well! - if (pContact->GetFormat() && pContact->GetFormat()->GetOtherTextBoxFormats()) + if (SwTextBoxHelper::getOtherTextBoxFormat(pContact->GetFormat(), + RES_DRAWFRMFMT)) { - SwTextBoxHelper::synchronizeGroupTextBoxProperty( - SwTextBoxHelper::changeAnchor, pContact->GetFormat(), pObj); + SwTextBoxHelper::syncFlyFrameAttr(*pContact->GetFormat(), + pContact->GetFormat()->GetAttrSet(), pObj); } } break; diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 97faf3a19a70..bb1d6f331dbc 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -64,6 +64,8 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo assert(pShape); assert(pObject); + const bool bIsGroupObj = dynamic_cast<SdrObjGroup*>(pObject->getParentSdrObjectFromSdrObject()); + // If TextBox wasn't enabled previously if (pShape->GetOtherTextBoxFormats() && pShape->GetOtherTextBoxFormats()->GetTextBox(pObject)) return; @@ -111,8 +113,9 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo } else { - auto& pTextBox = pShape->GetOtherTextBoxFormats(); + auto pTextBox = pShape->GetOtherTextBoxFormats(); pTextBox->AddTextBox(pObject, pFormat); + pShape->SetOtherTextBoxFormats(pTextBox); pFormat->SetOtherTextBoxFormats(pTextBox); } // Initialize properties. @@ -175,8 +178,8 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= eMode) syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)), pObject); - changeAnchor(pShape, pObject); - syncTextBoxSize(pShape, pObject); + if (bIsGroupObj) + doTextBoxPositioning(pShape, pObject); // Check if the shape had text before and move it to the new textframe if (!bCopyText || sCopyableText.isEmpty()) @@ -207,13 +210,35 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, 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->GetOtherTextBoxFormats()) + if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormats()) { // If it has a texbox, destroy it. if (pTextBoxNode->GetTextBox(pObj)) - pTextBoxNode->DelTextBox(pObj, true); + { + 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->SetOtherTextBoxFormats(pTextBoxNode); @@ -272,8 +297,25 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, 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::Any(sal_Int16(eMode)), pObj); - + 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. synchronizeGroupTextBoxProperty(&changeAnchor, pShapeFormat, pObj); synchronizeGroupTextBoxProperty(&syncTextBoxSize, pShapeFormat, pObj); @@ -284,10 +326,12 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* pObject) { // If a TextBox was enabled previously - auto& pTextBox = pShape->GetOtherTextBoxFormats(); - if (pTextBox) + auto pTextBox = pShape->GetOtherTextBoxFormats(); + if (pTextBox && pTextBox->IsTextBoxActive(pObject)) { // Unlink the TextBox's text range from the original shape. + pTextBox->SetTextBoxInactive(pObject); + // Delete the associated TextFrame. pTextBox->DelTextBox(pObject, true); } @@ -301,7 +345,7 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType, if (!pFormat || pFormat->Which() != nType) return false; - auto& pTextBox = pFormat->GetOtherTextBoxFormats(); + auto pTextBox = pFormat->GetOtherTextBoxFormats(); if (!pTextBox) return false; @@ -944,7 +988,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u } } } - auto aGuard = SwTextBoxLockGuard(*pShape->GetOtherTextBoxFormats()); + uno::Reference<beans::XPropertySet> const xPropertySet( SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); xPropertySet->setPropertyValue(aPropertyName, aValue); @@ -1138,10 +1182,8 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& } while (pItem && (0 != pItem->Which())); if (aTextBoxSet.Count()) - { - auto aGuard = SwTextBoxLockGuard(*rShape.GetOtherTextBoxFormats()); pFormat->SetFormatAttr(aTextBoxSet); - } + DoTextBoxZOrderCorrection(&rShape, pObj); } @@ -1193,22 +1235,6 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) { - if (!isAnchorSyncNeeded(pShape, pFormat)) - { - doTextBoxPositioning(pShape, pObj); - DoTextBoxZOrderCorrection(pShape, pObj); - if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR - && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR - && pFormat->GetVertOrient().GetRelationOrient() != text::RelOrientation::PRINT_AREA) - { - SwFormatVertOrient aTmp = pFormat->GetVertOrient(); - aTmp.SetRelationOrient(text::RelOrientation::PRINT_AREA); - pFormat->SetFormatAttr(aTmp); - } - - return false; - } - const SwFormatAnchor& rOldAnch = pFormat->GetAnchor(); const SwFormatAnchor& rNewAnch = pShape->GetAnchor(); @@ -1220,7 +1246,6 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) try { - auto aGuard = SwTextBoxLockGuard(*pShape->GetOtherTextBoxFormats()); ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); uno::Reference<beans::XPropertySet> const xPropertySet( SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); @@ -1237,7 +1262,6 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) { - assert(pNewCnt); uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, @@ -1261,7 +1285,6 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) { - assert(pNewCnt); uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, @@ -1276,13 +1299,7 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); - if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE - && rNewAnch.GetPageNum() == 0) - { - pFormat->SetFormatAttr(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1)); - } - else - pFormat->SetFormatAttr(pShape->GetAnchor()); + pFormat->SetFormatAttr(pShape->GetAnchor()); } } } @@ -1291,9 +1308,7 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) SAL_WARN("sw.core", "SwTextBoxHelper::changeAnchor(): " << e.Message); } - doTextBoxPositioning(pShape, pObj); - DoTextBoxZOrderCorrection(pShape, pObj); - return true; + return doTextBoxPositioning(pShape, pObj) && DoTextBoxZOrderCorrection(pShape, pObj); } return false; @@ -1305,8 +1320,6 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) { ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); - auto aGuard = SwTextBoxLockGuard(*pShape->GetOtherTextBoxFormats()); - // Special treatment for AS_CHAR textboxes: if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) { tools::Rectangle aRect( @@ -1403,7 +1416,6 @@ bool SwTextBoxHelper::syncTextBoxSize(SwFrameFormat* pShape, SdrObject* pObj) if (auto pTextBox = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) { - auto aGuard = SwTextBoxLockGuard(*pShape->GetOtherTextBoxFormats()); const auto& rSize = getTextRectangle(pObj, false).GetSize(); if (!rSize.IsEmpty()) { @@ -1426,8 +1438,6 @@ bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const Sdr if (pShpObj) { auto pTextBox = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj); - if (!pTextBox) - return false; SdrObject* pFrmObj = pTextBox->FindRealSdrObject(); if (!pFrmObj) { @@ -1515,103 +1525,19 @@ std::vector<SwFrameFormat*> SwTextBoxHelper::CollectTextBoxes(SdrObject* pGroupO return vRet; } -bool SwTextBoxHelper::isAnchorSyncNeeded(const SwFrameFormat* pFirst, const SwFrameFormat* pSecond) -{ - if (!pFirst) - return false; - - if (!pSecond) - return false; - - if (pFirst == pSecond) - return false; - - if (!pFirst->GetOtherTextBoxFormats()) - return false; - - if (!pSecond->GetOtherTextBoxFormats()) - return false; - - if (pFirst->GetOtherTextBoxFormats() != pSecond->GetOtherTextBoxFormats()) - return false; - - if (pFirst->GetOtherTextBoxFormats()->GetOwnerShape() == pSecond - || pFirst == pSecond->GetOtherTextBoxFormats()->GetOwnerShape()) - { - const auto& rShapeAnchor - = pFirst->Which() == RES_DRAWFRMFMT ? pFirst->GetAnchor() : pSecond->GetAnchor(); - const auto& rFrameAnchor - = pFirst->Which() == RES_FLYFRMFMT ? pFirst->GetAnchor() : pSecond->GetAnchor(); - - if (rShapeAnchor.GetAnchorId() == rFrameAnchor.GetAnchorId()) - { - if (rShapeAnchor.GetContentAnchor() && rFrameAnchor.GetContentAnchor()) - { - if (rShapeAnchor.GetContentAnchor()->nContent - != rFrameAnchor.GetContentAnchor()->nContent) - return true; - - if (rShapeAnchor.GetContentAnchor()->nNode - != rFrameAnchor.GetContentAnchor()->nNode) - return true; - - return false; - } - - if (rShapeAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE - && rFrameAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE) - { - if (rShapeAnchor.GetPageNum() == rFrameAnchor.GetPageNum()) - return false; - else - return true; - } - - return true; - } - - if (rShapeAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR - && rFrameAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR) - { - if (rShapeAnchor.GetContentAnchor() && rFrameAnchor.GetContentAnchor()) - { - if (rShapeAnchor.GetContentAnchor()->nContent - != rFrameAnchor.GetContentAnchor()->nContent) - return true; - - if (rShapeAnchor.GetContentAnchor()->nNode - != rFrameAnchor.GetContentAnchor()->nNode) - return true; - - return false; - } - } - return true; - } - return false; -} - SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape) { assert(pOwnerShape); assert(pOwnerShape->Which() == RES_DRAWFRMFMT); m_bIsCloningInProgress = false; - m_bLock = false; m_pOwnerShapeFormat = pOwnerShape; if (!m_pTextBoxes.empty()) m_pTextBoxes.clear(); } -SwTextBoxNode::~SwTextBoxNode() -{ - if (m_pTextBoxes.size() != 0) - { - SAL_WARN("sw.core", "SwTextBoxNode::~SwTextBoxNode(): Text-Box-Vector still not empty!"); - assert(false); - } -} +SwTextBoxNode::~SwTextBoxNode() { m_pTextBoxes.clear(); } void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBox) { @@ -1621,18 +1547,9 @@ void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBo assert(pDrawObject); SwTextBoxElement aElem; + aElem.m_bIsActive = true; aElem.m_pDrawObject = pDrawObject; aElem.m_pTextBoxFormat = pNewTextBox; - - for (const auto& rE : m_pTextBoxes) - { - if (rE.m_pDrawObject == pDrawObject || rE.m_pTextBoxFormat == pNewTextBox) - { - SAL_WARN("sw.core", "SwTextBoxNode::AddTextBox(): Already exist!"); - return; - } - } - auto pSwFlyDraw = dynamic_cast<SwFlyDrawObj*>(pDrawObject); if (pSwFlyDraw) { @@ -1653,22 +1570,20 @@ void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc) { if (bDelFromDoc) { - it->m_pTextBoxFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( + m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( it->m_pTextBoxFormat); // What about m_pTextBoxes? So, when the DelLayoutFormat() removes the format // then the ~SwFrameFormat() will call this method again to remove the entry. - return; + break; } else { it = m_pTextBoxes.erase(it); - return; + break; } } ++it; } - - SAL_WARN("sw.core", "SwTextBoxNode::DelTextBox(): Not found!"); } void SwTextBoxNode::DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc) @@ -1682,40 +1597,41 @@ void SwTextBoxNode::DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc) { if (bDelFromDoc) { - it->m_pTextBoxFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( + m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( it->m_pTextBoxFormat); // What about m_pTextBoxes? So, when the DelLayoutFormat() removes the format // then the ~SwFrameFormat() will call this method again to remove the entry. - return; + break; } else { it = m_pTextBoxes.erase(it); - return; + break; } } ++it; } - - SAL_WARN("sw.core", "SwTextBoxNode::DelTextBox(): Not found!"); } SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const { assert(pDrawObject); - assert(m_pOwnerShapeFormat); - - if (auto& pTextBoxes = m_pOwnerShapeFormat->GetOtherTextBoxFormats()) + if (!m_pTextBoxes.empty()) { - if (size_t(pTextBoxes.use_count()) != pTextBoxes->GetTextBoxCount() + size_t(1)) + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) { - SAL_WARN("sw.core", "SwTextBoxNode::GetTextBox(): RefCount and TexBox count mismatch!"); - assert(false); + if (it->m_pDrawObject == pDrawObject) + { + return it->m_pTextBoxFormat; + } } } + return nullptr; +} - if (m_bLock) - return nullptr; +bool SwTextBoxNode::IsTextBoxActive(const SdrObject* pDrawObject) const +{ + assert(pDrawObject); if (!m_pTextBoxes.empty()) { @@ -1723,58 +1639,42 @@ SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const { if (it->m_pDrawObject == pDrawObject) { - return it->m_pTextBoxFormat; + return it->m_bIsActive; } } - SAL_WARN("sw.core", "SwTextBoxNode::GetTextBox(): Not found!"); } - - return nullptr; + return false; } -void SwTextBoxNode::ClearAll() +void SwTextBoxNode::SetTextBoxActive(const SdrObject* pDrawObject) { - // If this called from ~SwDoc(), then only the address entries - // have to be removed, the format will be deleted by the - // the mpSpzFrameFormatTable->DeleteAndDestroyAll() in ~SwDoc()! - if (m_pOwnerShapeFormat->GetDoc()->IsInDtor()) - { - m_pTextBoxes.clear(); - return; - } - - // For loop control - sal_uInt16 nLoopCount = 0; - - // Reference not enough, copy needed. - const size_t nTextBoxCount = m_pTextBoxes.size(); + assert(pDrawObject); - // For loop has problems: When one entry deleted, the iterator has - // to be refreshed according to the new situation. So using While() instead. - while (!m_pTextBoxes.empty()) + if (!m_pTextBoxes.empty()) { - // Delete the last textbox of the vector from the doc - // (what will call deregister in ~SwFrameFormat() - m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( - m_pTextBoxes.back().m_pTextBoxFormat); - - // Check if we are looping - if (nLoopCount > (nTextBoxCount + 1)) - { - SAL_WARN("sw.core", "SwTextBoxNode::ClearAll(): Maximum loop count reached!"); - break; - } - else + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) { - nLoopCount++; + if (it->m_pDrawObject == pDrawObject) + { + it->m_bIsActive = true; + } } } +} + +void SwTextBoxNode::SetTextBoxInactive(const SdrObject* pDrawObject) +{ + assert(pDrawObject); - // Ensure the vector is empty. if (!m_pTextBoxes.empty()) { - SAL_WARN("sw.core", "SwTextBoxNode::ClearAll(): Text-Box-Vector still not empty!"); - assert(false); + for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++) + { + if (it->m_pDrawObject == pDrawObject) + { + it->m_bIsActive = false; + } + } } } @@ -1808,14 +1708,6 @@ void SwTextBoxNode::Clone(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFor o_pTarget->FindSdrObject(), bSetAttr, bMakeFrame); m_bIsCloningInProgress = false; - - for (auto& rElem : m_pTextBoxes) - { - SwTextBoxHelper::changeAnchor(m_pOwnerShapeFormat, rElem.m_pDrawObject); - SwTextBoxHelper::doTextBoxPositioning(m_pOwnerShapeFormat, rElem.m_pDrawObject); - SwTextBoxHelper::DoTextBoxZOrderCorrection(m_pOwnerShapeFormat, rElem.m_pDrawObject); - SwTextBoxHelper::syncTextBoxSize(m_pOwnerShapeFormat, rElem.m_pDrawObject); - } } void SwTextBoxNode::Clone_Impl(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, @@ -1831,10 +1723,7 @@ void SwTextBoxNode::Clone_Impl(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFra if (pSrcList && pDestList) { if (pSrcList->GetObjCount() != pDestList->GetObjCount()) - { - SAL_WARN("sw.core", "SwTextBoxNode::Clone_Impl(): Difference between the shapes!"); return; - } for (size_t i = 0; i < pSrcList->GetObjCount(); ++i) { diff --git a/sw/source/core/edit/edundo.cxx b/sw/source/core/edit/edundo.cxx index ec2a365e2662..826d3154ff78 100644 --- a/sw/source/core/edit/edundo.cxx +++ b/sw/source/core/edit/edundo.cxx @@ -34,8 +34,6 @@ #include <frmfmt.hxx> #include <docsh.hxx> #include <pagefrm.hxx> -#include <textboxhelper.hxx> -#include <fmtanchr.hxx> #include <wrtsh.hxx> @@ -66,13 +64,6 @@ void SwEditShell::HandleUndoRedoContext(::sw::UndoRedoContext & rContext) if (RES_DRAWFRMFMT == pSelFormat->Which()) { SdrObject* pSObj = pSelFormat->FindSdrObject(); - - // Before layout calc, inline anchored textboxes have to be synced unless crash. - if (pSelFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR - && pSelFormat->GetOtherTextBoxFormats() && pSObj) - SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::changeAnchor, - pSelFormat, pSObj); - static_cast<SwFEShell*>(this)->SelectObj( pSObj->GetCurrentBoundRect().Center() ); } diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index ebe0033ee5dc..3734963ead87 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -2547,23 +2547,14 @@ SwFrameFormat::~SwFrameFormat() } } - // Check if there any textboxes attached to this format. if( nullptr == m_pOtherTextBoxFormats ) return; // This is a fly-frame-format just delete this // textbox entry from the textbox collection. - // Note: Do not delete it from the doc, as that - // is already in progress. if (Which() == RES_FLYFRMFMT) m_pOtherTextBoxFormats->DelTextBox(this); - // This is a draw-frame-format what belongs to - // a shape with textbox(es). Delete all of them. - if (Which() == RES_DRAWFRMFMT) - m_pOtherTextBoxFormats->ClearAll(); - - // Release the pointer. m_pOtherTextBoxFormats.reset(); } diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index 221827cc2310..8944abe1994d 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -366,17 +366,12 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, if (auto pFormat = FindFrameFormat(pSdrObj)) { - if (pFormat->GetOtherTextBoxFormats() - && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) + if (pFormat->GetOtherTextBoxFormats()) { - // TODO: Improve security with moving this sync call to other place, - // where it works for typing but not during layout calc. const bool bModified = pFormat->GetDoc()->getIDocumentState().IsEnableSetModified(); pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(false); SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::changeAnchor, pFormat, pFormat->FindRealSdrObject()); - SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::syncTextBoxSize, - pFormat, pFormat->FindRealSdrObject()); pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(bModified); } } diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx index 2b989872f93a..fb624d68d6b0 100644 --- a/sw/source/core/undo/undobj1.cxx +++ b/sw/source/core/undo/undobj1.cxx @@ -56,16 +56,8 @@ SwUndoFlyBase::~SwUndoFlyBase() { if( m_bDelFormat ) // delete during an Undo? { - if (const auto& pTextBoxes = m_pFrameFormat->GetOtherTextBoxFormats()) - { - // Clear and unregister before release. - if (m_pFrameFormat->Which() == RES_FLYFRMFMT) - pTextBoxes->DelTextBox(m_pFrameFormat); - - if (m_pFrameFormat->Which() == RES_DRAWFRMFMT) - pTextBoxes->ClearAll(); - - // clear that before delete + if (m_pFrameFormat->GetOtherTextBoxFormats()) + { // clear that before delete m_pFrameFormat->SetOtherTextBoxFormats(nullptr); } delete m_pFrameFormat; diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx index 18b7be2fc29d..1104df24085a 100644 --- a/sw/source/core/unocore/unodraw.cxx +++ b/sw/source/core/unocore/unodraw.cxx @@ -1164,22 +1164,19 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a } else if (pEntry->nWID == FN_TEXT_BOX) { - auto pObj = SdrObject::getSdrObjectFromXShape(mxShape); if (pEntry->nMemberId == MID_TEXT_BOX) { bool bValue(false); aValue >>= bValue; - if (bValue) - SwTextBoxHelper::create(pFormat, pObj); + SwTextBoxHelper::create(pFormat, GetSvxShape()->GetSdrObject()); else - SwTextBoxHelper::destroy(pFormat, pObj); + SwTextBoxHelper::destroy(pFormat, GetSvxShape()->GetSdrObject()); } else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT) { - if (aValue.getValueType() - == cppu::UnoType<uno::Reference<text::XTextFrame>>::get()) - SwTextBoxHelper::set(pFormat, pObj, + if (aValue.getValueType() == cppu::UnoType<uno::Reference<text::XTextFrame>>::get()) + SwTextBoxHelper::set(pFormat, GetSvxShape()->GetSdrObject(), aValue.get<uno::Reference<text::XTextFrame>>()); else SAL_WARN( "sw.uno", "This is not a TextFrame!" ); @@ -1355,21 +1352,10 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a } if( bSetAttr ) pFormat->SetFormatAttr(aSet); - - // If this property is an anchor change, and there is a group shape with textboxes - // do anchor sync in time unless the anchor sync in the porfly will cause crash during - // layout calculation (When importing an inline shape in docx via dmapper). - if (pFormat->Which() == RES_DRAWFRMFMT && pFormat->GetOtherTextBoxFormats() - && pFormat->GetOtherTextBoxFormats()->GetTextBoxCount() - > o3tl::make_unsigned(1)) - SwTextBoxHelper::synchronizeGroupTextBoxProperty( - SwTextBoxHelper::changeAnchor, pFormat, - SdrObject::getSdrObjectFromXShape(mxShape)); } else pFormat->SetFormatAttr(aSet); } - // We have a pFormat and a pEntry as well: try to sync TextBox property. SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue, SdrObject::getSdrObjectFromXShape(mxShape)); diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx index 8d91dfe636d1..9add198df938 100644 --- a/sw/source/core/unocore/unotext.cxx +++ b/sw/source/core/unocore/unotext.cxx @@ -1771,29 +1771,6 @@ SwXText::convertToTextFrame( aAnchor.SetAnchor(aMovePam.Start()); m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat); } - else - { - // if this frame is a textbox of a shape anchored to us, move this textbox too. - const auto& pTextBoxes = pFrameFormat->GetOtherTextBoxFormats(); - if (pFrameFormat->Which() == RES_FLYFRMFMT && pTextBoxes - && pTextBoxes->GetOwnerShape()) - { - const auto& rShapeAnchor = pTextBoxes->GetOwnerShape()->GetAnchor(); - if (rShapeAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR - && rShapeAnchor.GetContentAnchor() && pFrameFormat->GetAnchor().GetContentAnchor() - && pStartPam->ContainsPosition(*pFrameFormat->GetAnchor().GetContentAnchor())) - { - const auto& rAnchorNode - = pFrameFormat->GetAnchor().GetContentAnchor()->nNode.GetNode(); - if (!(rAnchorNode.FindFooterStartNode() || rAnchorNode.FindHeaderStartNode())) - { - SwFormatAnchor aAnchor(pFrameFormat->GetAnchor()); - aAnchor.SetAnchor(aMovePam.Start()); - m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat); - } - } - } - } } } } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index cdbd753dd74e..6fbb7b7744b6 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -593,8 +593,8 @@ void DomainMapper_Impl::RemoveDummyParaForTableInSection() } void DomainMapper_Impl::AddDummyParaForTableInSection() { - // Shapes and textboxes can't have sections. - if (IsInShape() || m_bIsInTextBox) + // Shapes can't have sections. + if (IsInShape()) return; if (!m_aTextAppendStack.empty()) @@ -3770,13 +3770,9 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape { try { - uno::Reference<text::XTextRange> xFrame(xShapes->getByIndex(i), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xFramePropertySet; - if (xFrame) - xFramePropertySet.set(xFrame, uno::UNO_QUERY_THROW); - uno::Reference<beans::XPropertySet> xShapePropertySet(xShapes->getByIndex(i), uno::UNO_QUERY_THROW); - - comphelper::SequenceAsHashMap aGrabBag( xShapePropertySet->getPropertyValue("CharInteropGrabBag") ); + uno::Reference<text::XTextRange> xFrame(xShapes->getByIndex(i), uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xSyncedPropertySet(xFrame, uno::UNO_QUERY_THROW); + comphelper::SequenceAsHashMap aGrabBag( xSyncedPropertySet->getPropertyValue("CharInteropGrabBag") ); // only VML import has checked for style. Don't apply default parastyle properties to other imported shapes // - except for fontsize - to maintain compatibility with previous versions of LibreOffice. @@ -3804,7 +3800,7 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape PROP_CHAR_COLOR, PROP_PARA_ADJUST }; - const uno::Reference<beans::XPropertyState> xShapePropertyState(xShapePropertySet, uno::UNO_QUERY_THROW); + const uno::Reference<beans::XPropertyState> xSyncedPropertyState(xSyncedPropertySet, uno::UNO_QUERY_THROW); for ( const auto& eId : eIds ) { try @@ -3813,16 +3809,11 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape continue; const OUString sPropName = getPropertyName(eId); - if ( beans::PropertyState_DEFAULT_VALUE == xShapePropertyState->getPropertyState(sPropName) ) + if ( beans::PropertyState_DEFAULT_VALUE == xSyncedPropertyState->getPropertyState(sPropName) ) { const uno::Any aProp = GetPropertyFromStyleSheet(eId, pEntry, /*bDocDefaults=*/true, /*bPara=*/true); - if (aProp.hasValue()) - { - if (xFrame) - xFramePropertySet->setPropertyValue(sPropName, aProp); - else - xShapePropertySet->setPropertyValue(sPropName, aProp); - } + if ( aProp.hasValue() ) + xSyncedPropertySet->setPropertyValue( sPropName, aProp ); } } catch (const uno::Exception&) commit 633e0b5c2a8b227f4e5300f919b9700739ed23a7 Author: Justin Luth <[email protected]> AuthorDate: Wed Apr 12 08:01:40 2023 -0400 Commit: Andras Timar <[email protected]> CommitDate: Wed Apr 12 21:31:52 2023 +0200 Revert "tdf#153289: remove problematic assertion" This reverts commit d506ca99d9ecbedadc7d6a83669313eca78768c0. It was added for T38690 and removed for T41585 There was no urgency to get T38690 out, so these regression-prone patches should not have been backported into a stable product. All of these patches are in master and LO 7.4, so they will be part of 23.05 already. So T38690 is solved still in 23.05. Change-Id: I0deb4ba8ee09645957e51c930e1052f47050f0da Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150286 Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index c69f359d6be2..97faf3a19a70 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -1710,6 +1710,7 @@ SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const if (size_t(pTextBoxes.use_count()) != pTextBoxes->GetTextBoxCount() + size_t(1)) { SAL_WARN("sw.core", "SwTextBoxNode::GetTextBox(): RefCount and TexBox count mismatch!"); + assert(false); } }
