[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

Daniel Arato (NISZ) (via logerrit) logerrit at kemper.freedesktop.org
Tue Mar 2 10:11:32 UTC 2021


 sw/inc/pagedesc.hxx                     |   17 +++++
 sw/qa/uitest/data/tdf140117.fodt        |   95 ++++++++++++++++++++++++++++++++
 sw/qa/uitest/writer_tests7/tdf140117.py |   70 +++++++++++++++++++++++
 sw/source/core/doc/docdesc.cxx          |   70 ++++++++++++++++++-----
 sw/source/core/layout/pagedesc.cxx      |   73 ++++++++++++++++++++++++
 5 files changed, 311 insertions(+), 14 deletions(-)

New commits:
commit f5dc6b11d2218d94c9effe7a1ab418d0133da5e3
Author:     Daniel Arato (NISZ) <arato.daniel at nisz.hu>
AuthorDate: Tue Jan 26 13:11:42 2021 +0100
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Tue Mar 2 11:10:29 2021 +0100

    tdf#140117 sw UI: keep headers/footers when inactive
    
    Custom left page and first headers (and footers) used to disappear
    forever if hidden temporarily by checking the "Same content on left
    and right pages" or "Same content on first page" options, respectively.
    This commit stashes the endangered headers (footers) in SwPageDesc
    and restores them on demand.
    
    Change-Id: I1f6b605e2bd19af18726de1b825721487d29b4eb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110398
    Tested-by: Jenkins
    Reviewed-by: László Németh <nemeth at numbertext.org>

diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx
index 7f2eaa9c9d53..0d29eb0ca6e3 100644
--- a/sw/inc/pagedesc.hxx
+++ b/sw/inc/pagedesc.hxx
@@ -148,6 +148,17 @@ class SW_DLLPUBLIC SwPageDesc
     // FIXME epicycles growing here - page margins need to be stored differently
     SwFrameFormat    m_FirstMaster;
     SwFrameFormat    m_FirstLeft;
+
+    struct StashedPageDesc
+    {
+        std::shared_ptr<SwFrameFormat> m_pStashedFirst;
+        std::shared_ptr<SwFrameFormat> m_pStashedLeft;
+        std::shared_ptr<SwFrameFormat> m_pStashedFirstLeft;
+    };
+
+    mutable StashedPageDesc m_aStashedHeader;
+    mutable StashedPageDesc m_aStashedFooter;
+
     sw::WriterMultiListener m_aDepends; ///< Because of grid alignment (Registerhaltigkeit).
     mutable const SwTextFormatColl* m_pTextFormatColl;
     SwPageDesc *m_pFollow;
@@ -206,6 +217,12 @@ public:
     bool IsHidden() const { return m_IsHidden; }
     void SetHidden(bool const bValue) { m_IsHidden = bValue; }
 
+    /// Remember original header/footer formats even when they are hidden by "sharing".
+    void StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bool bLeft, bool bFirst);
+
+    /// Used to restore hidden header/footer formats.
+    const SwFrameFormat* GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const;
+
     /// 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/uitest/data/tdf140117.fodt b/sw/qa/uitest/data/tdf140117.fodt
new file mode 100644
index 000000000000..8487346d1d5c
--- /dev/null
+++ b/sw/qa/uitest/data/tdf140117.fodt
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/200
 4/writer" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooo="http://openoffice.org/2004/office" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:open
 document:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+  <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
