android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / filter / xml / xmlimp.cxx
blob49f51c0f5ac7293febf7a1eccaa0c522c6b856de
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <cassert>
25 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
26 #include <com/sun/star/document/XExporter.hpp>
27 #include <com/sun/star/drawing/XDrawPage.hpp>
28 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <com/sun/star/text/XTextDocument.hpp>
31 #include <com/sun/star/text/XTextRange.hpp>
33 #include <o3tl/any.hxx>
34 #include <xmloff/xmlnamespace.hxx>
35 #include <xmloff/xmlictxt.hxx>
36 #include <xmloff/txtimp.hxx>
37 #include <xmloff/XMLTextShapeImportHelper.hxx>
38 #include <xmloff/XMLFontStylesContext.hxx>
39 #include <xmloff/ProgressBarHelper.hxx>
40 #include <doc.hxx>
41 #include <drawdoc.hxx>
42 #include <IDocumentSettingAccess.hxx>
43 #include <IDocumentDeviceAccess.hxx>
44 #include <IDocumentListsAccess.hxx>
45 #include <IDocumentStylePoolAccess.hxx>
46 #include <IDocumentDrawModelAccess.hxx>
47 #include <TextCursorHelper.hxx>
48 #include <unotext.hxx>
49 #include <unotextrange.hxx>
50 #include <poolfmt.hxx>
51 #include <ndtxt.hxx>
52 #include <editsh.hxx>
53 #include <strings.hrc>
54 #include <svl/stritem.hxx>
55 #include "xmlimp.hxx"
56 #include "xmlimpit.hxx"
57 #include "xmltexti.hxx"
58 #include <list.hxx>
59 #include <swdll.hxx>
60 #include <xmloff/DocumentSettingsContext.hxx>
61 #include <docsh.hxx>
62 #include <svx/xmlgrhlp.hxx>
63 #include <svx/xmleohlp.hxx>
64 #include <sfx2/printer.hxx>
65 #include <sfx2/sfxmodelfactory.hxx>
66 #include <xmloff/xmluconv.hxx>
67 #include <unotools/fcm.hxx>
68 #include <unotools/mediadescriptor.hxx>
69 #include <unotools/streamwrap.hxx>
70 #include <unotools/tempfile.hxx>
71 #include <tools/UnitConversion.hxx>
72 #include <comphelper/diagnose_ex.hxx>
74 #include <vcl/svapp.hxx>
75 #include <unotxdoc.hxx>
76 #include <numrule.hxx>
78 #include <xmloff/xmlmetai.hxx>
79 #include <xmloff/xformsimport.hxx>
80 #include <comphelper/servicehelper.hxx>
81 #include <comphelper/processfactory.hxx>
82 #include <comphelper/propertysequence.hxx>
83 #include <officecfg/Office/Common.hxx>
85 #include <unordered_set>
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::text;
90 using namespace ::com::sun::star::lang;
91 using namespace ::com::sun::star::beans;
92 using namespace ::com::sun::star::container;
93 using namespace ::com::sun::star::i18n;
94 using namespace ::com::sun::star::drawing;
95 using namespace ::com::sun::star::xforms;
96 using namespace ::xmloff::token;
98 namespace {
100 class SwXMLBodyContext_Impl : public SvXMLImportContext
102 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
104 public:
106 SwXMLBodyContext_Impl( SwXMLImport& rImport );
108 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
109 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
114 SwXMLBodyContext_Impl::SwXMLBodyContext_Impl( SwXMLImport& rImport ) :
115 SvXMLImportContext( rImport )
117 // tdf#107211: if at this point we don't have a defined char style "Default"
118 // or "Default Style", add a mapping for it as it is not written
119 // into the file since it's not really a style but "no style"
120 // (hence referencing it actually makes no sense except for hyperlinks
121 // which default to something other than "Default")
122 OUString const sDefault(SwResId(STR_POOLCHR_STANDARD));
123 uno::Reference<container::XNameContainer> const& xStyles(
124 rImport.GetTextImport()->GetTextStyles());
125 if (!xStyles->hasByName("Default"))
126 { // this old name was used before LO 4.0
127 rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default", sDefault);
129 if (!xStyles->hasByName("Default_20_Style"))
130 { // this new name contains a space which is converted to _20_ on export
131 rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default_20_Style", sDefault);
133 bool isEncoded(false);
134 OUString const defaultEncoded(
135 rImport.GetMM100UnitConverter().encodeStyleName(sDefault, &isEncoded));
136 if (isEncoded && defaultEncoded != "Default_20_Style"
137 && !xStyles->hasByName(defaultEncoded))
138 { // new name may contain a space which is converted to _20_ on export
139 rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, defaultEncoded, sDefault);
143 css::uno::Reference< css::xml::sax::XFastContextHandler > SwXMLBodyContext_Impl::createFastChildContext(
144 sal_Int32 /*nElement*/,
145 const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
147 return GetSwImport().CreateBodyContentContext();
150 namespace {
152 // #i69629#
153 // enhance class <SwXMLDocContext_Impl> in order to be able to create subclasses
154 // NB: virtually inherit so we can multiply inherit properly
155 // in SwXMLOfficeDocContext_Impl
156 class SwXMLDocContext_Impl : public virtual SvXMLImportContext
158 sal_Int32 mnElement;
160 protected: // #i69629#
161 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
163 public:
164 SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
166 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
167 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
172 SwXMLDocContext_Impl::SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
173 SvXMLImportContext( rImport ), mnElement(nElement)
177 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLDocContext_Impl::createFastChildContext(
178 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
180 switch (nElement)
182 case XML_ELEMENT(OFFICE, XML_SCRIPTS):
183 return GetSwImport().CreateScriptContext();
184 case XML_ELEMENT(OFFICE, XML_SETTINGS):
185 return new XMLDocumentSettingsContext( GetImport() );
186 case XML_ELEMENT(OFFICE, XML_STYLES):
187 GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
188 return GetSwImport().CreateStylesContext( false );
189 case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
190 // don't use the autostyles from the styles-document for the progress
191 if ( mnElement != 0 && (mnElement & TOKEN_MASK) != XML_DOCUMENT_STYLES )
192 GetSwImport().GetProgressBarHelper()->Increment
193 ( PROGRESS_BAR_STEP );
194 return GetSwImport().CreateStylesContext( true );
195 case XML_ELEMENT(OFFICE, XML_MASTER_STYLES):
196 return GetSwImport().CreateMasterStylesContext();
197 case XML_ELEMENT(OFFICE, XML_FONT_FACE_DECLS):
198 return GetSwImport().CreateFontDeclsContext();
199 case XML_ELEMENT(OFFICE, XML_META):
200 OSL_FAIL(" XML_ELEMENT(OFFICE, XML_META): should not have come here, maybe document is invalid?");
201 break;
202 case XML_ELEMENT(OFFICE, XML_BODY):
203 GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
204 return new SwXMLBodyContext_Impl( GetSwImport() );
205 case XML_ELEMENT(XFORMS, XML_MODEL):
206 return createXFormsModelContext(GetImport());
207 default:
208 XMLOFF_WARN_UNKNOWN_ELEMENT("sw", nElement);
210 return nullptr;
213 namespace {
215 // #i69629# - new subclass <SwXMLOfficeDocContext_Impl> of class <SwXMLDocContext_Impl>
216 class SwXMLOfficeDocContext_Impl :
217 public SwXMLDocContext_Impl, public SvXMLMetaDocumentContext
219 public:
221 SwXMLOfficeDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement,
222 const Reference< document::XDocumentProperties >& xDocProps);
224 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
225 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
230 SwXMLOfficeDocContext_Impl::SwXMLOfficeDocContext_Impl(
231 SwXMLImport& rImport,
232 sal_Int32 nElement,
233 const Reference< document::XDocumentProperties >& xDocProps) :
234 SvXMLImportContext( rImport ),
235 SwXMLDocContext_Impl( rImport, nElement ),
236 SvXMLMetaDocumentContext( rImport, xDocProps )
240 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLOfficeDocContext_Impl::createFastChildContext(
241 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
243 // assign paragraph styles to list levels of outline style after all styles
244 // are imported and finished. This is the case, when <office:body> starts
245 // in flat OpenDocument file format.
247 if( nElement == XML_ELEMENT( OFFICE, XML_BODY ) )
249 GetImport().GetTextImport()->SetOutlineStyles( true );
253 // behave like meta base class iff we encounter office:meta
254 if ( nElement == XML_ELEMENT( OFFICE, XML_META ) ) {
255 return SvXMLMetaDocumentContext::createFastChildContext(
256 nElement, xAttrList );
257 } else {
258 return SwXMLDocContext_Impl::createFastChildContext(
259 nElement, xAttrList );
263 namespace {
265 // #i69629# - new subclass <SwXMLDocStylesContext_Impl> of class <SwXMLDocContext_Impl>
266 class SwXMLDocStylesContext_Impl : public SwXMLDocContext_Impl
268 public:
270 SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
272 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
277 SwXMLDocStylesContext_Impl::SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
278 SvXMLImportContext( rImport ),
279 SwXMLDocContext_Impl( rImport, nElement )
283 void SwXMLDocStylesContext_Impl::endFastElement(sal_Int32 )
285 // assign paragraph styles to list levels of outline style after all styles
286 // are imported and finished.
287 SwXMLImport& rSwImport = dynamic_cast<SwXMLImport&>( GetImport());
288 GetImport().GetTextImport()->SetOutlineStyles(
289 bool(rSwImport.GetStyleFamilyMask() & SfxStyleFamily::Para));
292 SvXMLImportContext *SwXMLImport::CreateFastContext( sal_Int32 nElement,
293 const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
295 SvXMLImportContext *pContext = nullptr;
297 switch (nElement)
299 case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
300 pContext = CreateMetaContext(nElement);
301 break;
302 case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
304 uno::Reference<document::XDocumentProperties> const xDocProps(
305 GetDocumentProperties());
306 // flat OpenDocument file format
307 pContext = new SwXMLOfficeDocContext_Impl( *this, nElement, xDocProps );
309 break;
310 // #i69629# - own subclasses for <office:document> and <office:document-styles>
311 case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
312 case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT):
313 pContext = new SwXMLDocContext_Impl( *this, nElement );
314 break;
315 case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES):
316 pContext = new SwXMLDocStylesContext_Impl( *this, nElement );
317 break;
319 return pContext;
322 SwXMLImport::SwXMLImport(
323 const uno::Reference< uno::XComponentContext >& rContext,
324 OUString const & implementationName, SvXMLImportFlags nImportFlags)
325 : SvXMLImport( rContext, implementationName, nImportFlags ),
326 m_nStyleFamilyMask( SfxStyleFamily::All ),
327 m_bLoadDoc( true ),
328 m_bInsert( false ),
329 m_bBlock( false ),
330 m_bOrganizerMode( false ),
331 m_bInititedXForms( false ),
332 m_pDoc( nullptr ),
333 m_sDefTableName(SwResId(STR_TABLE_DEFNAME))
335 InitItemImport();
338 SwXMLImport::~SwXMLImport() noexcept
340 if (HasShapeImport())
342 SAL_WARN("sw", "endDocument skipped, dropping shapes now to avoid dangling SvTextShapeImportHelper pointing to this");
343 ClearShapeImport();
345 FinitItemImport();
346 // Call cleanup() here because the destruction of some stuff like XMLRedlineImportHelper will cast
347 // to cast their mrImport to SwXMLImport and that is illegal after this destructor is done.
348 cleanup();
351 void SwXMLImport::setTextInsertMode(
352 const Reference< XTextRange > & rInsertPos )
354 m_bInsert = true;
356 Reference < XText > xText = rInsertPos->getText();
357 Reference < XTextCursor > xTextCursor =
358 xText->createTextCursorByRange( rInsertPos );
359 GetTextImport()->SetCursor( xTextCursor );
362 void SwXMLImport::setStyleInsertMode( SfxStyleFamily nFamilies,
363 bool bOverwrite )
365 m_bInsert = !bOverwrite;
366 m_nStyleFamilyMask = nFamilies;
367 m_bLoadDoc = false;
370 static OTextCursorHelper *lcl_xml_GetSwXTextCursor( const Reference < XTextCursor >& rTextCursor )
372 OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(rTextCursor.get());
373 OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
374 return pTextCursor;
377 void SwXMLImport::startDocument()
379 // delegate to parent
380 SvXMLImport::startDocument();
382 OSL_ENSURE( GetModel().is(), "model is missing" );
383 if( !GetModel().is() )
384 return;
386 // this method will modify the document directly -> lock SolarMutex
387 SolarMutexGuard aGuard;
389 Reference< XPropertySet > xImportInfo( getImportInfo() );
390 Reference< XPropertySetInfo > xPropertySetInfo;
391 if( xImportInfo.is() )
392 xPropertySetInfo = xImportInfo->getPropertySetInfo();
393 if( xPropertySetInfo.is() )
395 Any aAny;
396 // insert style mode?
397 OUString sStyleInsertModeFamilies("StyleInsertModeFamilies");
398 if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeFamilies) )
400 aAny = xImportInfo->getPropertyValue(sStyleInsertModeFamilies);
401 Sequence< OUString> aFamiliesSeq;
402 if( aAny >>= aFamiliesSeq )
404 SfxStyleFamily nFamilyMask = SfxStyleFamily::None;
405 for( const OUString& rFamily : std::as_const(aFamiliesSeq) )
407 if( rFamily=="FrameStyles" )
408 nFamilyMask |= SfxStyleFamily::Frame;
409 else if( rFamily=="PageStyles" )
410 nFamilyMask |= SfxStyleFamily::Page;
411 else if( rFamily=="CharacterStyles" )
412 nFamilyMask |= SfxStyleFamily::Char;
413 else if( rFamily=="ParagraphStyles" )
414 nFamilyMask |= SfxStyleFamily::Para;
415 else if( rFamily=="NumberingStyles" )
416 nFamilyMask |= SfxStyleFamily::Pseudo;
419 bool bOverwrite = false;
420 static const OUStringLiteral sStyleInsertModeOverwrite(u"StyleInsertModeOverwrite");
421 if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeOverwrite) )
423 aAny = xImportInfo->getPropertyValue(sStyleInsertModeOverwrite);
424 if( auto b = o3tl::tryAccess<bool>(aAny) )
426 if( *b )
427 bOverwrite = true;
431 setStyleInsertMode( nFamilyMask, bOverwrite );
435 // text insert mode?
436 static const OUStringLiteral sTextInsertModeRange(u"TextInsertModeRange");
437 if( xPropertySetInfo->hasPropertyByName(sTextInsertModeRange) )
439 aAny = xImportInfo->getPropertyValue(sTextInsertModeRange);
440 Reference<XTextRange> xInsertTextRange;
441 if( aAny >>= xInsertTextRange )
442 setTextInsertMode( xInsertTextRange );
445 // auto text mode
446 static const OUStringLiteral sAutoTextMode(u"AutoTextMode");
447 if( xPropertySetInfo->hasPropertyByName(sAutoTextMode) )
449 aAny = xImportInfo->getPropertyValue(sAutoTextMode);
450 if( auto b = o3tl::tryAccess<bool>(aAny) )
452 if( *b )
453 m_bBlock = true;
457 // organizer mode
458 static const OUStringLiteral sOrganizerMode(u"OrganizerMode");
459 if( xPropertySetInfo->hasPropertyByName(sOrganizerMode) )
461 aAny = xImportInfo->getPropertyValue(sOrganizerMode);
462 if( auto b = o3tl::tryAccess<bool>(aAny) )
464 if( *b )
465 m_bOrganizerMode = true;
469 // default document properties
470 static const OUStringLiteral sDefSettings(u"DefaultDocumentSettings");
471 if (xPropertySetInfo->hasPropertyByName(sDefSettings))
473 aAny = xImportInfo->getPropertyValue(sDefSettings);
474 Sequence<PropertyValue> aProps;
475 if (aAny >>= aProps)
477 Reference<lang::XMultiServiceFactory> xFac(GetModel(), UNO_QUERY);
478 Reference<XPropertySet> xProps(
479 xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY);
480 Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
482 if (xProps.is() && xInfo.is())
484 for (const auto& rProp : std::as_const(aProps))
486 if (xInfo->hasPropertyByName(rProp.Name))
488 xProps->setPropertyValue(rProp.Name, rProp.Value);
496 // There only is a text cursor by now if we are in insert mode. In any
497 // other case we have to create one at the start of the document.
498 // We also might change into the insert mode later, so we have to make
499 // sure to first set the insert mode and then create the text import
500 // helper. Otherwise it won't have the insert flag set!
501 OTextCursorHelper *pTextCursor = nullptr;
502 Reference < XTextCursor > xTextCursor;
503 if( HasTextImport() )
504 xTextCursor = GetTextImport()->GetCursor();
505 if( !xTextCursor.is() )
507 Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
508 Reference < XText > xText = xTextDoc->getText();
509 xTextCursor = xText->createTextCursor();
510 SwCursorShell *pCursorSh = nullptr;
511 SwDoc *pDoc = nullptr;
512 if( SvXMLImportFlags::ALL == getImportFlags() )
514 pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
515 OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
516 if( !pTextCursor )
517 return;
519 pDoc = pTextCursor->GetDoc();
520 OSL_ENSURE( pDoc, "SwDoc missing" );
521 if( !pDoc )
522 return;
524 // Is there an edit shell. If yes, then we are currently inserting
525 // a document. We then have to insert at the current edit shell's
526 // cursor position. That not quite clean code, but there is no other
527 // way currently.
528 pCursorSh = pDoc->GetEditShell();
530 if( pCursorSh )
532 const rtl::Reference<SwXTextRange> xInsertTextRange(
533 SwXTextRange::CreateXTextRange(
534 *pDoc, *pCursorSh->GetCursor()->GetPoint(), nullptr ) );
535 setTextInsertMode( xInsertTextRange );
536 xTextCursor = GetTextImport()->GetCursor();
537 pTextCursor = nullptr;
539 else
540 GetTextImport()->SetCursor( xTextCursor );
543 if( !(getImportFlags() & (SvXMLImportFlags::CONTENT|SvXMLImportFlags::MASTERSTYLES)) )
544 return;
546 if( !pTextCursor )
547 pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
548 OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
549 if( !pTextCursor )
550 return;
552 SwDoc *pDoc = pTextCursor->GetDoc();
553 OSL_ENSURE( pDoc, "SwDoc missing" );
554 if( !pDoc )
555 return;
557 if (SvXMLImportFlags::ALL == getImportFlags())
559 // for flat ODF - this is done in SwReader::Read() for package ODF
560 pDoc->SetInReading(true);
561 pDoc->SetInXMLImport(true);
564 if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
566 m_oSttNdIdx.emplace( pDoc->GetNodes() );
567 if( IsInsertMode() )
569 SwPaM *pPaM = pTextCursor->GetPaM();
570 const SwPosition* pPos = pPaM->GetPoint();
572 // Split once and remember the node that has been split.
573 pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
574 *m_oSttNdIdx = pPos->GetNodeIndex()-1;
576 // Split again.
577 pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
579 // Insert all content into the new node
580 pPaM->Move( fnMoveBackward );
581 pDoc->SetTextFormatColl
582 ( *pPaM, pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, false ) );
586 // We need a draw model to be able to set the z order
587 pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); // #i52858# - method name changed
589 // SJ: #i49801# locking the model to disable repaints
590 SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
591 if ( pDrawModel )
592 pDrawModel->setLock(true);
594 if (!GetGraphicStorageHandler().is())
596 m_xGraphicStorageHandler = SvXMLGraphicHelper::Create(SvXMLGraphicHelperMode::Read);
597 SetGraphicStorageHandler(m_xGraphicStorageHandler);
600 if( !GetEmbeddedResolver().is() )
602 SfxObjectShell *pPersist = pDoc->GetPersist();
603 if( pPersist )
605 m_xEmbeddedResolver = SvXMLEmbeddedObjectHelper::Create(
606 *pPersist,
607 SvXMLEmbeddedObjectHelperMode::Read );
608 SetEmbeddedResolver( m_xEmbeddedResolver );
613 void SwXMLImport::endDocument()
615 OSL_ENSURE( GetModel().is(), "model missing; maybe startDocument wasn't called?" );
616 if( !GetModel().is() )
617 return;
619 // this method will modify the document directly -> lock SolarMutex
620 SolarMutexGuard aGuard;
622 if (m_xGraphicStorageHandler)
623 m_xGraphicStorageHandler->dispose();
624 m_xGraphicStorageHandler.clear();
626 if( m_xEmbeddedResolver )
627 m_xEmbeddedResolver->dispose();
628 m_xEmbeddedResolver.clear();
629 // Clear the shape import to sort the shapes (and not in the
630 // destructor that might be called after the import has finished
631 // for Java filters.
632 if( HasShapeImport() )
633 ClearShapeImport();
635 SwDoc *pDoc = nullptr;
636 if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
638 Reference<XInterface> xCursorTunnel( GetTextImport()->GetCursor(),
639 UNO_QUERY);
640 assert(xCursorTunnel.is() && "missing XUnoTunnel for Cursor");
641 OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(xCursorTunnel.get());
642 assert(pTextCursor && "SwXTextCursor missing");
643 SwPaM *pPaM = pTextCursor->GetPaM();
644 if( IsInsertMode() && m_oSttNdIdx->GetIndex() )
646 // If we are in insert mode, join the split node that is in front
647 // of the new content with the first new node. Or in other words:
648 // Revert the first split node.
649 SwTextNode* pTextNode = m_oSttNdIdx->GetNode().GetTextNode();
650 SwNodeIndex aNxtIdx( *m_oSttNdIdx );
651 if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx ) &&
652 m_oSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() )
654 // If the PaM points to the first new node, move the PaM to the
655 // end of the previous node.
656 if( pPaM->GetPoint()->GetNode() == aNxtIdx.GetNode() )
658 pPaM->GetPoint()->Assign( *pTextNode,
659 pTextNode->GetText().getLength());
662 #if OSL_DEBUG_LEVEL > 0
663 // !!! This should be impossible !!!!
664 OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 !=
665 pPaM->GetBound().GetNodeIndex(),
666 "PaM.Bound1 point to new node " );
667 OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 !=
668 pPaM->GetBound( false ).GetNodeIndex(),
669 "PaM.Bound2 points to new node" );
671 if( m_oSttNdIdx->GetIndex()+1 ==
672 pPaM->GetBound().GetNodeIndex() )
674 const sal_Int32 nCntPos =
675 pPaM->GetBound().GetContentIndex();
676 pPaM->GetBound().SetContent(
677 pTextNode->GetText().getLength() + nCntPos );
679 if( m_oSttNdIdx->GetIndex()+1 ==
680 pPaM->GetBound( false ).GetNodeIndex() )
682 const sal_Int32 nCntPos =
683 pPaM->GetBound( false ).GetContentIndex();
684 pPaM->GetBound( false ).SetContent(
685 pTextNode->GetText().getLength() + nCntPos );
687 #endif
688 // If the first new node isn't empty, convert the node's text
689 // attributes into hints. Otherwise, set the new node's
690 // paragraph style at the previous (empty) node.
691 SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode();
692 if (!pTextNode->GetText().isEmpty())
693 pDelNd->FormatToTextAttr( pTextNode );
694 else
696 pTextNode->ResetAttr(RES_CHRATR_BEGIN, RES_CHRATR_END);
697 pTextNode->ChgFormatColl( pDelNd->GetTextColl() );
698 if (!pDelNd->GetNoCondAttr(RES_PARATR_LIST_ID, /*bInParents=*/false))
700 // MergeListsAtDocumentInsertPosition() will deal with lists below, copy
701 // paragraph direct formatting otherwise.
702 pDelNd->CopyCollFormat(*pTextNode);
705 pTextNode->JoinNext();
709 SwPosition* pPos = pPaM->GetPoint();
710 OSL_ENSURE( !pPos->GetContentIndex(), "last paragraph isn't empty" );
711 if( !pPos->GetContentIndex() )
713 SwTextNode* pCurrNd;
714 SwNodeOffset nNodeIdx = pPos->GetNodeIndex();
715 pDoc = &pPaM->GetDoc();
717 OSL_ENSURE( pPos->GetNode().IsContentNode(),
718 "insert position is not a content node" );
719 if( !IsInsertMode() )
721 // If we're not in insert mode, the last node is deleted.
722 const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
723 if( pPrev->IsContentNode() ||
724 ( pPrev->IsEndNode() &&
725 pPrev->StartOfSectionNode()->IsSectionNode() ) )
727 SwContentNode* pCNd = pPaM->GetPointContentNode();
728 if( pCNd && pCNd->StartOfSectionIndex()+2 <
729 pCNd->EndOfSectionIndex() )
731 SwNode& rDelNode = pPaM->GetPoint()->GetNode();
732 // move so we don't have a dangling SwContentIndex to the deleted node
733 pPaM->GetPoint()->Adjust(SwNodeOffset(+1));
734 if (pPaM->HasMark())
735 pPaM->GetMark()->Adjust(SwNodeOffset(+1));
736 pDoc->GetNodes().Delete( rDelNode );
740 else if( nullptr != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTextNode()) )
742 // Id we're in insert mode, the empty node is joined with
743 // the next and the previous one.
744 if( pCurrNd->CanJoinNext( pPos ))
746 SwTextNode* pNextNd = pPos->GetNode().GetTextNode();
747 bool endNodeFound = pDoc->GetNodes()[nNodeIdx-1]->IsEndNode();
748 SwNode *pLastPar = pDoc->GetNodes()[nNodeIdx -2];
749 if ( !pLastPar->IsTextNode() ) {
750 pLastPar = pDoc->GetNodes()[nNodeIdx -1];
752 if ( !endNodeFound && pLastPar->IsTextNode() )
754 pNextNd->ChgFormatColl(pLastPar->GetTextNode()->GetTextColl());
757 pPaM->SetMark(); pPaM->DeleteMark();
758 pNextNd->JoinPrev();
760 // Remove line break that has been inserted by the import,
761 // but only if one has been inserted and
762 // no endNode found to avoid removing section
763 if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && !endNodeFound &&
764 *m_oSttNdIdx != pPos->GetNode() )
766 pNextNd->JoinPrev();
769 else if (pCurrNd->GetText().isEmpty())
771 pPaM->SetMark(); pPaM->DeleteMark();
772 SwNode& rDelNode = pPos->GetNode();
773 // move so we don't have a dangling SwContentIndex to the deleted node
774 pPaM->GetPoint()->Adjust(SwNodeOffset(+1));
775 pDoc->GetNodes().Delete( rDelNode );
776 pPaM->Move( fnMoveBackward );
780 // tdf#113877
781 // when we insert one document with list inside into another one with list at the insert position,
782 // the resulting numbering in these lists is not consequent.
784 // Main document:
785 // 1. One
786 // 2. Two
787 // 3. Three
788 // 4. <-- insert position
790 // Inserted document:
791 // 1. One
792 // 2. Two
793 // 3. Three
794 // 4.
796 // Expected result
797 // 1. One
798 // 2. Two
799 // 3. Three
800 // 4. One
801 // 5. Two
802 // 6. Three
803 // 7.
805 MergeListsAtDocumentInsertPosition(pDoc);
809 /* Was called too early. Moved from SwXMLBodyContext_Impl::EndElement */
811 GetTextImport()->RedlineAdjustStartNodeCursor();
813 if( (getImportFlags() & SvXMLImportFlags::CONTENT) ||
814 ((getImportFlags() & SvXMLImportFlags::MASTERSTYLES) && IsStylesOnlyMode()) )
816 // pDoc might be 0. In this case UpdateTextCollCondition is looking
817 // for it itself.
818 UpdateTextCollConditions( pDoc );
821 GetTextImport()->ResetCursor();
823 m_oSttNdIdx.reset();
825 // tdf#150753: pDoc may be null e.g. when the package lacks content.xml;
826 // we should not forget to tidy up here, including unlocking draw model
827 if (!pDoc)
828 pDoc = getDoc();
829 assert(pDoc);
830 // SJ: #i49801# -> now permitting repaints
831 if (getImportFlags() == SvXMLImportFlags::ALL)
833 // Notify math objects. If we are in the package filter this will
834 // be done by the filter object itself
835 if (IsInsertMode())
836 pDoc->PrtOLENotify(false);
837 else if (pDoc->IsOLEPrtNotifyPending())
838 pDoc->PrtOLENotify(true);
840 assert(pDoc->IsInReading());
841 assert(pDoc->IsInXMLImport());
842 pDoc->SetInReading(false);
843 pDoc->SetInXMLImport(false);
846 SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
847 if (pDrawModel)
848 pDrawModel->setLock(false);
850 // #i90243#
851 if ( m_bInititedXForms )
853 Reference< xforms::XFormsSupplier > xFormsSupp( GetModel(), UNO_QUERY );
854 Reference< XNameAccess > xXForms;
855 if ( xFormsSupp.is() )
856 xXForms = xFormsSupp->getXForms().get();
858 if ( xXForms.is() )
862 Sequence< beans::PropertyValue > aXFormsSettings;
864 const OUString& sXFormsSettingsName( GetXMLToken( XML_XFORM_MODEL_SETTINGS ) );
865 if ( m_xLateInitSettings.is() && m_xLateInitSettings->hasByName( sXFormsSettingsName ) )
867 OSL_VERIFY( m_xLateInitSettings->getByName( sXFormsSettingsName ) >>= aXFormsSettings );
868 applyXFormsSettings( xXForms, aXFormsSettings );
871 catch( const Exception& )
877 for (SwNodeOffset i(0); i < pDoc->GetNodes().Count(); ++i)
879 if (SwTableNode *const pTableNode = pDoc->GetNodes()[i]->GetTableNode())
881 if (!pTableNode->GetTable().IsNewModel()
882 && pTableNode->GetTable().CanConvertSubtables())
884 pTableNode->GetTable().ConvertSubtables();
887 // don't skip to the end; nested tables could have subtables too...
890 // delegate to parent: takes care of error handling
891 SvXMLImport::endDocument();
892 ClearTextImport();
895 // tdf#113877
896 // when we insert one document with list inside into another one with list at the insert position,
897 // the resulting numbering in these lists is not consequent.
899 // CASE-1: Main document:
900 // 1. One
901 // 2. Two
902 // 3. Three
903 // 4. <-- insert position
905 // Inserted document:
906 // 1. One
907 // 2. Two
908 // 3. Three
909 // 4.
911 // Expected result
912 // 1. One
913 // 2. Two
914 // 3. Three
915 // 4. One
916 // 5. Two
917 // 6. Three
918 // 7.
920 // CASE-2: Main document:
921 // 1. One
922 // 2. Two
923 // 3. Three
924 // 4. <-- insert position
926 // Inserted document:
927 // A) One
928 // B) Two
929 // C) Three
930 // D)
932 // Expected result
933 // 1. One
934 // 2. Two
935 // 3. Three
936 // 4. One
937 // A) Two
938 // B) Three
939 // 5.
941 void SwXMLImport::MergeListsAtDocumentInsertPosition(SwDoc *pDoc)
943 // 1. check environment
944 if (! pDoc)
945 return;
947 if (! IsInsertMode() || ! m_oSttNdIdx->GetIndex())
948 return;
950 SwNodeOffset index(1);
952 // the last node of the main document where we have inserted a document
953 SwNode* const node1 = pDoc->GetNodes()[m_oSttNdIdx->GetIndex() + 0];
955 // the first node of the inserted document
956 SwNode* node2 = pDoc->GetNodes()[m_oSttNdIdx->GetIndex() + index];
958 if (! (node1 && node2
959 && (node1->GetNodeType() == node2->GetNodeType())
960 && (node1->IsTextNode() == node2->IsTextNode())
963 // not a text node at insert position
964 return;
967 // 2. get the first node of the inserted document,
968 // which will be used to detect if inside inserted document a new list was started after the first list
969 const SfxPoolItem* pListId2Initial = nullptr;
971 SwContentNode* contentNode1 = static_cast<SwContentNode *>(node1);
972 SwContentNode* contentNode2 = static_cast<SwContentNode *>(node2);
974 // check if both lists have the same list properties
975 const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
976 const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
978 if (! pListId1)
979 return;
980 if (! pListId2)
981 return;
983 auto pStringListId1 = dynamic_cast<const SfxStringItem*>(pListId1);
984 assert(pStringListId1);
985 const OUString& sListId1 = pStringListId1->GetValue();
986 auto pStringListId2 = dynamic_cast<const SfxStringItem*>(pListId2);
987 assert(pStringListId2);
988 const OUString& sListId2 = pStringListId2->GetValue();
990 const SwList* pList1 = pDoc->getIDocumentListsAccess().getListByName( sListId1 );
991 const SwList* pList2 = pDoc->getIDocumentListsAccess().getListByName( sListId2 );
993 if (! pList1)
994 return;
995 if (! pList2)
996 return;
998 const OUString& sDefaultListStyleName1 = pList1->GetDefaultListStyleName();
999 const OUString& sDefaultListStyleName2 = pList2->GetDefaultListStyleName();
1001 if (sDefaultListStyleName1 != sDefaultListStyleName2)
1003 const SwNumRule* pNumRule1 = pDoc->FindNumRulePtr( sDefaultListStyleName1 );
1004 const SwNumRule* pNumRule2 = pDoc->FindNumRulePtr( sDefaultListStyleName2 );
1006 if (pNumRule1 && pNumRule2)
1008 // check style of the each list level
1009 for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1011 if( pNumRule1->Get( n ) != pNumRule2->Get( n ) )
1013 return;
1017 // our list should be merged
1018 pListId2Initial = pListId2;
1021 else
1023 // our list should be merged
1024 pListId2Initial = pListId2;
1028 if (! pListId2Initial)
1030 // two lists have different styles => they should not be merged
1031 return;
1034 // 3. merge two lists
1035 while (
1036 node1 && node2
1037 && (node1->GetNodeType() == node2->GetNodeType())
1038 && (node1->IsTextNode() == node2->IsTextNode())
1041 SwContentNode* contentNode1 = static_cast<SwContentNode *>( node1 );
1042 SwContentNode* contentNode2 = static_cast<SwContentNode *>( node2 );
1044 const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
1045 const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
1047 if (! pListId1)
1048 return;
1049 if (! pListId2)
1050 return;
1052 if (*pListId2Initial != *pListId2)
1054 // no more list items of the first list inside inserted document
1055 return;
1058 // set list style to this list element
1059 contentNode2->SetAttr(*pListId1);
1061 // get next item
1062 index++;
1063 if (index >= pDoc->GetNodes().Count())
1065 // no more items
1066 return;
1069 node2 = pDoc->GetNodes()[m_oSttNdIdx->GetIndex() + index];
1073 namespace {
1075 // Locally derive XMLTextShapeImportHelper, so we can take care of the
1076 // form import This is Writer, but not text specific, so it should go
1077 // here!
1078 class SvTextShapeImportHelper : public XMLTextShapeImportHelper
1080 // hold own reference form import helper, because the SvxImport
1081 // stored in the superclass, from whom we originally got the
1082 // reference, is already destroyed when we want to use it in the
1083 // destructor
1084 rtl::Reference< ::xmloff::OFormLayerXMLImport > rFormImport;
1086 // hold reference to the one page (if it exists) for calling startPage()
1087 // and endPage. If !xPage.is(), then this document doesn't have a
1088 // XDrawPage.
1089 Reference<drawing::XDrawPage> xPage;
1091 public:
1092 explicit SvTextShapeImportHelper(SvXMLImport& rImp);
1093 virtual ~SvTextShapeImportHelper() override;
1098 SvTextShapeImportHelper::SvTextShapeImportHelper(SvXMLImport& rImp) :
1099 XMLTextShapeImportHelper(rImp)
1101 Reference<drawing::XDrawPageSupplier> xSupplier(rImp.GetModel(),UNO_QUERY);
1102 if (xSupplier.is())
1104 if (rImp.GetFormImport().is())
1106 rImp.GetFormImport()->startPage(xSupplier->getDrawPage());
1107 rFormImport = rImp.GetFormImport();
1110 xPage = xSupplier->getDrawPage();
1111 XMLShapeImportHelper::startPage( xPage );
1115 SvTextShapeImportHelper::~SvTextShapeImportHelper()
1117 rFormImport->endPage();
1119 if (xPage.is())
1121 XMLShapeImportHelper::endPage(xPage);
1125 XMLTextImportHelper* SwXMLImport::CreateTextImport()
1127 return new SwXMLTextImportHelper( GetModel(), *this, getImportInfo(),
1128 IsInsertMode(),
1129 IsStylesOnlyMode(),
1130 IsBlockMode(), m_bOrganizerMode );
1133 XMLShapeImportHelper* SwXMLImport::CreateShapeImport()
1135 return new SvTextShapeImportHelper( *this );
1138 SvXMLImportContext *SwXMLImport::CreateFontDeclsContext()
1140 XMLFontStylesContext *pFSContext =
1141 new XMLFontStylesContext( *this, osl_getThreadTextEncoding() );
1142 SetFontDecls( pFSContext );
1143 return pFSContext;
1146 void SwXMLImport::SetViewSettings(const Sequence < PropertyValue > & aViewProps)
1148 if (IsInsertMode() || IsStylesOnlyMode() || IsBlockMode() || m_bOrganizerMode || !GetModel().is() )
1149 return;
1151 // this method will modify the document directly -> lock SolarMutex
1152 SolarMutexGuard aGuard;
1154 SwDoc *pDoc = getDoc();
1155 tools::Rectangle aRect;
1156 if( pDoc->GetDocShell() )
1157 aRect = pDoc->GetDocShell()->GetVisArea( ASPECT_CONTENT );
1158 //TODO/LATER: why that cast?!
1159 //aRect = ((SfxInPlaceObject *)pDoc->GetDocShell())->GetVisArea();
1161 sal_Int64 nTmp = 0;
1162 bool bShowRedlineChanges = false, bBrowseMode = false;
1163 bool bChangeShowRedline = false, bChangeBrowseMode = false;
1165 //TODO/LATER: why that cast?!
1166 bool bTwip = pDoc->GetDocShell()->GetMapUnit ( ) == MapUnit::MapTwip;
1167 //sal_Bool bTwip = pDoc->GetDocShell()->SfxInPlaceObject::GetMapUnit ( ) == MapUnit::MapTwip;
1169 for (const PropertyValue& rValue : aViewProps)
1171 if ( rValue.Name == "ViewAreaTop" )
1173 rValue.Value >>= nTmp;
1174 aRect.SetPosY(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
1176 else if ( rValue.Name == "ViewAreaLeft" )
1178 rValue.Value >>= nTmp;
1179 aRect.SetPosX(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
1181 else if ( rValue.Name == "ViewAreaWidth" )
1183 rValue.Value >>= nTmp;
1184 Size aSize( aRect.GetSize() );
1185 aSize.setWidth(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
1186 aRect.SetSize( aSize );
1188 else if ( rValue.Name == "ViewAreaHeight" )
1190 rValue.Value >>= nTmp;
1191 Size aSize( aRect.GetSize() );
1192 aSize.setHeight(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp);
1193 aRect.SetSize( aSize );
1195 else if ( rValue.Name == "ShowRedlineChanges" )
1197 bShowRedlineChanges = *o3tl::doAccess<bool>(rValue.Value);
1198 bChangeShowRedline = true;
1200 // Headers and footers are not displayed in BrowseView anymore
1201 else if ( rValue.Name == "InBrowseMode" )
1203 bBrowseMode = *o3tl::doAccess<bool>(rValue.Value);
1204 bChangeBrowseMode = true;
1207 if( pDoc->GetDocShell() )
1208 pDoc->GetDocShell()->SetVisArea ( aRect );
1210 if (bChangeBrowseMode)
1211 pDoc->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, bBrowseMode );
1213 if (bChangeShowRedline)
1214 GetTextImport()->SetShowChanges( bShowRedlineChanges );
1217 // Note: this will be called only if there are OOo elements in settings.xml.
1218 // So if a setting is missing there we can assume that it was written
1219 // by an OOo/LO version that is older than the introduction of the setting!
1220 void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aConfigProps)
1222 // this method will modify the document directly -> lock SolarMutex
1223 SolarMutexGuard aGuard;
1225 Reference< lang::XMultiServiceFactory > xFac( GetModel(), UNO_QUERY );
1226 if( !xFac.is() )
1227 return;
1229 Reference< XPropertySet > xProps( xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY );
1230 if( !xProps.is() )
1231 return;
1233 Reference< XPropertySetInfo > xInfo( xProps->getPropertySetInfo() );
1234 if( !xInfo.is() )
1235 return;
1237 std::unordered_set< OUString > aExcludeAlways;
1238 aExcludeAlways.insert("LinkUpdateMode");
1239 // this should contain things that are actually user-settable, via Tools->Options
1240 std::unordered_set< OUString > aExcludeWhenNotLoadingUserSettings {
1241 "ForbiddenCharacters",
1242 "IsKernAsianPunctuation",
1243 "CharacterCompressionType",
1244 "FieldAutoUpdate",
1245 "ChartAutoUpdate",
1246 "AddParaTableSpacing",
1247 "AddParaTableSpacingAtStart",
1248 "PrintAnnotationMode",
1249 "PrintBlackFonts",
1250 "PrintControls",
1251 "PrintDrawings",
1252 "PrintGraphics",
1253 "PrintHiddenText",
1254 "PrintLeftPages",
1255 "PrintPageBackground",
1256 "PrintProspect",
1257 "PrintReversed",
1258 "PrintRightPages",
1259 "PrintFaxName",
1260 "PrintPaperFromSetup",
1261 "PrintTables",
1262 "PrintTextPlaceholder",
1263 "PrintSingleJobs",
1264 "UpdateFromTemplate",
1265 "PrinterIndependentLayout",
1266 "PrintEmptyPages",
1267 "ConsiderTextWrapOnObjPos",
1268 "DoNotJustifyLinesWithManualBreak",
1269 "ProtectForm",
1270 "MsWordCompTrailingBlanks",
1271 "SubtractFlysAnchoredAtFlys",
1272 "EmptyDbFieldHidesPara",
1275 bool bAreUserSettingsFromDocument = officecfg::Office::Common::Load::UserDefinedSettings::get();
1277 // for some properties we don't want to use the application
1278 // default if they're missing. So we watch for them in the loop
1279 // below, and set them if not found
1280 bool bPrinterIndependentLayout = false;
1281 bool bUseOldNumbering = false;
1282 bool bAddExternalLeading = false;
1283 bool bAddParaSpacingToTableCells = false;
1284 bool bAddParaLineSpacingToTableCells = false;
1285 bool bUseFormerLineSpacing = false;
1286 bool bUseFormerObjectPositioning = false;
1287 bool bUseFormerTextWrapping = false;
1288 bool bConsiderWrapOnObjPos = false;
1289 bool bIgnoreFirstLineIndentInNumbering = false;
1290 bool bDoNotJustifyLinesWithManualBreak = false;
1291 bool bDoNotResetParaAttrsForNumFont = false;
1292 bool bDoNotCaptureDrawObjsOnPage( false );
1293 bool bClipAsCharacterAnchoredWriterFlyFrames( false );
1294 bool bUnixForceZeroExtLeading = false;
1295 bool bSmallCapsPercentage66 = false;
1296 bool bTabOverflow = false;
1297 bool bTabOverMarginValue = false;
1298 bool bPropLineSpacingShrinksFirstLine = false;
1299 bool bSubtractFlysAnchoredAtFlys = false;
1300 bool bEmptyDbFieldHidesPara = false;
1301 bool bCollapseEmptyCellPara = false;
1302 bool bAutoFirstLineIndentDisregardLineSpace = false;
1303 bool bHyphenateURLs = false;
1304 bool bDoNotBreakWrappedTables = false;
1305 bool bAllowTextAfterFloatingTableBreak = false;
1306 bool bDropCapPunctuation = false;
1308 const PropertyValue* currentDatabaseDataSource = nullptr;
1309 const PropertyValue* currentDatabaseCommand = nullptr;
1310 const PropertyValue* currentDatabaseCommandType = nullptr;
1311 const PropertyValue* embeddedDatabaseName = nullptr;
1313 for( const PropertyValue& rValue : aConfigProps )
1315 bool bSet = aExcludeAlways.find(rValue.Name) == aExcludeAlways.end();
1316 if( bSet && !bAreUserSettingsFromDocument
1317 && (aExcludeWhenNotLoadingUserSettings.find(rValue.Name)
1318 != aExcludeWhenNotLoadingUserSettings.end()) )
1320 bSet = false;
1323 if( bSet )
1327 if( xInfo->hasPropertyByName( rValue.Name ) )
1329 if( rValue.Name == "RedlineProtectionKey" )
1331 Sequence<sal_Int8> aKey;
1332 rValue.Value >>= aKey;
1333 GetTextImport()->SetChangesProtectionKey( aKey );
1335 else
1337 // HACK: Setting these out of order does not work.
1338 if( rValue.Name == "CurrentDatabaseDataSource" )
1339 currentDatabaseDataSource = &rValue;
1340 else if( rValue.Name == "CurrentDatabaseCommand" )
1341 currentDatabaseCommand = &rValue;
1342 else if( rValue.Name == "CurrentDatabaseCommandType" )
1343 currentDatabaseCommandType = &rValue;
1344 else if (rValue.Name == "EmbeddedDatabaseName")
1345 embeddedDatabaseName = &rValue;
1346 else
1347 xProps->setPropertyValue( rValue.Name, rValue.Value );
1351 // did we find any of the non-default cases?
1352 if ( rValue.Name == "PrinterIndependentLayout" )
1353 bPrinterIndependentLayout = true;
1354 else if ( rValue.Name == "AddExternalLeading" )
1355 bAddExternalLeading = true;
1356 else if ( rValue.Name == "AddParaSpacingToTableCells" )
1357 bAddParaSpacingToTableCells = true;
1358 else if ( rValue.Name == "AddParaLineSpacingToTableCells" )
1359 bAddParaLineSpacingToTableCells = true;
1360 else if ( rValue.Name == "UseFormerLineSpacing" )
1361 bUseFormerLineSpacing = true;
1362 else if ( rValue.Name == "UseFormerObjectPositioning" )
1363 bUseFormerObjectPositioning = true;
1364 else if ( rValue.Name == "UseFormerTextWrapping" )
1365 bUseFormerTextWrapping = true;
1366 else if ( rValue.Name == "UseOldNumbering" )
1367 bUseOldNumbering = true;
1368 else if ( rValue.Name == "ConsiderTextWrapOnObjPos" )
1369 bConsiderWrapOnObjPos = true;
1370 else if ( rValue.Name == "IgnoreFirstLineIndentInNumbering" )
1371 bIgnoreFirstLineIndentInNumbering = true;
1372 else if ( rValue.Name == "DoNotJustifyLinesWithManualBreak" )
1373 bDoNotJustifyLinesWithManualBreak = true;
1374 else if ( rValue.Name == "DoNotResetParaAttrsForNumFont" )
1375 bDoNotResetParaAttrsForNumFont = true;
1376 else if ( rValue.Name == "DoNotCaptureDrawObjsOnPage" )
1377 bDoNotCaptureDrawObjsOnPage = true;
1378 else if ( rValue.Name == "ClipAsCharacterAnchoredWriterFlyFrames" )
1379 bClipAsCharacterAnchoredWriterFlyFrames = true;
1380 else if ( rValue.Name == "UnxForceZeroExtLeading" )
1381 bUnixForceZeroExtLeading = true;
1382 else if ( rValue.Name == "SmallCapsPercentage66" )
1383 bSmallCapsPercentage66 = true;
1384 else if ( rValue.Name == "TabOverflow" )
1385 bTabOverflow = true;
1386 else if ( rValue.Name == "TabOverMargin" )
1388 rValue.Value >>= bTabOverMarginValue;
1390 else if ( rValue.Name == "PropLineSpacingShrinksFirstLine" )
1391 bPropLineSpacingShrinksFirstLine = true;
1392 else if (rValue.Name == "SubtractFlysAnchoredAtFlys")
1393 bSubtractFlysAnchoredAtFlys = true;
1394 else if (rValue.Name == "EmptyDbFieldHidesPara")
1395 bEmptyDbFieldHidesPara = true;
1396 else if (rValue.Name == "CollapseEmptyCellPara")
1397 bCollapseEmptyCellPara = true;
1398 else if (rValue.Name == "AutoFirstLineIndentDisregardLineSpace")
1399 bAutoFirstLineIndentDisregardLineSpace = true;
1400 else if (rValue.Name == "HyphenateURLs")
1402 bHyphenateURLs = true;
1404 else if (rValue.Name == "DoNotBreakWrappedTables")
1406 rValue.Value >>= bDoNotBreakWrappedTables;
1408 else if (rValue.Name == "AllowTextAfterFloatingTableBreak")
1410 rValue.Value >>= bAllowTextAfterFloatingTableBreak;
1412 else if ( rValue.Name == "DropCapPunctuation" )
1413 bDropCapPunctuation = true;
1415 catch( Exception& )
1417 TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
1424 if( currentDatabaseDataSource != nullptr )
1425 xProps->setPropertyValue( currentDatabaseDataSource->Name, currentDatabaseDataSource->Value );
1426 if( currentDatabaseCommand != nullptr )
1427 xProps->setPropertyValue( currentDatabaseCommand->Name, currentDatabaseCommand->Value );
1428 if( currentDatabaseCommandType != nullptr )
1429 xProps->setPropertyValue( currentDatabaseCommandType->Name, currentDatabaseCommandType->Value );
1430 if (embeddedDatabaseName)
1431 xProps->setPropertyValue(embeddedDatabaseName->Name, embeddedDatabaseName->Value);
1432 } catch( Exception& )
1434 TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
1437 // finally, treat the non-default cases
1438 // introduce boolean, that indicates a document, written by version prior SO8.
1439 // If user settings are not loaded, we can't know if this is an old document. Better to assume no?
1440 const bool bDocumentPriorSO8 = !bConsiderWrapOnObjPos && bAreUserSettingsFromDocument;
1442 // Use old behaviour if this setting didn't exist, but only if this setting is being read from the document.
1443 // (Obviously the setting doesn't exist if we are explicitly ignoring it, so then stick with program/user defaults)
1444 if(!bPrinterIndependentLayout && bAreUserSettingsFromDocument)
1446 xProps->setPropertyValue( "PrinterIndependentLayout", Any(sal_Int16(document::PrinterIndependentLayout::DISABLED)) );
1449 if( ! bAddExternalLeading )
1451 xProps->setPropertyValue( "AddExternalLeading", Any( false ) );
1454 if( ! bUseFormerLineSpacing )
1456 xProps->setPropertyValue( "UseFormerLineSpacing", Any( true ) );
1459 if( !bUseFormerObjectPositioning )
1461 xProps->setPropertyValue( "UseFormerObjectPositioning", Any( true ) );
1464 if( !bUseOldNumbering )
1466 xProps->setPropertyValue( "UseOldNumbering", Any(true) );
1469 if( !bAddParaSpacingToTableCells )
1471 xProps->setPropertyValue( "AddParaSpacingToTableCells",
1472 Any( false ) );
1474 if (!bAddParaLineSpacingToTableCells)
1476 xProps->setPropertyValue("AddParaLineSpacingToTableCells", Any(false));
1479 if( !bUseFormerTextWrapping )
1481 xProps->setPropertyValue( "UseFormerTextWrapping", Any( true ) );
1484 if (!bConsiderWrapOnObjPos && bAreUserSettingsFromDocument)
1486 xProps->setPropertyValue( "ConsiderTextWrapOnObjPos", Any( false ) );
1489 // #i47448#
1490 // For SO7pp4, part of the 'new numbering' stuff has been backported from
1491 // SO8. Unfortunately, only part of it and by using the same compatibility option
1492 // like in SO8. Therefore documents generated with SO7pp4, containing
1493 // numbered paragraphs with first line indent differ between SO7pp4 and
1494 // SO8. In order to fix this for SO8pp1, I introduce a new compatibility
1495 // flag 'bIgnoreFirstLineIndentInNumbering'. This flag has to be set for all
1496 // documents < SO8, but not for SO8. So if the property is not present, the
1497 // flag will be set to 'true'. SO8 documents surely have the
1498 // 'ConsiderWrapOnObjPos' property set (no matter if 'true' or 'false'),
1499 // therefore the correct condition to set this flag is this:
1500 if( !bIgnoreFirstLineIndentInNumbering && bDocumentPriorSO8 )
1502 xProps->setPropertyValue( "IgnoreFirstLineIndentInNumbering",
1503 Any( true ) );
1506 // This flag has to be set for all documents < SO8
1507 if ( !bDoNotJustifyLinesWithManualBreak && bDocumentPriorSO8 )
1509 xProps->setPropertyValue( "DoNotJustifyLinesWithManualBreak",
1510 Any( true ) );
1513 // This flag has to be set for all documents < SO8
1514 if ( !bDoNotResetParaAttrsForNumFont && bDocumentPriorSO8 )
1516 xProps->setPropertyValue( "DoNotResetParaAttrsForNumFont",
1517 Any( true ) );
1520 // This flag has to be set for all documents < SO8
1521 if ( !bDoNotCaptureDrawObjsOnPage && bDocumentPriorSO8 )
1523 xProps->setPropertyValue( "DoNotCaptureDrawObjsOnPage",
1524 Any( true ) );
1527 // This flag has to be set for all documents < SO8
1528 if ( !bClipAsCharacterAnchoredWriterFlyFrames && bDocumentPriorSO8 )
1530 xProps->setPropertyValue( "ClipAsCharacterAnchoredWriterFlyFrames",
1531 Any( true ) );
1534 if ( !bUnixForceZeroExtLeading )
1536 xProps->setPropertyValue( "UnxForceZeroExtLeading", Any( true ) );
1539 // Old LO versions had 66 as the value for small caps percentage, later changed to 80.
1540 // In order to keep backwards compatibility, SmallCapsPercentage66 option is written to .odt
1541 // files, and the default for new documents is 'false'. Files without this option
1542 // are considered to be old files, so set the compatibility option too.
1543 if ( !bSmallCapsPercentage66 )
1545 xProps->setPropertyValue( "SmallCapsPercentage66", Any( true ) );
1548 if ( !bTabOverflow )
1550 xProps->setPropertyValue( "TabOverflow", Any( false ) );
1553 if (bTabOverMarginValue)
1554 // Let TabOverMargin imply the new default for
1555 // PrinterIndependentLayout, knowing the first is set by Word import
1556 // filters and Word defaults to our new default as well.
1557 xProps->setPropertyValue(
1558 "PrinterIndependentLayout",
1559 uno::Any(document::PrinterIndependentLayout::HIGH_RESOLUTION));
1561 if (!bPropLineSpacingShrinksFirstLine)
1562 xProps->setPropertyValue("PropLineSpacingShrinksFirstLine", Any(false));
1564 if (!bSubtractFlysAnchoredAtFlys && bAreUserSettingsFromDocument)
1565 xProps->setPropertyValue("SubtractFlysAnchoredAtFlys", Any(true));
1567 if (!bEmptyDbFieldHidesPara && bAreUserSettingsFromDocument)
1568 xProps->setPropertyValue("EmptyDbFieldHidesPara", Any(false));
1570 if (!bCollapseEmptyCellPara)
1571 xProps->setPropertyValue("CollapseEmptyCellPara", Any(false));
1573 if (!bAutoFirstLineIndentDisregardLineSpace)
1574 xProps->setPropertyValue("AutoFirstLineIndentDisregardLineSpace", Any(false));
1576 if (!bHyphenateURLs)
1578 xProps->setPropertyValue("HyphenateURLs", Any(true));
1581 if (bDoNotBreakWrappedTables)
1583 xProps->setPropertyValue("DoNotBreakWrappedTables", Any(true));
1586 if (bAllowTextAfterFloatingTableBreak)
1588 xProps->setPropertyValue("AllowTextAfterFloatingTableBreak", Any(true));
1591 // LO 7.4 and previous versions had different drop cap punctuation: very long dashes.
1592 // In order to keep backwards compatibility, DropCapPunctuation option is written to .odt
1593 // files, and the default for new documents is 'true'. Files without this option
1594 // are considered to be old files, so set the compatibility option too.
1595 if ( !bDropCapPunctuation )
1597 xProps->setPropertyValue( "DropCapPunctuation", Any( false ) );
1600 SwDoc *pDoc = getDoc();
1601 SfxPrinter *pPrinter = pDoc->getIDocumentDeviceAccess().getPrinter( false );
1602 if( pPrinter )
1604 // If the printer is known, then the OLE objects will
1605 // already have correct sizes, and we don't have to call
1606 // PrtOLENotify again. Otherwise we have to call it.
1607 // The flag might be set from setting the printer, so it
1608 // it is required to clear it.
1609 pDoc->SetOLEPrtNotifyPending( !pPrinter->IsKnown() );
1613 void SwXMLImport::SetDocumentSpecificSettings(
1614 const OUString& _rSettingsGroupName,
1615 const Sequence< PropertyValue>& _rSettings )
1617 // the only doc-specific settings group we know so far are the XForms settings
1618 if ( !IsXMLToken( _rSettingsGroupName, XML_XFORM_MODEL_SETTINGS ) )
1619 return;
1621 // preserve the settings for a later iteration - we are currently reading the settings.xml,
1622 // the content.xml will be read later, by another instance of SwXMLImport
1623 OSL_ENSURE( m_xLateInitSettings.is(), "SwXMLImport::SetDocumentSpecificSettings: no storage for those settings!" );
1624 if ( !m_xLateInitSettings.is() )
1625 return;
1629 if ( m_xLateInitSettings->hasByName( _rSettingsGroupName ) )
1631 m_xLateInitSettings->replaceByName( _rSettingsGroupName, Any( _rSettings ) );
1632 OSL_FAIL( "SwXMLImport::SetDocumentSpecificSettings: already have settings for this model!" );
1634 else
1635 m_xLateInitSettings->insertByName( _rSettingsGroupName, Any( _rSettings ) );
1637 catch( const Exception& )
1642 void SwXMLImport::initialize(
1643 const Sequence<Any>& aArguments )
1645 // delegate to super class
1646 SvXMLImport::initialize(aArguments);
1648 // we are only looking for a NamedValue "LateInitSettings"
1649 for(const auto& rArgument : aArguments)
1651 beans::NamedValue aNamedValue;
1652 if ( rArgument >>= aNamedValue )
1654 if (aNamedValue.Name == "LateInitSettings")
1656 OSL_VERIFY( aNamedValue.Value >>= m_xLateInitSettings );
1662 void SwXMLImport::initXForms()
1664 // obtain SwDoc
1665 auto pXTextDocument = comphelper::getFromUnoTunnel<SwXTextDocument>(GetModel());
1666 if( pXTextDocument == nullptr )
1667 return;
1669 SwDoc *pDoc = pXTextDocument->GetDocShell()->GetDoc();
1671 // init XForms (if not already done)
1672 // (no default model, since we'll load the models)
1673 if( ! pDoc->isXForms() )
1674 pDoc->initXForms( false );
1676 m_bInititedXForms = true;
1679 SwDoc* SwXMLImport::getDoc()
1681 if( m_pDoc != nullptr )
1682 return m_pDoc;
1683 Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
1684 Reference < XText > xText = xTextDoc->getText();
1685 SwXText* pText = dynamic_cast<SwXText*>(xText.get());
1686 assert( pText != nullptr );
1687 m_pDoc = pText->GetDoc();
1688 assert( m_pDoc != nullptr );
1689 return m_pDoc;
1692 const SwDoc* SwXMLImport::getDoc() const
1694 return const_cast< SwXMLImport* >( this )->getDoc();
1697 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1698 com_sun_star_comp_Writer_XMLOasisImporter_get_implementation(css::uno::XComponentContext* context,
1699 css::uno::Sequence<css::uno::Any> const &)
1701 return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisImporter",
1702 SvXMLImportFlags::ALL));
1706 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1707 com_sun_star_comp_Writer_XMLOasisStylesImporter_get_implementation(css::uno::XComponentContext* context,
1708 css::uno::Sequence<css::uno::Any> const &)
1710 return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisStylesImporter",
1711 SvXMLImportFlags::STYLES | SvXMLImportFlags::MASTERSTYLES | SvXMLImportFlags::AUTOSTYLES |
1712 SvXMLImportFlags::FONTDECLS));
1716 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1717 com_sun_star_comp_Writer_XMLOasisContentImporter_get_implementation(css::uno::XComponentContext* context,
1718 css::uno::Sequence<css::uno::Any> const &)
1720 return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisContentImporter",
1721 SvXMLImportFlags::CONTENT | SvXMLImportFlags::SCRIPTS | SvXMLImportFlags::AUTOSTYLES |
1722 SvXMLImportFlags::FONTDECLS));
1725 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1726 com_sun_star_comp_Writer_XMLOasisMetaImporter_get_implementation(css::uno::XComponentContext* context,
1727 css::uno::Sequence<css::uno::Any> const &)
1729 return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisMetaImporter",
1730 SvXMLImportFlags::META));
1734 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1735 com_sun_star_comp_Writer_XMLOasisSettingsImporter_get_implementation(css::uno::XComponentContext* context,
1736 css::uno::Sequence<css::uno::Any> const &)
1738 return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisSettingsImporter",
1739 SvXMLImportFlags::SETTINGS));
1742 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODT(SvStream &rStream)
1744 SwGlobals::ensure();
1746 SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
1747 xDocSh->DoInitNew();
1748 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1750 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1751 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1752 uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.XmlFilterAdaptor"), uno::UNO_SET_THROW);
1754 css::uno::Sequence<OUString> aUserData
1756 "com.sun.star.comp.filter.OdfFlatXml",
1758 "com.sun.star.comp.Writer.XMLOasisImporter",
1759 "com.sun.star.comp.Writer.XMLOasisExporter",
1762 "true"
1764 uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
1766 { "UserData", uno::Any(aUserData) },
1767 }));
1768 css::uno::Sequence<uno::Any> aOuterArgs{ uno::Any(aAdaptorArgs) };
1770 uno::Reference<lang::XInitialization> xInit(xInterface, uno::UNO_QUERY_THROW);
1771 xInit->initialize(aOuterArgs);
1773 uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
1774 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1776 { "InputStream", uno::Any(xStream) },
1777 { "URL", uno::Any(OUString("private:stream")) },
1778 }));
1779 xImporter->setTargetDocument(xModel);
1781 uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
1782 //SetLoading hack because the document properties will be re-initted
1783 //by the xml filter and during the init, while it's considered uninitialized,
1784 //setting a property will inform the document it's modified, which attempts
1785 //to update the properties, which throws cause the properties are uninitialized
1786 xDocSh->SetLoading(SfxLoadedFlags::NONE);
1787 bool ret = xFilter->filter(aArgs);
1788 xDocSh->SetLoading(SfxLoadedFlags::ALL);
1790 xDocSh->DoClose();
1792 return ret;
1795 extern "C" SAL_DLLPUBLIC_EXPORT bool TestPDFExportFODT(SvStream &rStream)
1797 // do the same sort of check as FilterDetect::detect
1798 OString const str(read_uInt8s_ToOString(rStream, 4000));
1799 rStream.Seek(STREAM_SEEK_TO_BEGIN);
1800 OUString resultString(str.getStr(), str.getLength(), RTL_TEXTENCODING_ASCII_US,
1801 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT|RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT|RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT);
1802 if (resultString.indexOf("office:mimetype=\"application/vnd.oasis.opendocument.text\"") == -1)
1803 return false;
1805 Reference<css::frame::XDesktop2> xDesktop = css::frame::Desktop::create(comphelper::getProcessComponentContext());
1806 Reference<css::frame::XFrame> xTargetFrame = xDesktop->findFrame("_blank", 0);
1808 Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
1809 Reference<css::frame::XModel2> xModel(xContext->getServiceManager()->createInstanceWithContext(
1810 "com.sun.star.text.TextDocument", xContext), UNO_QUERY_THROW);
1812 Reference<css::frame::XLoadable> xModelLoad(xModel, UNO_QUERY_THROW);
1813 xModelLoad->initNew();
1815 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1816 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1817 uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.XmlFilterAdaptor"), uno::UNO_SET_THROW);
1819 css::uno::Sequence<OUString> aUserData
1821 "com.sun.star.comp.filter.OdfFlatXml",
1823 "com.sun.star.comp.Writer.XMLOasisImporter",
1824 "com.sun.star.comp.Writer.XMLOasisExporter",
1827 "true"
1829 uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
1831 { "UserData", uno::Any(aUserData) },
1832 }));
1833 css::uno::Sequence<uno::Any> aOuterArgs{ uno::Any(aAdaptorArgs) };
1835 uno::Reference<lang::XInitialization> xInit(xInterface, uno::UNO_QUERY_THROW);
1836 xInit->initialize(aOuterArgs);
1838 uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
1839 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1841 { "InputStream", uno::Any(xStream) },
1842 { "URL", uno::Any(OUString("private:stream")) },
1843 }));
1844 xImporter->setTargetDocument(xModel);
1846 uno::Reference<document::XFilter> xFODTFilter(xInterface, uno::UNO_QUERY_THROW);
1847 bool ret = xFODTFilter->filter(aArgs);
1849 css::uno::Reference<css::frame::XController2> xController(xModel->createDefaultViewController(xTargetFrame), UNO_SET_THROW);
1851 utl::ConnectFrameControllerModel(xTargetFrame, xController, xModel);
1853 if (ret)
1855 utl::MediaDescriptor aMediaDescriptor;
1856 aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
1858 utl::TempFileNamed aTempFile;
1859 aTempFile.EnableKillingFile();
1861 uno::Reference<document::XFilter> xPDFFilter(
1862 xMultiServiceFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
1863 uno::Reference<document::XExporter> xExporter(xPDFFilter, uno::UNO_QUERY);
1864 xExporter->setSourceDocument(xModel);
1866 SvFileStream aOutputStream(aTempFile.GetURL(), StreamMode::WRITE);
1867 uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aOutputStream));
1869 uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence({
1870 { "FilterName", uno::Any(OUString("writer_pdf_Export")) },
1871 { "OutputStream", uno::Any(xOutputStream) }
1872 }));
1873 xPDFFilter->filter(aDescriptor);
1874 aOutputStream.Close();
1877 css::uno::Reference<css::util::XCloseable> xClose(xModel, css::uno::UNO_QUERY);
1878 xClose->close(false);
1880 return ret;
1883 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportDOCX(SvStream &rStream)
1885 SwGlobals::ensure();
1887 SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
1888 xDocSh->DoInitNew();
1889 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1891 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1892 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1894 uno::Reference<document::XFilter> xFilter(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_QUERY_THROW);
1896 uno::Reference<document::XImporter> xImporter(xFilter, uno::UNO_QUERY_THROW);
1897 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1899 { "InputStream", uno::Any(xStream) },
1900 { "InputMode", uno::Any(true) },
1901 }));
1902 xImporter->setTargetDocument(xModel);
1904 //SetLoading hack because the document properties will be re-initted
1905 //by the xml filter and during the init, while it's considered uninitialized,
1906 //setting a property will inform the document it's modified, which attempts
1907 //to update the properties, which throws cause the properties are uninitialized
1908 xDocSh->SetLoading(SfxLoadedFlags::NONE);
1909 bool ret = false;
1912 ret = xFilter->filter(aArgs);
1914 catch (...)
1917 xDocSh->SetLoading(SfxLoadedFlags::ALL);
1919 xDocSh->DoClose();
1921 return ret;
1924 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */