sw/qa/extras/rtfexport/data/tdf158586_pageBreak1_header.rtf |   17 +
 sw/qa/extras/rtfexport/rtfexport8.cxx                       |   13 
 writerfilter/source/dmapper/DomainMapper.cxx                |    9 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx           |  171 +++++-------
 writerfilter/source/dmapper/DomainMapper_Impl.hxx           |   80 ++---
 writerfilter/source/dmapper/SdtHelper.cxx                   |    4 
 6 files changed, 154 insertions(+), 140 deletions(-)

New commits:
commit 23d9c8ea006ad62b757f2610df1ad1c73c53b624
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jan 31 14:47:22 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Feb 6 20:33:53 2024 +0100

    writerfilter: move members to SubstreamContext
    
    writerfilter: move m_bParaHadField to SubstreamContext
    
    Change-Id: Ie15e35d304a423bfa3d7b7ead71015d5ec1228d4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162839
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 4913812baeabd44b46302e54b73a227e760c688a)
    
    writerfilter: use SubstreamContext for all substreams
    
    <vmiklos> possibly just nobody needed that so far. could be some more
    general SubstreamContext, i don't see an obvious problem reusing that at
    more places.
    
    Change-Id: If0749155452f65f8dfc4ac2b10f91bb8e48a6b2b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162840
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 95b01848b18283fd2f903c982108ccdb8efee022)
    
    writerfilter: move m_bFirstParagraphInCell to SubstreamContext
    
    This is a change to set it for all substreams.
    
    Change-Id: I44ed9a5485000f40f8ccfe3ec885ef8f05f5aab2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162841
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 30323c813977eb0127251848fecd2532dce75749)
    
    writerfilter: replace members w/ SubstreamContext::eSubstreamType
    
    This should not change any behaviour.
    
    Change-Id: Ic970f0e1b6401119d875c9e811589b9c210e0c34
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162842
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 992f7114ab8645fb5b7a22b5f974a95fe7be7712)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162933
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 6909e3925846..31448f77b596 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -357,10 +357,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bInStyleSheetImport( false ),
         m_bInNumberingImport(false),
         m_bInAnyTableImport( false ),
-        m_eInHeaderFooterImport( HeaderFooterImportState::none ),
         m_bDiscardHeaderFooter( false ),
-        m_bInFootOrEndnote(false),
-        m_bInFootnote(false),
         m_bHasFootnoteStyle(false),
         m_bCheckFootnoteStyle(false),
         m_eSkipFootnoteState(SkipFootnoteSeparator::OFF),
@@ -381,7 +378,6 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bIsPreviousParagraphFramed( false ),
         m_bIsLastParaInSection( false ),
         m_bIsLastSectionGroup( false ),
-        m_bIsInComments( false ),
         m_bParaSectpr( false ),
         m_bUsingEnhancedFields( false ),
         m_bSdt(false),
@@ -402,11 +398,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bIgnoreNextTab(false),
         m_bIsSplitPara(false),
         m_bIsActualParagraphFramed( false ),
-        m_bParaHadField(false),
-        m_bSaveParaHadField(false),
         m_bParaAutoBefore(false),
-        m_bFirstParagraphInCell(true),
-        m_bSaveFirstParagraphInCell(false),
         m_bParaWithInlineObject(false),
         m_bSaxError(false)
 {
@@ -964,7 +956,7 @@ bool DomainMapper_Impl::GetIsFirstParagraphInSection( bool 
bAfterRedline ) const
     // and none of them should be considered the first para in section.
     return ( bAfterRedline ? m_bIsFirstParaInSectionAfterRedline : 
m_bIsFirstParaInSection )
                 && !IsInShape()
-                && !m_bIsInComments
+                && !IsInComments()
                 && !IsInFootOrEndnote();
 }
 
