summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2019-12-16 12:58:46 +0100
committerMiklos Vajna <vmiklos@collabora.com>2020-01-16 18:07:52 +0100
commit4f7677f39fd079badc9ce788e693cc1eb27d0817 (patch)
tree0a64d7d817fb8975c9ff33ef259c6dcd1664ae4d
parent2a380ac6c8e30d7e96a84482ce5935ddf7014dfc (diff)
tdf#112202 writerfilter,sw: fix loss of headers
There are several problems here: * CloseSectionGroup() is not only called for actual sections in the document but also at the end of every special text like comment, footnote, etc; only actual sections can set page styles. Writer comments use editengine so cannot even contain sections. * With continous section breaks, headers and footers are inherited from the previous section unless defined by the current section; SwXText::copyText() did not copy the content of the header on page 4 to page 5 correctly because it used an SwXTextCursor to create the selection, which cannot select the table at the start of the header. * For continuous section breaks, WW8 import filter has a heuristic to find the first page break in the section and set the PageDescName property on that node to apply the page style with the headers of the new section; do something similar in writerfilter SectionPropertyMap::CloseSectionGroup() Change-Id: I3ebe3d299f83197cbf8f10de46c34de98677626c Reviewed-on: https://gerrit.libreoffice.org/85213 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@cib.de> (cherry picked from commit 08f13ab85b5c65b5dc8adfa15918fb3e426fcc3c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86911 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport8.cxx12
-rw-r--r--sw/source/core/unocore/unotext.cxx36
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx5
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx5
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx52
5 files changed, 101 insertions, 9 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index 5c36cf7421d3..d389f3cd890a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -572,7 +572,17 @@ DECLARE_OOXMLEXPORT_TEST(testN780843, "n780843.docx")
{
uno::Reference< text::XTextRange > xPara = getParagraph(1);
OUString aStyleName = getProperty<OUString>(xPara, "PageStyleName");
- CPPUNIT_ASSERT_EQUAL(OUString("First Page"), aStyleName);
+ // what happens on export here is that the "Default Style" isn't actually
+ // used on page 2, because of the hard page break with style "Converted2"
+ // and therefore SwPageDesc::IsFollowNextPageOfNode() returns false and
+ // "w:titlepg" element is not written
+ // (the export result is wrong with or without w:titlepg, because the footer
+ // on the 2nd page should be the text "shown footer")
+ if (mbExported)
+ CPPUNIT_ASSERT_EQUAL(OUString("Standard"), aStyleName);
+ else
+ CPPUNIT_ASSERT_EQUAL(OUString("First Page"), aStyleName);
+
//tdf64372 this document should only have one page break (2 pages, not 3)
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx
index 0657f7bc361d..2a84d8655a46 100644
--- a/sw/source/core/unocore/unotext.cxx
+++ b/sw/source/core/unocore/unotext.cxx
@@ -2218,6 +2218,12 @@ SwXText::copyText(
{
SolarMutexGuard aGuard;
+ uno::Reference<lang::XUnoTunnel> const xSourceTunnel(xSource,
+ uno::UNO_QUERY);
+ SwXText const*const pSource( xSourceTunnel.is()
+ ? ::sw::UnoTunnelGetImplementation<SwXText>(xSourceTunnel)
+ : nullptr);
+
uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
uno::Reference< text::XTextCursor > const xCursor =
xText->createTextCursor();
@@ -2235,7 +2241,35 @@ SwXText::copyText(
SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
SwPosition rPos( rNdIndex );
- m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange( *pCursor->GetPaM(), rPos, /*bCopyAll=*/false, /*bCheckPos=*/true );
+ // tdf#112202 need SwXText because cursor cannot select table at the start
+ if (pSource)
+ {
+ SwTextNode * pFirstNode;
+ {
+ SwPaM temp(*pSource->GetStartNode(), *pSource->GetStartNode()->EndOfSectionNode(), +1, -1);
+ pFirstNode = temp.GetMark()->nNode.GetNode().GetTextNode();
+ if (pFirstNode)
+ {
+ pFirstNode->MakeStartIndex(&temp.GetMark()->nContent);
+ }
+ if (SwTextNode *const pNode = temp.GetPoint()->nNode.GetNode().GetTextNode())
+ {
+ pNode->MakeEndIndex(&temp.GetPoint()->nContent);
+ }
+ m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, /*bCopyAll=*/false, /*bCheckPos=*/true);
+ }
+ if (!pFirstNode)
+ { // the node at rPos was split; get rid of the first empty one so
+ // that the pasted table is first
+ auto pDelCursor(m_pImpl->m_pDoc->CreateUnoCursor(SwPosition(SwNodeIndex(*GetStartNode(), 1))));
+ m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pDelCursor);
+ }
+ }
+ else
+ {
+ m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(*pCursor->GetPaM(), rPos, /*bCopyAll=*/false, /*bCheckPos=*/true);
+ }
+
}
SwXBodyText::SwXBodyText(SwDoc *const pDoc)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 8356ecb8e8ee..04432a9cb63e 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -589,7 +589,10 @@ void DomainMapper_Impl::PopProperties(ContextType eId)
if ( eId == CONTEXT_SECTION )
{
- m_pLastSectionContext = m_aPropertyStacks[eId].top( );
+ if (m_aPropertyStacks[eId].size() == 1) // tdf#112202 only top level !!!
+ {
+ m_pLastSectionContext = m_aPropertyStacks[eId].top();
+ }
}
else if (eId == CONTEXT_CHARACTER)
{
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 585241301a26..5d1ed1c4b7cf 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -908,6 +908,11 @@ public:
void SetIsOutsideAParagraph(bool bval) { m_bIsOutsideAParagraph = bval;}
void ApplySettingsTable();
+
+ css::uno::Reference<css::text::XTextAppend> GetCurrentXText() {
+ return m_aTextAppendStack.empty() ? nullptr : m_aTextAppendStack.top().xTextAppend;
+ }
+
SectionPropertyMap * GetSectionContext();
/// If the current paragraph has a numbering style associated, this method returns its character style (part of the numbering rules)
css::uno::Reference<css::beans::XPropertySet> GetCurrentNumberingCharStyle();
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 39e8488a8a34..7e63ef0de9db 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1351,12 +1351,13 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
}
catch ( const uno::Exception& )
{
- OSL_FAIL( "Exception in SectionPropertyMap::CloseSectionGroup" );
+ DBG_UNHANDLED_EXCEPTION("writerfilter.dmapper", "Exception in SectionPropertyMap::CloseSectionGroup");
}
}
}
- if ( m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous) )
+ if (m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous)
+ && !rDM_Impl.IsInComments())
{
//todo: insert a section or access the already inserted section
uno::Reference< beans::XPropertySet > xSection =
@@ -1375,7 +1376,43 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
OUString aName = m_bTitlePage ? m_sFirstPageStyleName : m_sFollowPageStyleName;
uno::Reference< beans::XPropertySet > xRangeProperties( lcl_GetRangeProperties( m_bIsFirstSection, rDM_Impl, m_xStartingRange ) );
if ( m_bIsFirstSection && !aName.isEmpty() && xRangeProperties.is() )
+ {
xRangeProperties->setPropertyValue( getPropertyName( PROP_PAGE_DESC_NAME ), uno::makeAny( aName ) );
+ }
+ else if ((!m_bFirstPageHeaderLinkToPrevious ||
+ !m_bFirstPageFooterLinkToPrevious ||
+ !m_bDefaultHeaderLinkToPrevious ||
+ !m_bDefaultFooterLinkToPrevious ||
+ !m_bEvenPageHeaderLinkToPrevious ||
+ !m_bEvenPageFooterLinkToPrevious)
+ && rDM_Impl.GetCurrentXText())
+ { // find a node in the section that has a page break and change
+ // it to apply the page style; see "nightmare scenario" in
+ // wwSectionManager::InsertSegments()
+ auto xTextAppend = rDM_Impl.GetCurrentXText();
+ uno::Reference<container::XEnumerationAccess> const xCursor(
+ xTextAppend->createTextCursorByRange(
+ uno::Reference<text::XTextContent>(xSection, uno::UNO_QUERY_THROW)->getAnchor()),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumeration> const xEnum(
+ xCursor->createEnumeration());
+ while (xEnum->hasMoreElements())
+ {
+ uno::Reference<beans::XPropertySet> xElem;
+ xEnum->nextElement() >>= xElem;
+ if (xElem->getPropertySetInfo()->hasPropertyByName("BreakType"))
+ {
+ style::BreakType bt;
+ if ((xElem->getPropertyValue("BreakType") >>= bt)
+ && bt == style::BreakType_PAGE_BEFORE)
+ {
+ xElem->setPropertyValue(getPropertyName(PROP_PAGE_DESC_NAME),
+ uno::makeAny(aName));
+ break;
+ }
+ }
+ }
+ }
}
catch ( const uno::Exception& )
{
@@ -1385,7 +1422,8 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
// If the section is of type "New column" (0x01), then simply insert a column break.
// But only if there actually are columns on the page, otherwise a column break
// seems to be handled like a page break by MSO.
- else if ( m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_nextColumn) && m_nColumnCount > 0 )
+ else if (m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_nextColumn)
+ && 0 < m_nColumnCount && !rDM_Impl.IsInComments())
{
try
{
@@ -1404,7 +1442,7 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
}
catch ( const uno::Exception& ) {}
}
- else
+ else if (!rDM_Impl.IsInComments())
{
uno::Reference< beans::XPropertySet > xSection;
ApplyProtectionProperties( xSection, rDM_Impl );
@@ -1515,7 +1553,7 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
}
catch ( const uno::Exception& )
{
- OSL_ENSURE( false, "Exception in SectionPropertyMap::CloseSectionGroup" );
+ DBG_UNHANDLED_EXCEPTION("writerfilter.dmapper", "Exception in SectionPropertyMap::CloseSectionGroup");
}
Insert( PROP_GRID_BASE_HEIGHT, uno::makeAny( nGridLinePitch ) );
@@ -1590,11 +1628,13 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
{
// Avoid setting page style in case of autotext: so inserting the autotext at the
// end of the document does not introduce an unwanted page break.
- if (!rDM_Impl.IsReadGlossaries())
+ if (!rDM_Impl.IsReadGlossaries() && !rDM_Impl.IsInFootOrEndnote())
+ {
xRangeProperties->setPropertyValue(
getPropertyName( PROP_PAGE_DESC_NAME ),
uno::makeAny( m_bTitlePage ? m_sFirstPageStyleName
: m_sFollowPageStyleName ) );
+ }
if (0 <= m_nPageNumber)
{