summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/pagedesc.hxx6
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport10.cxx5
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport14.cxx3
-rw-r--r--sw/qa/extras/ooxmlimport/ooxmlimport.cxx6
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx4
-rw-r--r--sw/qa/uitest/data/TestHiddenHeadersFooters.docxbin0 -> 18063 bytes
-rw-r--r--sw/qa/uitest/writer_tests7/tdf141158.py47
-rw-r--r--sw/source/core/doc/docdesc.cxx30
-rw-r--r--sw/source/core/doc/docfmt.cxx11
-rw-r--r--sw/source/core/layout/pagedesc.cxx96
-rw-r--r--sw/source/core/unocore/unostyle.cxx32
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx24
12 files changed, 247 insertions, 17 deletions
diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx
index 0d29eb0ca6e3..4178361349d6 100644
--- a/sw/inc/pagedesc.hxx
+++ b/sw/inc/pagedesc.hxx
@@ -223,6 +223,12 @@ public:
/// Used to restore hidden header/footer formats.
const SwFrameFormat* GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const;
+ /// Checks if the pagedescriptor has a stashed format according to the parameters or not.
+ bool HasStashedFormat(bool bHeader, bool bLeft, bool bFirst);
+
+ /// Gives the feature of removing the stashed format by hand if it is neccessarry.
+ void RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst);
+
/// Same as WriteUseOn(), but the >= HeaderShare part of the bitfield is not modified.
inline void SetUseOn( UseOnPage eNew );
inline UseOnPage GetUseOn() const;
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index c33f99cb4322..ba6a6a6a98e2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -688,7 +688,9 @@ DECLARE_OOXMLEXPORT_TEST(testBnc875718, "bnc875718.docx")
// is not SwXBodyText but rather SwXHeadFootText
uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
- for( int i = 0;
+ // The sample bugdoc has 3 footer.xml and has a textframe in each. The first one is hidden
+ // and it has no text in its anchored text range: it is anchored to body text. Ignoring...
+ for( int i = 1;
i < xIndexAccess->getCount();
++i )
{
@@ -700,6 +702,7 @@ DECLARE_OOXMLEXPORT_TEST(testBnc875718, "bnc875718.docx")
// Also check that the footer contents are not in the body text.
uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XText> text = textDocument->getText();
+ CPPUNIT_ASSERT(text); //Do not crash on empty content
CPPUNIT_ASSERT_EQUAL( OUString( "Text" ), text->getString());
}
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
index cd3ca2f39e46..951a4d8650f2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
@@ -670,7 +670,8 @@ DECLARE_OOXMLEXPORT_TEST(testTdf130167_spilloverHeaderShape, "testTdf130167_spil
uno::Reference<container::XIndexAccess> xNameAccess(
xTextGraphicObjectsSupplier->getGraphicObjects(), uno::UNO_QUERY);
// graphics from discarded headers were being added to the text body. Reduced from 5 to 2 shapes overall.
- CPPUNIT_ASSERT(xNameAccess->getCount() < 4);
+ // CPPUNIT_ASSERT(xNameAccess->getCount() <= 4); -> What about hidden headers?
+ CPPUNIT_ASSERT_LESS(sal_Int32(6), xNameAccess->getCount());
}
DECLARE_OOXMLEXPORT_TEST(testTdf124986, "tdf124986.docx")
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index 216fb0de07c0..59a2688232c8 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -564,10 +564,10 @@ DECLARE_OOXMLIMPORT_TEST(testN779627, "n779627.docx")
sal_Int32(9), nLeftMargin);
/*
- * Another problem tested with this document is the unnecessary loading of the shapes
- * anchored to a discarded header or footer
+ * Another problem tested with this document is the loading of the shapes
+ * anchored to a hidden header or footer
*/
- CPPUNIT_ASSERT_EQUAL(0, getShapes());
+ CPPUNIT_ASSERT_EQUAL(2, getShapes());
}
DECLARE_OOXMLIMPORT_TEST(testN779627b, "n779627b.docx")
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index e47594a27b42..f56cf50d328d 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -5055,7 +5055,9 @@ void SwUiWriterTest::testTdf92648()
SwDoc* pDoc = createDoc("tdf92648.docx");
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
// Make sure we have ten draw shapes.
- CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage));
+ // Yes, we have if the left/right pages have different header/footer,
+ // but if not we have only nine of them:
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(9), SwTextBoxHelper::getCount(pPage));
// and the text boxes haven't got zero height
sal_Int32 nCount = 0;
for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats())
diff --git a/sw/qa/uitest/data/TestHiddenHeadersFooters.docx b/sw/qa/uitest/data/TestHiddenHeadersFooters.docx
new file mode 100644
index 000000000000..f33482a93ba1
--- /dev/null
+++ b/sw/qa/uitest/data/TestHiddenHeadersFooters.docx
Binary files differ
diff --git a/sw/qa/uitest/writer_tests7/tdf141158.py b/sw/qa/uitest/writer_tests7/tdf141158.py
new file mode 100644
index 000000000000..906035e37e89
--- /dev/null
+++ b/sw/qa/uitest/writer_tests7/tdf141158.py
@@ -0,0 +1,47 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+
+from uitest.framework import UITestCase
+from libreoffice.uno.propertyvalue import mkPropertyValues
+from uitest.uihelper.common import get_state_as_dict
+import importlib
+import pathlib
+import org.libreoffice.unotest
+from uitest.uihelper.common import select_pos
+import time
+
+def get_url_for_data_file(file_name):
+ return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri()
+
+
+class TestTdf141158(UITestCase):
+ def test_tdf141158(self):
+ # load the desired bugdoc
+ self.ui_test.load_file(get_url_for_data_file("TestHiddenHeadersFooters.docx"))
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+ xWriterEdit = xWriterDoc.getChild("writer_edit")
+ document = self.ui_test.get_component()
+ # open the page styles dialog and select the headers tab
+ self.xUITest.executeCommand(".uno:PageStyleName")
+ TemplateDialog8 = self.xUITest.getTopFocusWindow()
+ xTabs = TemplateDialog8.getChild("tabcontrol")
+ select_pos(xTabs, "4")
+ # make the same left right page header state to off and apply the setting
+ checkSameLR = TemplateDialog8.getChild("checkSameLR")
+ checkSameLR.executeAction("CLICK",tuple())
+ ok = TemplateDialog8.getChild("ok")
+ self.ui_test.close_dialog_through_button(ok)
+ time.sleep(1)
+ # go to the left header
+ xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "2"}))
+ self.xUITest.executeCommand(".uno:JumpToHeader")
+ # get the text of the header
+ xPageSytle = document.getStyleFamilies().getByIndex(2)
+ xHeaderText = xPageSytle.getByIndex(0).HeaderText.String
+ xHeaderLeftText = xPageSytle.getByIndex(0).HeaderTextLeft.String
+ # without the fix in place it was "Right Header" (lost hidden left header),
+ # with the fix it should pass...
+ self.assertEqual("Left Header", xHeaderLeftText)
+ time.sleep(1)
+ self.ui_test.close_doc()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx
index 8450691eea9c..561d828d839e 100644
--- a/sw/source/core/doc/docdesc.cxx
+++ b/sw/source/core/doc/docdesc.cxx
@@ -400,11 +400,11 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
const bool bStashLeftHead = !rDesc.IsHeaderShared() && rChged.IsHeaderShared();
const bool bStashFirstMasterHead = !rDesc.IsFirstShared() && rChged.IsFirstShared();
const bool bStashFirstLeftHead = (!rDesc.IsHeaderShared() && rChged.IsHeaderShared()) || (!rDesc.IsFirstShared() && rChged.IsFirstShared());
- if (bStashLeftHead && rLeftHead.GetRegisteredIn())
+ if (bStashLeftHead && rLeftHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, true, false))
rDesc.StashFrameFormat(rChged.GetLeft(), true, true, false);
- if (bStashFirstMasterHead && rFirstMasterHead.GetRegisteredIn())
+ if (bStashFirstMasterHead && rFirstMasterHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, false, true))
rDesc.StashFrameFormat(rChged.GetFirstMaster(), true, false, true);
- if (bStashFirstLeftHead && rFirstLeftHead.GetRegisteredIn())
+ if (bStashFirstLeftHead && rFirstLeftHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, true, true))
rDesc.StashFrameFormat(rChged.GetFirstLeft(), true, true, true);
// Stash footer formats as needed.
@@ -414,11 +414,11 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
const bool bStashLeftFoot = !rDesc.IsFooterShared() && rChged.IsFooterShared();
const bool bStashFirstMasterFoot = !rDesc.IsFirstShared() && rChged.IsFirstShared();
const bool bStashFirstLeftFoot = (!rDesc.IsFooterShared() && rChged.IsFooterShared()) || (!rDesc.IsFirstShared() && rChged.IsFirstShared());
- if (bStashLeftFoot && rLeftFoot.GetRegisteredIn())
+ if (bStashLeftFoot && rLeftFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, true, false))
rDesc.StashFrameFormat(rChged.GetLeft(), false, true, false);
- if (bStashFirstMasterFoot && rFirstMasterFoot.GetRegisteredIn())
+ if (bStashFirstMasterFoot && rFirstMasterFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, false, true))
rDesc.StashFrameFormat(rChged.GetFirstMaster(), false, false, true);
- if (bStashFirstLeftFoot && rFirstLeftFoot.GetRegisteredIn())
+ if (bStashFirstLeftFoot && rFirstLeftFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, true, true))
rDesc.StashFrameFormat(rChged.GetFirstLeft(), false, true, true);
GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoPageDesc>(rDesc, rChged, this));
@@ -474,6 +474,15 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
CopyMasterHeader(rChged, pStashedFirstMasterFormat ? pStashedFirstMasterFormat->GetHeader() : rMasterHead, rDesc, false, true); // Copy first master
CopyMasterHeader(rChged, pStashedFirstLeftFormat ? pStashedFirstLeftFormat->GetHeader() : rMasterHead, rDesc, true, true); // Copy first left
+ if (pStashedLeftFormat)
+ rDesc.RemoveStashedFormat(true, true, false);
+
+ if (pStashedFirstMasterFormat)
+ rDesc.RemoveStashedFormat(true, false, true);
+
+ if (pStashedFirstLeftFormat)
+ rDesc.RemoveStashedFormat(true, true, true);
+
rDesc.ChgHeaderShare( rChged.IsHeaderShared() );
// Synch Footer.
@@ -489,6 +498,15 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
CopyMasterFooter(rChged, pStashedFirstMasterFoot ? pStashedFirstMasterFoot->GetFooter() : rMasterFoot, rDesc, false, true); // Copy first master
CopyMasterFooter(rChged, pStashedFirstLeftFoot ? pStashedFirstLeftFoot->GetFooter() : rMasterFoot, rDesc, true, true); // Copy first left
+ if (pStashedLeftFormat)
+ rDesc.RemoveStashedFormat(false, true, false);
+
+ if (pStashedFirstMasterFoot)
+ rDesc.RemoveStashedFormat(false, false, true);
+
+ if (pStashedFirstLeftFoot)
+ rDesc.RemoveStashedFormat(false, true, true);
+
rDesc.ChgFooterShare( rChged.IsFooterShared() );
// there is just one first shared flag for both header and footer?
rDesc.ChgFirstShare( rChged.IsFirstShared() );
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index a552585df6ab..77df6303c053 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -1523,6 +1523,17 @@ void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
rDstDesc.GetFirstMaster().CallSwClientNotify(aHint);
rDstDesc.GetFirstLeft().CallSwClientNotify(aHint);
}
+
+ // Copy the stashed formats as well between the page descriptors...
+ for (bool bFirst : { true, false })
+ for (bool bLeft : { true, false })
+ for (bool bHeader : { true, false })
+ {
+ if (!bLeft && !bFirst)
+ continue;
+ if (auto pStashedFormat = rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst))
+ rDstDesc.StashFrameFormat(*pStashedFormat, bHeader, bLeft, bFirst);
+ }
}
void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles )
diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx
index 8b8b5282abbf..c5c9c31ab7b9 100644
--- a/sw/source/core/layout/pagedesc.cxx
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -436,7 +436,9 @@ void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bo
}
else
{
- SAL_WARN("sw", "Stashing the right page header/footer is pointless.");
+ SAL_WARN(
+ "sw",
+ "SwPageDesc::StashFrameFormat: Stashing the right page header/footer is pointless.");
}
}
@@ -459,17 +461,101 @@ const SwFrameFormat* SwPageDesc::GetStashedFrameFormat(bool bHeader, bool bLeft,
if (pFormat)
{
- const SwFrameFormat* retVal = pFormat->get();
- pFormat->reset();
- return retVal;
+ return pFormat->get();
}
else
{
- SAL_WARN("sw", "Right page format is never stashed.");
+ SAL_WARN("sw", "SwPageDesc::GetStashedFrameFormat: Right page format is never stashed.");
return nullptr;
}
}
+bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst)
+{
+ if (bHeader)
+ {
+ if (bLeft && !bFirst)
+ {
+ return m_aStashedHeader.m_pStashedLeft != nullptr;
+ }
+ else if (!bLeft && bFirst)
+ {
+ return m_aStashedHeader.m_pStashedFirst != nullptr;
+ }
+ else if (bLeft && bFirst)
+ {
+ return m_aStashedHeader.m_pStashedFirstLeft != nullptr;
+ }
+ else
+ {
+ SAL_WARN("sw", "SwPageDesc::HasStashedFormat: Right page format is never stashed.");
+ return false;
+ }
+ }
+ else
+ {
+ if (bLeft && !bFirst)
+ {
+ return m_aStashedFooter.m_pStashedLeft != nullptr;
+ }
+ else if (!bLeft && bFirst)
+ {
+ return m_aStashedFooter.m_pStashedFirst != nullptr;
+ }
+ else if (bLeft && bFirst)
+ {
+ return m_aStashedFooter.m_pStashedFirstLeft != nullptr;
+ }
+ else
+ {
+ SAL_WARN("sw", "SwPageDesc::HasStashedFormat: Right page format is never stashed.");
+ return false;
+ }
+ }
+}
+
+void SwPageDesc::RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst)
+{
+ if (bHeader)
+ {
+ if (bLeft && !bFirst)
+ {
+ m_aStashedHeader.m_pStashedLeft.reset();
+ }
+ else if (!bLeft && bFirst)
+ {
+ m_aStashedHeader.m_pStashedFirst.reset();
+ }
+ else if (bLeft && bFirst)
+ {
+ m_aStashedHeader.m_pStashedFirstLeft.reset();
+ }
+ else
+ {
+ SAL_WARN("sw", "SwPageDesc::RemoveStashedFormat: Right page format is never stashed.");
+ }
+ }
+ else
+ {
+ if (bLeft && !bFirst)
+ {
+ m_aStashedFooter.m_pStashedLeft.reset();
+ }
+ else if (!bLeft && bFirst)
+ {
+ m_aStashedFooter.m_pStashedFirst.reset();
+ }
+ else if (bLeft && bFirst)
+ {
+ m_aStashedFooter.m_pStashedFirstLeft.reset();
+ }
+ else
+ {
+ SAL_WARN("sw", "SwPageDesc::RemoveStashedFormat: Right page format is never stashed.");
+ }
+ }
+}
+
// Page styles
static const char* STR_POOLPAGE[] =
{
diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx
index 9b3dc09f8e7a..a695cfdafa47 100644
--- a/sw/source/core/unocore/unostyle.cxx
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -3300,6 +3300,38 @@ void SwXPageStyle::setPropertyValue(const OUString& rPropertyName, const uno::An
SolarMutexGuard aGuard;
const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
const uno::Sequence<uno::Any> aValues(&rValue, 1);
+
+ // Trick: if the Domain Mapper changes the props of shared header/footer,
+ // store the old ones in time for later use.
+ const bool bIsHeader = rPropertyName == UNO_NAME_HEADER_IS_SHARED;
+ const bool bIsFooter = rPropertyName == UNO_NAME_FOOTER_IS_SHARED;
+ if ((bIsFooter || bIsHeader) && rValue == uno::Any(true))
+ {
+ // Find the matching page descriptor
+ for (size_t i = 0; i < GetDoc()->GetPageDescCnt(); i++)
+ {
+ auto pPageDesc = &GetDoc()->GetPageDesc(i);
+ // If we have the right page descriptor stash the neccessary formats in import time.
+ if (pPageDesc->GetName() == GetStyleName())
+ {
+ auto pLeftHeader = pPageDesc->GetLeft().GetHeader().GetHeaderFormat();
+ if (bIsHeader && pLeftHeader)
+ {
+ pPageDesc->StashFrameFormat(pPageDesc->GetLeft(), true, true, false);
+ pPageDesc->StashFrameFormat(pPageDesc->GetFirstMaster(), true, false, true);
+ pPageDesc->StashFrameFormat(pPageDesc->GetFirstLeft(), true, true, true);
+ }
+ auto pLeftFooter = pPageDesc->GetLeft().GetFooter().GetFooterFormat();
+ if (bIsFooter && pLeftFooter)
+ {
+ pPageDesc->StashFrameFormat(pPageDesc->GetLeft(), false, true, false);
+ pPageDesc->StashFrameFormat(pPageDesc->GetFirstMaster(), false, false, true);
+ pPageDesc->StashFrameFormat(pPageDesc->GetFirstLeft(), false, true, true);
+ }
+ }
+ }
+ }
+ // And set the props... as we did it before.
SetPropertyValues_Impl(aProperties, aValues);
}
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index d83ed06526f8..44ab9fdf3b36 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -2587,6 +2587,30 @@ void DomainMapper_Impl::PushPageHeaderFooter(bool bHeader, SectionPropertyMap::P
: xText->createTextCursorByRange(xText->getStart())));
m_bDiscardHeaderFooter = false; // set only on success!
}
+ // If we have *hidden* header footer
+ else if (bLeft && !GetSettingsTable()->GetEvenAndOddHeaders())
+ {
+ bool bIsShared;
+ // Turn on the headers
+ xPageStyle->setPropertyValue(getPropertyName(ePropIsOn), uno::makeAny(true));
+ // Store the state of the previous state of shared prop
+ xPageStyle->getPropertyValue(getPropertyName(ePropShared)) >>= bIsShared;
+ // Turn on the shared prop in order to save the headers/footers in time
+ xPageStyle->setPropertyValue(getPropertyName(ePropShared), uno::makeAny(false));
+ // Add the content of the headers footers to the doc
+ uno::Reference<text::XText> xText;
+ xPageStyle->getPropertyValue(getPropertyName(bLeft ? ePropTextLeft : ePropText))
+ >>= xText;
+
+ m_aTextAppendStack.push(
+ TextAppendContext(uno::Reference<text::XTextAppend>(xText, uno::UNO_QUERY_THROW),
+ m_bIsNewDoc ? uno::Reference<text::XTextCursor>()
+ : xText->createTextCursorByRange(xText->getStart())));
+ m_bDiscardHeaderFooter = false; // set only on success!
+ // Restore the original state of the shared prop after we stored the neccessary values.
+ xPageStyle->setPropertyValue(getPropertyName(ePropShared), uno::makeAny(bIsShared));
+ }
+
}
catch( const uno::Exception& )
{