+   <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
+   <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="Microsoft YaHei" style:font-family-asian="'Microsoft YaHei'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="Lucida Sans" style:font-family-complex="'Lucida Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
+  </style:style>
+  <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+   <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.247cm" style:contextual-spacing="false" fo:line-height="115%"/>
+  </style:style>
+  <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
+   <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Lucida Sans1" style:font-family-complex="'Lucida Sans'" style:font-family-generic-complex="swiss"/>
+  </style:style>
+  <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+   <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
+   <style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-name-complex="Lucida Sans1" style:font-family-complex="'Lucida Sans'" style:font-family-generic-complex="swiss" style:font-size-complex="12pt" style:font-style-complex="italic"/>
+  </style:style>
+  <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
+   <style:paragraph-properties text:number-lines="false" text:line-number="0"/>
+   <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Lucida Sans1" style:font-family-complex="'Lucida Sans'" style:font-family-generic-complex="swiss"/>
+  </style:style>
+  <style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+   <style:paragraph-properties text:number-lines="false" text:line-number="0">
+    <style:tab-stops>
+     <style:tab-stop style:position="8.5cm" style:type="center"/>
+     <style:tab-stop style:position="17cm" style:type="right"/>
+    </style:tab-stops>
+   </style:paragraph-properties>
+  </style:style>
+  <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Header_20_and_20_Footer" style:class="extra">
+   <style:paragraph-properties text:number-lines="false" text:line-number="0">
+    <style:tab-stops>
+     <style:tab-stop style:position="8.5cm" style:type="center"/>
+     <style:tab-stop style:position="17cm" style:type="right"/>
+    </style:tab-stops>
+   </style:paragraph-properties>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
+   <style:text-properties officeooo:rsid="0021d80c" officeooo:paragraph-rsid="0021d80c"/>
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
+   <style:paragraph-properties fo:break-before="page"/>
+   <style:text-properties officeooo:rsid="001a8fea" officeooo:paragraph-rsid="001a8fea"/>
+  </style:style>
+  <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard">
+   <style:text-properties fo:font-size="18pt" officeooo:rsid="0021d80c" officeooo:paragraph-rsid="0021d80c" style:font-size-asian="15.75pt" style:font-size-complex="18pt"/>
+  </style:style>
+  <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Header">
+   <style:text-properties officeooo:rsid="0021d80c" officeooo:paragraph-rsid="0021d80c"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
+    <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style>
+    <style:header-footer-properties fo:min-height="0.6cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:background-color="transparent" style:dynamic-spacing="false" draw:fill="none" draw:fill-color="#729fcf"/>
+   </style:header-style>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1">
+   <style:header>
+    <text:p text:style-name="P1">right</text:p>
+   </style:header>
+   <style:header-left>
+    <text:p text:style-name="P1">left</text:p>
+   </style:header-left>
+   <style:header-first>
+    <text:p text:style-name="P1">first</text:p>
+   </style:header-first>
+  </style:master-page>
+ </office:master-styles>
+ <office:body>
+  <office:text text:use-soft-page-breaks="true">
+   <text:p text:style-name="P3">a</text:p>
+   <text:p text:style-name="P2"/>
+   <text:p text:style-name="P2"/>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/uitest/writer_tests7/tdf140117.py b/sw/qa/uitest/writer_tests7/tdf140117.py
new file mode 100644
index 000000000000..75b9c6c2ff8a
--- /dev/null
+++ b/sw/qa/uitest/writer_tests7/tdf140117.py
@@ -0,0 +1,70 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+from uitest.framework import UITestCase
+from libreoffice.uno.propertyvalue import mkPropertyValues
+from uitest.uihelper.common import get_state_as_dict
+from uitest.uihelper.common import select_pos
+from uitest.uihelper.common import type_text
+import importlib
+import time
+import org.libreoffice.unotest
+import pathlib
+
+def get_url_for_data_file(file_name):
+    return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri()
+
+class tdf140117(UITestCase):
+    def test_tdf140117(self):
+        # load the sample file
+        self.ui_test.load_file(get_url_for_data_file("tdf140117.fodt"))
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+        xWriterEdit = xWriterDoc.getChild("writer_edit")
+        document = self.ui_test.get_component()
+
+        for i in range(3):
+                xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "2"}))
+
+                self.xUITest.executeCommand(".uno:JumpToHeader")
+
+                xPageSytle = document.getStyleFamilies().getByIndex(2)
+                xHeaderText = xPageSytle.getByIndex(0).HeaderText.String
+                xHeaderFirstText = xPageSytle.getByIndex(0).HeaderTextFirst.String
+                xHeaderLeftText = xPageSytle.getByIndex(0).HeaderTextLeft.String
+                xHeaderRightText = xPageSytle.getByIndex(0).HeaderTextRight.String
+
+                # Option "same content on left and right pages" is false,
+                # insert text "XXXX" before actual header text "left" on page 2
+                if i == 0:
+                        type_text(xWriterEdit, "XXXX")
+
+                # Option "same content on left and right pages" is true,
+                # header of page 2 contains the same text as page 1
+                elif i == 1:
+                        self.assertEqual("right", xHeaderText)
+                        self.assertEqual("right", xHeaderRightText)
+
+                # Option "same content on left and right pages" is false again.
+                # This was "right" instead of keeping the header content disabled
+                # temporarily for the second interation of the loop.
+                elif i == 2:
+                        self.assertEqual("XXXXleft", xHeaderLeftText)
+
+                self.ui_test.execute_dialog_through_command(".uno:PageDialog")
+                PageDialog = self.xUITest.getTopFocusWindow();
+
+                xTabs = PageDialog.getChild("tabcontrol")
+                select_pos(xTabs, "4")
+
+                # Change option "same content on left and right pages" for the next iteration
+                Button = xTabs.getChild('checkSameLR')
+                Button.executeAction("CLICK", tuple())
+                ok = PageDialog.getChild("ok")
+                self.ui_test.close_dialog_through_button(ok)
+
+        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 bd5308e27790..87a99ff13f84 100644
--- a/sw/source/core/doc/docdesc.cxx
+++ b/sw/source/core/doc/docdesc.cxx
@@ -433,38 +433,80 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
     bool bHeaderFooterChanged = false;
 
     // Synch header.
