summaryrefslogtreecommitdiffstats
path: root/sw/source/filter/xml/xmlimp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/xml/xmlimp.cxx')
-rw-r--r--sw/source/filter/xml/xmlimp.cxx1807
1 files changed, 1807 insertions, 0 deletions
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
new file mode 100644
index 000000000..a3b7485fd
--- /dev/null
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -0,0 +1,1807 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <cassert>
+
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+
+#include <o3tl/any.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/XMLTextShapeImportHelper.hxx>
+#include <xmloff/XMLFontStylesContext.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentListsAccess.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <TextCursorHelper.hxx>
+#include <unotext.hxx>
+#include <unotextrange.hxx>
+#include <poolfmt.hxx>
+#include <ndtxt.hxx>
+#include <editsh.hxx>
+#include <strings.hrc>
+#include <svl/stritem.hxx>
+#include "xmlimp.hxx"
+#include "xmlimpit.hxx"
+#include "xmltexti.hxx"
+#include <list.hxx>
+#include <swdll.hxx>
+#include <xmloff/DocumentSettingsContext.hxx>
+#include <docsh.hxx>
+#include <svx/xmlgrhlp.hxx>
+#include <svx/xmleohlp.hxx>
+#include <sfx2/printer.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <unotools/streamwrap.hxx>
+#include <tools/UnitConversion.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/svapp.hxx>
+#include <unotxdoc.hxx>
+#include <numrule.hxx>
+
+#include <xmloff/xmlmetai.hxx>
+#include <xmloff/xformsimport.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <unordered_set>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::xforms;
+using namespace ::xmloff::token;
+using namespace ::std;
+
+namespace {
+
+class SwXMLBodyContext_Impl : public SvXMLImportContext
+{
+ SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
+
+public:
+
+ SwXMLBodyContext_Impl( SwXMLImport& rImport );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+};
+
+}
+
+SwXMLBodyContext_Impl::SwXMLBodyContext_Impl( SwXMLImport& rImport ) :
+ SvXMLImportContext( rImport )
+{
+ // tdf#107211: if at this point we don't have a defined char style "Default"
+ // or "Default Style", add a mapping for it as it is not written
+ // into the file since it's not really a style but "no style"
+ // (hence referencing it actually makes no sense except for hyperlinks
+ // which default to something other than "Default")
+ OUString const sDefault(SwResId(STR_POOLCHR_STANDARD));
+ uno::Reference<container::XNameContainer> const& xStyles(
+ rImport.GetTextImport()->GetTextStyles());
+ if (!xStyles->hasByName("Default"))
+ { // this old name was used before LO 4.0
+ rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default", sDefault);
+ }
+ if (!xStyles->hasByName("Default_20_Style"))
+ { // this new name contains a space which is converted to _20_ on export
+ rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default_20_Style", sDefault);
+ }
+ bool isEncoded(false);
+ OUString const defaultEncoded(
+ rImport.GetMM100UnitConverter().encodeStyleName(sDefault, &isEncoded));
+ if (isEncoded && defaultEncoded != "Default_20_Style"
+ && !xStyles->hasByName(defaultEncoded))
+ { // new name may contain a space which is converted to _20_ on export
+ rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, defaultEncoded, sDefault);
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SwXMLBodyContext_Impl::createFastChildContext(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ return GetSwImport().CreateBodyContentContext();
+}
+
+namespace {
+
+// #i69629#
+// enhance class <SwXMLDocContext_Impl> in order to be able to create subclasses
+// NB: virtually inherit so we can multiply inherit properly
+// in SwXMLOfficeDocContext_Impl
+class SwXMLDocContext_Impl : public virtual SvXMLImportContext
+{
+ sal_Int32 mnElement;
+
+protected: // #i69629#
+ SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
+
+public:
+ SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+}
+
+SwXMLDocContext_Impl::SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
+ SvXMLImportContext( rImport ), mnElement(nElement)
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLDocContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_SCRIPTS):
+ return GetSwImport().CreateScriptContext();
+ case XML_ELEMENT(OFFICE, XML_SETTINGS):
+ return new XMLDocumentSettingsContext( GetImport() );
+ case XML_ELEMENT(OFFICE, XML_STYLES):
+ GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return GetSwImport().CreateStylesContext( false );
+ case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
+ // don't use the autostyles from the styles-document for the progress
+ if ( mnElement != 0 && (mnElement & TOKEN_MASK) != XML_DOCUMENT_STYLES )
+ GetSwImport().GetProgressBarHelper()->Increment
+ ( PROGRESS_BAR_STEP );
+ return GetSwImport().CreateStylesContext( true );
+ case XML_ELEMENT(OFFICE, XML_MASTER_STYLES):
+ return GetSwImport().CreateMasterStylesContext();
+ case XML_ELEMENT(OFFICE, XML_FONT_FACE_DECLS):
+ return GetSwImport().CreateFontDeclsContext();
+ case XML_ELEMENT(OFFICE, XML_META):
+ OSL_FAIL(" XML_ELEMENT(OFFICE, XML_META): should not have come here, maybe document is invalid?");
+ break;
+ case XML_ELEMENT(OFFICE, XML_BODY):
+ GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
+ return new SwXMLBodyContext_Impl( GetSwImport() );
+ case XML_ELEMENT(XFORMS, XML_MODEL):
+ return createXFormsModelContext(GetImport());
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("sw", nElement);
+ }
+ return nullptr;
+}
+
+namespace {
+
+// #i69629# - new subclass <SwXMLOfficeDocContext_Impl> of class <SwXMLDocContext_Impl>
+class SwXMLOfficeDocContext_Impl :
+ public SwXMLDocContext_Impl, public SvXMLMetaDocumentContext
+{
+public:
+
+ SwXMLOfficeDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement,
+ const Reference< document::XDocumentProperties >& xDocProps);
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
+};
+
+}
+
+SwXMLOfficeDocContext_Impl::SwXMLOfficeDocContext_Impl(
+ SwXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< document::XDocumentProperties >& xDocProps) :
+ SvXMLImportContext( rImport ),
+ SwXMLDocContext_Impl( rImport, nElement ),
+ SvXMLMetaDocumentContext( rImport, xDocProps )
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLOfficeDocContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
+{
+ // assign paragraph styles to list levels of outline style after all styles
+ // are imported and finished. This is the case, when <office:body> starts
+ // in flat OpenDocument file format.
+ {
+ if( nElement == XML_ELEMENT( OFFICE, XML_BODY ) )
+ {
+ GetImport().GetTextImport()->SetOutlineStyles( true );
+ }
+ }
+
+ // behave like meta base class iff we encounter office:meta
+ if ( nElement == XML_ELEMENT( OFFICE, XML_META ) ) {
+ return SvXMLMetaDocumentContext::createFastChildContext(
+ nElement, xAttrList );
+ } else {
+ return SwXMLDocContext_Impl::createFastChildContext(
+ nElement, xAttrList );
+ }
+}
+
+namespace {
+
+// #i69629# - new subclass <SwXMLDocStylesContext_Impl> of class <SwXMLDocContext_Impl>
+class SwXMLDocStylesContext_Impl : public SwXMLDocContext_Impl
+{
+public:
+
+ SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+}
+
+SwXMLDocStylesContext_Impl::SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
+ SvXMLImportContext( rImport ),
+ SwXMLDocContext_Impl( rImport, nElement )
+{
+}
+
+void SwXMLDocStylesContext_Impl::endFastElement(sal_Int32 )
+{
+ // assign paragraph styles to list levels of outline style after all styles
+ // are imported and finished.
+ SwXMLImport& rSwImport = dynamic_cast<SwXMLImport&>( GetImport());
+ GetImport().GetTextImport()->SetOutlineStyles(
+ bool(rSwImport.GetStyleFamilyMask() & SfxStyleFamily::Para));
+}
+
+SvXMLImportContext *SwXMLImport::CreateFastContext( sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
+ pContext = CreateMetaContext(nElement);
+ break;
+ case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
+ {
+ uno::Reference<document::XDocumentProperties> const xDocProps(
+ GetDocumentProperties());
+ // flat OpenDocument file format
+ pContext = new SwXMLOfficeDocContext_Impl( *this, nElement, xDocProps );
+ }
+ break;
+ // #i69629# - own subclasses for <office:document> and <office:document-styles>
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT):
+ pContext = new SwXMLDocContext_Impl( *this, nElement );
+ break;
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES):
+ pContext = new SwXMLDocStylesContext_Impl( *this, nElement );
+ break;
+ }
+ return pContext;
+}
+
+SwXMLImport::SwXMLImport(
+ const uno::Reference< uno::XComponentContext >& rContext,
+ OUString const & implementationName, SvXMLImportFlags nImportFlags)
+: SvXMLImport( rContext, implementationName, nImportFlags ),
+ m_nStyleFamilyMask( SfxStyleFamily::All ),
+ m_bLoadDoc( true ),
+ m_bInsert( false ),
+ m_bBlock( false ),
+ m_bOrganizerMode( false ),
+ m_bInititedXForms( false ),
+ m_pDoc( nullptr )
+{
+ InitItemImport();
+}
+
+SwXMLImport::~SwXMLImport() noexcept
+{
+ if (HasShapeImport())
+ {
+ SAL_WARN("sw", "endDocument skipped, dropping shapes now to avoid dangling SvTextShapeImportHelper pointing to this");
+ ClearShapeImport();
+ }
+ FinitItemImport();
+}
+
+void SwXMLImport::setTextInsertMode(
+ const Reference< XTextRange > & rInsertPos )
+{
+ m_bInsert = true;
+
+ Reference < XText > xText = rInsertPos->getText();
+ Reference < XTextCursor > xTextCursor =
+ xText->createTextCursorByRange( rInsertPos );
+ GetTextImport()->SetCursor( xTextCursor );
+}
+
+void SwXMLImport::setStyleInsertMode( SfxStyleFamily nFamilies,
+ bool bOverwrite )
+{
+ m_bInsert = !bOverwrite;
+ m_nStyleFamilyMask = nFamilies;
+ m_bLoadDoc = false;
+}
+
+const Sequence< sal_Int8 > & SwXMLImport::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSwXMLImportUnoTunnelId;
+ return theSwXMLImportUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SwXMLImport::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvXMLImport>{});
+}
+
+static OTextCursorHelper *lcl_xml_GetSwXTextCursor( const Reference < XTextCursor >& rTextCursor )
+{
+ OTextCursorHelper* pTextCursor = comphelper::getFromUnoTunnel<OTextCursorHelper>(rTextCursor);
+ OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
+ return pTextCursor;
+}
+
+void SwXMLImport::startDocument()
+{
+ // delegate to parent
+ SvXMLImport::startDocument();
+
+ OSL_ENSURE( GetModel().is(), "model is missing" );
+ if( !GetModel().is() )
+ return;
+
+ // this method will modify the document directly -> lock SolarMutex
+ SolarMutexGuard aGuard;
+
+ Reference< XPropertySet > xImportInfo( getImportInfo() );
+ Reference< XPropertySetInfo > xPropertySetInfo;
+ if( xImportInfo.is() )
+ xPropertySetInfo = xImportInfo->getPropertySetInfo();
+ if( xPropertySetInfo.is() )
+ {
+ Any aAny;
+ // insert style mode?
+ OUString sStyleInsertModeFamilies("StyleInsertModeFamilies");
+ if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeFamilies) )
+ {
+ aAny = xImportInfo->getPropertyValue(sStyleInsertModeFamilies);
+ Sequence< OUString> aFamiliesSeq;
+ if( aAny >>= aFamiliesSeq )
+ {
+ SfxStyleFamily nFamilyMask = SfxStyleFamily::None;
+ for( const OUString& rFamily : std::as_const(aFamiliesSeq) )
+ {
+ if( rFamily=="FrameStyles" )
+ nFamilyMask |= SfxStyleFamily::Frame;
+ else if( rFamily=="PageStyles" )
+ nFamilyMask |= SfxStyleFamily::Page;
+ else if( rFamily=="CharacterStyles" )
+ nFamilyMask |= SfxStyleFamily::Char;
+ else if( rFamily=="ParagraphStyles" )
+ nFamilyMask |= SfxStyleFamily::Para;
+ else if( rFamily=="NumberingStyles" )
+ nFamilyMask |= SfxStyleFamily::Pseudo;
+ }
+
+ bool bOverwrite = false;
+ static const OUStringLiteral sStyleInsertModeOverwrite(u"StyleInsertModeOverwrite");
+ if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeOverwrite) )
+ {
+ aAny = xImportInfo->getPropertyValue(sStyleInsertModeOverwrite);
+ if( auto b = o3tl::tryAccess<bool>(aAny) )
+ {
+ if( *b )
+ bOverwrite = true;
+ }
+ }
+
+ setStyleInsertMode( nFamilyMask, bOverwrite );
+ }
+ }
+
+ // text insert mode?
+ static const OUStringLiteral sTextInsertModeRange(u"TextInsertModeRange");
+ if( xPropertySetInfo->hasPropertyByName(sTextInsertModeRange) )
+ {
+ aAny = xImportInfo->getPropertyValue(sTextInsertModeRange);
+ Reference<XTextRange> xInsertTextRange;
+ if( aAny >>= xInsertTextRange )
+ setTextInsertMode( xInsertTextRange );
+ }
+
+ // auto text mode
+ static const OUStringLiteral sAutoTextMode(u"AutoTextMode");
+ if( xPropertySetInfo->hasPropertyByName(sAutoTextMode) )
+ {
+ aAny = xImportInfo->getPropertyValue(sAutoTextMode);
+ if( auto b = o3tl::tryAccess<bool>(aAny) )
+ {
+ if( *b )
+ m_bBlock = true;
+ }
+ }
+
+ // organizer mode
+ static const OUStringLiteral sOrganizerMode(u"OrganizerMode");
+ if( xPropertySetInfo->hasPropertyByName(sOrganizerMode) )
+ {
+ aAny = xImportInfo->getPropertyValue(sOrganizerMode);
+ if( auto b = o3tl::tryAccess<bool>(aAny) )
+ {
+ if( *b )
+ m_bOrganizerMode = true;
+ }
+ }
+
+ // default document properties
+ static const OUStringLiteral sDefSettings(u"DefaultDocumentSettings");
+ if (xPropertySetInfo->hasPropertyByName(sDefSettings))
+ {
+ aAny = xImportInfo->getPropertyValue(sDefSettings);
+ Sequence<PropertyValue> aProps;
+ if (aAny >>= aProps)
+ {
+ Reference<lang::XMultiServiceFactory> xFac(GetModel(), UNO_QUERY);
+ Reference<XPropertySet> xProps(
+ xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY);
+ Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
+
+ if (xProps.is() && xInfo.is())
+ {
+ for (const auto& rProp : std::as_const(aProps))
+ {
+ if (xInfo->hasPropertyByName(rProp.Name))
+ {
+ xProps->setPropertyValue(rProp.Name, rProp.Value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // There only is a text cursor by now if we are in insert mode. In any
+ // other case we have to create one at the start of the document.
+ // We also might change into the insert mode later, so we have to make
+ // sure to first set the insert mode and then create the text import
+ // helper. Otherwise it won't have the insert flag set!
+ OTextCursorHelper *pTextCursor = nullptr;
+ Reference < XTextCursor > xTextCursor;
+ if( HasTextImport() )
+ xTextCursor = GetTextImport()->GetCursor();
+ if( !xTextCursor.is() )
+ {
+ Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
+ Reference < XText > xText = xTextDoc->getText();
+ xTextCursor = xText->createTextCursor();
+ SwCursorShell *pCursorSh = nullptr;
+ SwDoc *pDoc = nullptr;
+ if( SvXMLImportFlags::ALL == getImportFlags() )
+ {
+ pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
+ OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
+ if( !pTextCursor )
+ return;
+
+ pDoc = pTextCursor->GetDoc();
+ OSL_ENSURE( pDoc, "SwDoc missing" );
+ if( !pDoc )
+ return;
+
+ // Is there an edit shell. If yes, then we are currently inserting
+ // a document. We then have to insert at the current edit shell's
+ // cursor position. That not quite clean code, but there is no other
+ // way currently.
+ pCursorSh = pDoc->GetEditShell();
+ }
+ if( pCursorSh )
+ {
+ const uno::Reference<text::XTextRange> xInsertTextRange(
+ SwXTextRange::CreateXTextRange(
+ *pDoc, *pCursorSh->GetCursor()->GetPoint(), nullptr ) );
+ setTextInsertMode( xInsertTextRange );
+ xTextCursor = GetTextImport()->GetCursor();
+ pTextCursor = nullptr;
+ }
+ else
+ GetTextImport()->SetCursor( xTextCursor );
+ }
+
+ if( !(getImportFlags() & (SvXMLImportFlags::CONTENT|SvXMLImportFlags::MASTERSTYLES)) )
+ return;
+
+ if( !pTextCursor )
+ pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
+ OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
+ if( !pTextCursor )
+ return;
+
+ SwDoc *pDoc = pTextCursor->GetDoc();
+ OSL_ENSURE( pDoc, "SwDoc missing" );
+ if( !pDoc )
+ return;
+
+ if (SvXMLImportFlags::ALL == getImportFlags())
+ {
+ // for flat ODF - this is done in SwReader::Read() for package ODF
+ pDoc->SetInReading(true);
+ pDoc->SetInXMLImport(true);
+ }
+
+ if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
+ {
+ m_pSttNdIdx.reset(new SwNodeIndex( pDoc->GetNodes() ));
+ if( IsInsertMode() )
+ {
+ SwPaM *pPaM = pTextCursor->GetPaM();
+ const SwPosition* pPos = pPaM->GetPoint();
+
+ // Split once and remember the node that has been split.
+ pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
+ *m_pSttNdIdx = pPos->nNode.GetIndex()-1;
+
+ // Split again.
+ pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
+
+ // Insert all content into the new node
+ pPaM->Move( fnMoveBackward );
+ pDoc->SetTextFormatColl
+ ( *pPaM, pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, false ) );
+ }
+ }
+
+ // We need a draw model to be able to set the z order
+ pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); // #i52858# - method name changed
+
+ // SJ: #i49801# locking the model to disable repaints
+ SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if ( pDrawModel )
+ pDrawModel->setLock(true);
+
+ if (!GetGraphicStorageHandler().is())
+ {
+ m_xGraphicStorageHandler = SvXMLGraphicHelper::Create(SvXMLGraphicHelperMode::Read);
+ SetGraphicStorageHandler(m_xGraphicStorageHandler);
+ }
+
+ if( !GetEmbeddedResolver().is() )
+ {
+ SfxObjectShell *pPersist = pDoc->GetPersist();
+ if( pPersist )
+ {
+ m_xEmbeddedResolver = SvXMLEmbeddedObjectHelper::Create(
+ *pPersist,
+ SvXMLEmbeddedObjectHelperMode::Read );
+ SetEmbeddedResolver( m_xEmbeddedResolver );
+ }
+ }
+}
+
+void SwXMLImport::endDocument()
+{
+ OSL_ENSURE( GetModel().is(), "model missing; maybe startDocument wasn't called?" );
+ if( !GetModel().is() )
+ return;
+
+ // this method will modify the document directly -> lock SolarMutex
+ SolarMutexGuard aGuard;
+
+ if (m_xGraphicStorageHandler)
+ m_xGraphicStorageHandler->dispose();
+ m_xGraphicStorageHandler.clear();
+
+ if( m_xEmbeddedResolver )
+ m_xEmbeddedResolver->dispose();
+ m_xEmbeddedResolver.clear();
+ // Clear the shape import to sort the shapes (and not in the
+ // destructor that might be called after the import has finished
+ // for Java filters.
+ if( HasShapeImport() )
+ ClearShapeImport();
+
+ SwDoc *pDoc = nullptr;
+ if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
+ {
+ Reference<XUnoTunnel> xCursorTunnel( GetTextImport()->GetCursor(),
+ UNO_QUERY);
+ assert(xCursorTunnel.is() && "missing XUnoTunnel for Cursor");
+ OTextCursorHelper* pTextCursor = comphelper::getFromUnoTunnel<OTextCursorHelper>(xCursorTunnel);
+ assert(pTextCursor && "SwXTextCursor missing");
+ SwPaM *pPaM = pTextCursor->GetPaM();
+ if( IsInsertMode() && m_pSttNdIdx->GetIndex() )
+ {
+ // If we are in insert mode, join the split node that is in front
+ // of the new content with the first new node. Or in other words:
+ // Revert the first split node.
+ SwTextNode* pTextNode = m_pSttNdIdx->GetNode().GetTextNode();
+ SwNodeIndex aNxtIdx( *m_pSttNdIdx );
+ if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx ) &&
+ m_pSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() )
+ {
+ // If the PaM points to the first new node, move the PaM to the
+ // end of the previous node.
+ if( pPaM->GetPoint()->nNode == aNxtIdx )
+ {
+ pPaM->GetPoint()->nNode = *m_pSttNdIdx;
+ pPaM->GetPoint()->nContent.Assign( pTextNode,
+ pTextNode->GetText().getLength());
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ // !!! This should be impossible !!!!
+ OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 !=
+ pPaM->GetBound().nNode.GetIndex(),
+ "PaM.Bound1 point to new node " );
+ OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 !=
+ pPaM->GetBound( false ).nNode.GetIndex(),
+ "PaM.Bound2 points to new node" );
+
+ if( m_pSttNdIdx->GetIndex()+1 ==
+ pPaM->GetBound().nNode.GetIndex() )
+ {
+ const sal_Int32 nCntPos =
+ pPaM->GetBound().nContent.GetIndex();
+ pPaM->GetBound().nContent.Assign( pTextNode,
+ pTextNode->GetText().getLength() + nCntPos );
+ }
+ if( m_pSttNdIdx->GetIndex()+1 ==
+ pPaM->GetBound( false ).nNode.GetIndex() )
+ {
+ const sal_Int32 nCntPos =
+ pPaM->GetBound( false ).nContent.GetIndex();
+ pPaM->GetBound( false ).nContent.Assign( pTextNode,
+ pTextNode->GetText().getLength() + nCntPos );
+ }
+#endif
+ // If the first new node isn't empty, convert the node's text
+ // attributes into hints. Otherwise, set the new node's
+ // paragraph style at the previous (empty) node.
+ SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode();
+ if (!pTextNode->GetText().isEmpty())
+ pDelNd->FormatToTextAttr( pTextNode );
+ else
+ {
+ pTextNode->ResetAttr(RES_CHRATR_BEGIN, RES_CHRATR_END);
+ pTextNode->ChgFormatColl( pDelNd->GetTextColl() );
+ if (!pDelNd->GetNoCondAttr(RES_PARATR_LIST_ID, /*bInParents=*/false))
+ {
+ // MergeListsAtDocumentInsertPosition() will deal with lists below, copy
+ // paragraph direct formatting otherwise.
+ pDelNd->CopyCollFormat(*pTextNode);
+ }
+ }
+ pTextNode->JoinNext();
+ }
+ }
+
+ SwPosition* pPos = pPaM->GetPoint();
+ OSL_ENSURE( !pPos->nContent.GetIndex(), "last paragraph isn't empty" );
+ if( !pPos->nContent.GetIndex() )
+ {
+ SwTextNode* pCurrNd;
+ SwNodeOffset nNodeIdx = pPos->nNode.GetIndex();
+ pDoc = &pPaM->GetDoc();
+
+ OSL_ENSURE( pPos->nNode.GetNode().IsContentNode(),
+ "insert position is not a content node" );
+ if( !IsInsertMode() )
+ {
+ // If we're not in insert mode, the last node is deleted.
+ const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
+ if( pPrev->IsContentNode() ||
+ ( pPrev->IsEndNode() &&
+ pPrev->StartOfSectionNode()->IsSectionNode() ) )
+ {
+ SwContentNode* pCNd = pPaM->GetContentNode();
+ if( pCNd && pCNd->StartOfSectionIndex()+2 <
+ pCNd->EndOfSectionIndex() )
+ {
+ pPaM->GetBound().nContent.Assign( nullptr, 0 );
+ pPaM->GetBound(false).nContent.Assign( nullptr, 0 );
+ pDoc->GetNodes().Delete( pPaM->GetPoint()->nNode );
+ }
+ }
+ }
+ else if( nullptr != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTextNode()) )
+ {
+ // Id we're in insert mode, the empty node is joined with
+ // the next and the previous one.
+ if( pCurrNd->CanJoinNext( &pPos->nNode ))
+ {
+ SwTextNode* pNextNd = pPos->nNode.GetNode().GetTextNode();
+ bool endNodeFound = pDoc->GetNodes()[nNodeIdx-1]->IsEndNode();
+ SwNode *pLastPar = pDoc->GetNodes()[nNodeIdx -2];
+ if ( !pLastPar->IsTextNode() ) {
+ pLastPar = pDoc->GetNodes()[nNodeIdx -1];
+ }
+ if ( !endNodeFound && pLastPar->IsTextNode() )
+ {
+ pNextNd->ChgFormatColl(pLastPar->GetTextNode()->GetTextColl());
+ }
+
+ pPos->nContent.Assign( pNextNd, 0 );
+ pPaM->SetMark(); pPaM->DeleteMark();
+ pNextNd->JoinPrev();
+
+ // Remove line break that has been inserted by the import,
+ // but only if one has been inserted and
+ // no endNode found to avoid removing section
+ if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && !endNodeFound &&
+ *m_pSttNdIdx != pPos->nNode )
+ {
+ pNextNd->JoinPrev();
+ }
+ }
+ else if (pCurrNd->GetText().isEmpty())
+ {
+ pPos->nContent.Assign( nullptr, 0 );
+ pPaM->SetMark(); pPaM->DeleteMark();
+ pDoc->GetNodes().Delete( pPos->nNode );
+ pPaM->Move( fnMoveBackward );
+ }
+ }
+
+ // tdf#113877
+ // when we insert one document with list inside into another one with list at the insert position,
+ // the resulting numbering in these lists is not consequent.
+ //
+ // Main document:
+ // 1. One
+ // 2. Two
+ // 3. Three
+ // 4. <-- insert position
+ //
+ // Inserted document:
+ // 1. One
+ // 2. Two
+ // 3. Three
+ // 4.
+ //
+ // Expected result
+ // 1. One
+ // 2. Two
+ // 3. Three
+ // 4. One
+ // 5. Two
+ // 6. Three
+ // 7.
+ //
+ MergeListsAtDocumentInsertPosition(pDoc);
+ }
+ }
+
+ /* Was called too early. Moved from SwXMLBodyContext_Impl::EndElement */
+
+ GetTextImport()->RedlineAdjustStartNodeCursor();
+
+ if( (getImportFlags() & SvXMLImportFlags::CONTENT) ||
+ ((getImportFlags() & SvXMLImportFlags::MASTERSTYLES) && IsStylesOnlyMode()) )
+ {
+ // pDoc might be 0. In this case UpdateTextCollCondition is looking
+ // for it itself.
+ UpdateTextCollConditions( pDoc );
+ }
+
+ GetTextImport()->ResetCursor();
+
+ m_pSttNdIdx.reset();
+
+ // SJ: #i49801# -> now permitting repaints
+ if ( pDoc )
+ {
+ if( getImportFlags() == SvXMLImportFlags::ALL )
+ {
+ // Notify math objects. If we are in the package filter this will
+ // be done by the filter object itself
+ if( IsInsertMode() )
+ pDoc->PrtOLENotify( false );
+ else if ( pDoc->IsOLEPrtNotifyPending() )
+ pDoc->PrtOLENotify( true );
+
+ assert(pDoc->IsInReading());
+ assert(pDoc->IsInXMLImport());
+ pDoc->SetInReading(false);
+ pDoc->SetInXMLImport(false);
+ }
+
+ SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if ( pDrawModel )
+ pDrawModel->setLock(false);
+ }
+
+ // #i90243#
+ if ( m_bInititedXForms )
+ {
+ Reference< xforms::XFormsSupplier > xFormsSupp( GetModel(), UNO_QUERY );
+ Reference< XNameAccess > xXForms;
+ if ( xFormsSupp.is() )
+ xXForms = xFormsSupp->getXForms().get();
+
+ if ( xXForms.is() )
+ {
+ try
+ {
+ Sequence< beans::PropertyValue > aXFormsSettings;
+
+ const OUString& sXFormsSettingsName( GetXMLToken( XML_XFORM_MODEL_SETTINGS ) );
+ if ( m_xLateInitSettings.is() && m_xLateInitSettings->hasByName( sXFormsSettingsName ) )
+ {
+ OSL_VERIFY( m_xLateInitSettings->getByName( sXFormsSettingsName ) >>= aXFormsSettings );
+ applyXFormsSettings( xXForms, aXFormsSettings );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+ }
+ }
+
+#if 1
+ if (!pDoc) { pDoc = SwImport::GetDocFromXMLImport(*this); }
+ for (SwNodeOffset i(0); i < pDoc->GetNodes().Count(); ++i)
+ {
+ if (SwTableNode *const pTableNode = pDoc->GetNodes()[i]->GetTableNode())
+ {
+ if (!pTableNode->GetTable().IsNewModel()
+ && pTableNode->GetTable().CanConvertSubtables())
+ {
+ pTableNode->GetTable().ConvertSubtables();
+ }
+ }
+ // don't skip to the end; nested tables could have subtables too...
+ }
+#endif
+
+ // delegate to parent: takes care of error handling
+ SvXMLImport::endDocument();
+ ClearTextImport();
+}
+
+// tdf#113877
+// when we insert one document with list inside into another one with list at the insert position,
+// the resulting numbering in these lists is not consequent.
+//
+// CASE-1: Main document:
+// 1. One
+// 2. Two
+// 3. Three
+// 4. <-- insert position
+//
+// Inserted document:
+// 1. One
+// 2. Two
+// 3. Three
+// 4.
+//
+// Expected result
+// 1. One
+// 2. Two
+// 3. Three
+// 4. One
+// 5. Two
+// 6. Three
+// 7.
+//
+// CASE-2: Main document:
+// 1. One
+// 2. Two
+// 3. Three
+// 4. <-- insert position
+//
+// Inserted document:
+// A) One
+// B) Two
+// C) Three
+// D)
+//
+// Expected result
+// 1. One
+// 2. Two
+// 3. Three
+// 4. One
+// A) Two
+// B) Three
+// 5.
+//
+void SwXMLImport::MergeListsAtDocumentInsertPosition(SwDoc *pDoc)
+{
+ // 1. check environment
+ if (! pDoc)
+ return;
+
+ if (! IsInsertMode() || ! m_pSttNdIdx->GetIndex())
+ return;
+
+ SwNodeOffset index(1);
+
+ // the last node of the main document where we have inserted a document
+ SwNode* const node1 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + 0];
+
+ // the first node of the inserted document
+ SwNode* node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
+
+ if (! (node1 && node2
+ && (node1->GetNodeType() == node2->GetNodeType())
+ && (node1->IsTextNode() == node2->IsTextNode())
+ ))
+ {
+ // not a text node at insert position
+ return;
+ }
+
+ // 2. get the first node of the inserted document,
+ // which will be used to detect if inside inserted document a new list was started after the first list
+ const SfxPoolItem* pListId2Initial = nullptr;
+ {
+ SwContentNode* contentNode1 = static_cast<SwContentNode *>(node1);
+ SwContentNode* contentNode2 = static_cast<SwContentNode *>(node2);
+
+ // check if both lists have the same list properties
+ const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
+ const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
+
+ if (! pListId1)
+ return;
+ if (! pListId2)
+ return;
+
+ auto pStringListId1 = dynamic_cast<const SfxStringItem*>(pListId1);
+ assert(pStringListId1);
+ const OUString& sListId1 = pStringListId1->GetValue();
+ auto pStringListId2 = dynamic_cast<const SfxStringItem*>(pListId2);
+ assert(pStringListId2);
+ const OUString& sListId2 = pStringListId2->GetValue();
+
+ const SwList* pList1 = pDoc->getIDocumentListsAccess().getListByName( sListId1 );
+ const SwList* pList2 = pDoc->getIDocumentListsAccess().getListByName( sListId2 );
+
+ if (! pList1)
+ return;
+ if (! pList2)
+ return;
+
+ const OUString& sDefaultListStyleName1 = pList1->GetDefaultListStyleName();
+ const OUString& sDefaultListStyleName2 = pList2->GetDefaultListStyleName();
+
+ if (sDefaultListStyleName1 != sDefaultListStyleName2)
+ {
+ const SwNumRule* pNumRule1 = pDoc->FindNumRulePtr( sDefaultListStyleName1 );
+ const SwNumRule* pNumRule2 = pDoc->FindNumRulePtr( sDefaultListStyleName2 );
+
+ if (pNumRule1 && pNumRule2)
+ {
+ // check style of the each list level
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ {
+ if( pNumRule1->Get( n ) != pNumRule2->Get( n ) )
+ {
+ return;
+ }
+ }
+
+ // our list should be merged
+ pListId2Initial = pListId2;
+ }
+ }
+ else
+ {
+ // our list should be merged
+ pListId2Initial = pListId2;
+ }
+ }
+
+ if (! pListId2Initial)
+ {
+ // two lists have different styles => they should not be merged
+ return;
+ }
+
+ // 3. merge two lists
+ while (
+ node1 && node2
+ && (node1->GetNodeType() == node2->GetNodeType())
+ && (node1->IsTextNode() == node2->IsTextNode())
+ )
+ {
+ SwContentNode* contentNode1 = static_cast<SwContentNode *>( node1 );
+ SwContentNode* contentNode2 = static_cast<SwContentNode *>( node2 );
+
+ const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
+ const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
+
+ if (! pListId1)
+ return;
+ if (! pListId2)
+ return;
+
+ if (*pListId2Initial != *pListId2)
+ {
+ // no more list items of the first list inside inserted document
+ return;
+ }
+
+ // set list style to this list element
+ contentNode2->SetAttr(*pListId1);
+
+ // get next item
+ index++;
+ if (index >= pDoc->GetNodes().Count())
+ {
+ // no more items
+ return;
+ }
+
+ node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
+ }
+}
+
+namespace {
+
+// Locally derive XMLTextShapeImportHelper, so we can take care of the
+// form import This is Writer, but not text specific, so it should go
+// here!
+class SvTextShapeImportHelper : public XMLTextShapeImportHelper
+{
+ // hold own reference form import helper, because the SvxImport
+ // stored in the superclass, from whom we originally got the
+ // reference, is already destroyed when we want to use it in the
+ // destructor
+ rtl::Reference< ::xmloff::OFormLayerXMLImport > rFormImport;
+
+ // hold reference to the one page (if it exists) for calling startPage()
+ // and endPage. If !xPage.is(), then this document doesn't have a
+ // XDrawPage.
+ Reference<drawing::XDrawPage> xPage;
+
+public:
+ explicit SvTextShapeImportHelper(SvXMLImport& rImp);
+ virtual ~SvTextShapeImportHelper() override;
+};
+
+}
+
+SvTextShapeImportHelper::SvTextShapeImportHelper(SvXMLImport& rImp) :
+ XMLTextShapeImportHelper(rImp)
+{
+ Reference<drawing::XDrawPageSupplier> xSupplier(rImp.GetModel(),UNO_QUERY);
+ if (xSupplier.is())
+ {
+ if (rImp.GetFormImport().is())
+ {
+ rImp.GetFormImport()->startPage(xSupplier->getDrawPage());
+ rFormImport = rImp.GetFormImport();
+ }
+
+ xPage = xSupplier->getDrawPage();
+ XMLShapeImportHelper::startPage( xPage );
+ }
+}
+
+SvTextShapeImportHelper::~SvTextShapeImportHelper()
+{
+ rFormImport->endPage();
+
+ if (xPage.is())
+ {
+ XMLShapeImportHelper::endPage(xPage);
+ }
+}
+
+XMLTextImportHelper* SwXMLImport::CreateTextImport()
+{
+ return new SwXMLTextImportHelper( GetModel(), *this, getImportInfo(),
+ IsInsertMode(),
+ IsStylesOnlyMode(),
+ IsBlockMode(), m_bOrganizerMode );
+}
+
+XMLShapeImportHelper* SwXMLImport::CreateShapeImport()
+{
+ return new SvTextShapeImportHelper( *this );
+}
+
+SvXMLImportContext *SwXMLImport::CreateFontDeclsContext()
+{
+ XMLFontStylesContext *pFSContext =
+ new XMLFontStylesContext( *this, osl_getThreadTextEncoding() );
+ SetFontDecls( pFSContext );
+ return pFSContext;
+}
+
+void SwXMLImport::SetViewSettings(const Sequence < PropertyValue > & aViewProps)
+{
+ if (IsInsertMode() || IsStylesOnlyMode() || IsBlockMode() || m_bOrganizerMode || !GetModel().is() )
+ return;
+
+ // this method will modify the document directly -> lock SolarMutex
+ SolarMutexGuard aGuard;
+
+ SwDoc *pDoc = getDoc();
+ tools::Rectangle aRect;
+ if( pDoc->GetDocShell() )
+ aRect = pDoc->GetDocShell()->GetVisArea( ASPECT_CONTENT );
+ //TODO/LATER: why that cast?!
+ //aRect = ((SfxInPlaceObject *)pDoc->GetDocShell())->GetVisArea();
+
+ sal_Int64 nTmp = 0;
+ bool bShowRedlineChanges = false, bBrowseMode = false;
+ bool bChangeShowRedline = false, bChangeBrowseMode = false;
+
+ //TODO/LATER: why that cast?!
+ bool bTwip = pDoc->GetDocShell()->GetMapUnit ( ) == MapUnit::MapTwip;
+ //sal_Bool bTwip = pDoc->GetDocShell()->SfxInPlaceObject::GetMapUnit ( ) == MapUnit::MapTwip;
+
+ for (const PropertyValue& rValue : aViewProps)
+ {
+ if ( rValue.Name == "ViewAreaTop" )
+ {
+ rValue.Value >>= nTmp;
+ aRect.SetPosY(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
+ }
+ else if ( rValue.Name == "ViewAreaLeft" )
+ {
+ rValue.Value >>= nTmp;
+ aRect.SetPosX(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
+ }
+ else if ( rValue.Name == "ViewAreaWidth" )
+ {
+ rValue.Value >>= nTmp;
+ Size aSize( aRect.GetSize() );
+ aSize.setWidth(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
+ aRect.SetSize( aSize );
+ }
+ else if ( rValue.Name == "ViewAreaHeight" )
+ {
+ rValue.Value >>= nTmp;
+ Size aSize( aRect.GetSize() );
+ aSize.setHeight(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
+ aRect.SetSize( aSize );
+ }
+ else if ( rValue.Name == "ShowRedlineChanges" )
+ {
+ bShowRedlineChanges = *o3tl::doAccess<bool>(rValue.Value);
+ bChangeShowRedline = true;
+ }
+// Headers and footers are not displayed in BrowseView anymore
+ else if ( rValue.Name == "InBrowseMode" )
+ {
+ bBrowseMode = *o3tl::doAccess<bool>(rValue.Value);
+ bChangeBrowseMode = true;
+ }
+ }
+ if( pDoc->GetDocShell() )
+ pDoc->GetDocShell()->SetVisArea ( aRect );
+
+ if (bChangeBrowseMode)
+ pDoc->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, bBrowseMode );
+
+ if (bChangeShowRedline)
+ GetTextImport()->SetShowChanges( bShowRedlineChanges );
+}
+
+// Note: this will be called only if there are OOo elements in settings.xml.
+// So if a setting is missing there we can assume that it was written
+// by an OOo/LO version that is older than the introduction of the setting!
+void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aConfigProps)
+{
+ // this method will modify the document directly -> lock SolarMutex
+ SolarMutexGuard aGuard;
+
+ Reference< lang::XMultiServiceFactory > xFac( GetModel(), UNO_QUERY );
+ if( !xFac.is() )
+ return;
+
+ Reference< XPropertySet > xProps( xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY );
+ if( !xProps.is() )
+ return;
+
+ Reference< XPropertySetInfo > xInfo( xProps->getPropertySetInfo() );
+ if( !xInfo.is() )
+ return;
+
+ std::unordered_set< OUString > aExcludeAlways;
+ aExcludeAlways.insert("LinkUpdateMode");
+ // this should contain things that are actually user-settable, via Tools->Options
+ std::unordered_set< OUString > aExcludeWhenNotLoadingUserSettings {
+ "ForbiddenCharacters",
+ "IsKernAsianPunctuation",
+ "CharacterCompressionType",
+ "FieldAutoUpdate",
+ "ChartAutoUpdate",
+ "AddParaTableSpacing",
+ "AddParaTableSpacingAtStart",
+ "PrintAnnotationMode",
+ "PrintBlackFonts",
+ "PrintControls",
+ "PrintDrawings",
+ "PrintGraphics",
+ "PrintHiddenText",
+ "PrintLeftPages",
+ "PrintPageBackground",
+ "PrintProspect",
+ "PrintReversed",
+ "PrintRightPages",
+ "PrintFaxName",
+ "PrintPaperFromSetup",
+ "PrintTables",
+ "PrintTextPlaceholder",
+ "PrintSingleJobs",
+ "UpdateFromTemplate",
+ "PrinterIndependentLayout",
+ "PrintEmptyPages",
+ "ConsiderTextWrapOnObjPos",
+ "DoNotJustifyLinesWithManualBreak",
+ "ProtectForm",
+ "MsWordCompTrailingBlanks",
+ "SubtractFlysAnchoredAtFlys",
+ "EmptyDbFieldHidesPara"
+ };
+
+ bool bAreUserSettingsFromDocument = officecfg::Office::Common::Load::UserDefinedSettings::get();
+
+ // for some properties we don't want to use the application
+ // default if they're missing. So we watch for them in the loop
+ // below, and set them if not found
+ bool bPrinterIndependentLayout = false;
+ bool bUseOldNumbering = false;
+ bool bAddExternalLeading = false;
+ bool bAddParaSpacingToTableCells = false;
+ bool bAddParaLineSpacingToTableCells = false;
+ bool bUseFormerLineSpacing = false;
+ bool bUseFormerObjectPositioning = false;
+ bool bUseFormerTextWrapping = false;
+ bool bConsiderWrapOnObjPos = false;
+ bool bIgnoreFirstLineIndentInNumbering = false;
+ bool bDoNotJustifyLinesWithManualBreak = false;
+ bool bDoNotResetParaAttrsForNumFont = false;
+ bool bDoNotCaptureDrawObjsOnPage( false );
+ bool bClipAsCharacterAnchoredWriterFlyFrames( false );
+ bool bUnixForceZeroExtLeading = false;
+ bool bSmallCapsPercentage66 = false;
+ bool bTabOverflow = false;
+ bool bTabOverMarginValue = false;
+ bool bPropLineSpacingShrinksFirstLine = false;
+ bool bSubtractFlysAnchoredAtFlys = false;
+ bool bEmptyDbFieldHidesPara = false;
+ bool bCollapseEmptyCellPara = false;
+ bool bAutoFirstLineIndentDisregardLineSpace = false;
+
+ const PropertyValue* currentDatabaseDataSource = nullptr;
+ const PropertyValue* currentDatabaseCommand = nullptr;
+ const PropertyValue* currentDatabaseCommandType = nullptr;
+ const PropertyValue* embeddedDatabaseName = nullptr;
+
+ for( const PropertyValue& rValue : aConfigProps )
+ {
+ bool bSet = aExcludeAlways.find(rValue.Name) == aExcludeAlways.end();
+ if( bSet && !bAreUserSettingsFromDocument
+ && (aExcludeWhenNotLoadingUserSettings.find(rValue.Name)
+ != aExcludeWhenNotLoadingUserSettings.end()) )
+ {
+ bSet = false;
+ }
+
+ if( bSet )
+ {
+ try
+ {
+ if( xInfo->hasPropertyByName( rValue.Name ) )
+ {
+ if( rValue.Name == "RedlineProtectionKey" )
+ {
+ Sequence<sal_Int8> aKey;
+ rValue.Value >>= aKey;
+ GetTextImport()->SetChangesProtectionKey( aKey );
+ }
+ else
+ {
+ // HACK: Setting these out of order does not work.
+ if( rValue.Name == "CurrentDatabaseDataSource" )
+ currentDatabaseDataSource = &rValue;
+ else if( rValue.Name == "CurrentDatabaseCommand" )
+ currentDatabaseCommand = &rValue;
+ else if( rValue.Name == "CurrentDatabaseCommandType" )
+ currentDatabaseCommandType = &rValue;
+ else if (rValue.Name == "EmbeddedDatabaseName")
+ embeddedDatabaseName = &rValue;
+ else
+ xProps->setPropertyValue( rValue.Name, rValue.Value );
+ }
+ }
+
+ // did we find any of the non-default cases?
+ if ( rValue.Name == "PrinterIndependentLayout" )
+ bPrinterIndependentLayout = true;
+ else if ( rValue.Name == "AddExternalLeading" )
+ bAddExternalLeading = true;
+ else if ( rValue.Name == "AddParaSpacingToTableCells" )
+ bAddParaSpacingToTableCells = true;
+ else if ( rValue.Name == "AddParaLineSpacingToTableCells" )
+ bAddParaLineSpacingToTableCells = true;
+ else if ( rValue.Name == "UseFormerLineSpacing" )
+ bUseFormerLineSpacing = true;
+ else if ( rValue.Name == "UseFormerObjectPositioning" )
+ bUseFormerObjectPositioning = true;
+ else if ( rValue.Name == "UseFormerTextWrapping" )
+ bUseFormerTextWrapping = true;
+ else if ( rValue.Name == "UseOldNumbering" )
+ bUseOldNumbering = true;
+ else if ( rValue.Name == "ConsiderTextWrapOnObjPos" )
+ bConsiderWrapOnObjPos = true;
+ else if ( rValue.Name == "IgnoreFirstLineIndentInNumbering" )
+ bIgnoreFirstLineIndentInNumbering = true;
+ else if ( rValue.Name == "DoNotJustifyLinesWithManualBreak" )
+ bDoNotJustifyLinesWithManualBreak = true;
+ else if ( rValue.Name == "DoNotResetParaAttrsForNumFont" )
+ bDoNotResetParaAttrsForNumFont = true;
+ else if ( rValue.Name == "DoNotCaptureDrawObjsOnPage" )
+ bDoNotCaptureDrawObjsOnPage = true;
+ else if ( rValue.Name == "ClipAsCharacterAnchoredWriterFlyFrames" )
+ bClipAsCharacterAnchoredWriterFlyFrames = true;
+ else if ( rValue.Name == "UnxForceZeroExtLeading" )
+ bUnixForceZeroExtLeading = true;
+ else if ( rValue.Name == "SmallCapsPercentage66" )
+ bSmallCapsPercentage66 = true;
+ else if ( rValue.Name == "TabOverflow" )
+ bTabOverflow = true;
+ else if ( rValue.Name == "TabOverMargin" )
+ {
+ rValue.Value >>= bTabOverMarginValue;
+ }
+ else if ( rValue.Name == "PropLineSpacingShrinksFirstLine" )
+ bPropLineSpacingShrinksFirstLine = true;
+ else if (rValue.Name == "SubtractFlysAnchoredAtFlys")
+ bSubtractFlysAnchoredAtFlys = true;
+ else if (rValue.Name == "EmptyDbFieldHidesPara")
+ bEmptyDbFieldHidesPara = true;
+ else if (rValue.Name == "CollapseEmptyCellPara")
+ bCollapseEmptyCellPara = true;
+ else if (rValue.Name == "AutoFirstLineIndentDisregardLineSpace")
+ bAutoFirstLineIndentDisregardLineSpace = true;
+ }
+ catch( Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
+ }
+ }
+ }
+
+ try
+ {
+ if( currentDatabaseDataSource != nullptr )
+ xProps->setPropertyValue( currentDatabaseDataSource->Name, currentDatabaseDataSource->Value );
+ if( currentDatabaseCommand != nullptr )
+ xProps->setPropertyValue( currentDatabaseCommand->Name, currentDatabaseCommand->Value );
+ if( currentDatabaseCommandType != nullptr )
+ xProps->setPropertyValue( currentDatabaseCommandType->Name, currentDatabaseCommandType->Value );
+ if (embeddedDatabaseName)
+ xProps->setPropertyValue(embeddedDatabaseName->Name, embeddedDatabaseName->Value);
+ } catch( Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
+ }
+
+ // finally, treat the non-default cases
+ // introduce boolean, that indicates a document, written by version prior SO8.
+ // If user settings are not loaded, we can't know if this is an old document. Better to assume no?
+ const bool bDocumentPriorSO8 = !bConsiderWrapOnObjPos && bAreUserSettingsFromDocument;
+
+ // Use old behaviour if this setting didn't exist, but only if this setting is being read from the document.
+ // (Obviously the setting doesn't exist if we are explicitly ignoring it, so then stick with program/user defaults)
+ if(!bPrinterIndependentLayout && bAreUserSettingsFromDocument)
+ {
+ xProps->setPropertyValue( "PrinterIndependentLayout", Any(sal_Int16(document::PrinterIndependentLayout::DISABLED)) );
+ }
+
+ if( ! bAddExternalLeading )
+ {
+ xProps->setPropertyValue( "AddExternalLeading", Any( false ) );
+ }
+
+ if( ! bUseFormerLineSpacing )
+ {
+ xProps->setPropertyValue( "UseFormerLineSpacing", Any( true ) );
+ }
+
+ if( !bUseFormerObjectPositioning )
+ {
+ xProps->setPropertyValue( "UseFormerObjectPositioning", Any( true ) );
+ }
+
+ if( !bUseOldNumbering )
+ {
+ xProps->setPropertyValue( "UseOldNumbering", Any(true) );
+ }
+
+ if( !bAddParaSpacingToTableCells )
+ {
+ xProps->setPropertyValue( "AddParaSpacingToTableCells",
+ Any( false ) );
+ }
+ if (!bAddParaLineSpacingToTableCells)
+ {
+ xProps->setPropertyValue("AddParaLineSpacingToTableCells", Any(false));
+ }
+
+ if( !bUseFormerTextWrapping )
+ {
+ xProps->setPropertyValue( "UseFormerTextWrapping", Any( true ) );
+ }
+
+ if (!bConsiderWrapOnObjPos && bAreUserSettingsFromDocument)
+ {
+ xProps->setPropertyValue( "ConsiderTextWrapOnObjPos", Any( false ) );
+ }
+
+ // #i47448#
+ // For SO7pp4, part of the 'new numbering' stuff has been backported from
+ // SO8. Unfortunately, only part of it and by using the same compatibility option
+ // like in SO8. Therefore documents generated with SO7pp4, containing
+ // numbered paragraphs with first line indent differ between SO7pp4 and
+ // SO8. In order to fix this for SO8pp1, I introduce a new compatibility
+ // flag 'bIgnoreFirstLineIndentInNumbering'. This flag has to be set for all
+ // documents < SO8, but not for SO8. So if the property is not present, the
+ // flag will be set to 'true'. SO8 documents surely have the
+ // 'ConsiderWrapOnObjPos' property set (no matter if 'true' or 'false'),
+ // therefore the correct condition to set this flag is this:
+ if( !bIgnoreFirstLineIndentInNumbering && bDocumentPriorSO8 )
+ {
+ xProps->setPropertyValue( "IgnoreFirstLineIndentInNumbering",
+ Any( true ) );
+ }
+
+ // This flag has to be set for all documents < SO8
+ if ( !bDoNotJustifyLinesWithManualBreak && bDocumentPriorSO8 )
+ {
+ xProps->setPropertyValue( "DoNotJustifyLinesWithManualBreak",
+ Any( true ) );
+ }
+
+ // This flag has to be set for all documents < SO8
+ if ( !bDoNotResetParaAttrsForNumFont && bDocumentPriorSO8 )
+ {
+ xProps->setPropertyValue( "DoNotResetParaAttrsForNumFont",
+ Any( true ) );
+ }
+
+ // This flag has to be set for all documents < SO8
+ if ( !bDoNotCaptureDrawObjsOnPage && bDocumentPriorSO8 )
+ {
+ xProps->setPropertyValue( "DoNotCaptureDrawObjsOnPage",
+ Any( true ) );
+ }
+
+ // This flag has to be set for all documents < SO8
+ if ( !bClipAsCharacterAnchoredWriterFlyFrames && bDocumentPriorSO8 )
+ {
+ xProps->setPropertyValue( "ClipAsCharacterAnchoredWriterFlyFrames",
+ Any( true ) );
+ }
+
+ if ( !bUnixForceZeroExtLeading )
+ {
+ xProps->setPropertyValue( "UnxForceZeroExtLeading", Any( true ) );
+ }
+
+ // Old LO versions had 66 as the value for small caps percentage, later changed to 80.
+ // In order to keep backwards compatibility, SmallCapsPercentage66 option is written to .odt
+ // files, and the default for new documents is 'false'. Files without this option
+ // are considered to be old files, so set the compatibility option too.
+ if ( !bSmallCapsPercentage66 )
+ {
+ xProps->setPropertyValue( "SmallCapsPercentage66", Any( true ) );
+ }
+
+ if ( !bTabOverflow )
+ {
+ xProps->setPropertyValue( "TabOverflow", Any( false ) );
+ }
+
+ if (bTabOverMarginValue)
+ // Let TabOverMargin imply the new default for
+ // PrinterIndependentLayout, knowing the first is set by Word import
+ // filters and Word defaults to our new default as well.
+ xProps->setPropertyValue(
+ "PrinterIndependentLayout",
+ uno::Any(document::PrinterIndependentLayout::HIGH_RESOLUTION));
+
+ if (!bPropLineSpacingShrinksFirstLine)
+ xProps->setPropertyValue("PropLineSpacingShrinksFirstLine", Any(false));
+
+ if (!bSubtractFlysAnchoredAtFlys && bAreUserSettingsFromDocument)
+ xProps->setPropertyValue("SubtractFlysAnchoredAtFlys", Any(true));
+
+ if (!bEmptyDbFieldHidesPara && bAreUserSettingsFromDocument)
+ xProps->setPropertyValue("EmptyDbFieldHidesPara", Any(false));
+
+ if (!bCollapseEmptyCellPara)
+ xProps->setPropertyValue("CollapseEmptyCellPara", Any(false));
+
+ if (!bAutoFirstLineIndentDisregardLineSpace)
+ xProps->setPropertyValue("AutoFirstLineIndentDisregardLineSpace", Any(false));
+
+ SwDoc *pDoc = getDoc();
+ SfxPrinter *pPrinter = pDoc->getIDocumentDeviceAccess().getPrinter( false );
+ if( pPrinter )
+ {
+ // If the printer is known, then the OLE objects will
+ // already have correct sizes, and we don't have to call
+ // PrtOLENotify again. Otherwise we have to call it.
+ // The flag might be set from setting the printer, so it
+ // it is required to clear it.
+ pDoc->SetOLEPrtNotifyPending( !pPrinter->IsKnown() );
+ }
+}
+
+void SwXMLImport::SetDocumentSpecificSettings(
+ const OUString& _rSettingsGroupName,
+ const Sequence< PropertyValue>& _rSettings )
+{
+ // the only doc-specific settings group we know so far are the XForms settings
+ if ( !IsXMLToken( _rSettingsGroupName, XML_XFORM_MODEL_SETTINGS ) )
+ return;
+
+ // preserve the settings for a later iteration - we are currently reading the settings.xml,
+ // the content.xml will be read later, by another instance of SwXMLImport
+ OSL_ENSURE( m_xLateInitSettings.is(), "SwXMLImport::SetDocumentSpecificSettings: no storage for those settings!" );
+ if ( !m_xLateInitSettings.is() )
+ return;
+
+ try
+ {
+ if ( m_xLateInitSettings->hasByName( _rSettingsGroupName ) )
+ {
+ m_xLateInitSettings->replaceByName( _rSettingsGroupName, Any( _rSettings ) );
+ OSL_FAIL( "SwXMLImport::SetDocumentSpecificSettings: already have settings for this model!" );
+ }
+ else
+ m_xLateInitSettings->insertByName( _rSettingsGroupName, Any( _rSettings ) );
+ }
+ catch( const Exception& )
+ {
+ }
+}
+
+void SwXMLImport::initialize(
+ const Sequence<Any>& aArguments )
+{
+ // delegate to super class
+ SvXMLImport::initialize(aArguments);
+
+ // we are only looking for a NamedValue "LateInitSettings"
+ for(const auto& rArgument : aArguments)
+ {
+ beans::NamedValue aNamedValue;
+ if ( rArgument >>= aNamedValue )
+ {
+ if (aNamedValue.Name == "LateInitSettings")
+ {
+ OSL_VERIFY( aNamedValue.Value >>= m_xLateInitSettings );
+ }
+ }
+ }
+}
+
+SwDoc* SwImport::GetDocFromXMLImport( SvXMLImport const & rImport )
+{
+ auto pTextDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(rImport.GetModel());
+ assert( pTextDoc );
+ assert( pTextDoc->GetDocShell() );
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ OSL_ENSURE( pDoc, "Where is my document?" );
+ return pDoc;
+}
+
+void SwXMLImport::initXForms()
+{
+ // obtain SwDoc
+ auto pXTextDocument = comphelper::getFromUnoTunnel<SwXTextDocument>(GetModel());
+ if( pXTextDocument == nullptr )
+ return;
+
+ SwDoc *pDoc = pXTextDocument->GetDocShell()->GetDoc();
+
+ // init XForms (if not already done)
+ // (no default model, since we'll load the models)
+ if( ! pDoc->isXForms() )
+ pDoc->initXForms( false );
+
+ m_bInititedXForms = true;
+}
+
+SwDoc* SwXMLImport::getDoc()
+{
+ if( m_pDoc != nullptr )
+ return m_pDoc;
+ Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
+ Reference < XText > xText = xTextDoc->getText();
+ Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY);
+ assert( xTextTunnel.is());
+ SwXText* pText = comphelper::getFromUnoTunnel<SwXText>(xTextTunnel);
+ assert( pText != nullptr );
+ m_pDoc = pText->GetDoc();
+ assert( m_pDoc != nullptr );
+ return m_pDoc;
+}
+
+const SwDoc* SwXMLImport::getDoc() const
+{
+ return const_cast< SwXMLImport* >( this )->getDoc();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisImporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisImporter",
+ SvXMLImportFlags::ALL));
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisStylesImporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisStylesImporter",
+ SvXMLImportFlags::STYLES | SvXMLImportFlags::MASTERSTYLES | SvXMLImportFlags::AUTOSTYLES |
+ SvXMLImportFlags::FONTDECLS));
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisContentImporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisContentImporter",
+ SvXMLImportFlags::CONTENT | SvXMLImportFlags::SCRIPTS | SvXMLImportFlags::AUTOSTYLES |
+ SvXMLImportFlags::FONTDECLS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisMetaImporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisMetaImporter",
+ SvXMLImportFlags::META));
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisSettingsImporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisSettingsImporter",
+ SvXMLImportFlags::SETTINGS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODT(SvStream &rStream)
+{
+ SwGlobals::ensure();
+
+ SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
+ xDocSh->DoInitNew();
+ uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
+
+ uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
+ uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
+ uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.XmlFilterAdaptor"), uno::UNO_SET_THROW);
+
+ css::uno::Sequence<OUString> aUserData
+ {
+ "com.sun.star.comp.filter.OdfFlatXml",
+ "",
+ "com.sun.star.comp.Writer.XMLOasisImporter",
+ "com.sun.star.comp.Writer.XMLOasisExporter",
+ "",
+ "",
+ "true"
+ };
+ uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
+ {
+ { "UserData", uno::Any(aUserData) },
+ }));
+ css::uno::Sequence<uno::Any> aOuterArgs{ uno::Any(aAdaptorArgs) };
+
+ uno::Reference<lang::XInitialization> xInit(xInterface, uno::UNO_QUERY_THROW);
+ xInit->initialize(aOuterArgs);
+
+ uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ {
+ { "InputStream", uno::Any(xStream) },
+ { "URL", uno::Any(OUString("private:stream")) },
+ }));
+ xImporter->setTargetDocument(xModel);
+
+ uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
+ //SetLoading hack because the document properties will be re-initted
+ //by the xml filter and during the init, while it's considered uninitialized,
+ //setting a property will inform the document it's modified, which attempts
+ //to update the properties, which throws cause the properties are uninitialized
+ xDocSh->SetLoading(SfxLoadedFlags::NONE);
+ bool ret = xFilter->filter(aArgs);
+ xDocSh->SetLoading(SfxLoadedFlags::ALL);
+
+ xDocSh->DoClose();
+
+ return ret;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportDOCX(SvStream &rStream)
+{
+ SwGlobals::ensure();
+
+ SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
+ xDocSh->DoInitNew();
+ uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
+
+ uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
+ uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
+
+ uno::Reference<document::XFilter> xFilter(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_QUERY_THROW);
+
+ uno::Reference<document::XImporter> xImporter(xFilter, uno::UNO_QUERY_THROW);
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ {
+ { "InputStream", uno::Any(xStream) },
+ { "InputMode", uno::Any(true) },
+ }));
+ xImporter->setTargetDocument(xModel);
+
+ //SetLoading hack because the document properties will be re-initted
+ //by the xml filter and during the init, while it's considered uninitialized,
+ //setting a property will inform the document it's modified, which attempts
+ //to update the properties, which throws cause the properties are uninitialized
+ xDocSh->SetLoading(SfxLoadedFlags::NONE);
+ bool ret = false;
+ try
+ {
+ ret = xFilter->filter(aArgs);
+ }
+ catch (...)
+ {
+ }
+ xDocSh->SetLoading(SfxLoadedFlags::ALL);
+
+ xDocSh->DoClose();
+
+ return ret;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */