diff options
author | Attila Bakos (NISZ) <bakos.attilakaroly@nisz.hu> | 2020-10-30 13:28:02 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2020-11-17 16:02:09 +0100 |
commit | a7bd634371285dbdceaf775dc31b6b586c7ca02f (patch) | |
tree | eea7f95832d1bfaa4a081b23271bc28d9626e018 | |
parent | 129629de708b35154a0812eaf19dd19e76e38331 (diff) |
tdf#137802 tdf#84691 sw: sync anchoring of textbox with UNO
It was possible to anchor the textbox both to page and
paragraph, resulting crash during file saving.
Change-Id: I0c95a13c0d8d58cd7cc1fa86de1b80bf088ba782
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105046
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r-- | sw/qa/extras/uiwriter/data3/AtPageTextBoxCrash.odt | bin | 0 -> 9880 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter3.cxx | 39 | ||||
-rw-r--r-- | sw/source/core/doc/textboxhelper.cxx | 50 |
3 files changed, 73 insertions, 16 deletions
diff --git a/sw/qa/extras/uiwriter/data3/AtPageTextBoxCrash.odt b/sw/qa/extras/uiwriter/data3/AtPageTextBoxCrash.odt Binary files differnew file mode 100644 index 000000000000..20e58dfc0670 --- /dev/null +++ b/sw/qa/extras/uiwriter/data3/AtPageTextBoxCrash.odt diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 09cad813f162..841b03493bf6 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -1856,6 +1856,45 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf127652) CPPUNIT_ASSERT_EQUAL_MESSAGE("We are on the wrong page!", assertPage, currentPage); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, AtPageTextBoxCrash) +{ + // Load sample file + load(DATA_DIRECTORY, "AtPageTextBoxCrash.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + + // Get the Writer-Shell for later use + SwWrtShell* pWrtSh = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtSh); + + // Get the format of the shape + const SwFrameFormats& rFrmFormats = *pWrtSh->GetDoc()->GetSpzFrameFormats(); + CPPUNIT_ASSERT(rFrmFormats.size() >= size_t(o3tl::make_unsigned(1))); + auto pShape = rFrmFormats.front(); + CPPUNIT_ASSERT(pShape); + + // Add a textbox to the shape + SwTextBoxHelper::create(pShape); + auto pTxBxFrm = SwTextBoxHelper::getOtherTextBoxFormat(getShape(1)); + CPPUNIT_ASSERT(pTxBxFrm); + + // Change its anchor to page + uno::Reference<beans::XPropertySet> xShpProps(getShape(1), uno::UNO_QUERY_THROW); + xShpProps->setPropertyValue( + "AnchorType", uno::makeAny(text::TextContentAnchorType::TextContentAnchorType_AT_PAGE)); + + // The page anchored objects must not have content anchor + // unless this will lead to crash later, for example on + // removing the paragraph where it is achored to... + CPPUNIT_ASSERT_EQUAL(RndStdIds::FLY_AT_PAGE, pTxBxFrm->GetAnchor().GetAnchorId()); + CPPUNIT_ASSERT(!pTxBxFrm->GetAnchor().GetContentAnchor()); + + // Remove the paragraph where the textframe should be anchored + // before. Now with the patch it must not crash... + auto xPara = getParagraph(1); + xPara->getText()->setString(OUString()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135661) { load(DATA_DIRECTORY, "tdf135661.odt"); diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 82a1c9b6fdd7..b62269faa787 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -130,6 +130,8 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape) uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY); syncProperty(pShape, RES_FOLLOW_TEXT_FLOW, MID_FOLLOW_TEXT_FLOW, xShapePropertySet->getPropertyValue(UNO_NAME_IS_FOLLOWING_TEXT_FLOW)); + syncProperty(pShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, + xShapePropertySet->getPropertyValue(UNO_NAME_ANCHOR_TYPE)); syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT)); syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_RELATION, @@ -160,15 +162,10 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape) return; SfxItemSet aTxFrmSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange); - SwFormatAnchor aNewAnch = pFormat->GetAnchor(); - if (pShape->GetAnchor().GetContentAnchor()) - aNewAnch.SetAnchor(pShape->GetAnchor().GetContentAnchor()); - if (pShape->GetAnchor().GetPageNum() > 0) - aNewAnch.SetPageNum(pShape->GetAnchor().GetPageNum()); - - aNewAnch.SetType(pShape->GetAnchor().GetAnchorId()); - aTxFrmSet.Put(aNewAnch); + if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR + || rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) + aTxFrmSet.Put(rAnch); SwFormatVertOrient aVOri(pFormat->GetVertOrient()); SwFormatHoriOrient aHOri(pFormat->GetHoriOrient()); @@ -626,17 +623,38 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u switch (nMemberID) { case MID_ANCHOR_ANCHORTYPE: + { + uno::Reference<beans::XPropertySet> const xPropertySet( + SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), + uno::UNO_QUERY); + // Surround (Wrap) has to be THROUGH always: + xPropertySet->setPropertyValue(UNO_NAME_SURROUND, + uno::makeAny(text::WrapTextMode_THROUGH)); + // Use At_Char anchor instead of As_Char anchoring: if (aValue.get<text::TextContentAnchorType>() - == text::TextContentAnchorType_AS_CHARACTER) + == text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER) { - uno::Reference<beans::XPropertySet> const xPropertySet( - SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), - uno::UNO_QUERY); - xPropertySet->setPropertyValue(UNO_NAME_SURROUND, - uno::makeAny(text::WrapTextMode_THROUGH)); - return; + xPropertySet->setPropertyValue( + UNO_NAME_ANCHOR_TYPE, + uno::makeAny( + text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER)); } - break; + else // Otherwise copy the anchor type of the shape + { + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); + } + // After anchoring the position must be set as well: + if (aValue.get<text::TextContentAnchorType>() + == text::TextContentAnchorType::TextContentAnchorType_AT_PAGE) + { + xPropertySet->setPropertyValue( + UNO_NAME_ANCHOR_PAGE_NO, + uno::makeAny(pShape->GetAnchor().GetPageNum())); + } + + return; + } + break; } break; case FN_TEXT_RANGE: |