-    const SwFormatHeader &rHead = rChged.GetMaster().GetHeader();
+    const SwFormatHeader& rMasterHead = rChged.GetMaster().GetHeader();
+    const SwFormatHeader& rLeftHead = rChged.GetLeft().GetHeader();
+    const SwFormatHeader& rFirstMasterHead = rChged.GetFirstMaster().GetHeader();
+    const SwFormatHeader& rFirstLeftHead = rChged.GetFirstLeft().GetHeader();
     if (undoGuard.UndoWasEnabled())
     {
         // #i46909# no undo if header or footer changed
         // Did something change in the nodes?
-        const SwFormatHeader &rOldHead = rDesc.GetMaster().GetHeader();
+        const SwFormatHeader &rOldMasterHead = rDesc.GetMaster().GetHeader();
         bHeaderFooterChanged |=
-            ( rHead.IsActive() != rOldHead.IsActive() ||
+            ( rMasterHead.IsActive() != rOldMasterHead.IsActive() ||
               rChged.IsHeaderShared() != rDesc.IsHeaderShared() ||
               rChged.IsFirstShared() != rDesc.IsFirstShared() );
     }
-    rDesc.GetMaster().SetFormatAttr( rHead );
-    CopyMasterHeader(rChged, rHead, rDesc, true, false); // Copy left header
-    CopyMasterHeader(rChged, rHead, rDesc, false, true); // Copy first master
-    CopyMasterHeader(rChged, rHead, rDesc, true, true);  // Copy first left
+    rDesc.GetMaster().SetFormatAttr( rMasterHead );
+    const bool bRestoreStashedLeftHead = rDesc.IsHeaderShared() && !rChged.IsHeaderShared();
+    const bool bRestoreStashedFirstMasterHead = rDesc.IsFirstShared() && !rChged.IsFirstShared();
+    const bool bRestoreStashedFirstLeftHead = (rDesc.IsHeaderShared() && !rChged.IsHeaderShared()) || (rDesc.IsFirstShared() && !rChged.IsFirstShared());
+    const SwFrameFormat* pStashedLeftFormat = bRestoreStashedLeftHead ? rChged.GetStashedFrameFormat(true, true, false) : nullptr;
+    const SwFrameFormat* pStashedFirstMasterFormat = bRestoreStashedFirstMasterHead ? rChged.GetStashedFrameFormat(true, false, true) : nullptr;
+    const SwFrameFormat* pStashedFirstLeftFormat = bRestoreStashedFirstLeftHead ? rChged.GetStashedFrameFormat(true, true, true) : nullptr;
+    CopyMasterHeader(rChged, pStashedLeftFormat ? pStashedLeftFormat->GetHeader() : rMasterHead, rDesc, true, false); // Copy left header
+    CopyMasterHeader(rChged, pStashedFirstMasterFormat ? pStashedFirstMasterFormat->GetHeader() : rMasterHead, rDesc, false, true); // Copy first master
+    CopyMasterHeader(rChged, pStashedFirstLeftFormat ? pStashedFirstLeftFormat->GetHeader() : rMasterHead, rDesc, true, true); // Copy first left
+
+    // Stash header formats as needed.
+    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 (rLeftHead.GetRegisteredIn() && bStashLeftHead)
+        rDesc.StashFrameFormat(rChged.GetLeft(), true, true, false);
+    if (rFirstMasterHead.GetRegisteredIn() && bStashFirstMasterHead)
+        rDesc.StashFrameFormat(rChged.GetFirstMaster(), true, false, true);
+    if (rFirstLeftHead.GetRegisteredIn() && bStashFirstLeftHead)
+        rDesc.StashFrameFormat(rChged.GetFirstLeft(), true, true, true);
+
     rDesc.ChgHeaderShare( rChged.IsHeaderShared() );
 
     // Synch Footer.
-    const SwFormatFooter &rFoot = rChged.GetMaster().GetFooter();
+    const SwFormatFooter& rMasterFoot = rChged.GetMaster().GetFooter();
+    const SwFormatFooter& rLeftFoot = rChged.GetLeft().GetFooter();
+    const SwFormatFooter& rFirstMasterFoot = rChged.GetFirstMaster().GetFooter();
+    const SwFormatFooter& rFirstLeftFoot = rChged.GetFirstLeft().GetFooter();
     if (undoGuard.UndoWasEnabled())
     {
         // #i46909# no undo if header or footer changed
         // Did something change in the Nodes?
-        const SwFormatFooter &rOldFoot = rDesc.GetMaster().GetFooter();
+        const SwFormatFooter &rOldMasterFoot = rDesc.GetMaster().GetFooter();
         bHeaderFooterChanged |=
-            ( rFoot.IsActive() != rOldFoot.IsActive() ||
+            ( rMasterFoot.IsActive() != rOldMasterFoot.IsActive() ||
               rChged.IsFooterShared() != rDesc.IsFooterShared() );
     }
-    rDesc.GetMaster().SetFormatAttr( rFoot );
-    CopyMasterFooter(rChged, rFoot, rDesc, true, false); // Copy left footer
-    CopyMasterFooter(rChged, rFoot, rDesc, false, true); // Copy first master
-    CopyMasterFooter(rChged, rFoot, rDesc, true, true);  // Copy first left
+    rDesc.GetMaster().SetFormatAttr( rMasterFoot );
+    const bool bRestoreStashedLeftFoot = rDesc.IsFooterShared() && !rChged.IsFooterShared();
+    const bool bRestoreStashedFirstMasterFoot = rDesc.IsFirstShared() && !rChged.IsFirstShared();
+    const bool bRestoreStashedFirstLeftFoot = (rDesc.IsFooterShared() && !rChged.IsFooterShared()) || (rDesc.IsFirstShared() && !rChged.IsFirstShared());
+    const SwFrameFormat* pStashedLeftFoot = bRestoreStashedLeftFoot ? rChged.GetStashedFrameFormat(false, true, false) : nullptr;
+    const SwFrameFormat* pStashedFirstMasterFoot = bRestoreStashedFirstMasterFoot ? rChged.GetStashedFrameFormat(false, false, true) : nullptr;
+    const SwFrameFormat* pStashedFirstLeftFoot = bRestoreStashedFirstLeftFoot ? rChged.GetStashedFrameFormat(false, true, true) : nullptr;
+    CopyMasterFooter(rChged, pStashedLeftFoot ? pStashedLeftFoot->GetFooter() : rMasterFoot, rDesc, true, false); // Copy left footer
+    CopyMasterFooter(rChged, pStashedFirstMasterFoot ? pStashedFirstMasterFoot->GetFooter() : rMasterFoot, rDesc, false, true); // Copy first master
+    CopyMasterFooter(rChged, pStashedFirstLeftFoot ? pStashedFirstLeftFoot->GetFooter() : rMasterFoot, rDesc, true, true); // Copy first left
+
+    // Stash footer formats as needed.
+    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 (rLeftFoot.GetRegisteredIn() && bStashLeftFoot)
+        rDesc.StashFrameFormat(rChged.GetLeft(), false, true, false);
+    if (rFirstMasterFoot.GetRegisteredIn() && bStashFirstMasterFoot)
+        rDesc.StashFrameFormat(rChged.GetFirstMaster(), false, false, true);
+    if (rFirstLeftFoot.GetRegisteredIn() && bStashFirstLeftFoot)
+        rDesc.StashFrameFormat(rChged.GetFirstLeft(), 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/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx
index 3672a02bd9df..97c714e245d5 100644
--- a/sw/source/core/layout/pagedesc.cxx
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -28,6 +28,7 @@
 #include <sal/log.hxx>
 #include <fmtclds.hxx>
 #include <fmtfsize.hxx>
+#include <fmthdft.hxx>
 #include <pagefrm.hxx>
 #include <pagedesc.hxx>
 #include <swtable.hxx>
@@ -48,6 +49,8 @@ SwPageDesc::SwPageDesc(const OUString& rName, SwFrameFormat *pFormat, SwDoc *con
     , m_Left( pDoc->GetAttrPool(), rName, pFormat )
     , m_FirstMaster( pDoc->GetAttrPool(), rName, pFormat )
     , m_FirstLeft( pDoc->GetAttrPool(), rName, pFormat )
+    , m_aStashedHeader()
+    , m_aStashedFooter()
     , m_aDepends(*this)
     , m_pTextFormatColl(nullptr)
     , m_pFollow( this )
@@ -81,6 +84,14 @@ SwPageDesc::SwPageDesc( const SwPageDesc &rCpy )
     , m_FootnoteInfo( rCpy.GetFootnoteInfo() )
     , m_pdList( nullptr )
 {
+    m_aStashedHeader.m_pStashedFirst = rCpy.m_aStashedHeader.m_pStashedFirst;
+    m_aStashedHeader.m_pStashedLeft = rCpy.m_aStashedHeader.m_pStashedLeft;
+    m_aStashedHeader.m_pStashedFirstLeft = rCpy.m_aStashedHeader.m_pStashedFirstLeft;
+
+    m_aStashedFooter.m_pStashedFirst = rCpy.m_aStashedFooter.m_pStashedFirst;
+    m_aStashedFooter.m_pStashedLeft = rCpy.m_aStashedFooter.m_pStashedLeft;
+    m_aStashedFooter.m_pStashedFirstLeft = rCpy.m_aStashedFooter.m_pStashedFirstLeft;
+
     if (rCpy.m_pTextFormatColl && rCpy.m_aDepends.IsListeningTo(rCpy.m_pTextFormatColl))
     {
         m_pTextFormatColl = rCpy.m_pTextFormatColl;
@@ -99,6 +110,15 @@ SwPageDesc & SwPageDesc::operator = (const SwPageDesc & rSrc)
     m_Left = rSrc.m_Left;
     m_FirstMaster = rSrc.m_FirstMaster;
     m_FirstLeft = rSrc.m_FirstLeft;
+
+    m_aStashedHeader.m_pStashedFirst = rSrc.m_aStashedHeader.m_pStashedFirst;
+    m_aStashedHeader.m_pStashedLeft = rSrc.m_aStashedHeader.m_pStashedLeft;
+    m_aStashedHeader.m_pStashedFirstLeft = rSrc.m_aStashedHeader.m_pStashedFirstLeft;
+
+    m_aStashedFooter.m_pStashedFirst = rSrc.m_aStashedFooter.m_pStashedFirst;
+    m_aStashedFooter.m_pStashedLeft = rSrc.m_aStashedFooter.m_pStashedLeft;
+    m_aStashedFooter.m_pStashedFirstLeft = rSrc.m_aStashedFooter.m_pStashedFirstLeft;
+
     m_aDepends.EndListeningAll();
     if (rSrc.m_pTextFormatColl && rSrc.m_aDepends.IsListeningTo(rSrc.m_pTextFormatColl))
     {
@@ -386,6 +406,59 @@ void SwPageDesc::ChgFirstShare( bool bNew )
         m_eUse &= UseOnPage::NoFirstShare;
 }
 
+void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bool bLeft, bool bFirst)
+{
+    assert(rFormat.GetRegisteredIn());
+    std::shared_ptr<SwFrameFormat>* pFormat = nullptr;
+
+    if (bHeader)
+    {
+        if (bLeft && !bFirst)
+            pFormat = &m_aStashedHeader.m_pStashedLeft;
+        else if (!bLeft && bFirst)
+            pFormat = &m_aStashedHeader.m_pStashedFirst;
+        else if (bLeft && bFirst)
+            pFormat = &m_aStashedHeader.m_pStashedFirstLeft;
+    }
+    else
+    {
+        if (bLeft && !bFirst)
+            pFormat = &m_aStashedFooter.m_pStashedLeft;
+        else if (!bLeft && bFirst)
+            pFormat = &m_aStashedFooter.m_pStashedFirst;
+        else if (bLeft && bFirst)
+            pFormat = &m_aStashedFooter.m_pStashedFirstLeft;
+    }
+
+    if (!pFormat)
+    {
+        SAL_WARN("sw", "Stashing the right page header/footer is pointless.");
+    }
+    else
+    {
+        *pFormat = std::make_shared<SwFrameFormat>(rFormat);
+    }
+}
+
+const SwFrameFormat* SwPageDesc::GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const
+{
+    if (bLeft && !bFirst)
+    {
+        return bHeader ? m_aStashedHeader.m_pStashedLeft.get() : m_aStashedFooter.m_pStashedLeft.get();
+    }
+    else if (!bLeft && bFirst)
+    {
+        return bHeader ? m_aStashedHeader.m_pStashedFirst.get() : m_aStashedFooter.m_pStashedFirst.get();
+    }
+    else if (bLeft && bFirst)
+    {
+        return bHeader ? m_aStashedHeader.m_pStashedFirstLeft.get() : m_aStashedFooter.m_pStashedFirstLeft.get();
+    }
+
+    SAL_WARN("sw", "Right page format is never stashed.");
+    return nullptr;
+}
+
 // Page styles
 static const char* STR_POOLPAGE[] =
 {


More information about the Libreoffice-commits mailing list