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 <[email protected]> AuthorDate: Fri Sep 20 19:42:16 2019 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> 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 <[email protected]> AuthorDate: Fri Sep 20 17:18:41 2019 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> 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; } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
