diff options
author | Attila Szűcs <szucs.attila3@nisz.hu> | 2021-07-27 11:45:58 +0200 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2021-09-06 23:54:47 +0200 |
commit | 7ec91bcb7d248c38522375c31f2b6f640b1b84e2 (patch) | |
tree | a78269db9ba5bbfdfb4916092dbd4b5069df7f91 | |
parent | Adapt solenv/flatpak-manifest.in to recent download.lst changes (diff) | |
download | core-7ec91bcb7d248c38522375c31f2b6f640b1b84e2.tar.gz core-7ec91bcb7d248c38522375c31f2b6f640b1b84e2.zip |
tdf#143384 DOCX import: fix SAXException at header with table
Regression from commit d656191ec308d4280b93c7169372e543a255d108
"tdf#119952 DOCX import: fix negative page margins".
Add SwXHeadFootText::CreateTextCursor(bool bIgnoreTables = false)
(modeled after SwXBodyText::CreateTextCursor) to create text cursor
for copying the header/footer also started with table during
fly frame creation in convertoToTextFrame().
Note: add hidden property PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF
to use the new feature in domainmapper (followed
commit af4e5ee0f93c1ff442d08caed5c875f2b2c1fd43
"tdf#97128 DOCX import: fix frame direction").
Co-authored-by: Tibor Nagy (NISZ)
Change-Id: I96e2cf2dddcecd146c53c12d7fdb44fc4d90fa0d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119549
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit c1ad429d925855c1baacbdeca1ef42f4486eb9c2)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120985
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r-- | sw/inc/unotextbodyhf.hxx | 2 | ||||
-rw-r--r-- | sw/inc/unotextrange.hxx | 3 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx | bin | 0 -> 58566 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport11.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/unocore/unoframe.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/unocore/unoobj2.cxx | 15 | ||||
-rw-r--r-- | sw/source/core/unocore/unotext.cxx | 56 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyIds.cxx | 1 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyIds.hxx | 1 |
10 files changed, 83 insertions, 18 deletions
diff --git a/sw/inc/unotextbodyhf.hxx b/sw/inc/unotextbodyhf.hxx index fbccc982ef04..99887c6beb5c 100644 --- a/sw/inc/unotextbodyhf.hxx +++ b/sw/inc/unotextbodyhf.hxx @@ -115,6 +115,8 @@ public: static css::uno::Reference< css::text::XText > CreateXHeadFootText(SwFrameFormat & rHeadFootFormat, const bool bIsHeader); + css::uno::Reference<css::text::XTextCursor> CreateTextCursor(const bool bIgnoreTables = false); + // XInterface virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType) override; diff --git a/sw/inc/unotextrange.hxx b/sw/inc/unotextrange.hxx index f3ed06fb4a06..4d8ed2df2c06 100644 --- a/sw/inc/unotextrange.hxx +++ b/sw/inc/unotextrange.hxx @@ -57,7 +57,8 @@ namespace sw { enum class TextRangeMode { RequireTextNode, - AllowNonTextNode + AllowNonTextNode, + AllowTableNode }; void DeepCopyPaM(SwPaM const & rSource, SwPaM & rTarget); diff --git a/sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx b/sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx Binary files differnew file mode 100644 index 000000000000..918c1029fb4a --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx index 431d5d71753d..17f05d1dcd16 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx @@ -1599,6 +1599,13 @@ DECLARE_OOXMLEXPORT_TEST(testTdf119952_negativeMargins, "tdf119952_negativeMargi CPPUNIT_ASSERT_EQUAL(OUString(" aaaa bbbb cccc dddd eeee"), parseDump("/root/page[3]/header/txt/anchored/fly")); } +DECLARE_OOXMLEXPORT_TEST(testTdf143384_tableInFoot_negativeMargins, "tdf143384_tableInFoot_negativeMargins.docx") +{ + // There should be no crash during loading of the document + // so, let's check just how much pages we have + CPPUNIT_ASSERT_EQUAL(1, getPages()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index a430d92f5b7f..8fd930322a38 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -1417,7 +1417,13 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& const ::SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName(rPropertyName); if (!pEntry) - throw beans::UnknownPropertyException( "Unknown property: " + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) ); + { + // Hack to skip the dummy CursorNotIgnoreTables property + if (rPropertyName == "CursorNotIgnoreTables") + return; + else + throw beans::UnknownPropertyException("Unknown property: " + rPropertyName, static_cast <cppu::OWeakObject*> (this)); + } const sal_uInt8 nMemberId(pEntry->nMemberId); uno::Any aValue(_rValue); diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx index 2103220de62b..e99450378bac 100644 --- a/sw/source/core/unocore/unoobj2.cxx +++ b/sw/source/core/unocore/unoobj2.cxx @@ -1116,6 +1116,7 @@ bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill, SwXTextPortion* pPortion = nullptr; SwXText* pText = nullptr; SwXParagraph* pPara = nullptr; + SwXHeadFootText* pHeadText = nullptr; if(xRangeTunnel.is()) { pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel); @@ -1125,12 +1126,26 @@ bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill, ::sw::UnoTunnelGetImplementation<SwXTextPortion>(xRangeTunnel); pText = ::sw::UnoTunnelGetImplementation<SwXText>(xRangeTunnel); pPara = ::sw::UnoTunnelGetImplementation<SwXParagraph>(xRangeTunnel); + if (eMode == TextRangeMode::AllowTableNode) + pHeadText = dynamic_cast<SwXHeadFootText*>(pText); } // if it's a text then create a temporary cursor there and re-use // the pCursor variable // #i108489#: Reference in outside scope to keep cursor alive uno::Reference< text::XTextCursor > xTextCursor; + if (pHeadText) + { + // if it is a header / footer text, and eMode == TextRangeMode::AllowTableNode + // then set the cursor to the beginning of the text + // if it is started with a table then set into the table + xTextCursor.set(pHeadText->CreateTextCursor(true)); + xTextCursor->gotoEnd(true); + pCursor = + comphelper::getUnoTunnelImplementation<OTextCursorHelper>(xTextCursor); + pCursor->GetPaM()->Normalize(); + } + else if (pText) { xTextCursor.set( pText->CreateCursor() ); diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx index 7e0c73d8c778..fa779d95abd8 100644 --- a/sw/source/core/unocore/unotext.cxx +++ b/sw/source/core/unocore/unotext.cxx @@ -1537,14 +1537,31 @@ SwXText::convertToTextFrame( { throw uno::RuntimeException(); } + // tdf#143384 recognize dummy property, that was set to make createTextCursor + // to not ignore tables. + // It is enough to use this hack only for the range start, + // because as far as I know, the range cannot end with table when this property is set. + ::sw::TextRangeMode eMode = ::sw::TextRangeMode::RequireTextNode; + for (const auto& rCellProperty : rFrameProperties) + { + if (rCellProperty.Name == "CursorNotIgnoreTables") + { + bool bAllowNonTextNode = false; + rCellProperty.Value >>= bAllowNonTextNode; + if (bAllowNonTextNode) + eMode = ::sw::TextRangeMode::AllowTableNode; + break; + } + } uno::Reference< text::XTextContent > xRet; std::optional<SwUnoInternalPaM> pTempStartPam(*GetDoc()); std::optional<SwUnoInternalPaM> pEndPam(*GetDoc()); - if (!::sw::XTextRangeToSwPaM(*pTempStartPam, xStart) || - !::sw::XTextRangeToSwPaM(*pEndPam, xEnd)) + if (!::sw::XTextRangeToSwPaM(*pTempStartPam, xStart, eMode) + || !::sw::XTextRangeToSwPaM(*pEndPam, xEnd)) { throw lang::IllegalArgumentException(); } + auto pStartPam(GetDoc()->CreateUnoCursor(*pTempStartPam->GetPoint())); if (pTempStartPam->HasMark()) { @@ -2613,8 +2630,7 @@ uno::Any SAL_CALL SwXHeadFootText::queryInterface(const uno::Type& rType) : ret; } -uno::Reference<text::XTextCursor> SAL_CALL -SwXHeadFootText::createTextCursor() +uno::Reference<text::XTextCursor> SwXHeadFootText::CreateTextCursor(const bool bIgnoreTables) { SolarMutexGuard aGuard; @@ -2632,18 +2648,22 @@ SwXHeadFootText::createTextCursor() // after the table - otherwise the cursor would be in the body text! SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType( (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode); - // is there a table here? - SwTableNode* pTableNode = rUnoCursor.GetNode().FindTableNode(); - SwContentNode* pCont = nullptr; - while (pTableNode) - { - rUnoCursor.GetPoint()->nNode = *pTableNode->EndOfSectionNode(); - pCont = GetDoc()->GetNodes().GoNext(&rUnoCursor.GetPoint()->nNode); - pTableNode = pCont->FindTableNode(); - } - if (pCont) + + if (!bIgnoreTables) { - rUnoCursor.GetPoint()->nContent.Assign(pCont, 0); + // is there a table here? + SwTableNode* pTableNode = rUnoCursor.GetNode().FindTableNode(); + SwContentNode* pCont = nullptr; + while (pTableNode) + { + rUnoCursor.GetPoint()->nNode = *pTableNode->EndOfSectionNode(); + pCont = GetDoc()->GetNodes().GoNext(&rUnoCursor.GetPoint()->nNode); + pTableNode = pCont->FindTableNode(); + } + if (pCont) + { + rUnoCursor.GetPoint()->nContent.Assign(pCont, 0); + } } SwStartNode const*const pNewStartNode = rUnoCursor.GetNode().FindSttNodeByType( (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode); @@ -2656,6 +2676,12 @@ SwXHeadFootText::createTextCursor() return static_cast<text::XWordCursor*>(pXCursor.get()); } +uno::Reference<text::XTextCursor> SAL_CALL +SwXHeadFootText::createTextCursor() +{ + return CreateTextCursor(false); +} + uno::Reference<text::XTextCursor> SAL_CALL SwXHeadFootText::createTextCursorByRange( const uno::Reference<text::XTextRange>& xTextPosition) { diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index b175e3752b70..f4a1f81cbdc3 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -2677,6 +2677,12 @@ void DomainMapper_Impl::ConvertHeaderFooterToTextFrame(bool bDynamicHeightTop, b aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_OPAQUE), false)); aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_WIDTH_TYPE), text::SizeType::MIN)); aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_SIZE_TYPE), text::SizeType::MIN)); + // tdf#143384 If the header/footer started with a table, convertToTextFrame could not + // convert the table, because it used createTextCursor() -which ignore tables- + // to set the conversion range. + // This dummy property is set to make convertToTextFrame to use an other CreateTextCursor + // method that can be parameterized to not ignore tables. + aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF), true)); fillEmptyFrameProperties(aFrameProperties, false); @@ -2686,7 +2692,7 @@ void DomainMapper_Impl::ConvertHeaderFooterToTextFrame(bool bDynamicHeightTop, b uno::Reference<text::XTextAppendAndConvert> xBodyText( xRangeStart->getText(), uno::UNO_QUERY); - xBodyText->convertToTextFrame(xRangeStart, xRangeEnd, + xBodyText->convertToTextFrame(xTextAppend, xRangeEnd, comphelper::containerToSequence(aFrameProperties)); } m_aHeaderFooterTextAppendStack.pop(); diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx index 0100313bdf45..ebf6e9b7dcf5 100644 --- a/writerfilter/source/dmapper/PropertyIds.cxx +++ b/writerfilter/source/dmapper/PropertyIds.cxx @@ -363,6 +363,7 @@ OUString getPropertyName( PropertyIds eId ) case PROP_RTL_GUTTER: sName = "RtlGutter"; break; + case PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF: sName = "CursorNotIgnoreTables"; break; } assert(sName.getLength()>0); return sName; diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx index a6afe0c5313f..cbadf04056e3 100644 --- a/writerfilter/source/dmapper/PropertyIds.hxx +++ b/writerfilter/source/dmapper/PropertyIds.hxx @@ -360,6 +360,7 @@ enum PropertyIds ,PROP_CELL_FORMULA_CONVERTED ,PROP_GUTTER_MARGIN ,PROP_RTL_GUTTER + ,PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF }; //Returns the UNO string equivalent to eId. |