diff options
Diffstat (limited to 'writerfilter')
-rw-r--r-- | writerfilter/qa/cppunittests/ooxml/data/recursive_header_rels.docx | bin | 0 -> 16911 bytes | |||
-rw-r--r-- | writerfilter/qa/cppunittests/ooxml/ooxml.cxx | 7 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 4 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 62 | ||||
-rw-r--r-- | writerfilter/source/dmapper/StyleSheetTable.cxx | 467 | ||||
-rw-r--r-- | writerfilter/source/dmapper/StyleSheetTable.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/filter/WriterFilter.cxx | 2 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLDocumentImpl.cxx | 3 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLDocumentImpl.hxx | 2 |
9 files changed, 447 insertions, 103 deletions
diff --git a/writerfilter/qa/cppunittests/ooxml/data/recursive_header_rels.docx b/writerfilter/qa/cppunittests/ooxml/data/recursive_header_rels.docx Binary files differnew file mode 100644 index 0000000000..8000760017 --- /dev/null +++ b/writerfilter/qa/cppunittests/ooxml/data/recursive_header_rels.docx diff --git a/writerfilter/qa/cppunittests/ooxml/ooxml.cxx b/writerfilter/qa/cppunittests/ooxml/ooxml.cxx index 32133df9ba..42c8d22226 100644 --- a/writerfilter/qa/cppunittests/ooxml/ooxml.cxx +++ b/writerfilter/qa/cppunittests/ooxml/ooxml.cxx @@ -62,6 +62,13 @@ CPPUNIT_TEST_FIXTURE(Test, testFloatingTableLeak) CPPUNIT_ASSERT(xParagraph->supportsService("com.sun.star.text.Paragraph")); CPPUNIT_ASSERT(!xParaEnum->hasMoreElements()); } + +CPPUNIT_TEST_FIXTURE(Test, testRecursiveHeaderRels) +{ + // Given a document with self-referencing rels in a header/footer: + loadFromFile(u"recursive_header_rels.docx"); + // It should not crash/hang on load +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 7e4eeda7d3..344a36cf95 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -2601,7 +2601,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_PPrBase_pStyle: { StyleSheetTablePtr pStyleTable = m_pImpl->GetStyleSheetTable(); - const OUString sConvertedStyleName = pStyleTable->ConvertStyleName( sStringValue, true ); + const OUString sConvertedStyleName = pStyleTable->ConvertStyleNameExt(sStringValue); m_pImpl->SetCurrentParaStyleName( sConvertedStyleName ); if (m_pImpl->GetTopContext() && m_pImpl->GetTopContextType() != CONTEXT_SECTION) m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::Any( sConvertedStyleName )); @@ -2609,7 +2609,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) break; case NS_ooxml::LN_EG_RPrBase_rStyle: { - OUString sConvertedName( m_pImpl->GetStyleSheetTable()->ConvertStyleName( sStringValue, true ) ); + OUString const sConvertedName(m_pImpl->GetStyleSheetTable()->ConvertStyleNameExt(sStringValue)); if (m_pImpl->CheckFootnoteStyle() && m_pImpl->GetFootnoteContext()) m_pImpl->SetHasFootnoteStyle(m_pImpl->GetFootnoteContext()->GetFootnoteStyle() == sConvertedName); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 028b4b4c9a..4c5dff02fc 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -5433,13 +5433,27 @@ std::tuple<OUString, std::vector<OUString>, std::vector<OUString> > splitFieldCo OUString const token = lcl_ExtractToken(rCommand, nStartIndex, bHaveToken, bIsSwitch); assert(nStartIndex <= rCommand.size()); + static std::map<OUString, std::set<OUString>> const noArgumentSwitches = { + { u"STYLEREF"_ustr, + { u"\\l"_ustr, u"\\n"_ustr, u"\\p"_ustr, u"\\r"_ustr, u"\\t"_ustr, u"\\w"_ustr } } + }; if (bHaveToken) { if (sType.isEmpty()) { sType = token.toAsciiUpperCase(); } - else if (bIsSwitch || !switches.empty()) + else if (bIsSwitch) + { + switches.push_back(token); + } + // evidently Word evaluates 'STYLEREF \t "Heading 1" \* MERGEFORMAT' + // despite the grammar specifying that the style name must + // precede switches like '\t'; try to approximate that here + // by checking for known switches that don't expect arguments + else if (auto const it = noArgumentSwitches.find(sType); + !switches.empty() && (it == noArgumentSwitches.end() + || it->second.find(switches.back().toAsciiLowerCase()) == it->second.end())) { switches.push_back(token); } @@ -6908,21 +6922,18 @@ static OUString UnquoteFieldText(std::u16string_view s) OUString DomainMapper_Impl::ConvertTOCStyleName(OUString const& rTOCStyleName) { assert(!rTOCStyleName.isEmpty()); - if (auto const pStyle = GetStyleSheetTable()->FindStyleSheetByISTD(rTOCStyleName)) - { // theoretical case: what OOXML says - return pStyle->m_sStyleName; - } - auto const pStyle = GetStyleSheetTable()->FindStyleSheetByISTD(FilterChars(rTOCStyleName)); - if (pStyle && m_bIsNewDoc) - { // practical case: Word wrote i18n name to TOC field, but it doesn't - // exist in styles.xml; tdf#153083 clone it for best roundtrip - SAL_INFO("writerfilter.dmapper", "cloning TOC paragraph style (presumed built-in) " << rTOCStyleName << " from " << pStyle->m_sStyleName); - return GetStyleSheetTable()->CloneTOCStyle(GetFontTable(), pStyle, rTOCStyleName); - } - else + if (auto const pStyle = GetStyleSheetTable()->FindStyleSheetByISTD(FilterChars(rTOCStyleName))) { - return GetStyleSheetTable()->ConvertStyleName(rTOCStyleName); + auto const [convertedStyleName, isBuiltIn] = StyleSheetTable::ConvertStyleName(pStyle->m_sStyleName); + if (isBuiltIn && m_bIsNewDoc) + { // practical case: Word wrote i18n name to TOC field, but it doesn't + // exist in styles.xml; tdf#153083 clone it for best roundtrip + assert(convertedStyleName == pStyle->m_sConvertedStyleName); + return GetStyleSheetTable()->CloneTOCStyle(GetFontTable(), pStyle, rTOCStyleName); + } } + // theoretical case: what OOXML says + return StyleSheetTable::ConvertStyleName(rTOCStyleName).first; } void DomainMapper_Impl::handleToc @@ -7992,29 +8003,8 @@ void DomainMapper_Impl::CloseFieldCommand() getPropertyName(PROP_REFERENCE_FIELD_SOURCE), uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE))); - OUString sStyleSheetName - = GetStyleSheetTable()->ConvertStyleName(sFirstParam, true); - uno::Any aStyleDisplayName; - - uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier( - GetTextDocument(), uno::UNO_QUERY_THROW); - uno::Reference<container::XNameAccess> xStyleFamilies - = xStylesSupplier->getStyleFamilies(); - uno::Reference<container::XNameAccess> xStyles; - xStyleFamilies->getByName(getPropertyName(PROP_PARAGRAPH_STYLES)) - >>= xStyles; - uno::Reference<css::beans::XPropertySet> xStyle; - - try - { - xStyles->getByName(sStyleSheetName) >>= xStyle; - aStyleDisplayName = xStyle->getPropertyValue("DisplayName"); - } - catch (css::container::NoSuchElementException) - { - aStyleDisplayName <<= sStyleSheetName; - } + aStyleDisplayName <<= ConvertTOCStyleName(sFirstParam); xFieldProperties->setPropertyValue( getPropertyName(PROP_SOURCE_NAME), aStyleDisplayName); diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx index 711a90290f..d932be695b 100644 --- a/writerfilter/source/dmapper/StyleSheetTable.cxx +++ b/writerfilter/source/dmapper/StyleSheetTable.cxx @@ -813,7 +813,7 @@ void StyleSheetTable::lcl_entry(writerfilter::Reference<Properties>::Pointer_t r m_pImpl->m_rDMapper.PopStyleSheetProperties(); if( !m_pImpl->m_rDMapper.IsOOXMLImport() || !m_pImpl->m_pCurrentEntry->m_sStyleName.isEmpty()) { - m_pImpl->m_pCurrentEntry->m_sConvertedStyleName = ConvertStyleName( m_pImpl->m_pCurrentEntry->m_sStyleName ); + m_pImpl->m_pCurrentEntry->m_sConvertedStyleName = ConvertStyleName(m_pImpl->m_pCurrentEntry->m_sStyleName).first; m_pImpl->m_aStyleSheetEntries.push_back( m_pImpl->m_pCurrentEntry ); m_pImpl->m_aStyleSheetEntriesMap.emplace( m_pImpl->m_pCurrentEntry->m_sStyleIdentifierD, m_pImpl->m_pCurrentEntry ); } @@ -922,7 +922,7 @@ void StyleSheetTable::ApplyNumberingStyleNameToParaStyles() if (pStyleSheetProperties->props().GetListId() > -1) { uno::Reference< style::XStyle > xStyle; - xParaStyles->getByName( ConvertStyleName(pEntry->m_sStyleName) ) >>= xStyle; + xParaStyles->getByName(ConvertStyleName(pEntry->m_sStyleName).first) >>= xStyle; if ( !xStyle.is() ) break; @@ -1030,6 +1030,20 @@ void StyleSheetTable_Impl::ApplyClonedTOCStylesToXText(uno::Reference<text::XTex xPara->setPropertyValue(u"ParaStyleName"_ustr, uno::Any(it->second)); } } + uno::Reference<container::XEnumerationAccess> const xParaEA{xPara, uno::UNO_QUERY_THROW}; + uno::Reference<container::XEnumeration> const xEnum{xParaEA->createEnumeration()}; + while (xEnum->hasMoreElements()) + { + uno::Reference<beans::XPropertySet> const xPortion{xEnum->nextElement(), uno::UNO_QUERY_THROW}; + if (xPortion->getPropertyValue(u"CharStyleName"_ustr) >>= styleName) + { + auto const it{m_ClonedTOCStylesMap.find(styleName)}; + if (it != m_ClonedTOCStylesMap.end()) + { + xPortion->setPropertyValue(u"CharStyleName"_ustr, uno::Any(it->second)); + } + } + } } else if (xElem->supportsService(u"com.sun.star.text.TextTable"_ustr)) { @@ -1076,14 +1090,19 @@ void StyleSheetTable::ApplyClonedTOCStyles() OUString StyleSheetTable::CloneTOCStyle(FontTablePtr const& rFontTable, StyleSheetEntryPtr const pStyle, OUString const& rNewName) { + auto const it = m_pImpl->m_ClonedTOCStylesMap.find(pStyle->m_sConvertedStyleName); + if (it != m_pImpl->m_ClonedTOCStylesMap.end()) + { + return it->second; + } + SAL_INFO("writerfilter.dmapper", "cloning TOC paragraph style (presumed built-in) " << rNewName << " from " << pStyle->m_sStyleName); StyleSheetEntryPtr const pClone(new StyleSheetEntry(*pStyle)); pClone->m_sStyleIdentifierD = rNewName; pClone->m_sStyleName = rNewName; - pClone->m_sConvertedStyleName = ConvertStyleName(rNewName); + pClone->m_sConvertedStyleName = ConvertStyleName(rNewName).first; m_pImpl->m_aStyleSheetEntries.push_back(pClone); - // add it so it will be found if referenced from another TOC - m_pImpl->m_aStyleSheetEntriesMap.emplace(rNewName, pClone); - m_pImpl->m_ClonedTOCStylesMap.emplace(pStyle->m_sStyleName, pClone->m_sConvertedStyleName); + // the old converted name is what is applied to paragraphs + m_pImpl->m_ClonedTOCStylesMap.emplace(pStyle->m_sConvertedStyleName, pClone->m_sConvertedStyleName); std::vector<StyleSheetEntryPtr> const styles{ pClone }; ApplyStyleSheetsImpl(rFontTable, styles); return pClone->m_sConvertedStyleName; @@ -1127,7 +1146,7 @@ void StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std:: bool bInsert = false; uno::Reference< container::XNameContainer > xStyles = bParaStyle ? xParaStyles : (bListStyle ? xNumberingStyles : xCharStyles); uno::Reference< style::XStyle > xStyle; - const OUString sConvertedStyleName = ConvertStyleName( pEntry->m_sStyleName ); + const OUString sConvertedStyleName(ConvertStyleName(pEntry->m_sStyleName).first); if(xStyles->hasByName( sConvertedStyleName )) { @@ -1194,7 +1213,7 @@ void StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std:: // Writer core doesn't support numbering styles having a parent style, it seems if (pParent && !bListStyle) { - const OUString sParentStyleName = ConvertStyleName( pParent->m_sStyleName ); + const OUString sParentStyleName(ConvertStyleName(pParent->m_sStyleName).first); if ( !sParentStyleName.isEmpty() && !xStyles->hasByName( sParentStyleName ) ) aMissingParent.emplace_back( sParentStyleName, xStyle ); else @@ -1254,7 +1273,7 @@ void StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std:: StyleSheetEntryPtr pLinkStyle = FindStyleSheetByISTD(pEntry->m_sLinkStyleIdentifier); if (pLinkStyle && !pLinkStyle->m_sStyleName.isEmpty()) - aMissingLink.emplace_back(ConvertStyleName(pLinkStyle->m_sStyleName), + aMissingLink.emplace_back(ConvertStyleName(pLinkStyle->m_sStyleName).first, xStyle); } } @@ -1266,7 +1285,7 @@ void StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std:: { StyleSheetEntryPtr pFollowStyle = FindStyleSheetByISTD( pEntry->m_sNextStyleIdentifier ); if ( pFollowStyle && !pFollowStyle->m_sStyleName.isEmpty() ) - aMissingFollow.emplace_back( ConvertStyleName( pFollowStyle->m_sStyleName ), xStyle ); + aMissingFollow.emplace_back(ConvertStyleName(pFollowStyle->m_sStyleName).first, xStyle); } // Set the outline levels @@ -1514,10 +1533,9 @@ const StyleSheetEntryPtr & StyleSheetTable::GetCurrentEntry() const return m_pImpl->m_pCurrentEntry; } -OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExtendedSearch) +OUString StyleSheetTable::ConvertStyleNameExt(const OUString& rWWName) { OUString sRet( rWWName ); - if( bExtendedSearch ) { //search for the rWWName in the IdentifierD of the existing styles and convert the sStyleName member auto findIt = m_pImpl->m_aStyleSheetEntriesMap.find(rWWName); @@ -1529,16 +1547,32 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten } } + return ConvertStyleName(sRet).first; +} + +std::pair<OUString, bool> +StyleSheetTable::ConvertStyleName(const OUString& rWWName) +{ + OUString sRet(rWWName); + // create a map only once // This maps Word's special style manes to Writer's (the opposite to what MSWordStyles::GetWWId // and ww::GetEnglishNameFromSti do on export). The mapping gives a Writer's style name, which // will point to a style with specific RES_POOL* in its m_nPoolFormatId. Then on export, the // pool format id will map to a ww::sti enum value, and finally to a Word style name. Keep this // part in sync with the export functions mentioned above! - // In addition to "standard" names, some case variations are handled here; and also there are - // a number of strange mappings like "BodyTextIndentItalic" -> "Text body indent italic", which - // map something unused in Word to something unused in Writer :-/ + // In addition to "standard" names, some case variations are handled here. + // It's required to know all the Word paragraph/character styles for + // STYLEREF/TOC fields; the ones that don't have a Writer equivalent have + // an empty string in the map, and the code should return the original name. + // Also very unclear: at least in DOCX, style names appear to be case + // sensitive; if Word imports 2 styles that have the same case-insensitive + // name as a built-in style, it renames one of them by appending a number. + // These are from the w:latentStyles in the styles.xml of a Word 15.0 DOCX, + // plus some pre-existing additions and variants. static const std::map< OUString, OUString> StyleNameMap { +// FIXME: testFdo77716, testTdf129575_docDefault etc. fail with correct mapping +// { "Normal", "Default Paragraph Style" }, // RES_POOLCOLL_STANDARD { "Normal", "Standard" }, // RES_POOLCOLL_STANDARD { "heading 1", "Heading 1" }, // RES_POOLCOLL_HEADLINE1 { "heading 2", "Heading 2" }, // RES_POOLCOLL_HEADLINE2 @@ -1561,12 +1595,21 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten { "Index 1", "Index 1" }, // RES_POOLCOLL_TOX_IDX1 { "Index 2", "Index 2" }, // RES_POOLCOLL_TOX_IDX2 { "Index 3", "Index 3" }, // RES_POOLCOLL_TOX_IDX3 -// { "Index 4", "" }, -// { "Index 5", "" }, -// { "Index 6", "" }, -// { "Index 7", "" }, -// { "Index 8", "" }, -// { "Index 9", "" }, + { "Index 4", "" }, + { "Index 5", "" }, + { "Index 6", "" }, + { "Index 7", "" }, + { "Index 8", "" }, + { "Index 9", "" }, + { "index 1", "Index 1" }, // RES_POOLCOLL_TOX_IDX1 + { "index 2", "Index 2" }, // RES_POOLCOLL_TOX_IDX2 + { "index 3", "Index 3" }, // RES_POOLCOLL_TOX_IDX3 + { "index 4", "" }, + { "index 5", "" }, + { "index 6", "" }, + { "index 7", "" }, + { "index 8", "" }, + { "index 9", "" }, { "TOC 1", "Contents 1" }, // RES_POOLCOLL_TOX_CNTNT1 { "TOC 2", "Contents 2" }, // RES_POOLCOLL_TOX_CNTNT2 { "TOC 3", "Contents 3" }, // RES_POOLCOLL_TOX_CNTNT3 @@ -1576,8 +1619,6 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten { "TOC 7", "Contents 7" }, // RES_POOLCOLL_TOX_CNTNT7 { "TOC 8", "Contents 8" }, // RES_POOLCOLL_TOX_CNTNT8 { "TOC 9", "Contents 9" }, // RES_POOLCOLL_TOX_CNTNT9 - { "TOC Heading", "Contents Heading" }, // RES_POOLCOLL_TOX_CNTNTH - { "TOCHeading", "Contents Heading" }, // RES_POOLCOLL_TOX_CNTNTH { "toc 1", "Contents 1" }, // RES_POOLCOLL_TOX_CNTNT1 { "toc 2", "Contents 2" }, // RES_POOLCOLL_TOX_CNTNT2 { "toc 3", "Contents 3" }, // RES_POOLCOLL_TOX_CNTNT3 @@ -1596,37 +1637,48 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten { "TOC7", "Contents 7" }, // RES_POOLCOLL_TOX_CNTNT7 { "TOC8", "Contents 8" }, // RES_POOLCOLL_TOX_CNTNT8 { "TOC9", "Contents 9" }, // RES_POOLCOLL_TOX_CNTNT9 -// { "Normal Indent", "" }, + { "Normal Indent", "" }, { "footnote text", "Footnote" }, // RES_POOLCOLL_FOOTNOTE { "Footnote Text", "Footnote" }, // RES_POOLCOLL_FOOTNOTE { "Annotation Text", "Marginalia" }, // RES_POOLCOLL_MARGINAL + { "annotation text", "Marginalia" }, // RES_POOLCOLL_MARGINAL { "Header", "Header" }, // RES_POOLCOLL_HEADER { "header", "Header" }, // RES_POOLCOLL_HEADER { "Footer", "Footer" }, // RES_POOLCOLL_FOOTER { "footer", "Footer" }, // RES_POOLCOLL_FOOTER { "Index Heading", "Index Heading" }, // RES_POOLCOLL_TOX_IDXH + { "index heading", "Index Heading" }, // RES_POOLCOLL_TOX_IDXH { "Caption", "Caption" }, // RES_POOLCOLL_LABEL + { "caption", "Caption" }, // RES_POOLCOLL_LABEL { "table of figures", "Figure Index 1" }, // RES_POOLCOLL_TOX_ILLUS1 { "Table of Figures", "Figure Index 1" }, // RES_POOLCOLL_TOX_ILLUS1 { "Envelope Address", "Addressee" }, // RES_POOLCOLL_ENVELOPE_ADDRESS + { "envelope address", "Addressee" }, // RES_POOLCOLL_ENVELOPE_ADDRESS { "Envelope Return", "Sender" }, // RES_POOLCOLL_SEND_ADDRESS - { "footnote reference", "Footnote Symbol" }, // RES_POOLCHR_FOOTNOTE; tdf#82173 - { "Footnote Reference", "Footnote Symbol" }, // RES_POOLCHR_FOOTNOTE; tdf#82173 -// { "Annotation Reference", "" }, - { "Line Number", "Line numbering" }, // RES_POOLCHR_LINENUM + { "envelope return", "Sender" }, // RES_POOLCOLL_SEND_ADDRESS + { "footnote reference", "Footnote Characters" }, // RES_POOLCHR_FOOTNOTE; tdf#82173 + { "Footnote Reference", "Footnote Characters" }, // RES_POOLCHR_FOOTNOTE; tdf#82173 + { "Annotation Reference", "" }, + { "annotation reference", "" }, + { "Line Number", "Line Numbering" }, // RES_POOLCHR_LINENUM + { "line number", "Line Numbering" }, // RES_POOLCHR_LINENUM { "Page Number", "Page Number" }, // RES_POOLCHR_PAGENO - { "endnote reference", "Endnote Symbol" }, // RES_POOLCHR_ENDNOTE; tdf#82173 - { "Endnote Reference", "Endnote Symbol" }, // RES_POOLCHR_ENDNOTE; tdf#82173 + { "page number", "Page Number" }, // RES_POOLCHR_PAGENO + { "PageNumber", "Page Number" }, // RES_POOLCHR_PAGENO + { "endnote reference", "Endnote Characters" }, // RES_POOLCHR_ENDNOTE; tdf#82173 + { "Endnote Reference", "Endnote Characters" }, // RES_POOLCHR_ENDNOTE; tdf#82173 { "endnote text", "Endnote" }, // RES_POOLCOLL_ENDNOTE { "Endnote Text", "Endnote" }, // RES_POOLCOLL_ENDNOTE { "Table of Authorities", "Bibliography Heading" }, // RES_POOLCOLL_TOX_AUTHORITIESH -// { "Macro Text", "" }, -// { "TOA Heading", "" }, + { "table of authorities", "Bibliography Heading" }, // RES_POOLCOLL_TOX_AUTHORITIESH + { "macro", "" }, + { "TOA Heading", "" }, + { "toa heading", "" }, { "List", "List" }, // RES_POOLCOLL_NUMBER_BULLET_BASE -// { "List 2", "" }, -// { "List 3", "" }, -// { "List 4", "" }, -// { "List 5", "" }, + { "List 2", "" }, + { "List 3", "" }, + { "List 4", "" }, + { "List 5", "" }, { "List Bullet", "List 1" }, // RES_POOLCOLL_BULLET_LEVEL1 { "List Bullet 2", "List 2" }, // RES_POOLCOLL_BULLET_LEVEL2 { "List Bullet 3", "List 3" }, // RES_POOLCOLL_BULLET_LEVEL3 @@ -1640,49 +1692,339 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten { "Title", "Title" }, // RES_POOLCOLL_DOC_TITLE { "Closing", "Appendix" }, // RES_POOLCOLL_DOC_APPENDIX { "Signature", "Signature" }, // RES_POOLCOLL_SIGNATURE -// { "Default Paragraph Font", "" }, - { "DefaultParagraphFont", "Default Paragraph Font" }, + { "Default Paragraph Font", "" }, + { "DefaultParagraphFont", "" }, +// FIXME: testTdf118947_tableStyle fails with correct mapping +// { "Body Text", "Body Text" }, // RES_POOLCOLL_TEXT { "Body Text", "Text body" }, // RES_POOLCOLL_TEXT - { "BodyText", "Text body" }, // RES_POOLCOLL_TEXT - { "BodyTextIndentItalic", "Text body indent italic" }, - { "Body Text Indent", "Text body indent" }, // RES_POOLCOLL_TEXT_MOVE - { "BodyTextIndent", "Text body indent" }, // RES_POOLCOLL_TEXT_MOVE - { "BodyTextIndent2", "Text body indent2" }, + { "BodyText", "Body Text" }, // RES_POOLCOLL_TEXT + { "BodyTextIndentItalic", "" }, + { "Body Text Indent", "Body Text, Indented" }, // RES_POOLCOLL_TEXT_MOVE + { "BodyTextIndent", "Body Text, Indented" }, // RES_POOLCOLL_TEXT_MOVE + { "BodyTextIndent2", "" }, { "List Continue", "List 1 Cont." }, // RES_POOLCOLL_BULLET_NONUM1 { "List Continue 2", "List 2 Cont." }, // RES_POOLCOLL_BULLET_NONUM2 { "List Continue 3", "List 3 Cont." }, // RES_POOLCOLL_BULLET_NONUM3 { "List Continue 4", "List 4 Cont." }, // RES_POOLCOLL_BULLET_NONUM4 { "List Continue 5", "List 5 Cont." }, // RES_POOLCOLL_BULLET_NONUM5 -// { "Message Header", "" }, + { "Message Header", "" }, { "Subtitle", "Subtitle" }, // RES_POOLCOLL_DOC_SUBTITLE - { "Salutation", "Salutation" }, // RES_POOLCOLL_GREETING -// { "Date", "" }, - { "Body Text First Indent", "First line indent" }, // RES_POOLCOLL_TEXT_IDENT -// { "Body Text First Indent 2", "" }, -// { "Note Heading", "" }, -// { "Body Text 2", "" }, -// { "Body Text 3", "" }, -// { "Body Text Indent 2", "" }, -// { "Body Text Indent 3", "" }, -// { "Block Text", "" }, - { "Hyperlink", "Internet link" }, // RES_POOLCHR_INET_NORMAL + { "Salutation", "Complimentary Close" }, // RES_POOLCOLL_GREETING + { "Date", "" }, + { "Body Text First Indent", "First Line Indent" }, // RES_POOLCOLL_TEXT_IDENT + { "Body Text First Indent 2", "" }, + { "Note Heading", "" }, + { "Body Text 2", "" }, + { "Body Text 3", "" }, + { "Body Text Indent 2", "" }, + { "Body Text Indent 3", "" }, + { "Block Text", "" }, + { "Hyperlink", "Internet Link" }, // RES_POOLCHR_INET_NORMAL { "FollowedHyperlink", "Visited Internet Link" }, // RES_POOLCHR_INET_VISIT { "Strong", "Strong Emphasis" }, // RES_POOLCHR_HTML_STRONG { "Emphasis", "Emphasis" }, // RES_POOLCHR_HTML_EMPHASIS -// { "Document Map", "" }, -// { "Plain Text", "" }, - { "NoList", "No List" }, + { "Document Map", "" }, + { "DocumentMap", "" }, + { "Plain Text", "" }, + { "E-mail Signature", "" }, + { "HTML Top of Form", "" }, + { "HTML Bottom of Form", "" }, + { "Normal (Web)", "" }, + { "HTML Acronym", "" }, + { "HTML Address", "" }, + { "HTML Cite", "" }, + { "HTML Code", "" }, + { "HTML Definition", "" }, + { "HTML Keyboard", "" }, + { "HTML Preformatted", "" }, + { "HTML Sample", "" }, + { "HTML Typewriter", "" }, + { "HTML Variable", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "Normal Table", "" }, + { "annotation subject", "" }, + { "No List", "No List" }, // RES_POOLNUMRULE_NOLIST + { "NoList", "No List" }, // RES_POOLNUMRULE_NOLIST + { "Outline List 1", "" }, + { "Outline List 2", "" }, + { "Outline List 3", "" }, + { "Table Simple 1", "" }, + { "Table Simple 2", "" }, + { "Table Simple 3", "" }, + { "Table Classic 1", "" }, + { "Table Classic 2", "" }, + { "Table Classic 3", "" }, + { "Table Classic 4", "" }, + { "Table Colorful 1", "" }, + { "Table Colorful 2", "" }, + { "Table Colorful 3", "" }, + { "Table Columns 1", "" }, + { "Table Columns 2", "" }, + { "Table Columns 3", "" }, + { "Table Columns 4", "" }, + { "Table Columns 5", "" }, + { "Table Grid 1", "" }, + { "Table Grid 2", "" }, + { "Table Grid 3", "" }, + { "Table Grid 4", "" }, + { "Table Grid 5", "" }, + { "Table Grid 6", "" }, + { "Table Grid 7", "" }, + { "Table Grid 8", "" }, + { "Table List 1", "" }, + { "Table List 2", "" }, + { "Table List 3", "" }, + { "Table List 4", "" }, + { "Table List 5", "" }, + { "Table List 6", "" }, + { "Table List 7", "" }, + { "Table List 8", "" }, + { "Table 3D effects 1", "" }, + { "Table 3D effects 2", "" }, + { "Table 3D effects 3", "" }, + { "Table Contemporary", "" }, + { "Table Elegant", "" }, + { "Table Professional", "" }, + { "Table Subtle 1", "" }, + { "Table Subtle 2", "" }, + { "Table Web 1", "" }, + { "Table Web 2", "" }, + { "Table Web 3", "" }, + { "Balloon Text", "" }, + { "Table Grid", "" }, + { "Table Theme", "" }, + { "Placeholder Text", "" }, + { "No Spacing", "" }, + { "Light Shading", "" }, + { "Light List", "" }, + { "Light Grid", "" }, + { "Medium Shading 1", "" }, + { "Medium Shading 2", "" }, + { "Medium List 1", "" }, + { "Medium List 2", "" }, + { "Medium Grid 1", "" }, + { "Medium Grid 2", "" }, + { "Medium Grid 3", "" }, + { "Dark List", "" }, + { "Colorful Shading", "" }, + { "Colorful List", "" }, + { "Colorful Grid", "" }, + { "Light Shading Accent 1", "" }, + { "Light List Accent 1", "" }, + { "Light Grid Accent 1", "" }, + { "Medium Shading 1 Accent 1", "" }, + { "Medium Shading 2 Accent 1", "" }, + { "Medium List 1 Accent 1", "" }, + { "Revision", "" }, + { "List Paragraph", "" }, + { "Quote", "" }, + { "Intense Quote", "" }, + { "Medium List 2 Accent 1", "" }, + { "Medium Grid 1 Accent 1", "" }, + { "Medium Grid 2 Accent 1", "" }, + { "Medium Grid 3 Accent 1", "" }, + { "Dark List Accent 1", "" }, + { "Colorful Shading Accent 1", "" }, + { "Colorful List Accent 1", "" }, + { "Colorful Grid Accent 1", "" }, + { "Light Shading Accent 2", "" }, + { "Light List Accent 2", "" }, + { "Light Grid Accent 2", "" }, + { "Medium Shading 1 Accent 2", "" }, + { "Medium Shading 2 Accent 2", "" }, + { "Medium List 1 Accent 2", "" }, + { "Medium List 2 Accent 2", "" }, + { "Medium Grid 1 Accent 2", "" }, + { "Medium Grid 2 Accent 2", "" }, + { "Medium Grid 3 Accent 2", "" }, + { "Dark List Accent 2", "" }, + { "Colorful Shading Accent 2", "" }, + { "Colorful List Accent 2", "" }, + { "Colorful Grid Accent 2", "" }, + { "Light Shading Accent 3", "" }, + { "Light List Accent 3", "" }, + { "Light Grid Accent 3", "" }, + { "Medium Shading 1 Accent 3", "" }, + { "Medium Shading 2 Accent 3", "" }, + { "Medium List 1 Accent 3", "" }, + { "Medium List 2 Accent 3", "" }, + { "Medium Grid 1 Accent 3", "" }, + { "Medium Grid 2 Accent 3", "" }, + { "Medium Grid 3 Accent 3", "" }, + { "Dark List Accent 3", "" }, + { "Colorful Shading Accent 3", "" }, + { "Colorful List Accent 3", "" }, + { "Colorful Grid Accent 3", "" }, + { "Light Shading Accent 4", "" }, + { "Light List Accent 4", "" }, + { "Light Grid Accent 4", "" }, + { "Medium Shading 1 Accent 4", "" }, + { "Medium Shading 2 Accent 4", "" }, + { "Medium List 1 Accent 4", "" }, + { "Medium List 2 Accent 4", "" }, + { "Medium Grid 1 Accent 4", "" }, + { "Medium Grid 2 Accent 4", "" }, + { "Medium Grid 3 Accent 4", "" }, + { "Dark List Accent 4", "" }, + { "Colorful Shading Accent 4", "" }, + { "Colorful List Accent 4", "" }, + { "Colorful Grid Accent 4", "" }, + { "Light Shading Accent 5", "" }, + { "Light List Accent 5", "" }, + { "Light Grid Accent 5", "" }, + { "Medium Shading 1 Accent 5", "" }, + { "Medium Shading 2 Accent 5", "" }, + { "Medium List 1 Accent 5", "" }, + { "Medium List 2 Accent 5", "" }, + { "Medium Grid 1 Accent 5", "" }, + { "Medium Grid 2 Accent 5", "" }, + { "Medium Grid 3 Accent 5", "" }, + { "Dark List Accent 5", "" }, + { "Colorful Shading Accent 5", "" }, + { "Colorful List Accent 5", "" }, + { "Colorful Grid Accent 5", "" }, + { "Light Shading Accent 6", "" }, + { "Light List Accent 6", "" }, + { "Light Grid Accent 6", "" }, + { "Medium Shading 1 Accent 6", "" }, + { "Medium Shading 2 Accent 6", "" }, + { "Medium List 1 Accent 6", "" }, + { "Medium List 2 Accent 6", "" }, + { "Medium Grid 1 Accent 6", "" }, + { "Medium Grid 2 Accent 6", "" }, + { "Medium Grid 3 Accent 6", "" }, + { "Dark List Accent 6", "" }, + { "Colorful Shading Accent 6", "" }, + { "Colorful List Accent 6", "" }, + { "Colorful Grid Accent 6", "" }, + { "Subtle Emphasis", "" }, + { "Intense Emphasis", "" }, + { "Subtle Reference", "" }, + { "Intense Reference", "" }, + { "Book Title", "" }, + { "Bibliography", "" }, + { "TOC Heading", "Contents Heading" }, // RES_POOLCOLL_TOX_CNTNTH + { "TOCHeading", "Contents Heading" }, // RES_POOLCOLL_TOX_CNTNTH + { "Plain Table 1", "" }, + { "Plain Table 2", "" }, + { "Plain Table 3", "" }, + { "Plain Table 4", "" }, + { "Plain Table 5", "" }, + { "Grid Table Light", "" }, + { "Grid Table 1 Light", "" }, + { "Grid Table 2", "" }, + { "Grid Table 3", "" }, + { "Grid Table 4", "" }, + { "Grid Table 5 Dark", "" }, + { "Grid Table 6 Colorful", "" }, + { "Grid Table 7 Colorful", "" }, + { "Grid Table 1 Light Accent 1", "" }, + { "Grid Table 2 Accent 1", "" }, + { "Grid Table 3 Accent 1", "" }, + { "Grid Table 4 Accent 1", "" }, + { "Grid Table 5 Dark Accent 1", "" }, + { "Grid Table 6 Colorful Accent 1", "" }, + { "Grid Table 7 Colorful Accent 1", "" }, + { "Grid Table 1 Light Accent 2", "" }, + { "Grid Table 2 Accent 2", "" }, + { "Grid Table 3 Accent 2", "" }, + { "Grid Table 4 Accent 2", "" }, + { "Grid Table 5 Dark Accent 2", "" }, + { "Grid Table 6 Colorful Accent 2", "" }, + { "Grid Table 7 Colorful Accent 2", "" }, + { "Grid Table 1 Light Accent 3", "" }, + { "Grid Table 2 Accent 3", "" }, + { "Grid Table 3 Accent 3", "" }, + { "Grid Table 4 Accent 3", "" }, + { "Grid Table 5 Dark Accent 3", "" }, + { "Grid Table 6 Colorful Accent 3", "" }, + { "Grid Table 7 Colorful Accent 3", "" }, + { "Grid Table 1 Light Accent 4", "" }, + { "Grid Table 2 Accent 4", "" }, + { "Grid Table 3 Accent 4", "" }, + { "Grid Table 4 Accent 4", "" }, + { "Grid Table 5 Dark Accent 4", "" }, + { "Grid Table 6 Colorful Accent 4", "" }, + { "Grid Table 7 Colorful Accent 4", "" }, + { "Grid Table 1 Light Accent 5", "" }, + { "Grid Table 2 Accent 5", "" }, + { "Grid Table 3 Accent 5", "" }, + { "Grid Table 4 Accent 5", "" }, + { "Grid Table 5 Dark Accent 5", "" }, + { "Grid Table 6 Colorful Accent 5", "" }, + { "Grid Table 7 Colorful Accent 5", "" }, + { "Grid Table 1 Light Accent 6", "" }, + { "Grid Table 2 Accent 6", "" }, + { "Grid Table 3 Accent 6", "" }, + { "Grid Table 4 Accent 6", "" }, + { "Grid Table 5 Dark Accent 6", "" }, + { "Grid Table 6 Colorful Accent 6", "" }, + { "Grid Table 7 Colorful Accent 6", "" }, + { "List Table 1 Light", "" }, + { "List Table 2", "" }, + { "List Table 3", "" }, + { "List Table 4", "" }, + { "List Table 5 Dark", "" }, + { "List Table 6 Colorful", "" }, + { "List Table 7 Colorful", "" }, + { "List Table 1 Light Accent 1", "" }, + { "List Table 2 Accent 1", "" }, + { "List Table 3 Accent 1", "" }, + { "List Table 4 Accent 1", "" }, + { "List Table 5 Dark Accent 1", "" }, + { "List Table 6 Colorful Accent 1", "" }, + { "List Table 7 Colorful Accent 1", "" }, + { "List Table 1 Light Accent 2", "" }, + { "List Table 2 Accent 2", "" }, + { "List Table 3 Accent 2", "" }, + { "List Table 4 Accent 2", "" }, + { "List Table 5 Dark Accent 2", "" }, + { "List Table 6 Colorful Accent 2", "" }, + { "List Table 7 Colorful Accent 2", "" }, + { "List Table 1 Light Accent 3", "" }, + { "List Table 2 Accent 3", "" }, + { "List Table 3 Accent 3", "" }, + { "List Table 4 Accent 3", "" }, + { "List Table 5 Dark Accent 3", "" }, + { "List Table 6 Colorful Accent 3", "" }, + { "List Table 7 Colorful Accent 3", "" }, + { "List Table 1 Light Accent 4", "" }, + { "List Table 2 Accent 4", "" }, + { "List Table 3 Accent 4", "" }, + { "List Table 4 Accent 4", "" }, + { "List Table 5 Dark Accent 4", "" }, + { "List Table 6 Colorful Accent 4", "" }, + { "List Table 7 Colorful Accent 4", "" }, + { "List Table 1 Light Accent 5", "" }, + { "List Table 2 Accent 5", "" }, + { "List Table 3 Accent 5", "" }, + { "List Table 4 Accent 5", "" }, + { "List Table 5 Dark Accent 5", "" }, + { "List Table 6 Colorful Accent 5", "" }, + { "List Table 7 Colorful Accent 5", "" }, + { "List Table 1 Light Accent 6", "" }, + { "List Table 2 Accent 6", "" }, + { "List Table 3 Accent 6", "" }, + { "List Table 4 Accent 6", "" }, + { "List Table 5 Dark Accent 6", "" }, + { "List Table 6 Colorful Accent 6", "" }, + { "List Table 7 Colorful Accent 6", "" }, + + // ??? unsure what these are, they are not in Word's styles.xml { "AbstractHeading", "Abstract Heading" }, { "AbstractBody", "Abstract Body" }, - { "PageNumber", "Page Number" }, // RES_POOLCHR_PAGENO { "TableNormal", "Normal Table" }, - { "DocumentMap", "Document Map" }, }; // find style-name using map - if (const auto aIt = StyleNameMap.find(sRet); aIt != StyleNameMap.end()) + if (const auto aIt = StyleNameMap.find(sRet); aIt != StyleNameMap.end() && !aIt->second.isEmpty()) { + // if there's no Writer built-in to map to, aIt.second is empty! + // if it's a Word built-in but not Writer built-in, it can still collide (e.g. "List 5"). sRet = aIt->second; + return { sRet, true }; } else { @@ -1704,9 +2046,8 @@ OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExten // the UI names of built-in styles. if (ReservedStyleNames.find(sRet) != ReservedStyleNames.end() || sRet.endsWith(" (WW)")) sRet += " (WW)"; + return { sRet, aIt != StyleNameMap.end() }; } - - return sRet; } void StyleSheetTable::applyDefaults(bool bParaProperties) diff --git a/writerfilter/source/dmapper/StyleSheetTable.hxx b/writerfilter/source/dmapper/StyleSheetTable.hxx index 5cffd7d9d2..92024d8007 100644 --- a/writerfilter/source/dmapper/StyleSheetTable.hxx +++ b/writerfilter/source/dmapper/StyleSheetTable.hxx @@ -98,7 +98,8 @@ public: StyleSheetEntryPtr FindStyleSheetByConvertedStyleName(std::u16string_view rIndex); StyleSheetEntryPtr FindDefaultParaStyle(); - OUString ConvertStyleName( const OUString& rWWName, bool bExtendedSearch = false ); + OUString ConvertStyleNameExt(const OUString& rWWName); + static std::pair<OUString, bool> ConvertStyleName(const OUString& rWWName); OUString CloneTOCStyle(FontTablePtr const& rFontTable, StyleSheetEntryPtr const pStyle, OUString const& rName); void ApplyClonedTOCStyles(); diff --git a/writerfilter/source/filter/WriterFilter.cxx b/writerfilter/source/filter/WriterFilter.cxx index e7d32c4843..44efc0c42c 100644 --- a/writerfilter/source/filter/WriterFilter.cxx +++ b/writerfilter/source/filter/WriterFilter.cxx @@ -330,6 +330,8 @@ void WriterFilter::setTargetDocument(const uno::Reference<lang::XComponent>& xDo xSettings->setPropertyValue("DisableOffPagePositioning", uno::Any(true)); xSettings->setPropertyValue("DropCapPunctuation", uno::Any(true)); // rely on default for HyphenateURLs=false + // rely on default for APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH=true + xSettings->setPropertyValue("DoNotMirrorRtlDrawObjs", uno::Any(true)); } void WriterFilter::setSourceDocument(const uno::Reference<lang::XComponent>& xDoc) diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx index d9900ea7e4..07f2ecb73e 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx @@ -762,8 +762,9 @@ void OOXMLDocumentImpl::resolveEmbeddingsStream(const OOXMLStream::Pointer_t& pS { importSubStreamRelations(pStream, OOXMLStream::CHARTS); } - if(bHeaderFooterFound) + if (bHeaderFooterFound && !maSeenStreams.contains(customTarget)) { + maSeenStreams.insert(customTarget); try { OOXMLStream::Pointer_t Stream = OOXMLDocumentFactory::createStream(pStream, streamType); diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx index 1983ed2583..3cf39ba766 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx @@ -30,6 +30,7 @@ #include <vector> #include <stack> +#include <set> namespace writerfilter::ooxml { @@ -55,6 +56,7 @@ class OOXMLDocumentImpl : public OOXMLDocument css::uno::Reference<css::io::XInputStream> mxEmbeddings; css::uno::Sequence < css::beans::PropertyValue > mxEmbeddingsList; std::vector<css::beans::PropertyValue> m_aEmbeddings; + std::set<OUString> maSeenStreams; bool mbIsSubstream; bool mbSkipImages; /// How many paragraphs equal to 1 percent? |