[Libreoffice-commits] core.git: 2 commits - sw/source writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Mon Sep 23 11:36:07 UTC 2019


 sw/source/filter/ww8/wrtw8num.cxx                 |   37 ++++++++++++++++++++--
 sw/source/filter/ww8/wrtww8.hxx                   |   10 +++++
 sw/source/filter/ww8/ww8atr.cxx                   |   13 ++++++-
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   16 +++++++--
 writerfilter/source/dmapper/NumberingManager.cxx  |   25 +++++++++++---
 writerfilter/source/dmapper/NumberingManager.hxx  |    7 +++-
 6 files changed, 93 insertions(+), 15 deletions(-)

New commits:
commit 1db6fb0f831e92ac3902af9c58e33f49ede5532b
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 20 19:42:16 2019 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Mon Sep 23 13:35:19 2019 +0200

    writerfilter: fix assert importing fdo77404-1.docx
    
    The problem is that StyleSheetTable::ApplyStyleSheets() inserts a
    SwNumRule with name "WW8Num1" and then ListDef::CreateNumberingRule()
    also wants to insert a SwNumRule with name "WW8Num1" but gets an
    exception instead, leaving ListDef::m_xNumRules null, and then
    finishParagraph thinks it's numbered but there's no ListId.
    
    Try to avoid collisions of the generated names in
    ListDef::GetStyleName(), by checking what styles actually exist in the
    document (which works better in the Insert->File case), and
    on the assumption that the initialising call always happens before
    the using calls.
    
    (regression from 7992bd73a2307edce96a145e954f8e4c3ab9f57d)
    
    Change-Id: I91c98aa897c12778fb214e9690da0bae99550b93
    Reviewed-on: https://gerrit.libreoffice.org/79312
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 192b5ab70130..81acdf59ebce 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1237,9 +1237,10 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
     {
         bool bNumberingFromBaseStyle = false;
         sal_Int32 nListId = pEntry ? lcl_getListId(pEntry, GetStyleSheetTable(), bNumberingFromBaseStyle) : -1;
-        if (nListId >= 0 && !pParaContext->isSet(PROP_NUMBERING_STYLE_NAME))
+        auto const pList(GetListTable()->GetList(nListId));
+        if (pList && nListId >= 0 && !pParaContext->isSet(PROP_NUMBERING_STYLE_NAME))
         {
-            pParaContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( ListDef::GetStyleName( nListId ) ), false);
+            pParaContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( pList->GetStyleName(nListId) ), false);
             isNumberingViaStyle = true;
 
             // Indent properties from the paragraph style have priority
@@ -6075,7 +6076,12 @@ uno::Reference<container::XIndexAccess> DomainMapper_Impl::GetCurrentNumberingRu
             *pListLevel = pStyleSheetProperties->GetListLevel();
 
         // So we are in a paragraph style and it has numbering. Look up the relevant numbering rules.
-        OUString aListName = ListDef::GetStyleName(nListId);
+        auto const pList(GetListTable()->GetList(nListId));
+        OUString aListName;
+        if (pList)
+        {
+            aListName = pList->GetStyleName(nListId);
+        }
         uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier(GetTextDocument(), uno::UNO_QUERY_THROW);
         uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies();
         uno::Reference<container::XNameAccess> xNumberingStyles;
@@ -6190,7 +6196,9 @@ sal_Int32 DomainMapper_Impl::getNumberingProperty(const sal_Int32 nListId, sal_I
         if (nNumberingLevel < 0) // It seems it's valid to omit numbering level, and in that case it means zero.
             nNumberingLevel = 0;
 
-        const OUString aListName = ListDef::GetStyleName(nListId);
+        auto const pList(GetListTable()->GetList(nListId));
+        assert(pList);
+        const OUString aListName = pList->GetStyleName(nListId);
         const uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier(GetTextDocument(), uno::UNO_QUERY_THROW);
         const uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies();
         uno::Reference<container::XNameAccess> xNumberingStyles;
diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx
index 1b8a8b283f99..8f7d05e5f4d0 100644
--- a/writerfilter/source/dmapper/NumberingManager.cxx
+++ b/writerfilter/source/dmapper/NumberingManager.cxx
@@ -447,12 +447,27 @@ ListDef::~ListDef( )
 {
 }
 
-OUString ListDef::GetStyleName( sal_Int32 nId )
+OUString ListDef::GetStyleName(sal_Int32 const nId,
+    uno::Reference<container::XNameContainer> const& xStyles)
 {
-    OUString sStyleName( "WWNum" );
-    sStyleName += OUString::number( nId );
+    if (xStyles.is())
+    {
+        OUString sStyleName( "WWNum" );
+        sStyleName += OUString::number( nId );
+
+        while (xStyles.is() && xStyles->hasByName(sStyleName)) // unique
+        {
+            sStyleName += "a";
+        }
+
+        m_StyleName = sStyleName;
+    }
+    else
+    {
+// fails in rtftok test        assert(!m_StyleName.isEmpty()); // must be inited first
+    }
 
-    return sStyleName;
+    return m_StyleName;
 }
 
 uno::Sequence<uno::Sequence<beans::PropertyValue>> ListDef::GetMergedPropertyValues()
@@ -519,7 +534,7 @@ void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
                 xFactory->createInstance("com.sun.star.style.NumberingStyle"),
                 uno::UNO_QUERY_THROW );
 
