DOCX import of w:numPicBullet

Change-Id: Ifc827d5180ce1dc0e3db095c2b92023f4c2d72ec
diff --git a/writerfilter/inc/dmapper/DomainMapper.hxx b/writerfilter/inc/dmapper/DomainMapper.hxx
index 519367b..8dc82fe 100644
--- a/writerfilter/inc/dmapper/DomainMapper.hxx
+++ b/writerfilter/inc/dmapper/DomainMapper.hxx
@@ -111,6 +111,9 @@ public:
    boost::shared_ptr< StyleSheetTable > GetStyleSheetTable( );
    GraphicZOrderHelper* graphicZOrderHelper();

    /// Return the first from the pending (not inserted to the document) shapes, if there are any.
    com::sun::star::uno::Reference<com::sun::star::drawing::XShape> PopPendingShape();

    bool IsInHeaderFooter() const;
    /**
     @see DomainMapper_Impl::processDeferredCharacterProperties()
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 276aaa5..2744ac30f 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3425,14 +3425,24 @@ void DomainMapper::markLastParagraphInSection( )

void DomainMapper::lcl_startShape( uno::Reference< drawing::XShape > xShape )
{
    m_pImpl->PushShapeContext( xShape );
    lcl_startParagraphGroup();
    if (m_pImpl->GetTopContext())
    {
        m_pImpl->PushShapeContext( xShape );
        lcl_startParagraphGroup();
    }
    else
        // No context? Then this image should not appear directly inside the
        // document, just save it for later usage.
        m_pImpl->PushPendingShape(xShape);
}

void DomainMapper::lcl_endShape( )
{
    lcl_endParagraphGroup();
    m_pImpl->PopShapeContext( );
    if (m_pImpl->GetTopContext())
    {
        lcl_endParagraphGroup();
        m_pImpl->PopShapeContext( );
    }
}

void DomainMapper::PushStyleSheetProperties( PropertyMapPtr pStyleProperties, bool bAffectTableMngr )
@@ -3973,6 +3983,11 @@ GraphicZOrderHelper* DomainMapper::graphicZOrderHelper()
    return zOrderHelper.get();
}

uno::Reference<drawing::XShape> DomainMapper::PopPendingShape()
{
    return m_pImpl->PopPendingShape();
}

bool DomainMapper::IsInHeaderFooter() const
{
    return m_pImpl->IsInHeaderFooter();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index b4ca0fb..175e53f 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1614,6 +1614,22 @@ void DomainMapper_Impl::PopAnnotation()

}

void DomainMapper_Impl::PushPendingShape( const uno::Reference< drawing::XShape > xShape )
{
    m_aPendingShapes.push_back(xShape);
}

uno::Reference<drawing::XShape> DomainMapper_Impl::PopPendingShape()
{
    uno::Reference<drawing::XShape> xRet;
    if (!m_aPendingShapes.empty())
    {
        xRet = m_aPendingShapes.front();
        m_aPendingShapes.pop_front();
    }
    return xRet;
}

void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape > xShape )
{
    if (m_aTextAppendStack.empty())
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index d59ffd9..11adedf 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -324,6 +324,7 @@ private:
    ContextStack            m_aContextStack;
    FontTablePtr            m_pFontTable;
    ListsManager::Pointer   m_pListTable;
    std::deque< com::sun::star::uno::Reference< com::sun::star::drawing::XShape > > m_aPendingShapes;
    StyleSheetTablePtr      m_pStyleSheetTable;
    ThemeTablePtr           m_pThemeTable;
    SettingsTablePtr        m_pSettingsTable;
@@ -516,6 +517,10 @@ public:

    void PushShapeContext( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape );
    void PopShapeContext();
    /// Add a pending shape: it's currently inserted into the document, but it should be removed before the import finishes.
    void PushPendingShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape );
    /// Get the first pending shape, if there are any.
    ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > PopPendingShape();

    void PushPageHeader(SectionPropertyMap::PageType eType);
    void PushPageFooter(SectionPropertyMap::PageType eType);
diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx
index 2a61ec1..9308d82 100644
--- a/writerfilter/source/dmapper/NumberingManager.cxx
+++ b/writerfilter/source/dmapper/NumberingManager.cxx
@@ -277,7 +277,11 @@ uno::Sequence< beans::PropertyValue > ListLevel::GetLevelProperties( )

    sal_Int16 nNumberFormat = ConversionHelper::ConvertNumberingType(m_nNFC);
    if( m_nNFC >= 0)
    {
        if (!m_sGraphicURL.isEmpty())
            nNumberFormat = style::NumberingType::BITMAP;
        aNumberingProperties.push_back( MAKE_PROPVAL(PROP_NUMBERING_TYPE, nNumberFormat ));
    }

    if( m_nJC >= 0 && m_nJC <= sal::static_int_cast<sal_Int32>(sizeof(aWWToUnoAdjust) / sizeof(sal_Int16)) )
        aNumberingProperties.push_back( MAKE_PROPVAL(PROP_ADJUST, aWWToUnoAdjust[m_nJC]));
@@ -287,6 +291,8 @@ uno::Sequence< beans::PropertyValue > ListLevel::GetLevelProperties( )
        // todo: this is not the bullet char
        if( nNumberFormat == style::NumberingType::CHAR_SPECIAL && !m_sBulletChar.isEmpty() )
            aNumberingProperties.push_back( MAKE_PROPVAL(PROP_BULLET_CHAR, m_sBulletChar.copy(0,1)));
        if (!m_sGraphicURL.isEmpty())
            aNumberingProperties.push_back(MAKE_PROPVAL(PROP_GRAPHIC_URL, m_sGraphicURL));
    }

    aNumberingProperties.push_back( MAKE_PROPVAL( PROP_LISTTAB_STOP_POSITION, m_nTabstop ) );
@@ -399,6 +405,35 @@ void ListLevel::AddParaProperties( uno::Sequence< beans::PropertyValue >* props 
    }
}

NumPicBullet::NumPicBullet()
    : m_nId(0)
{
}

NumPicBullet::~NumPicBullet()
{
}

void NumPicBullet::SetId(sal_Int32 nId)
{
    m_nId = nId;
}

void NumPicBullet::SetShape(uno::Reference<drawing::XShape> xShape)
{
    m_xShape = xShape;
}

sal_Int32 NumPicBullet::GetId()
{
    return m_nId;
}

uno::Reference<drawing::XShape> NumPicBullet::GetShape()
{
    return m_xShape;
}

//--------------------------------------- AbstractListDef implementation

AbstractListDef::AbstractListDef( ) :
@@ -687,12 +722,23 @@ ListsManager::~ListsManager( )

void ListsManager::lcl_attribute( Id nName, Value& rVal )
{
    OSL_ENSURE( m_pCurrentDefinition.get(), "current entry has to be set here");
    if(!m_pCurrentDefinition.get())
        return ;
    ListLevel::Pointer pCurrentLvl;

    if (nName != NS_ooxml::LN_CT_NumPicBullet_numPicBulletId)
    {
        OSL_ENSURE( m_pCurrentDefinition.get(), "current entry has to be set here");
        if(!m_pCurrentDefinition.get())
            return ;
        pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );
    }
    else
    {
        SAL_WARN_IF(!m_pCurrentNumPicBullet.get(), "writerfilter", "current entry has to be set here");
        if (!m_pCurrentNumPicBullet.get())
            return;
    }
    int nIntValue = rVal.getInt();

    ListLevel::Pointer pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );


    switch(nName)
@@ -786,6 +832,9 @@ void ListsManager::lcl_attribute( Id nName, Value& rVal )
            // TODO Do something of that
        }
        break;
        case NS_ooxml::LN_CT_NumPicBullet_numPicBulletId:
            m_pCurrentNumPicBullet->SetId(rVal.getString().toInt32());
        break;
        default:
        {
#if OSL_DEBUG_LEVEL > 0
@@ -809,7 +858,9 @@ void ListsManager::lcl_sprm( Sprm& rSprm )
    sal_uInt32 nSprmId = rSprm.getId();
    if( m_pCurrentDefinition.get() ||
        nSprmId == NS_ooxml::LN_CT_Numbering_abstractNum ||
        nSprmId == NS_ooxml::LN_CT_Numbering_num )
        nSprmId == NS_ooxml::LN_CT_Numbering_num ||
        (nSprmId == NS_ooxml::LN_CT_NumPicBullet_pict && m_pCurrentNumPicBullet.get()) ||
        nSprmId == NS_ooxml::LN_CT_Numbering_numPicBullet)
    {
        sal_Int32 nIntValue = rSprm.getValue()->getInt();
        switch( nSprmId )
@@ -846,6 +897,47 @@ void ListsManager::lcl_sprm( Sprm& rSprm )
                }
            }
            break;
            case NS_ooxml::LN_CT_Numbering_numPicBullet:
            {
                writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
                if (pProperties.get())
                {
                    NumPicBullet::Pointer numPicBullet(new NumPicBullet());
                    m_pCurrentNumPicBullet = numPicBullet;
                    pProperties->resolve(*this);
                    m_aNumPicBullets.push_back(numPicBullet);
                    m_pCurrentNumPicBullet = NumPicBullet::Pointer();
                }
            }
            break;
            case NS_ooxml::LN_CT_NumPicBullet_pict:
            {
                uno::Reference<drawing::XShape> xShape = m_rDMapper.PopPendingShape();
                m_pCurrentNumPicBullet->SetShape(xShape);
            }
            break;
            case NS_ooxml::LN_CT_Lvl_lvlPicBulletId:
            {
                uno::Reference<drawing::XShape> xShape;
                for (std::vector<NumPicBullet::Pointer>::iterator it = m_aNumPicBullets.begin(); it != m_aNumPicBullets.end(); ++it)
                {
                    if ((*it)->GetId() == nIntValue)
                    {
                        xShape = (*it)->GetShape();
                        break;
                    }
                }
                if (xShape.is())
                {
                    uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
                    m_pCurrentDefinition->GetCurrentLevel()->SetGraphicURL(xPropertySet->getPropertyValue("GraphicURL").get<OUString>());

                    // Now that we saved the URL of the graphic, remove it from the document.
                    uno::Reference<lang::XComponent> xShapeComponent(xShape, uno::UNO_QUERY);
                    xShapeComponent->dispose();
                }
            }
            break;
            case NS_ooxml::LN_CT_Num_abstractNumId:
            {
                sal_Int32 nAbstractNumId = rSprm.getValue()->getInt();
diff --git a/writerfilter/source/dmapper/NumberingManager.hxx b/writerfilter/source/dmapper/NumberingManager.hxx
index b52aeb4..2a109ff8 100644
--- a/writerfilter/source/dmapper/NumberingManager.hxx
+++ b/writerfilter/source/dmapper/NumberingManager.hxx
@@ -52,6 +52,7 @@ class ListLevel : public PropertyMap
    OUString                               m_sRGBXchNums;     //LN_RGBXCHNUMS
    sal_Int16                                     m_nXChFollow;      //LN_IXCHFOLLOW
    OUString                               m_sBulletChar;
    OUString                               m_sGraphicURL;
    sal_Int32                                     m_nTabstop;
    boost::shared_ptr< StyleSheetEntry >          m_pParaStyle;
    bool                                          m_outline;
@@ -79,6 +80,7 @@ public:
    // Setters for the import
    void SetValue( Id nId, sal_Int32 nValue );
    void SetBulletChar( OUString sValue ) { m_sBulletChar = sValue; };
    void SetGraphicURL( OUString sValue ) { m_sGraphicURL = sValue; };
    void SetParaStyle( boost::shared_ptr< StyleSheetEntry > pStyle );
    void AddRGBXchNums( OUString sValue ) { m_sRGBXchNums += sValue; };

@@ -106,6 +108,23 @@ private:
    void AddParaProperties( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* props );
};

/// Represents a numbering picture bullet: an id and a graphic.
class NumPicBullet
{
public:
    typedef boost::shared_ptr<NumPicBullet> Pointer;
    NumPicBullet();
    virtual ~NumPicBullet();

    void SetId(sal_Int32 nId);
    sal_Int32 GetId();
    void SetShape(com::sun::star::uno::Reference<com::sun::star::drawing::XShape> xShape);
    com::sun::star::uno::Reference<com::sun::star::drawing::XShape> GetShape();
private:
    sal_Int32 m_nId;
    com::sun::star::uno::Reference<com::sun::star::drawing::XShape> m_xShape;
};

class AbstractListDef
{
private:
@@ -200,12 +219,14 @@ private:
        com::sun::star::lang::XMultiServiceFactory >    m_xFactory;

    // The numbering entries
    std::vector< NumPicBullet::Pointer >                m_aNumPicBullets;
    std::vector< AbstractListDef::Pointer >             m_aAbstractLists;
    std::vector< ListDef::Pointer >                     m_aLists;


    // These members are used for import only
    AbstractListDef::Pointer                            m_pCurrentDefinition;
    NumPicBullet::Pointer                               m_pCurrentNumPicBullet;
    bool                                                m_bIsLFOImport;

    AbstractListDef::Pointer    GetAbstractList( sal_Int32 nId );
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index 1ad4c11..08f3ac2 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -322,6 +322,7 @@ const OUString& PropertyNameSupplier::GetName( PropertyIds eId ) const
            case PROP_SHADOW_FORMAT: sName = "ShadowFormat"; break;
            case PROP_RELATIVE_WIDTH: sName = "RelativeWidth"; break;
            case PROP_IS_WIDTH_RELATIVE: sName = "IsWidthRelative"; break;
            case PROP_GRAPHIC_URL: sName = "GraphicURL"; break;
        }
        ::std::pair<PropertyNameMap_t::iterator,bool> aInsertIt =
                m_pImpl->aNameMap.insert( PropertyNameMap_t::value_type( eId, sName ));
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index 460ff33..2ee7119 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -294,6 +294,7 @@ enum PropertyIds
        ,PROP_SHADOW_FORMAT
        ,PROP_RELATIVE_WIDTH
        ,PROP_IS_WIDTH_RELATIVE
        ,PROP_GRAPHIC_URL
    };
struct PropertyNameSupplier_Impl;
class PropertyNameSupplier
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 8bfce16..f4ecb34 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -23390,6 +23390,11 @@
    <resource name="CT_MultiLevelType" resource="Value" tag="numbering">
      <attribute name="val" tokenid="ooxml:CT_MultiLevelType_val" action="setValue"/>
    </resource>
    <resource name="CT_NumPicBullet" resource="Properties" tag="numbering">
      <kind name="paragraph"/>
      <element name="pict" tokenid="ooxml:CT_NumPicBullet_pict"/>
      <attribute name="numPicBulletId" tokenid="ooxml:CT_NumPicBullet_numPicBulletId"/>
    </resource>
    <resource name="CT_AbstractNum" resource="Properties" tag="numbering">
      <kind name="paragraph"/>
      <element name="nsid" tokenid="rtf:LSID"/>