@@ -2361,7 +2353,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
         {
             if ( GetIsFirstParagraphInShape() ||
                  (GetIsFirstParagraphInSection() && GetSectionContext() && 
GetSectionContext()->IsFirstSection()) ||
-                (m_bFirstParagraphInCell
+                (m_StreamStateStack.top().bFirstParagraphInCell
                  && 0 < m_StreamStateStack.top().nTableDepth
                  && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth))
             {
@@ -2616,7 +2608,8 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                 else
                 {
                     uno::Reference<text::XTextCursor> xCursor;
-                    if (m_bParaHadField && !m_bIsInComments && 
!m_xTOCMarkerCursor.is())
+                    if (m_StreamStateStack.top().bParaHadField
+                        && !IsInComments() && !m_xTOCMarkerCursor.is())
                     {
                         // Workaround to make sure char props of the field are 
not lost.
                         // Not relevant for editeng-based comments.
@@ -2658,9 +2651,10 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                                 TOOLS_WARN_EXCEPTION("writerfilter", 
"DomainMapper_Impl::finishParagraph NumberingRules");
                             }
                         }
-                        else if ( 
m_xPreviousParagraph->getPropertySetInfo()->hasPropertyByName("NumberingStyleName")
 &&
+                        else if 
(m_xPreviousParagraph->getPropertySetInfo()->hasPropertyByName("NumberingStyleName")
                                 // don't update before tables
-                                (m_StreamStateStack.top().nTableDepth == 0 || 
!m_bFirstParagraphInCell))
+                            && (m_StreamStateStack.top().nTableDepth == 0
+                                || 
!m_StreamStateStack.top().bFirstParagraphInCell))
                         {
                             aCurrentNumberingName = GetListStyleName(nListId);
                             
m_xPreviousParagraph->getPropertyValue("NumberingStyleName") >>= 
aPreviousNumberingName;
@@ -2844,7 +2838,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                 css::uno::Reference<css::beans::XPropertySet> 
xParaProps(xTextRange, uno::UNO_QUERY);
 
                 // table style precedence and not hidden shapes anchored to 
hidden empty table paragraphs
-                if (xParaProps && !m_bIsInComments
+                if (xParaProps && !IsInComments()
                     && (0 < m_StreamStateStack.top().nTableDepth
                         || !m_aAnchoredObjectAnchors.empty()))
                 {
@@ -2996,7 +2990,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
     m_previousRedline.clear();
     m_bParaChanged = false;
 
-    if (m_bIsInComments && pParaContext)
+    if (IsInComments() && pParaContext)
     {
         if (const OUString sParaId = pParaContext->props().GetParaId(); 
!sParaId.isEmpty())
         {
@@ -3019,15 +3013,15 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
     }
 
     SetIsOutsideAParagraph(true);
-    m_bParaHadField = false;
+    m_StreamStateStack.top().bParaHadField = false;
 
     // don't overwrite m_bFirstParagraphInCell in table separator nodes
     // and in text boxes anchored to the first paragraph of table cells
     if (0 < m_StreamStateStack.top().nTableDepth
         && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth
-        && !IsInShape() && !m_bIsInComments)
+        && !IsInShape() && !IsInComments())
     {
-        m_bFirstParagraphInCell = false;
+        m_StreamStateStack.top().bFirstParagraphInCell = false;
     }
 
     m_bParaAutoBefore = false;
@@ -3199,7 +3193,7 @@ void DomainMapper_Impl::applyToggleAttributes(const 
PropertyMapPtr& pPropertyMap
     {
         applyToggleAttributes(pPropertyMap);
         // If we are in comments, then disable CharGrabBag, comment text 
doesn't support that.
-        uno::Sequence< beans::PropertyValue > aValues = 
pPropertyMap->GetPropertyValues(/*bCharGrabBag=*/!m_bIsInComments);
+        uno::Sequence<beans::PropertyValue> aValues = 
pPropertyMap->GetPropertyValues(/*bCharGrabBag=*/!IsInComments());
 
         if (IsInTOC() || m_bStartIndex || m_bStartBibliography)
             for( auto& rValue : asNonConstRange(aValues) )
@@ -3791,9 +3785,6 @@ bool isContentEmpty(uno::Reference<text::XText> const& 
xText, uno::Reference<tex
 
 void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, 
PageType eType)
 {
-    m_bSaveParaHadField = m_bParaHadField;
-    m_StreamStateStack.emplace();
-
     bool bHeader = ePagePartType == PagePartType::Header;
 
     const PropertyIds ePropIsOn = bHeader ? PROP_HEADER_IS_ON: 
PROP_FOOTER_IS_ON;
@@ -3803,7 +3794,7 @@ void DomainMapper_Impl::PushPageHeaderFooter(PagePartType 
ePagePartType, PageTyp
     const PropertyIds ePropTextRight = bHeader ? PROP_HEADER_TEXT: 
PROP_FOOTER_TEXT;
 
     m_bDiscardHeaderFooter = true;
-    m_eInHeaderFooterImport = bHeader ? HeaderFooterImportState::header : 
HeaderFooterImportState::footer;
+    m_StreamStateStack.top().eSubstreamType = bHeader ? SubstreamType::Header 
: SubstreamType::Footer;
 
     //get the section context
     SectionPropertyMap* pSectionContext = GetSectionContext();;
@@ -3961,21 +3952,13 @@ void 
DomainMapper_Impl::PopPageHeaderFooter(PagePartType ePagePartType, PageType
         }
         m_bDiscardHeaderFooter = false;
     }
-    m_eInHeaderFooterImport = HeaderFooterImportState::none;
-
-    assert(!m_StreamStateStack.empty());
-    m_StreamStateStack.pop();
-
-    m_bParaHadField = m_bSaveParaHadField;
 }
 
 void DomainMapper_Impl::PushFootOrEndnote( bool bIsFootnote )
 {
-    SAL_WARN_IF(m_bInFootOrEndnote, "writerfilter.dmapper", 
"PushFootOrEndnote() is called from another foot or endnote");
-    m_bInFootOrEndnote = true;
-    m_bInFootnote = bIsFootnote;
+    SAL_WARN_IF(m_StreamStateStack.top().eSubstreamType != 
SubstreamType::Body, "writerfilter.dmapper", "PushFootOrEndnote() is called 
from another foot or endnote");
+    m_StreamStateStack.top().eSubstreamType = bIsFootnote ? 
SubstreamType::Footnote : SubstreamType::Endnote;
     m_bCheckFirstFootnoteTab = true;
-    m_bSaveFirstParagraphInCell = m_bFirstParagraphInCell;
     try
     {
         // Redlines outside the footnote should not affect footnote content
@@ -4240,7 +4223,7 @@ void DomainMapper_Impl::PushAnnotation()
 {
     try
     {
-        m_bIsInComments = true;
+        m_StreamStateStack.top().eSubstreamType = SubstreamType::Annotation;
         if (!GetTextFactory().is())
             return;
         m_xAnnotationField.set( GetTextFactory()->createInstance( 
"com.sun.star.text.TextField.Annotation" ),
@@ -4502,16 +4485,13 @@ void DomainMapper_Impl::PopFootOrEndnote()
     }
     m_aRedlines.pop();
     m_eSkipFootnoteState = SkipFootnoteSeparator::OFF;
-    m_bInFootOrEndnote = m_bInFootnote = false;
     m_pFootnoteContext = nullptr;
-    m_bFirstParagraphInCell = m_bSaveFirstParagraphInCell;
 }
 
 void DomainMapper_Impl::PopAnnotation()
 {
     RemoveLastParagraph();
 
-    m_bIsInComments = false;
     m_aTextAppendStack.pop();
 
     try
@@ -4991,7 +4971,7 @@ void DomainMapper_Impl::ClearPreviousParagraph()
     m_xPreviousParagraph.clear();
 
     // next table paragraph will be first paragraph in a cell
-    m_bFirstParagraphInCell = true;
+    m_StreamStateStack.top().bFirstParagraphInCell = true;
 }
 
 void DomainMapper_Impl::HandleAltChunk(const OUString& rStreamName)
@@ -5941,7 +5921,7 @@ uno::Reference<beans::XPropertySet> 
DomainMapper_Impl::FindOrCreateFieldMaster(c
 
 void DomainMapper_Impl::PushFieldContext()
 {
-    m_bParaHadField = true;
+    m_StreamStateStack.top().bParaHadField = true;
     if(m_bDiscardHeaderFooter)
         return;
 #ifdef DBG_UTIL
@@ -7054,7 +7034,7 @@ void DomainMapper_Impl::handleToc
 
     m_bStartTOC = true;
     pContext->SetTOC(xTOC);
-    m_bParaHadField = false;
+    m_StreamStateStack.top().bParaHadField = false;
 
     if (!xTOC)
         return;
@@ -7287,7 +7267,7 @@ void DomainMapper_Impl::handleBibliography
         xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), 
uno::Any(OUString()));
 
     pContext->SetTOC( xTOC );
-    m_bParaHadField = false;
+    m_StreamStateStack.top().bParaHadField = false;
 
     uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
     appendTextContent(xToInsert, uno::Sequence< beans::PropertyValue >() );
@@ -7330,7 +7310,7 @@ void DomainMapper_Impl::handleIndex
         }
     }
     pContext->SetTOC( xTOC );
-    m_bParaHadField = false;
+    m_StreamStateStack.top().bParaHadField = false;
 
     uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
     appendTextContent(xToInsert, uno::Sequence< beans::PropertyValue >() );
@@ -8348,7 +8328,7 @@ void DomainMapper_Impl::CloseFieldCommand()
                 }
             }
             else
-                m_bParaHadField = false;
+                m_StreamStateStack.top().bParaHadField = false;
         }
     }
     catch( const uno::Exception& )
@@ -8918,8 +8898,11 @@ void DomainMapper_Impl::StartOrEndBookmark( const 
OUString& rId )
                     // keep bookmark range, if it doesn't exceed cell boundary
                     uno::Reference< text::XTextRange > xStart = 
xCursor->getStart();
                     xCursor->goLeft( 1, false );
-                    if (m_StreamStateStack.top().nTableDepth == 0 || 
!m_bFirstParagraphInCell)
+                    if (m_StreamStateStack.top().nTableDepth == 0
+                        || !m_StreamStateStack.top().bFirstParagraphInCell)
+                    {
                         xCursor->gotoRange(xStart, true );
+                    }
                 }
                 uno::Reference< container::XNamed > xBkmNamed( xBookmark, 
uno::UNO_QUERY_THROW );
                 SAL_WARN_IF(aBookmarkIter->second.m_sBookmarkName.isEmpty(), 
"writerfilter.dmapper", "anonymous bookmark");
@@ -9757,6 +9740,8 @@ void DomainMapper_Impl::substream(Id rName,
     appendTableHandler();
     getTableManager().startLevel();
 
+    m_StreamStateStack.emplace();
+
     //import of page header/footer
     //Ensure that only one header/footer per section is pushed
 
@@ -9787,8 +9772,12 @@ void DomainMapper_Impl::substream(Id rName,
     case NS_ooxml::LN_annotation :
         PushAnnotation();
     break;
+    default:
+        assert(false); // unexpected?
     }
 
+    assert(m_StreamStateStack.top().eSubstreamType != SubstreamType::Body);
+
     try
     {
         ref->resolve(m_rDMapper);
@@ -9828,6 +9817,9 @@ void DomainMapper_Impl::substream(Id rName,
     break;
     }
 
+    assert(!m_StreamStateStack.empty());
+    m_StreamStateStack.pop();
+
     getTableManager().endLevel();
     popTableManager();
     m_bHasFtn = bHasFtn;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index aad946e81702..3417147a92f3 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -146,6 +146,16 @@ enum StoredRedlines
     NONE
 };
 
+enum class SubstreamType
+{
+    Body,
+    Header,
+    Footer,
+    Footnote,
+    Endnote,
+    Annotation,
+};
+
 /**
  * Storage for state that is relevant outside a header/footer, but not inside 
it.
  *
@@ -157,6 +167,7 @@ enum StoredRedlines
  */
 struct SubstreamContext
 {
+    SubstreamType eSubstreamType = SubstreamType::Body;
     bool      bTextInserted = false;
     /**
      * This contains the raw table depth. nTableDepth > 0 is the same as
@@ -170,6 +181,10 @@ struct SubstreamContext
     bool      bIsColumnBreakDeferred = false;
     bool      bIsPageBreakDeferred = false;
     sal_Int32 nLineBreaksDeferred = 0;
+    /// Current paragraph had at least one field in it.
+    bool      bParaHadField = false;
+    /// Current paragraph in a table is first paragraph of a cell
+    bool      bFirstParagraphInCell = true;
 };
 
 /// Information about a paragraph to be finished after a field end.
@@ -543,15 +558,7 @@ private:
     bool                            m_bInStyleSheetImport; //in import of 
fonts, styles, lists or lfos
     bool                            m_bInNumberingImport; //in import of 
numbering (i.e. numbering.xml)
     bool                            m_bInAnyTableImport; //in import of fonts, 
styles, lists or lfos
-    enum class HeaderFooterImportState
-    {
-        none,
-        header,
-        footer,
-    }                               m_eInHeaderFooterImport;
     bool                            m_bDiscardHeaderFooter;
-    bool                            m_bInFootOrEndnote;
-    bool                            m_bInFootnote;
     PropertyMapPtr m_pFootnoteContext;
     bool m_bHasFootnoteStyle;
     bool m_bCheckFootnoteStyle;
@@ -599,7 +606,6 @@ private:
     bool                            m_bIsPreviousParagraphFramed;
     bool                            m_bIsLastParaInSection;
     bool                            m_bIsLastSectionGroup;
-    bool                            m_bIsInComments;
     /// If the current paragraph contains section property definitions.
     bool                            m_bParaSectpr;
     bool                            m_bUsingEnhancedFields;
@@ -751,7 +757,7 @@ public:
     /// Getter method for m_bSdt.
     bool GetSdt() const { return m_bSdt;}
     bool GetParaChanged() const { return m_bParaChanged;}
-    bool GetParaHadField() const { return m_bParaHadField; }
+    bool GetParaHadField() const { return 
m_StreamStateStack.top().bParaHadField; }
     bool GetRemoveThisPara() const { return m_bRemoveThisParagraph; }
 
     void deferBreak( BreakType deferredBreakType );
@@ -871,7 +877,7 @@ public:
     css::uno::Reference<css::drawing::XShape> PopPendingShape();
 
     void PopPageHeaderFooter(PagePartType ePagePartType, PageType eType);
-    bool IsInHeaderFooter() const { return m_eInHeaderFooterImport != 
HeaderFooterImportState::none; }
+    bool IsInHeaderFooter() const { auto const 
type(m_StreamStateStack.top().eSubstreamType); return type == 
SubstreamType::Header || type == SubstreamType::Footer; }
     void ConvertHeaderFooterToTextFrame(bool, bool);
     static void 
fillEmptyFrameProperties(std::vector<css::beans::PropertyValue>& 
rFrameProperties, bool bSetAnchorToChar);
 
@@ -879,8 +885,8 @@ public:
 
     void PushFootOrEndnote( bool bIsFootnote );
     void PopFootOrEndnote();
-    bool IsInFootOrEndnote() const { return m_bInFootOrEndnote; }
-    bool IsInFootnote() const { return IsInFootOrEndnote() && m_bInFootnote; }
+    bool IsInFootOrEndnote() const { auto const 
type(m_StreamStateStack.top().eSubstreamType); return type == 
SubstreamType::Footnote || type == SubstreamType::Endnote; }
+    bool IsInFootnote() const { return m_StreamStateStack.top().eSubstreamType 
== SubstreamType::Footnote; }
 
     void StartCustomFootnote(const PropertyMapPtr pContext);
     void EndCustomFootnote();
@@ -1026,7 +1032,7 @@ public:
     void SetInFootnoteProperties(bool bSet) { m_bIsInFootnoteProperties = 
bSet;}
     bool IsInFootnoteProperties() const { return m_bIsInFootnoteProperties;}
 
-    bool IsInComments() const { return m_bIsInComments; };
+    bool IsInComments() const { return m_StreamStateStack.top().eSubstreamType 
== SubstreamType::Annotation; };
 
     std::vector<css::beans::PropertyValue> MakeFrameProperties(const 
ParagraphProperties& rProps);
     void CheckUnregisteredFrameConversion(bool bPreventOverlap = false);
@@ -1207,15 +1213,9 @@ private:
     // Start a new index section; if needed, finish current paragraph
     css::uno::Reference<css::beans::XPropertySet> 
StartIndexSectionChecked(const OUString& sServiceName);
     std::vector<css::uno::Reference< css::drawing::XShape > > 
m_vTextFramesForChaining ;
-    /// Current paragraph had at least one field in it.
-    bool m_bParaHadField;
-    bool m_bSaveParaHadField;
     css::uno::Reference<css::beans::XPropertySet> m_xPreviousParagraph;
     /// Current paragraph has automatic before spacing.
     bool m_bParaAutoBefore;
-    /// Current paragraph in a table is first paragraph of a cell
-    bool m_bFirstParagraphInCell;
-    bool m_bSaveFirstParagraphInCell;
     /// Current paragraph had at least one inline object in it.
     bool m_bParaWithInlineObject;
     /// SAXException was seen so document will be abandoned
commit 0a53b7f64dddc31b705080bb21230aae99212062
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jan 31 14:33:46 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Feb 6 20:33:43 2024 +0100

    tdf#158586 writerfilter: RTF import: fix \page \sect \skbnone w/ header
    
    The problem was not fixed yet for the less-minimized bugzilla attachment
    where the sections contain headers and footers.
    
    What happened there is that first \page caused a deferred page break,
    then \sect and sectBreak() delayed-read the header substream and the
    \par in the header resets all the deferred break flags.
    
    Add the deferred break to an already existing Context class, and remove
    the direct members in DomainMapper_Impl in favor of always using the
    m_StreamStateStack.
    
    Probably this problem cannot occur for DOCX import, because it imports
    header/footer eagerly where the reference element is, and sectPr is
    before any runs that contain breaks in the same paragraph element.
    
    Change-Id: Iba971955e9cf0c398d416518e72d99307d3e1cfd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162833
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 17e2c7226a73675d69febf0915aaeae61ad8e9f1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162823
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/extras/rtfexport/data/tdf158586_pageBreak1_header.rtf 
b/sw/qa/extras/rtfexport/data/tdf158586_pageBreak1_header.rtf
new file mode 100644
index 000000000000..cd8eefabb276
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf158586_pageBreak1_header.rtf
@@ -0,0 +1,17 @@
+{ tf1
+
+\paperw8419\paperh5953
+
+\spltpgpar
+
+\ltrpar \sectd
+
+{\headerl \pard\plain \par}
+
+\pard\plain \wrapdefault\pvmrg\posxlbsw0bsh0\phcol \posyilbslock\dxfrtext10
+
+\page \sect \sectd \sbknone
+
+\pard\plain Second page
+\par
+}
diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx 
b/sw/qa/extras/rtfexport/rtfexport8.cxx
index ebc2c3d2bf3f..167539197051 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -85,6 +85,19 @@ DECLARE_RTFEXPORT_TEST(testTdf158586_1, 
"tdf158586_pageBreak1.rtf")
     assertXPathContent(pLayout, "/root/page[2]/body//txt"_ostr, "Second page");
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf158586_1header, 
"tdf158586_pageBreak1_header.rtf")
+{
+    // None of the specified text frame settings initiates a real text frame - 
page break not lost
+    CPPUNIT_ASSERT_EQUAL(2, getPages());
+    CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
+
+    // There should be no empty carriage return at the start of the second page
+    const auto& pLayout = parseLayoutDump();
+    // on import there is a section on page 2; on reimport there is no section
+    // (probably not an important difference?)
+    assertXPathContent(pLayout, "/root/page[2]/body//txt"_ostr, "Second page");
+}
+
 DECLARE_RTFEXPORT_TEST(testTdf158586_lostFrame, "tdf158586_lostFrame.rtf")
 {
     // The anchor and align properties are sufficient to define a frame
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 34e3c04e35a8..b9093998a4d1 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3258,7 +3258,8 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
          * section is a table. So in case first element is a table add a dummy 
para
          * and remove it again when lcl_endSectionGroup is called
          */
-        if(m_pImpl->m_nTableDepth == 0 && 
m_pImpl->GetIsFirstParagraphInSection()
+        if (m_pImpl->m_StreamStateStack.top().nTableDepth == 0
+            && m_pImpl->GetIsFirstParagraphInSection()
                 && !m_pImpl->GetIsDummyParaAddedForTableInSection() && 
!m_pImpl->GetIsTextFrameInserted()
                 && !m_pImpl->GetIsPreviousParagraphFramed() && 
!IsInHeaderFooter())
         {
@@ -3266,7 +3267,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
         }
 
         // if first paragraph style in table has break-before-page, transfer 
that setting to the table itself.
-        if( m_pImpl->m_nTableDepth == 0 )
+        if (m_pImpl->m_StreamStateStack.top().nTableDepth == 0)
         {
             const uno::Any aBreakType(style::BreakType_PAGE_BEFORE);
             const PropertyMapPtr pParagraphProps = 
m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
@@ -3287,11 +3288,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
             }
         }
 
-        m_pImpl->m_nTableDepth++;
+        m_pImpl->m_StreamStateStack.top().nTableDepth++;
     }
     break;
     case NS_ooxml::LN_tblEnd:
-        m_pImpl->m_nTableDepth--;
+        m_pImpl->m_StreamStateStack.top().nTableDepth--;
     break;
     case NS_ooxml::LN_tcStart:
         m_pImpl->m_nTableCellDepth++;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 5342e7a21b83..6909e3925846 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -341,9 +341,6 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bSetCitation( false ),
         m_bSetDateValue( false ),
         m_bIsFirstSection( true ),
-        m_bIsColumnBreakDeferred( false ),
-        m_bIsPageBreakDeferred( false ),
-        m_nLineBreaksDeferred( 0 ),
         m_bSdtEndDeferred(false),
         m_bParaSdtEndDeferred(false),
         m_bStartTOC(false),
@@ -352,7 +349,6 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bStartIndex(false),
         m_bStartBibliography(false),
         m_nStartGenericField(0),
-        m_bTextInserted(false),
         m_bTextDeleted(false),
         m_nLastRedlineMovedID(1),
         m_sCurrentPermId(0),
@@ -399,7 +395,6 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", 
false)),
         m_bIsAltChunk(rMediaDesc.getUnpackedValueOrDefault("AltChunkMode", 
false)),
         
m_bIsReadGlossaries(rMediaDesc.getUnpackedValueOrDefault("ReadGlossaries", 
false)),
-        m_nTableDepth(0),
         m_nTableCellDepth(0),
         m_bHasFtn(false),
         m_bHasFtnSep(false),
@@ -415,6 +410,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bParaWithInlineObject(false),
         m_bSaxError(false)
 {
+    m_StreamStateStack.emplace(); // add state for document body
     m_aBaseUrl = rMediaDesc.getUnpackedValueOrDefault(
         utl::MediaDescriptor::PROP_DOCUMENTBASEURL, OUString());
     if (m_aBaseUrl.isEmpty()) {
@@ -454,6 +450,7 @@ DomainMapper_Impl::DomainMapper_Impl(
 
 DomainMapper_Impl::~DomainMapper_Impl()
 {
+    assert(!m_StreamStateStack.empty());
     ChainTextFrames();
     // Don't remove last paragraph when pasting, sw expects that empty 
paragraph.
     if (m_bIsNewDoc)
@@ -1599,21 +1596,22 @@ ListsManager::Pointer const & 
DomainMapper_Impl::GetListTable()
 
 void DomainMapper_Impl::deferBreak( BreakType deferredBreakType)
 {
+    assert(!m_StreamStateStack.empty());
     switch (deferredBreakType)
     {
     case LINE_BREAK:
-        m_nLineBreaksDeferred++;
+        m_StreamStateStack.top().nLineBreaksDeferred++;
         break;
     case COLUMN_BREAK:
-        m_bIsColumnBreakDeferred = true;
+        m_StreamStateStack.top().bIsColumnBreakDeferred = true;
     break;
     case PAGE_BREAK:
             // See SwWW8ImplReader::HandlePageBreakChar(), page break should be
             // ignored inside tables.
-            if (m_nTableDepth > 0)
+            if (0 < m_StreamStateStack.top().nTableDepth)
                 return;
 
-            m_bIsPageBreakDeferred = true;
+            m_StreamStateStack.top().bIsPageBreakDeferred = true;
         break;
     default:
         return;
@@ -1622,14 +1620,15 @@ void DomainMapper_Impl::deferBreak( BreakType 
deferredBreakType)
 
 bool DomainMapper_Impl::isBreakDeferred( BreakType deferredBreakType )
 {
+    assert(!m_StreamStateStack.empty());
     switch (deferredBreakType)
     {
     case LINE_BREAK:
-        return m_nLineBreaksDeferred > 0;
+        return 0 < m_StreamStateStack.top().nLineBreaksDeferred;
     case COLUMN_BREAK:
-        return m_bIsColumnBreakDeferred;
+        return m_StreamStateStack.top().bIsColumnBreakDeferred;
     case PAGE_BREAK:
-        return m_bIsPageBreakDeferred;
+        return m_StreamStateStack.top().bIsPageBreakDeferred;
     default:
         return false;
     }
@@ -1637,17 +1636,18 @@ bool DomainMapper_Impl::isBreakDeferred( BreakType 
deferredBreakType )
 
 void DomainMapper_Impl::clearDeferredBreak(BreakType deferredBreakType)
 {
+    assert(!m_StreamStateStack.empty());
     switch (deferredBreakType)
     {
     case LINE_BREAK:
-        assert(m_nLineBreaksDeferred > 0);
-        m_nLineBreaksDeferred--;
+        assert(0 < m_StreamStateStack.top().nLineBreaksDeferred);
+        m_StreamStateStack.top().nLineBreaksDeferred--;
         break;
     case COLUMN_BREAK:
-        m_bIsColumnBreakDeferred = false;
+        m_StreamStateStack.top().bIsColumnBreakDeferred = false;
         break;
     case PAGE_BREAK:
-        m_bIsPageBreakDeferred = false;
+        m_StreamStateStack.top().bIsPageBreakDeferred = false;
         break;
     default:
         break;
@@ -1656,9 +1656,10 @@ void DomainMapper_Impl::clearDeferredBreak(BreakType 
deferredBreakType)
 
 void DomainMapper_Impl::clearDeferredBreaks()
 {
-    m_nLineBreaksDeferred = 0;
-    m_bIsColumnBreakDeferred = false;
-    m_bIsPageBreakDeferred = false;
+    assert(!m_StreamStateStack.empty());
+    m_StreamStateStack.top().nLineBreaksDeferred = 0;
+    m_StreamStateStack.top().bIsColumnBreakDeferred = false;
+    m_StreamStateStack.top().bIsPageBreakDeferred = false;
 }
 
 void DomainMapper_Impl::setSdtEndDeferred(bool bSdtEndDeferred)
@@ -2360,7 +2361,9 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
         {
             if ( GetIsFirstParagraphInShape() ||
                  (GetIsFirstParagraphInSection() && GetSectionContext() && 
GetSectionContext()->IsFirstSection()) ||
-                 (m_bFirstParagraphInCell && m_nTableDepth > 0 && 
m_nTableDepth == m_nTableCellDepth) )
+                (m_bFirstParagraphInCell
+                 && 0 < m_StreamStateStack.top().nTableDepth
+                 && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth))
             {
                 // export requires grabbag to match top_margin, so keep them 
in sync
                 if (nBeforeAutospacing && bIsAutoSet)
@@ -2657,7 +2660,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                         }
                         else if ( 
m_xPreviousParagraph->getPropertySetInfo()->hasPropertyByName("NumberingStyleName")
 &&
                                 // don't update before tables
-                                (m_nTableDepth == 0 || 
!m_bFirstParagraphInCell))
+                                (m_StreamStateStack.top().nTableDepth == 0 || 
!m_bFirstParagraphInCell))
                         {
                             aCurrentNumberingName = GetListStyleName(nListId);
                             
m_xPreviousParagraph->getPropertyValue("NumberingStyleName") >>= 
aPreviousNumberingName;
@@ -2812,7 +2815,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
 
                     // tdf#77417 trim right white spaces in table cells in 
2010 compatibility mode
                     sal_Int32 nMode = 
GetSettingsTable()->GetWordCompatibilityMode();
-                    if ( m_nTableDepth > 0 && nMode > 0 && nMode <= 14 )
+                    if (0 < m_StreamStateStack.top().nTableDepth && 0 < nMode 
&& nMode <= 14)
                     {
                         // skip new line
                         xCur->goLeft(1, false);
@@ -2842,7 +2845,8 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
 
                 // table style precedence and not hidden shapes anchored to 
hidden empty table paragraphs
                 if (xParaProps && !m_bIsInComments
-                    && (m_nTableDepth > 0 || 
!m_aAnchoredObjectAnchors.empty()))
+                    && (0 < m_StreamStateStack.top().nTableDepth
+                        || !m_aAnchoredObjectAnchors.empty()))
                 {
                     // table style has got bigger precedence than docDefault 
style
                     // collect these pending paragraph properties to process 
in endTable()
@@ -2852,7 +2856,7 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                     uno::Reference<text::XTextCursor> xCur2 =  
xTextRange->getText()->createTextCursorByRange(xCur);
                     uno::Reference<text::XParagraphCursor> xParaCursor(xCur2, 
uno::UNO_QUERY_THROW);
                     xParaCursor->gotoStartOfParagraph(false);
-                    if (m_nTableDepth > 0)
+                    if (0 < m_StreamStateStack.top().nTableDepth)
                     {
                         TableParagraph aPending{xParaCursor, xCur, 
pParaContext, xParaProps};
                         
getTableManager().getCurrentParagraphs()->push_back(aPending);
@@ -3019,8 +3023,12 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
 
     // don't overwrite m_bFirstParagraphInCell in table separator nodes
     // and in text boxes anchored to the first paragraph of table cells
-    if (m_nTableDepth > 0 && m_nTableDepth == m_nTableCellDepth && 
!IsInShape() && !m_bIsInComments)
+    if (0 < m_StreamStateStack.top().nTableDepth
+        && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth
+        && !IsInShape() && !m_bIsInComments)
+    {
         m_bFirstParagraphInCell = false;
+    }
 
     m_bParaAutoBefore = false;
     m_bParaWithInlineObject = false;
@@ -3262,7 +3270,7 @@ void DomainMapper_Impl::applyToggleAttributes(const 
PropertyMapPtr& pPropertyMap
                     SAL_WARN_IF(!xTextRange.is(), "writerfilter.dmapper", 
"insertTextPortion failed");
                     if (!xTextRange.is())
                         throw uno::Exception("insertTextPortion failed", 
nullptr);
-                    m_bTextInserted = true;
+                    m_StreamStateStack.top().bTextInserted = true;
                     xTOCTextCursor->gotoRange(xTextRange->getEnd(), true);
                     if (m_nStartGenericField == 0)
                     {
@@ -3784,9 +3792,7 @@ bool isContentEmpty(uno::Reference<text::XText> const& 
xText, uno::Reference<tex
 void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, 
PageType eType)
 {
     m_bSaveParaHadField = m_bParaHadField;
-    m_aHeaderFooterStack.push(HeaderFooterContext(m_bTextInserted, 
m_nTableDepth));
-    m_bTextInserted = false;
-    m_nTableDepth = 0;
+    m_StreamStateStack.emplace();
 
     bool bHeader = ePagePartType == PagePartType::Header;
 
@@ -3957,12 +3963,8 @@ void DomainMapper_Impl::PopPageHeaderFooter(PagePartType 
ePagePartType, PageType
     }
     m_eInHeaderFooterImport = HeaderFooterImportState::none;
 
-    if (!m_aHeaderFooterStack.empty())
-    {
-        m_bTextInserted = m_aHeaderFooterStack.top().getTextInserted();
-        m_nTableDepth = m_aHeaderFooterStack.top().getTableDepth();
-        m_aHeaderFooterStack.pop();
-    }
+    assert(!m_StreamStateStack.empty());
+    m_StreamStateStack.pop();
 
     m_bParaHadField = m_bSaveParaHadField;
 }
@@ -4121,7 +4123,7 @@ void 
DomainMapper_Impl::CreateRedline(uno::Reference<text::XTextRange> const& xR
         }
         // store frame and (possible floating) table redline data for 
restoring them after frame conversion
         enum StoredRedlines eType;
-        if (m_bIsActualParagraphFramed || m_nTableDepth > 0)
+        if (m_bIsActualParagraphFramed || 0 < 
m_StreamStateStack.top().nTableDepth)
             eType = StoredRedlines::FRAME;
         else if (IsInFootOrEndnote())
             eType = IsInFootnote() ? StoredRedlines::FOOTNOTE : 
StoredRedlines::ENDNOTE;
@@ -4977,7 +4979,7 @@ bool DomainMapper_Impl::IsDiscardHeaderFooter() const
 void DomainMapper_Impl::ClearPreviousParagraph()
 {
     // in table cells, set bottom auto margin of last paragraph to 0, except 
in paragraphs with numbering
-    if ((m_nTableDepth == (m_nTableCellDepth + 1))
+    if ((m_StreamStateStack.top().nTableDepth == (m_nTableCellDepth + 1))
         && m_xPreviousParagraph.is()
         && hasTableManager() && 
getTableManager().isCellLastParaAfterAutospacing())
     {
@@ -5984,18 +5986,6 @@ void DomainMapper_Impl::SetFieldLocked()
         m_aFieldStack.back()->SetFieldLocked();
 }
 
-HeaderFooterContext::HeaderFooterContext(bool bTextInserted, sal_Int32 
nTableDepth)
-    : m_bTextInserted(bTextInserted)
-    , m_nTableDepth(nTableDepth)
-{
-}
-
-bool HeaderFooterContext::getTextInserted() const
-{
-    return m_bTextInserted;
-}
-
-sal_Int32 HeaderFooterContext::getTableDepth() const { return m_nTableDepth; }
 
 FieldContext::FieldContext(uno::Reference< text::XTextRange > xStart)
     : m_bFieldCommandCompleted(false)
@@ -8680,7 +8670,7 @@ void DomainMapper_Impl::PopFieldContext()
                         }
                         m_bStartedTOC = false;
                         m_aTextAppendStack.pop();
-                        m_bTextInserted = false;
+                        m_StreamStateStack.top().bTextInserted = false;
                         m_bParaChanged = true; // the paragraph must stay 
anyway
                     }
                     m_bStartTOC = false;
@@ -8802,9 +8792,9 @@ void DomainMapper_Impl::PopFieldContext()
                         {
                             --m_nStartGenericField;
                             PopFieldmark(m_aTextAppendStack, xCrsr, 
pContext->GetFieldId());
-                            if(m_bTextInserted)
+                            if (m_StreamStateStack.top().bTextInserted)
                             {
-                                m_bTextInserted = false;
+                                m_StreamStateStack.top().bTextInserted = false;
                             }
                         }
                     }
@@ -8884,8 +8874,10 @@ void DomainMapper_Impl::StartOrEndBookmark( const 
OUString& rId )
      * iff the first element in the section is a table. If the dummy para is 
not added yet, then add it;
      * So bookmark is not attached to the wrong paragraph.
      */
-    if(hasTableManager() && getTableManager().isInCell() && m_nTableDepth == 0 
&& GetIsFirstParagraphInSection()
-                    && !GetIsDummyParaAddedForTableInSection() 
&&!GetIsTextFrameInserted())
+    if (hasTableManager() && getTableManager().isInCell()
+        && m_StreamStateStack.top().nTableDepth == 0
+        && GetIsFirstParagraphInSection()
+        && !GetIsDummyParaAddedForTableInSection() && 
!GetIsTextFrameInserted())
     {
         AddDummyParaForTableInSection();
     }
@@ -8926,7 +8918,7 @@ void DomainMapper_Impl::StartOrEndBookmark( const 
OUString& rId )
                     // keep bookmark range, if it doesn't exceed cell boundary
                     uno::Reference< text::XTextRange > xStart = 
xCursor->getStart();
                     xCursor->goLeft( 1, false );
-                    if (m_nTableDepth == 0 || !m_bFirstParagraphInCell)
+                    if (m_StreamStateStack.top().nTableDepth == 0 || 
!m_bFirstParagraphInCell)
                         xCursor->gotoRange(xStart, true );
                 }
                 uno::Reference< container::XNamed > xBkmNamed( xBookmark, 
uno::UNO_QUERY_THROW );
@@ -9005,7 +8997,8 @@ void 
DomainMapper_Impl::startOrEndPermissionRange(sal_Int32 permissinId)
     * if the first element in the section is a table. If the dummy para is not 
added yet, then add it;
     * So permission is not attached to the wrong paragraph.
     */
-    if (getTableManager().isInCell() && m_nTableDepth == 0 && 
GetIsFirstParagraphInSection()
+    if (getTableManager().isInCell()
+        && m_StreamStateStack.top().nTableDepth == 0 && 
GetIsFirstParagraphInSection()
         && !GetIsDummyParaAddedForTableInSection() && 
!GetIsTextFrameInserted())
     {
         AddDummyParaForTableInSection();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index fbca4aa1f3f0..aad946e81702 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -152,16 +152,24 @@ enum StoredRedlines
  * In case some state of DomainMapper_Impl should be reset before handling the
  * header/footer and should be restored once handling of header/footer is done,
  * then you can use this class to do so.
+ *
+ * note: presumably more state should be moved here.
  */
-class HeaderFooterContext
+struct SubstreamContext
 {
-    bool      m_bTextInserted;
-    sal_Int32 m_nTableDepth;
-
-public:
-    explicit HeaderFooterContext(bool bTextInserted, sal_Int32 nTableDepth);
-    bool getTextInserted() const;
-    sal_Int32 getTableDepth() const;
+    bool      bTextInserted = false;
+    /**
+     * This contains the raw table depth. nTableDepth > 0 is the same as
+     * getTableManager().isInTable(), unless we're in the first paragraph of a
+     * table, or first paragraph after a table, as the table manager is only
+     * updated once we ended the paragraph (and know if the para has the
+     * inTbl SPRM or not).
+     */
+    sal_Int32 nTableDepth = 0;
+    // deferred breaks need to be saved for RTF, probably not for DOCX
+    bool      bIsColumnBreakDeferred = false;
+    bool      bIsPageBreakDeferred = false;
+    sal_Int32 nLineBreaksDeferred = 0;
 };
 
 /// Information about a paragraph to be finished after a field end.
@@ -460,7 +468,9 @@ private:
 
     std::stack<TextAppendContext>                                              
     m_aTextAppendStack;
     std::stack<AnchoredContext>                                                
     m_aAnchoredStack;
-    std::stack<HeaderFooterContext>                                            
     m_aHeaderFooterStack;
+public: // DomainMapper needs it
+    std::stack<SubstreamContext> m_StreamStateStack;
+private:
     std::stack<std::pair<TextAppendContext, PagePartType>> 
m_aHeaderFooterTextAppendStack;
 
     std::deque<FieldContextPtr> m_aFieldStack;
@@ -471,9 +481,6 @@ private:
     bool                                                                       
     m_bSetCitation;
     bool                                                                       
     m_bSetDateValue;
     bool                                                                       
     m_bIsFirstSection;
-    bool                                                                       
     m_bIsColumnBreakDeferred;
-    bool                                                                       
     m_bIsPageBreakDeferred;
-    sal_Int32                                                                  
     m_nLineBreaksDeferred;
     /// If we want to set "sdt end" on the next character context.
     bool                                                                       
     m_bSdtEndDeferred;
     /// If we want to set "paragraph sdt end" on the next paragraph context.
@@ -485,7 +492,6 @@ private:
     bool                                                                       
     m_bStartIndex;
     bool                                                                       
     m_bStartBibliography;
     unsigned int                                                               
     m_nStartGenericField;
-    bool                                                                       
     m_bTextInserted;
     bool                                                                       
     m_bTextDeleted;
     LineNumberSettings                                                         
     m_aLineNumberSettings;
 
@@ -1104,14 +1110,6 @@ public:
     /// Document background color, applied to every page style.
     std::optional<sal_Int32> m_oBackgroundColor;
 
-    /**
-     * This contains the raw table depth. m_nTableDepth > 0 is the same as
-     * getTableManager().isInTable(), unless we're in the first paragraph of a
-     * table, or first paragraph after a table, as the table manager is only
-     * updated once we ended the paragraph (and know if the para has the
-     * inTbl SPRM or not).
-     */
-    sal_Int32 m_nTableDepth;
     /// Raw table cell depth.
     sal_Int32 m_nTableCellDepth;
 
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 922ac5bea106..09e7903b5f98 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -355,7 +355,7 @@ void SdtHelper::createPlainTextControl()
     try
     {
         bool bIsInTable = (m_rDM_Impl.hasTableManager() && 
m_rDM_Impl.getTableManager().isInTable())
-                              != (m_rDM_Impl.m_nTableDepth > 0)
+                              != (0 < 
m_rDM_Impl.m_StreamStateStack.top().nTableDepth)
                           && m_rDM_Impl.GetIsDummyParaAddedForTableInSection();
         if (bIsInTable)
             xCrsr->goRight(1, false);
@@ -459,7 +459,7 @@ void SdtHelper::createDateContentControl()
         // tdf#138093: Date selector reset, if placed inside table
         // Modified to XOR relationship and adding dummy paragraph conditions
         bool bIsInTable = (m_rDM_Impl.hasTableManager() && 
m_rDM_Impl.getTableManager().isInTable())
-                              != (m_rDM_Impl.m_nTableDepth > 0)
+                              != (0 < 
m_rDM_Impl.m_StreamStateStack.top().nTableDepth)
                           && m_rDM_Impl.GetIsDummyParaAddedForTableInSection();
         if (bIsInTable)
             xCrsr->goRight(1, false);

Reply via email to