-            OUString sStyleName = GetStyleName( GetId( ) );
+            OUString sStyleName = GetStyleName(GetId(), xStyles);
 
             xStyles->insertByName( sStyleName, makeAny( xStyle ) );
 
diff --git a/writerfilter/source/dmapper/NumberingManager.hxx b/writerfilter/source/dmapper/NumberingManager.hxx
index c484b7bd9803..0ba356f64f3c 100644
--- a/writerfilter/source/dmapper/NumberingManager.hxx
+++ b/writerfilter/source/dmapper/NumberingManager.hxx
@@ -170,6 +170,9 @@ private:
     // Cache for the UNO numbering rules
     css::uno::Reference< css::container::XIndexReplace > m_xNumRules;
 
+    /// mapped list style name
+    OUString m_StyleName;
+
 public:
     typedef tools::SvRef< ListDef > Pointer;
 
@@ -181,7 +184,9 @@ public:
     const AbstractListDef::Pointer& GetAbstractDefinition( ) { return m_pAbstractDef; };
 
     // Mapping functions
-    static OUString GetStyleName( sal_Int32 nId );
+    OUString GetStyleName(sal_Int32 nId,
+            css::uno::Reference<css::container::XNameContainer> const& xStyles
+                = css::uno::Reference<css::container::XNameContainer>());
 
     css::uno::Sequence< css::uno::Sequence<css::beans::PropertyValue> > GetMergedPropertyValues();
 
commit adceab34ca45128d4848edcc58affa220be87686
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 20 17:18:41 2019 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Mon Sep 23 13:35:14 2019 +0200

    sw: DOCX export of lists: handle multiple SwList with same SwNumRule
    
    This can be reproduced with ODT documents, e.g. fdo45994-2.fodt.
    
    Multiple lists use the same list style / SwNumRule - one of them will be
    the default list style of the SwList - map the others to duplicated
    SwNumRules, each of which will be exported to a new w:abstractNum.
    
    (assert is regression from 1f6b7030cbdc81e8e408e3a13bfcd01fcbdd7550)
    
    Change-Id: Ib691c7c6b0b3e6da27204d038a64f094a1bde17d
    Reviewed-on: https://gerrit.libreoffice.org/79309
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index 807c85251ed1..d9f284c3380b 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -45,9 +45,8 @@ using namespace ::com::sun::star;
 using namespace sw::types;
 using namespace sw::util;
 
-sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
+SwNumRule* MSWordExportBase::DuplicateNumRuleImpl(const SwNumRule *pRule)
 {
-    sal_uInt16 nNumId = USHRT_MAX;
     const OUString sPrefix("WW8TempExport" + OUString::number( m_nUniqueList++ ));
     SwNumRule* pMyNumRule =
             new SwNumRule( m_pDoc->GetUniqueNumRuleName( &sPrefix ),
@@ -59,6 +58,14 @@ sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8
         const SwNumFormat& rSubRule = pRule->Get(i);
         pMyNumRule->Set( i, rSubRule );
     }
+    return pMyNumRule;
+}
+
+sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
+{
+    sal_uInt16 nNumId = USHRT_MAX;
+
+    SwNumRule *const pMyNumRule = DuplicateNumRuleImpl(pRule);
 
     SwNumFormat aNumFormat( pMyNumRule->Get( nLevel ) );
     aNumFormat.SetStart( nVal );
@@ -72,6 +79,26 @@ sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8
     return nNumId;
 }
 
