summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAttila Szűcs <szucs.attila3@nisz.hu>2021-07-27 11:45:58 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2021-09-06 23:54:47 +0200
commit7ec91bcb7d248c38522375c31f2b6f640b1b84e2 (patch)
treea78269db9ba5bbfdfb4916092dbd4b5069df7f91
parentAdapt solenv/flatpak-manifest.in to recent download.lst changes (diff)
downloadcore-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.hxx2
-rw-r--r--sw/inc/unotextrange.hxx3
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docxbin0 -> 58566 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport11.cxx7
-rw-r--r--sw/source/core/unocore/unoframe.cxx8
-rw-r--r--sw/source/core/unocore/unoobj2.cxx15
-rw-r--r--sw/source/core/unocore/unotext.cxx56
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx8
-rw-r--r--writerfilter/source/dmapper/PropertyIds.cxx1
-rw-r--r--writerfilter/source/dmapper/PropertyIds.hxx1
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
new file mode 100644
index 000000000000..918c1029fb4a
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx
Binary files differ
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.