diff options
-rw-r--r-- | include/xmloff/xmlimp.hxx | 2 | ||||
-rw-r--r-- | xmloff/inc/txtlists.hxx | 5 | ||||
-rw-r--r-- | xmloff/qa/unit/data/continue-numbering-word.odt | bin | 0 -> 6151 bytes | |||
-rw-r--r-- | xmloff/qa/unit/text.cxx | 25 | ||||
-rw-r--r-- | xmloff/source/core/xmlimp.cxx | 22 | ||||
-rw-r--r-- | xmloff/source/text/XMLTextListBlockContext.cxx | 8 | ||||
-rw-r--r-- | xmloff/source/text/txtlists.cxx | 23 |
7 files changed, 85 insertions, 0 deletions
diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx index caa5f738aba5..1a77317393dd 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -464,6 +464,8 @@ public: OUString GetODFVersion() const; bool IsOOoXML() const; // legacy non-ODF format? + /// Determines if the document was generated by Microsoft Office. + bool IsMSO() const; /** * Record an error condition that occurred during import. The diff --git a/xmloff/inc/txtlists.hxx b/xmloff/inc/txtlists.hxx index 30529a141fb9..dda522c441f9 100644 --- a/xmloff/inc/txtlists.hxx +++ b/xmloff/inc/txtlists.hxx @@ -121,6 +121,9 @@ class XMLTextListsHelper bool* o_pRestartNumbering = nullptr, bool* io_pSetDefaults = nullptr); + /// Looks up the last list id of a given list style, by name. + OUString GetLastIdOfStyleName(const OUString& sListStyleName) const; + private: /** list context: list, list-item, numbered-paragraph @@ -152,6 +155,8 @@ class XMLTextListsHelper typedef ::std::map< OUString, OUString > tMapForContinuingLists; std::unique_ptr<tMapForContinuingLists> mpContinuingLists; + std::unique_ptr<std::map<OUString, OUString>> mpStyleNameLastListIds; + // stack type for opened list elements and its list style: // vector with pair( <ListId>, <ListStyleName> ) as value typedef ::std::vector< ::std::pair< OUString, OUString > > diff --git a/xmloff/qa/unit/data/continue-numbering-word.odt b/xmloff/qa/unit/data/continue-numbering-word.odt Binary files differnew file mode 100644 index 000000000000..278a1fa65684 --- /dev/null +++ b/xmloff/qa/unit/data/continue-numbering-word.odt diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index 9ac9ac93dbc4..1d239e2e0c09 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -220,6 +220,31 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testParaStyleListLevel) "list-level", "2"); } +CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testContinueNumberingWord) +{ + // Given a document, which is produced by Word and contains text:continue-numbering="true": + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "continue-numbering-word.odt"; + + // When loading that document: + getComponent() = loadFromDesktop(aURL); + + // Then make sure that the numbering from the 1st para is continued on the 3rd para: + uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + xParaEnum->nextElement(); + xParaEnum->nextElement(); + uno::Reference<beans::XPropertySet> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + auto aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + // Without the accompanying fix in place, this failed with: + // - Expected: 2. + // - Actual : 1. + // i.e. the numbering was not continued, like in Word. + CPPUNIT_ASSERT_EQUAL(OUString("2."), aActual); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 337eb2146d52..9c68c2be6da1 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -58,6 +58,7 @@ #include <com/sun/star/xml/sax/FastParser.hpp> #include <com/sun/star/xml/sax/SAXException.hpp> #include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> #include <comphelper/fileformat.h> #include <comphelper/namecontainer.hxx> #include <comphelper/servicehelper.hxx> @@ -291,6 +292,8 @@ public: bool mbIsOOoXML; + std::optional<bool> mbIsMSO; + // Boolean, indicating that position attributes // of shapes are given in horizontal left-to-right layout. This is the case // for the OpenOffice.org file format. (#i28749#) @@ -1864,6 +1867,25 @@ bool SvXMLImport::IsOOoXML() const return mpImpl->mbIsOOoXML; } +bool SvXMLImport::IsMSO() const +{ + if (!mpImpl->mbIsMSO.has_value()) + { + uno::Reference<document::XDocumentPropertiesSupplier> xSupplier(GetModel(), uno::UNO_QUERY); + if (xSupplier.is()) + { + uno::Reference<document::XDocumentProperties> xProps + = xSupplier->getDocumentProperties(); + if (xProps.is()) + { + mpImpl->mbIsMSO = xProps->getGenerator().startsWith("MicrosoftOffice"); + } + } + } + + return mpImpl->mbIsMSO.has_value() ? *mpImpl->mbIsMSO : false; +} + // xml:id for RDF metadata void SvXMLImport::SetXmlId(uno::Reference<uno::XInterface> const & i_xIfc, OUString const & i_rXmlId) diff --git a/xmloff/source/text/XMLTextListBlockContext.cxx b/xmloff/source/text/XMLTextListBlockContext.cxx index 03c9fe0e537e..7c688f4c5e6c 100644 --- a/xmloff/source/text/XMLTextListBlockContext.cxx +++ b/xmloff/source/text/XMLTextListBlockContext.cxx @@ -181,6 +181,14 @@ XMLTextListBlockContext::XMLTextListBlockContext( } } + bool bContinueNumbering = bIsContinueNumberingAttributePresent && !mbRestartNumbering; + if (msContinueListId.isEmpty() && bContinueNumbering && GetImport().IsMSO()) + { + // No "continue list" id, but continue numbering was requested. Connect to the last list of + // the same list style in the Word case, even if there was a different list in the meantime. + msContinueListId = rTextListsHelper.GetLastIdOfStyleName(msListStyleName); + } + if ( !msContinueListId.isEmpty() ) { if ( !rTextListsHelper.IsListProcessed( msContinueListId ) ) diff --git a/xmloff/source/text/txtlists.cxx b/xmloff/source/text/txtlists.cxx index ec66f9d7d72c..9b3b46f175e7 100644 --- a/xmloff/source/text/txtlists.cxx +++ b/xmloff/source/text/txtlists.cxx @@ -124,6 +124,13 @@ void XMLTextListsHelper::KeepListAsProcessed( const OUString& sListId, msLastProcessedListId = sListId; msListStyleOfLastProcessedList = sListStyleName; + // Remember what is the last list id of this list style. + if (!mpStyleNameLastListIds) + { + mpStyleNameLastListIds = std::make_unique<std::map<OUString, OUString>>(); + } + (*mpStyleNameLastListIds)[sListStyleName] = sListId; + // Inconsistent behavior regarding lists (#i92811#) if ( sListStyleDefaultListId.isEmpty()) return; @@ -473,4 +480,20 @@ XMLTextListsHelper::MakeNumRule( return xNumRules; } +OUString XMLTextListsHelper::GetLastIdOfStyleName(const OUString& sListStyleName) const +{ + if (!mpStyleNameLastListIds) + { + return {}; + } + + auto it = mpStyleNameLastListIds->find(sListStyleName); + if (it == mpStyleNameLastListIds->end()) + { + return {}; + } + + return it->second; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |