sw/inc/list.hxx | 4 +- sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 3 - sw/source/filter/ww8/attributeoutputbase.hxx | 4 ++ sw/source/filter/ww8/docxattributeoutput.cxx | 12 ++++++ sw/source/filter/ww8/docxattributeoutput.hxx | 3 + sw/source/filter/ww8/rtfattributeoutput.cxx | 2 - sw/source/filter/ww8/rtfexport.cxx | 4 +- sw/source/filter/ww8/wrtw8num.cxx | 50 +++++++++++++++++++++++---- sw/source/filter/ww8/wrtww8.hxx | 11 +++++ sw/source/filter/ww8/ww8atr.cxx | 29 ++++++++++++++- 10 files changed, 107 insertions(+), 15 deletions(-)
New commits: commit 1f6b7030cbdc81e8e408e3a13bfcd01fcbdd7550 Author: Michael Stahl <[email protected]> AuthorDate: Wed Sep 4 12:27:52 2019 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Thu Sep 5 10:18:12 2019 +0200 tdf#95848 sw: DOCX export: crude implementation of abstractNum mapping The abstractNum needs to correspond to a SwList, not to a SwNumRule as it is currently implemented. Add a mapping to MSWordExportBase for "overriding" numbering definitions; these are added to m_pUsedNumTable, which appears to be necessary to interact with DuplicateNumRule(), but here we just add nullpointers, because we don't need to modify the SwNumrule, and neither do we want the vector to double-delete it. The mapping is created while iterating over the document, in AttributeOutputBase::ParaNumRule(). It turns out that this approach would work for WW8 too as DuplicateNumRule() was originally added for that format but it won't work easily for RTF; in the DOCX case the WriteNumbering() is called after the main text and footnotes/endnotes, but with RTF it's the other way around :( Change-Id: Ia0409f5ad0b2e089005024ef7f61850a06d4dcbe Reviewed-on: https://gerrit.libreoffice.org/78607 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/inc/list.hxx b/sw/inc/list.hxx index 1cfdad5e0716..d8b3e16943ea 100644 --- a/sw/inc/list.hxx +++ b/sw/inc/list.hxx @@ -24,6 +24,8 @@ #include <rtl/ustring.hxx> #include <memory> +#include "swdllapi.h" + class SwNumRule; class SwNodes; class SwNodeNum; @@ -40,7 +42,7 @@ class SwList const OUString & GetListId() const; - const OUString & GetDefaultListStyleName() const; + SW_DLLPUBLIC const OUString & GetDefaultListStyleName() const; void SetDefaultListStyleName(OUString const&); void InsertListItem( SwNodeNum& rNodeNum, diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index ed6bcc309c93..88e65268cf01 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -66,8 +66,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121374_sectionHF2, "tdf121374_sectionHF2.doc") CPPUNIT_ASSERT( xHeaderText->getString().startsWith("virkamatka-anomus") ); } -// TODO export has the same wrong assumption that abstractNum = SwNumRule -DECLARE_SW_EXPORT_TEST(testTdf95848, "tdf95848.docx", nullptr, Test) +DECLARE_OOXMLEXPORT_TEST(testTdf95848, "tdf95848.docx") { OUString listId; OUString listStyle; diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index b6eca7f2da22..ef681cf01e5a 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -346,6 +346,10 @@ public: /// Definition of a numbering instance. virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule ) = 0; + /// Numbering defintion that overrides abstract numbering definition + virtual void OverrideNumberingDefinition(sal_uInt16 /*nNum*/, sal_uInt16 /*nAbstractNum*/) + { assert(false); } // TODO implement for WW8/RTF + /// Start of the abstract numbering definition instance. virtual void StartAbstractNumbering( sal_uInt16 /*nId*/ ) {} diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index debba8ae9ae1..deaf3fd59917 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -6558,6 +6558,18 @@ void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule & m_pSerializer->endElementNS( XML_w, XML_num ); } +void DocxAttributeOutput::OverrideNumberingDefinition( + sal_uInt16 const nNum, sal_uInt16 const nAbstractNum) +{ + m_pSerializer->startElementNS(XML_w, XML_num, FSNS(XML_w, XML_numId), OString::number(nNum)); + + m_pSerializer->singleElementNS(XML_w, XML_abstractNumId, FSNS(XML_w, XML_val), OString::number(nAbstractNum)); + + // TODO: write SwNumRule into w:lvlOverride + + m_pSerializer->endElementNS( XML_w, XML_num ); +} + void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId ) { const SwNumRule* pRule = (*m_rExport.m_pUsedNumTable)[nId - 1]; diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 899c99f45a04..d40a6c317342 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -323,6 +323,9 @@ public: /// Definition of a numbering instance. virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule ) override; + /// Numbering defintion that overrides abstract numbering definition + virtual void OverrideNumberingDefinition(sal_uInt16 nNum, sal_uInt16 nAbstractNum) override; + /// Start of the abstract numbering definition instance. virtual void StartAbstractNumbering( sal_uInt16 nId ) override; diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx index 4b8938dd0e5d..8d9321b71798 100644 --- a/sw/source/filter/ww8/wrtw8num.cxx +++ b/sw/source/filter/ww8/wrtw8num.cxx @@ -70,6 +70,31 @@ sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 return nNumId; } +// 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 +// that reference an existing w:abstractNum and may override its formatting; +// of course this will end up exporting some w:num that aren't actually used. +sal_uInt16 MSWordExportBase::OverrideNumRule( + SwNumRule const& rExistingRule, + SwNumRule const& rAbstractRule) +{ + assert(&rExistingRule != &rAbstractRule); + auto const numdef = GetNumberingId(rExistingRule); + auto const absnumdef = GetNumberingId(rAbstractRule); + auto const mapping = std::make_pair(numdef, absnumdef); + + auto it = m_OverridingNumsR.find(mapping); + if (it == m_OverridingNumsR.end()) + { + 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... + } + return it->second; +} + sal_uInt16 MSWordExportBase::GetNumberingId( const SwNumRule& rNumRule ) { if ( !m_pUsedNumTable ) @@ -179,9 +204,17 @@ void MSWordExportBase::NumberingDefinitions() // Write static data of SwNumRule - LSTF for ( sal_uInt16 n = 0; n < nCount; ++n ) { - const SwNumRule& rRule = *(*m_pUsedNumTable)[ n ]; - - AttrOutput().NumberingDefinition( n + 1, rRule ); + const SwNumRule *const pRule = (*m_pUsedNumTable)[ n ]; + if (pRule) + { + AttrOutput().NumberingDefinition(n + 1, *pRule); + } + else + { + auto it = m_OverridingNums.find(n); + assert(it != m_OverridingNums.end()); + AttrOutput().OverrideNumberingDefinition(n + 1, it->second.second + 1); + } } } @@ -357,6 +390,11 @@ void MSWordExportBase::AbstractNumberingDefinitions() for( n = 0; n < nCount; ++n ) { + if (nullptr == (*m_pUsedNumTable)[ n ]) + { + continue; + } + AttrOutput().StartAbstractNumbering( n + 1 ); const SwNumRule& rRule = *(*m_pUsedNumTable)[ n ]; diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 4d9e637f442d..c35163c067b8 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -460,6 +460,10 @@ public: const SfxItemSet* m_pISet; // for double attributes WW8_WrPct* m_pPiece; // Pointer to Piece-Table std::unique_ptr<SwNumRuleTable> m_pUsedNumTable; // all used NumRules + /// overriding numdef index -> (existing numdef index, abstractnumdef index) + 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; 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. @@ -650,6 +654,11 @@ public: /// which duplicates words behaviour in this respect. sal_uInt16 DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal ); + /// Create a overriding numbering definition (if it does not yet exist) + /// @return index of the overriding numbering definition + sal_uInt16 OverrideNumRule(SwNumRule const& rExistingRule, + SwNumRule const& rAbstractRule); + /// Access to the attribute output class. virtual AttributeOutputBase& AttrOutput() const = 0; diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index d3cc0bedfff4..6aa988a4caa1 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -94,6 +94,8 @@ #include <IDocumentSettingAccess.hxx> #include <IDocumentFieldsAccess.hxx> #include <IDocumentStylePoolAccess.hxx> +#include <IDocumentListsAccess.hxx> +#include <list.hxx> #include <docary.hxx> #include <pam.hxx> #include <paratr.hxx> @@ -3555,6 +3557,28 @@ void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule ) if ( USHRT_MAX != nNumId ) ++nNumId; } + else if (GetExport().GetExportFormat() == MSWordExportBase::DOCX) // FIXME + { + // tdf#95848 find the abstract list definition + OUString const listId(pTextNd->GetListId()); + if (!listId.isEmpty() + && listId != pRule->GetDefaultListId()) + { + SwList const*const pList( + GetExport().m_pDoc->getIDocumentListsAccess().getListByName(listId)); + if (pList) + { + SwNumRule const*const pAbstractRule( + GetExport().m_pDoc->FindNumRulePtr( + pList->GetDefaultListStyleName())); + assert(pAbstractRule); + nNumId = GetExport().OverrideNumRule( + *pRule, *pAbstractRule); + assert(nNumId != USHRT_MAX); + ++nNumId; + } + } + } } else { commit 276156a882fb5bd5a60411f636ce76f6e46f7bc7 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 3 18:37:34 2019 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Thu Sep 5 10:18:04 2019 +0200 sw: rename one MSWordExportBase::GetId() overload Change-Id: I9d87b5e987dc60431d8de5f5dde0cf7cc436bf97 Reviewed-on: https://gerrit.libreoffice.org/78606 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index c9705c740717..80c677fdf7ce 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -2960,7 +2960,7 @@ void RtfAttributeOutput::ParaNumRule_Impl(const SwTextNode* pTextNd, sal_Int32 n else m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}"); m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS); - m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetId(*pRule)) + 1); + m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetNumberingId(*pRule)) + 1); m_aStyles.append(' '); } FormatLRSpace(aLR); diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index d76d52cb7608..f237d3e2a6cd 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -209,7 +209,7 @@ void RtfExport::BuildNumbering() SwNumRule* pOutlineRule = m_pDoc->GetOutlineNumRule(); if (IsExportNumRule(*pOutlineRule)) - GetId(*pOutlineRule); + GetNumberingId(*pOutlineRule); for (auto n = rListTable.size(); n;) { @@ -218,7 +218,7 @@ void RtfExport::BuildNumbering() continue; if (IsExportNumRule(*pRule)) - GetId(*pRule); + GetNumberingId(*pRule); } } diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx index 508ea7d0aad6..4b8938dd0e5d 100644 --- a/sw/source/filter/ww8/wrtw8num.cxx +++ b/sw/source/filter/ww8/wrtw8num.cxx @@ -62,15 +62,15 @@ sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 aNumFormat.SetStart( nVal ); pMyNumRule->Set( nLevel, aNumFormat ); - nNumId = GetId( *pMyNumRule ); + nNumId = GetNumberingId( *pMyNumRule ); // Map the old list to our new list - m_aRuleDuplicates[GetId( *pRule )] = nNumId; + m_aRuleDuplicates[GetNumberingId( *pRule )] = nNumId; return nNumId; } -sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule ) +sal_uInt16 MSWordExportBase::GetNumberingId( const SwNumRule& rNumRule ) { if ( !m_pUsedNumTable ) { diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 883f9b5eeba2..4d9e637f442d 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -599,7 +599,7 @@ public: void ExportPoolItemsToCHP( ww8::PoolItems &rItems, sal_uInt16 nScript, const SvxFontItem *pFont, bool bWriteCombChars = false ); /// Return the numeric id of the numbering rule - sal_uInt16 GetId( const SwNumRule& rNumRule ); + sal_uInt16 GetNumberingId( const SwNumRule& rNumRule ); /// Return the numeric id of the style. sal_uInt16 GetId( const SwTextFormatColl& rColl ) const; diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index 0e2ddb3ba90a..d3cc0bedfff4 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -720,7 +720,7 @@ void WW8AttributeOutput::OutlineNumbering(sal_uInt8 nLvl) m_rWW8Export.pO->push_back( nLvl ); SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::sprmPIlfo ); SwWW8Writer::InsUInt16( *m_rWW8Export.pO, - 1 + m_rWW8Export.GetId( *m_rWW8Export.m_pDoc->GetOutlineNumRule() ) ); + 1 + m_rWW8Export.GetNumberingId(*m_rWW8Export.m_pDoc->GetOutlineNumRule()) ); } // #i77805# @@ -3526,7 +3526,8 @@ void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule ) { const SwNumRule* pRule = GetExport().m_pDoc->FindNumRulePtr( rNumRule.GetValue() ); - if ( pRule && USHRT_MAX != ( nNumId = GetExport().GetId( *pRule ) ) ) + nNumId = pRule ? GetExport().GetNumberingId(*pRule) : USHRT_MAX; + if (USHRT_MAX != nNumId) { ++nNumId; if ( GetExport().m_pOutFormatNode ) _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
