[Libreoffice-commits] core.git: sw/inc sw/qa sw/source writerfilter/source
Attila Szűcs (via logerrit)
logerrit at kemper.freedesktop.org
Wed Aug 25 11:45:59 UTC 2021
sw/inc/unotextbodyhf.hxx | 2
sw/inc/unotextrange.hxx | 3
sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx |binary
sw/qa/extras/ooxmlexport/ooxmlexport11.cxx | 7 +
sw/source/core/unocore/unoframe.cxx | 8 +
sw/source/core/unocore/unoobj2.cxx | 15 ++
sw/source/core/unocore/unotext.cxx | 56 +++++++---
writerfilter/source/dmapper/DomainMapper_Impl.cxx | 8 +
writerfilter/source/dmapper/PropertyIds.cxx | 1
writerfilter/source/dmapper/PropertyIds.hxx | 1
10 files changed, 83 insertions(+), 18 deletions(-)
New commits:
commit c1ad429d925855c1baacbdeca1ef42f4486eb9c2
Author: Attila Szűcs <szucs.attila3 at nisz.hu>
AuthorDate: Tue Jul 27 11:45:58 2021 +0200
Commit: László Németh <nemeth at numbertext.org>
CommitDate: Wed Aug 25 13:45:23 2021 +0200
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 at numbertext.org>
Reviewed-by: László Németh <nemeth at numbertext.org>
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
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf143384_tableInFoot_negativeMargins.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index de3eea4c0659..08e0cbd9f8f7 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -1618,6 +1618,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 74d366d9961d..8b9250671d78 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1418,7 +1418,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 8fffee9d32e4..c6c423ea6517 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -2742,6 +2742,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);
@@ -2751,7 +2757,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 c3e7cbaa2de9..00d5b795b132 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -364,6 +364,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 f1bef16da581..8e23533c57ba 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -361,6 +361,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.
More information about the Libreoffice-commits
mailing list