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           |  105 +++++-------
 writerfilter/source/dmapper/DomainMapper_Impl.hxx           |   41 ++--
 writerfilter/source/dmapper/SdtHelper.cxx                   |    2 
 6 files changed, 105 insertions(+), 82 deletions(-)

New commits:
commit ae3f45e39b59583a60a751dcb54889f1ee28197b
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jan 31 14:33:46 2024 +0100
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Thu Feb 1 12:43:49 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/+/162848
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.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 70dd0974c616..d0b2ed0f2c2e 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -82,6 +82,19 @@ DECLARE_RTFEXPORT_TEST(testTdf158586_1, 
"tdf158586_pageBreak1.rtf")
     assertXPathContent(pLayout, "/root/page[2]/body//txt", "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", "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 4ca1900ee173..c4001cf0fe61 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3257,7 +3257,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())
         {
@@ -3265,7 +3266,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);
@@ -3286,11 +3287,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 d4da6625be61..2461c62b023b 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -339,9 +339,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),
@@ -350,7 +347,6 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bStartIndex(false),
         m_bStartBibliography(false),
         m_nStartGenericField(0),
-        m_bTextInserted(false),
         m_bTextDeleted(false),
         m_sCurrentPermId(0),
         m_bFrameDirectionSet(false),
@@ -397,7 +393,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_nLastTableCellParagraphDepth(0),
         m_bHasFtn(false),
@@ -414,6 +409,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()) {
@@ -453,6 +449,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)
@@ -1562,21 +1559,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;
@@ -1585,14 +1583,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;
     }
@@ -1600,17 +1599,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;
@@ -1619,9 +1619,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)
@@ -2317,7 +2318,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)
@@ -2614,7 +2617,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;
@@ -2769,7 +2772,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);
@@ -2799,7 +2802,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()
@@ -2809,7 +2813,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);
@@ -2976,8 +2980,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;
@@ -3077,7 +3085,7 @@ void DomainMapper_Impl::appendTextPortion( const 
OUString& rString, const Proper
                     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)
                     {
@@ -3477,9 +3485,7 @@ void 
DomainMapper_Impl::ConvertHeaderFooterToTextFrame(bool bDynamicHeightTop, b
 void DomainMapper_Impl::PushPageHeaderFooter(bool bHeader, 
SectionPropertyMap::PageType eType)
 {
     m_bSaveParaHadField = m_bParaHadField;
-    m_aHeaderFooterStack.push(HeaderFooterContext(m_bTextInserted, 
m_nTableDepth));
-    m_bTextInserted = false;
-    m_nTableDepth = 0;
+    m_StreamStateStack.emplace();
 
     const PropertyIds ePropIsOn = bHeader? PROP_HEADER_IS_ON: 
PROP_FOOTER_IS_ON;
     const PropertyIds ePropShared = bHeader? PROP_HEADER_IS_SHARED: 
PROP_FOOTER_IS_SHARED;
@@ -3598,12 +3604,8 @@ void DomainMapper_Impl::PopPageHeaderFooter()
     }
     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;
 }
@@ -3728,7 +3730,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;
@@ -4584,7 +4586,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())
     {
@@ -5591,18 +5593,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)
@@ -8240,7 +8230,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;
@@ -8362,9 +8352,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;
                             }
                         }
                     }
@@ -8436,8 +8426,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();
     }
@@ -8478,7 +8470,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 );
@@ -8557,7 +8549,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 76be3e6701e3..7b6c504bc3a9 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.
@@ -465,8 +473,11 @@ 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, bool>>                             
     m_aHeaderFooterTextAppendStack;
+
     std::deque<FieldContextPtr> m_aFieldStack;
     bool m_bForceGenericFields;
     /// Type of decimal symbol associated to the document language in Writer 
locale definition
@@ -475,9 +486,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.
@@ -489,7 +497,6 @@ private:
     bool                                                                       
     m_bStartIndex;
     bool                                                                       
     m_bStartBibliography;
     unsigned int                                                               
     m_nStartGenericField;
-    bool                                                                       
     m_bTextInserted;
     bool                                                                       
     m_bTextDeleted;
     LineNumberSettings                                                         
     m_aLineNumberSettings;
 
@@ -1102,14 +1109,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;
     /// Table cell depth of the last finished paragraph.
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 041802147605..8b5bf401477f 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -387,7 +387,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