oox/inc/drawingml/textparagraphpropertiescontext.hxx    |   12 +++
 oox/source/drawingml/textparagraphpropertiescontext.cxx |   50 +++++++++++++++-
 2 files changed, 60 insertions(+), 2 deletions(-)

New commits:
commit 857e609d34f975d04abede09b0fdd278a1fc9a5f
Author:     Dr. David Alan Gilbert <[email protected]>
AuthorDate: Tue Oct 14 19:00:23 2025 +0100
Commit:     David Gilbert <[email protected]>
CommitDate: Thu Oct 30 15:56:49 2025 +0100

    tdf#168406: oox: Add mask to track numbered list
    
    Add the ability to track which level we're in a numbered list
    at.
    The code to track it is in TextParagraphPropertiesContext but
    it needs to be tracked across multiple paragraphs within a
    body, so pass a pointer in (pointer because only some situations
    need tracking).
    
    Change-Id: I76ca6034c94322295af118391a1f21fe07fc193d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192412
    Tested-by: Jenkins
    Reviewed-by: David Gilbert <[email protected]>

diff --git a/oox/inc/drawingml/textparagraphpropertiescontext.hxx 
b/oox/inc/drawingml/textparagraphpropertiescontext.hxx
index 33b8493aa228..d18febc09bbf 100644
--- a/oox/inc/drawingml/textparagraphpropertiescontext.hxx
+++ b/oox/inc/drawingml/textparagraphpropertiescontext.hxx
@@ -33,16 +33,26 @@ class TextParagraphPropertiesContext final : public 
::oox::core::ContextHandler2
 public:
     TextParagraphPropertiesContext( ::oox::core::ContextHandler2Helper const & 
rParent,
             const ::oox::AttributeList& rAttributes,
-            TextParagraphProperties& rTextParagraphProperties );
+            TextParagraphProperties& rTextParagraphProperties,
+            uint16_t* pListNumberingMask = nullptr);
     virtual ~TextParagraphPropertiesContext() override;
 
     virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 
Element, const ::oox::AttributeList& rAttribs ) override;
 
 private:
+    // Returns True iff we're tracking numbered lists, and we were not already 
in a numbered list at this level
+    bool markListNumbered();
+    void markListUnnumbered();
+
     TextParagraphProperties& mrTextParagraphProperties;
     BulletList&     mrBulletList;
     std::vector< css::style::TabStop >  maTabList;
     std::shared_ptr< BlipFillProperties > mxBlipProps;
+
+    // A pointer to an integer mask where we track the list status
+    // If bit 'n' is 1 then we're in a numbered list at that level
+    // (n=0 is what pptx calls level 1)
+    uint16_t*              mpListNumberingMask;
 };
 
 }
diff --git a/oox/source/drawingml/textparagraphpropertiescontext.cxx 
b/oox/source/drawingml/textparagraphpropertiescontext.cxx
index c94954daf0e3..8ae21020441b 100644
--- a/oox/source/drawingml/textparagraphpropertiescontext.cxx
+++ b/oox/source/drawingml/textparagraphpropertiescontext.cxx
@@ -76,10 +76,12 @@ double  lclGetGraphicAspectRatio( const Reference< XGraphic 
>& rxGraphic )
 // CT_TextParagraphProperties
 TextParagraphPropertiesContext::TextParagraphPropertiesContext( 
ContextHandler2Helper const & rParent,
                                                                 const 
AttributeList& rAttribs,
-                                                                
TextParagraphProperties& rTextParagraphProperties )
+                                                                
TextParagraphProperties& rTextParagraphProperties,
+                                                                uint16_t* 
pListNumberingMask)
 : ContextHandler2( rParent )
 , mrTextParagraphProperties( rTextParagraphProperties )
 , mrBulletList( rTextParagraphProperties.getBulletList() )
+, mpListNumberingMask( pListNumberingMask )
 {
     OUString sValue;
 
@@ -199,6 +201,52 @@ 
TextParagraphPropertiesContext::~TextParagraphPropertiesContext()
         rPropertyMap.setProperty( PROP_ParaAdjust, 
*mrTextParagraphProperties.getParaAdjust());
 }
 
+bool TextParagraphPropertiesContext::markListNumbered()
+{
+    sal_Int16 nLevel = mrTextParagraphProperties.getLevel();
+
+    // We only track list state in some situations
+    if (mpListNumberingMask == nullptr)
+    {
+        return false;
+    }
+
+    uint16_t nOldMask = *mpListNumberingMask;
+    // The bit that represents this level  (..0001000)
+    uint16_t nOurBit = static_cast<uint16_t>(1) << nLevel;
+
+    uint16_t nTmp = nOldMask;
+    // Clears all bits at our level and lower (..0000xxx)
+    nTmp &= nOurBit - 1;
+    // and put our bit in (..0001xxx)
+    nTmp |= nOurBit;
+
+    *mpListNumberingMask = nTmp;
+
+    return (nOldMask & nOurBit) == 0;
+}
+
+void TextParagraphPropertiesContext::markListUnnumbered()
+{
+    sal_Int16 nLevel = mrTextParagraphProperties.getLevel();
+
+    // We only track list state in some situations
+    if (mpListNumberingMask == nullptr)
+    {
+        return;
+    }
+
+    uint16_t nOldMask = *mpListNumberingMask;
+    // The bit that represents this level  (..0001000)
+    uint16_t nOurBit = static_cast<uint16_t>(1) << nLevel;
+
+    uint16_t nTmp = nOldMask;
+    // Clears all bits at our level and lower (..0000xxx)
+    nTmp &= nOurBit - 1;
+
+    *mpListNumberingMask = nTmp;
+}
+
 ContextHandlerRef TextParagraphPropertiesContext::onCreateContext( sal_Int32 
aElementToken, const AttributeList& rAttribs )
 {
     switch( aElementToken )

Reply via email to