+// multiple SwList can be based on the same SwNumRule; ensure one w:abstractNum
+// per SwList
+sal_uInt16 MSWordExportBase::DuplicateAbsNum(OUString const& rListId,
+        SwNumRule const& rAbstractRule)
+{
+    auto const it(m_Lists.find(rListId));
+    if (it != m_Lists.end())
+    {
+        return it->second;
+    }
+    else
+    {
+        auto const pNewAbstractRule = DuplicateNumRuleImpl(&rAbstractRule);
+        assert(GetNumberingId(*pNewAbstractRule) == m_pUsedNumTable->size() - 1);
+        (void) pNewAbstractRule;
+        m_Lists.insert(std::make_pair(rListId, m_pUsedNumTable->size() - 1));
+        return m_pUsedNumTable->size() - 1;
+    }
+}
+
 // Ideally we want to map SwList to w:abstractNum and SwNumRule to w:num
 // The current approach is to keep exporting every SwNumRule to
 // 1 w:abstractNum and 1 w:num, and then add extra w:num via this function
@@ -79,11 +106,14 @@ sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8
 // of course this will end up exporting some w:num that aren't actually used.
 sal_uInt16 MSWordExportBase::OverrideNumRule(
         SwNumRule const& rExistingRule,
+        OUString const& rListId,
         SwNumRule const& rAbstractRule)
 {
     assert(&rExistingRule != &rAbstractRule);
     auto const numdef = GetNumberingId(rExistingRule);
-    auto const absnumdef = GetNumberingId(rAbstractRule);
+    auto const absnumdef = rListId == rAbstractRule.GetDefaultListId()
+        ? GetNumberingId(rAbstractRule)
+        : DuplicateAbsNum(rListId, rAbstractRule);
     auto const mapping = std::make_pair(numdef, absnumdef);
 
     auto it = m_OverridingNumsR.find(mapping);
@@ -91,6 +121,7 @@ sal_uInt16 MSWordExportBase::OverrideNumRule(
     {
         it = m_OverridingNumsR.insert(std::make_pair(mapping, m_pUsedNumTable->size())).first;
         m_OverridingNums.insert(std::make_pair(m_pUsedNumTable->size(), mapping));
+
         m_pUsedNumTable->push_back(nullptr); // dummy, it's unique_ptr...
         ++m_nUniqueList; // counter for DuplicateNumRule...
     }
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 5ca2c60fed45..13661d22e748 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -464,6 +464,9 @@ public:
     std::map<size_t, std::pair<size_t, size_t>> m_OverridingNums;
     /// same in reverse
     std::map<std::pair<size_t, size_t>, size_t> m_OverridingNumsR;
+    /// list-id -> abstractnumdef index
+    std::map<OUString, size_t> m_Lists;
+
     const SwTextNode *m_pTopNodeOfHdFtPage; ///< Top node of host page when in hd/ft
     std::map< sal_uInt16, sal_uInt16 > m_aRuleDuplicates; //map to Duplicated numrules
     std::stack< sal_Int32 > m_aCurrentCharPropStarts; ///< To remember the position in a run.
@@ -653,10 +656,17 @@ public:
     /// completely new list based on this one and export that instead,
     /// which duplicates words behaviour in this respect.
     sal_uInt16 DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal );
+    SwNumRule * DuplicateNumRuleImpl(const SwNumRule *pRule);
+
+    /// check if a new abstractNum is needed for this list
+    sal_uInt16 DuplicateAbsNum(OUString const& rListId,
+                               SwNumRule const& rAbstractRule);
+
 
     /// Create a overriding numbering definition (if it does not yet exist)
     /// @return index of the overriding numbering definition
     sal_uInt16 OverrideNumRule(SwNumRule const& rExistingRule,
+                               OUString const& rListId,
                                SwNumRule const& rAbstractRule);
 
     /// Access to the attribute output class.
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 60de4f0df789..7ca8b34cb9a9 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -3561,6 +3561,7 @@ void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule )
                             // tdf#95848 find the abstract list definition
                             OUString const listId(pTextNd->GetListId());
                             if (!listId.isEmpty()
+                                // default list id uses the 1:1 mapping
                                 && listId != pRule->GetDefaultListId())
                             {
                                 SwList const*const pList(
@@ -3571,8 +3572,16 @@ void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule )
                                         GetExport().m_pDoc->FindNumRulePtr(
                                             pList->GetDefaultListStyleName()));
                                     assert(pAbstractRule);
-                                    nNumId = GetExport().OverrideNumRule(
-                                            *pRule, *pAbstractRule);
+                                    if (pAbstractRule == pRule)
+                                    {
+                                        // different list, but no override
+                                        nNumId = GetExport().DuplicateAbsNum(listId, *pAbstractRule);
+                                    }
+                                    else
+                                    {
+                                        nNumId = GetExport().OverrideNumRule(
+                                                *pRule, listId, *pAbstractRule);
+                                    }
                                     assert(nNumId != USHRT_MAX);
                                     ++nNumId;
                                 }


More information about the Libreoffice-commits mailing list