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 )
