1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <cassert>
24 
25 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
26 #include <com/sun/star/drawing/XDrawPage.hpp>
27 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
28 #include <com/sun/star/text/XTextDocument.hpp>
29 #include <com/sun/star/text/XTextRange.hpp>
30 
31 #include <o3tl/any.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmltkmap.hxx>
34 #include <xmloff/xmlictxt.hxx>
35 #include <xmloff/txtimp.hxx>
36 #include <xmloff/XMLTextShapeImportHelper.hxx>
37 #include <xmloff/XMLFontStylesContext.hxx>
38 #include <xmloff/ProgressBarHelper.hxx>
39 #include <doc.hxx>
40 #include <drawdoc.hxx>
41 #include <IDocumentSettingAccess.hxx>
42 #include <IDocumentDeviceAccess.hxx>
43 #include <IDocumentListsAccess.hxx>
44 #include <IDocumentStylePoolAccess.hxx>
45 #include <IDocumentDrawModelAccess.hxx>
46 #include <TextCursorHelper.hxx>
47 #include <unotext.hxx>
48 #include <unotextrange.hxx>
49 #include <poolfmt.hxx>
50 #include <ndtxt.hxx>
51 #include <editsh.hxx>
52 #include <strings.hrc>
53 #include <svl/stritem.hxx>
54 #include "xmlimp.hxx"
55 #include "xmlimpit.hxx"
56 #include "xmltexti.hxx"
57 #include <list.hxx>
58 #include <swdll.hxx>
59 #include <xmloff/DocumentSettingsContext.hxx>
60 #include <docsh.hxx>
61 #include <svx/xmlgrhlp.hxx>
62 #include <svx/xmleohlp.hxx>
63 #include <sfx2/printer.hxx>
64 #include <xmloff/xmluconv.hxx>
65 #include <unotools/saveopt.hxx>
66 #include <unotools/streamwrap.hxx>
67 #include <tools/UnitConversion.hxx>
68 #include <tools/diagnose_ex.h>
69 
70 #include <vcl/svapp.hxx>
71 #include <unotxdoc.hxx>
72 #include <numrule.hxx>
73 
74 #include <xmloff/xmlmetai.hxx>
75 #include <xmloff/xformsimport.hxx>
76 #include <comphelper/servicehelper.hxx>
77 #include <comphelper/processfactory.hxx>
78 #include <comphelper/propertysequence.hxx>
79 
80 #include <unordered_set>
81 
82 using namespace ::com::sun::star;
83 using namespace ::com::sun::star::uno;
84 using namespace ::com::sun::star::text;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::beans;
87 using namespace ::com::sun::star::container;
88 using namespace ::com::sun::star::i18n;
89 using namespace ::com::sun::star::drawing;
90 using namespace ::com::sun::star::xforms;
91 using namespace ::xmloff::token;
92 using namespace ::std;
93 
94 namespace {
95 
96 class SwXMLBodyContext_Impl : public SvXMLImportContext
97 {
GetSwImport()98     SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
99 
100 public:
101 
102     SwXMLBodyContext_Impl( SwXMLImport& rImport );
103 
104     virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
105             sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
106 };
107 
108 }
109 
SwXMLBodyContext_Impl(SwXMLImport & rImport)110 SwXMLBodyContext_Impl::SwXMLBodyContext_Impl( SwXMLImport& rImport ) :
111     SvXMLImportContext( rImport )
112 {
113     // tdf#107211: if at this point we don't have a defined char style "Default"
114     // or "Default Style", add a mapping for it as it is not written
115     // into the file since it's not really a style but "no style"
116     // (hence referencing it actually makes no sense except for hyperlinks
117     // which default to something other than "Default")
118     OUString const sDefault(SwResId(STR_POOLCHR_STANDARD));
119     uno::Reference<container::XNameContainer> const& xStyles(
120             rImport.GetTextImport()->GetTextStyles());
121     if (!xStyles->hasByName("Default"))
122     {   // this old name was used before LO 4.0
123         rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default", sDefault);
124     }
125     if (!xStyles->hasByName("Default_20_Style"))
126     {   // this new name contains a space which is converted to _20_ on export
127         rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, "Default_20_Style", sDefault);
128     }
129     bool isEncoded(false);
130     OUString const defaultEncoded(
131         rImport.GetMM100UnitConverter().encodeStyleName(sDefault, &isEncoded));
132     if (isEncoded && defaultEncoded != "Default_20_Style"
133         && !xStyles->hasByName(defaultEncoded))
134     {   // new name may contain a space which is converted to _20_ on export
135         rImport.AddStyleDisplayName(XmlStyleFamily::TEXT_TEXT, defaultEncoded, sDefault);
136     }
137 }
138 
createFastChildContext(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)139 css::uno::Reference< css::xml::sax::XFastContextHandler > SwXMLBodyContext_Impl::createFastChildContext(
140     sal_Int32 /*nElement*/,
141     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
142 {
143     return GetSwImport().CreateBodyContentContext();
144 }
145 
146 namespace {
147 
148 // #i69629#
149 // enhance class <SwXMLDocContext_Impl> in order to be able to create subclasses
150 // NB: virtually inherit so we can multiply inherit properly
151 //     in SwXMLOfficeDocContext_Impl
152 class SwXMLDocContext_Impl : public virtual SvXMLImportContext
153 {
154     sal_Int32 mnElement;
155 
156 protected: // #i69629#
GetSwImport()157     SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
158 
159 public:
160     SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
161 
162     virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
163         sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
164 };
165 
166 }
167 
SwXMLDocContext_Impl(SwXMLImport & rImport,sal_Int32 nElement)168 SwXMLDocContext_Impl::SwXMLDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
169     SvXMLImportContext( rImport ), mnElement(nElement)
170 {
171 }
172 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)173 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLDocContext_Impl::createFastChildContext(
174     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
175 {
176     switch (nElement)
177     {
178         case XML_ELEMENT(OFFICE, XML_SCRIPTS):
179             return GetSwImport().CreateScriptContext();
180         case XML_ELEMENT(OFFICE, XML_SETTINGS):
181             return new XMLDocumentSettingsContext( GetImport() );
182         case XML_ELEMENT(OFFICE, XML_STYLES):
183             GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
184             return GetSwImport().CreateStylesContext( false );
185         case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
186             // don't use the autostyles from the styles-document for the progress
187             if ( mnElement != 0 && (mnElement & TOKEN_MASK) != XML_DOCUMENT_STYLES )
188                 GetSwImport().GetProgressBarHelper()->Increment
189                     ( PROGRESS_BAR_STEP );
190             return GetSwImport().CreateStylesContext( true );
191         case XML_ELEMENT(OFFICE, XML_MASTER_STYLES):
192             return GetSwImport().CreateMasterStylesContext();
193         case XML_ELEMENT(OFFICE, XML_FONT_FACE_DECLS):
194             return GetSwImport().CreateFontDeclsContext();
195         case XML_ELEMENT(OFFICE, XML_META):
196             OSL_FAIL(" XML_ELEMENT(OFFICE, XML_META): should not have come here, maybe document is invalid?");
197             break;
198         case XML_ELEMENT(OFFICE, XML_BODY):
199             GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
200             return new SwXMLBodyContext_Impl( GetSwImport() );
201         case XML_ELEMENT(XFORMS, XML_MODEL):
202             return createXFormsModelContext(GetImport());
203         default:
204             XMLOFF_WARN_UNKNOWN_ELEMENT("sw", nElement);
205     }
206     return nullptr;
207 }
208 
209 namespace {
210 
211 // #i69629# - new subclass <SwXMLOfficeDocContext_Impl> of class <SwXMLDocContext_Impl>
212 class SwXMLOfficeDocContext_Impl :
213          public SwXMLDocContext_Impl, public SvXMLMetaDocumentContext
214 {
215 public:
216 
217     SwXMLOfficeDocContext_Impl( SwXMLImport& rImport, sal_Int32 nElement,
218                 const Reference< document::XDocumentProperties >& xDocProps);
219 
220     virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
221         sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
222 };
223 
224 }
225 
SwXMLOfficeDocContext_Impl(SwXMLImport & rImport,sal_Int32 nElement,const Reference<document::XDocumentProperties> & xDocProps)226 SwXMLOfficeDocContext_Impl::SwXMLOfficeDocContext_Impl(
227                 SwXMLImport& rImport,
228                 sal_Int32 nElement,
229                 const Reference< document::XDocumentProperties >& xDocProps) :
230     SvXMLImportContext( rImport ),
231     SwXMLDocContext_Impl( rImport, nElement ),
232     SvXMLMetaDocumentContext( rImport, xDocProps )
233 {
234 }
235 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)236 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SwXMLOfficeDocContext_Impl::createFastChildContext(
237     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
238 {
239     // assign paragraph styles to list levels of outline style after all styles
240     // are imported and finished. This is the case, when <office:body> starts
241     // in flat OpenDocument file format.
242     {
243         if( nElement == XML_ELEMENT( OFFICE, XML_BODY ) )
244         {
245             GetImport().GetTextImport()->SetOutlineStyles( true );
246         }
247     }
248 
249     // behave like meta base class iff we encounter office:meta
250     if ( nElement == XML_ELEMENT( OFFICE, XML_META ) ) {
251         return SvXMLMetaDocumentContext::createFastChildContext(
252                     nElement, xAttrList );
253     } else {
254         return SwXMLDocContext_Impl::createFastChildContext(
255                     nElement, xAttrList );
256     }
257 }
258 
259 namespace {
260 
261 // #i69629# - new subclass <SwXMLDocStylesContext_Impl> of class <SwXMLDocContext_Impl>
262 class SwXMLDocStylesContext_Impl : public SwXMLDocContext_Impl
263 {
264 public:
265 
266     SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement );
267 
268     virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
269 };
270 
271 }
272 
SwXMLDocStylesContext_Impl(SwXMLImport & rImport,sal_Int32 nElement)273 SwXMLDocStylesContext_Impl::SwXMLDocStylesContext_Impl( SwXMLImport& rImport, sal_Int32 nElement ) :
274     SvXMLImportContext( rImport ),
275     SwXMLDocContext_Impl( rImport, nElement )
276 {
277 }
278 
endFastElement(sal_Int32)279 void SwXMLDocStylesContext_Impl::endFastElement(sal_Int32 )
280 {
281     // assign paragraph styles to list levels of outline style after all styles
282     // are imported and finished.
283     SwXMLImport& rSwImport = dynamic_cast<SwXMLImport&>( GetImport());
284     GetImport().GetTextImport()->SetOutlineStyles(
285             bool(rSwImport.GetStyleFamilyMask() & SfxStyleFamily::Para));
286 }
287 
CreateFastContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)288 SvXMLImportContext *SwXMLImport::CreateFastContext( sal_Int32 nElement,
289         const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
290 {
291     SvXMLImportContext *pContext = nullptr;
292 
293     switch (nElement)
294     {
295         case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
296             pContext = CreateMetaContext(nElement);
297         break;
298         case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
299         {
300             uno::Reference<document::XDocumentProperties> const xDocProps(
301                 GetDocumentProperties());
302             // flat OpenDocument file format
303             pContext = new SwXMLOfficeDocContext_Impl( *this, nElement, xDocProps );
304         }
305         break;
306         // #i69629# - own subclasses for <office:document> and <office:document-styles>
307         case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
308         case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT):
309             pContext = new SwXMLDocContext_Impl( *this, nElement );
310             break;
311         case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES):
312             pContext = new SwXMLDocStylesContext_Impl( *this, nElement );
313             break;
314     }
315     return pContext;
316 }
317 
SwXMLImport(const uno::Reference<uno::XComponentContext> & rContext,OUString const & implementationName,SvXMLImportFlags nImportFlags)318 SwXMLImport::SwXMLImport(
319     const uno::Reference< uno::XComponentContext >& rContext,
320     OUString const & implementationName, SvXMLImportFlags nImportFlags)
321 :   SvXMLImport( rContext, implementationName, nImportFlags ),
322     m_nStyleFamilyMask( SfxStyleFamily::All ),
323     m_bLoadDoc( true ),
324     m_bInsert( false ),
325     m_bBlock( false ),
326     m_bOrganizerMode( false ),
327     m_bInititedXForms( false ),
328     m_pDoc( nullptr )
329 {
330     InitItemImport();
331 }
332 
~SwXMLImport()333 SwXMLImport::~SwXMLImport() noexcept
334 {
335     if (HasShapeImport())
336     {
337         SAL_WARN("sw", "endDocument skipped, dropping shapes now to avoid dangling SvTextShapeImportHelper pointing to this");
338         ClearShapeImport();
339     }
340     FinitItemImport();
341 }
342 
setTextInsertMode(const Reference<XTextRange> & rInsertPos)343 void SwXMLImport::setTextInsertMode(
344          const Reference< XTextRange > & rInsertPos )
345 {
346     m_bInsert = true;
347 
348     Reference < XText > xText = rInsertPos->getText();
349     Reference < XTextCursor > xTextCursor =
350         xText->createTextCursorByRange( rInsertPos );
351     GetTextImport()->SetCursor( xTextCursor );
352 }
353 
setStyleInsertMode(SfxStyleFamily nFamilies,bool bOverwrite)354 void SwXMLImport::setStyleInsertMode( SfxStyleFamily nFamilies,
355                                       bool bOverwrite )
356 {
357     m_bInsert = !bOverwrite;
358     m_nStyleFamilyMask = nFamilies;
359     m_bLoadDoc = false;
360 }
361 
getUnoTunnelId()362 const Sequence< sal_Int8 > & SwXMLImport::getUnoTunnelId() noexcept
363 {
364     static const UnoTunnelIdInit theSwXMLImportUnoTunnelId;
365     return theSwXMLImportUnoTunnelId.getSeq();
366 }
367 
getSomething(const Sequence<sal_Int8> & rId)368 sal_Int64 SAL_CALL SwXMLImport::getSomething( const Sequence< sal_Int8 >& rId )
369 {
370     if( isUnoTunnelId<SwXMLImport>(rId) )
371     {
372         return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
373     }
374     return SvXMLImport::getSomething( rId );
375 }
376 
lcl_xml_GetSwXTextCursor(const Reference<XTextCursor> & rTextCursor)377 static OTextCursorHelper *lcl_xml_GetSwXTextCursor( const Reference < XTextCursor >& rTextCursor )
378 {
379     Reference<XUnoTunnel> xCursorTunnel( rTextCursor, UNO_QUERY );
380     OSL_ENSURE( xCursorTunnel.is(), "missing XUnoTunnel for Cursor" );
381     if( !xCursorTunnel.is() )
382         return nullptr;
383     OTextCursorHelper *pTextCursor = reinterpret_cast< OTextCursorHelper *>(
384             sal::static_int_cast< sal_IntPtr >( xCursorTunnel->getSomething(  OTextCursorHelper::getUnoTunnelId() )));
385     OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
386     return pTextCursor;
387 }
388 
startDocument()389 void SwXMLImport::startDocument()
390 {
391     // delegate to parent
392     SvXMLImport::startDocument();
393 
394     OSL_ENSURE( GetModel().is(), "model is missing" );
395     if( !GetModel().is() )
396         return;
397 
398     // this method will modify the document directly -> lock SolarMutex
399     SolarMutexGuard aGuard;
400 
401     Reference< XPropertySet > xImportInfo( getImportInfo() );
402     Reference< XPropertySetInfo > xPropertySetInfo;
403     if( xImportInfo.is() )
404         xPropertySetInfo = xImportInfo->getPropertySetInfo();
405     if( xPropertySetInfo.is() )
406     {
407         Any aAny;
408         // insert style mode?
409         OUString sStyleInsertModeFamilies("StyleInsertModeFamilies");
410         if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeFamilies) )
411         {
412             aAny = xImportInfo->getPropertyValue(sStyleInsertModeFamilies);
413             Sequence< OUString> aFamiliesSeq;
414             if( aAny >>= aFamiliesSeq )
415             {
416                 SfxStyleFamily nFamilyMask = SfxStyleFamily::None;
417                 for( const OUString& rFamily : std::as_const(aFamiliesSeq) )
418                 {
419                     if( rFamily=="FrameStyles" )
420                         nFamilyMask |= SfxStyleFamily::Frame;
421                     else if( rFamily=="PageStyles" )
422                         nFamilyMask |= SfxStyleFamily::Page;
423                     else if( rFamily=="CharacterStyles" )
424                         nFamilyMask |= SfxStyleFamily::Char;
425                     else if( rFamily=="ParagraphStyles" )
426                         nFamilyMask |= SfxStyleFamily::Para;
427                     else if( rFamily=="NumberingStyles" )
428                         nFamilyMask |= SfxStyleFamily::Pseudo;
429                 }
430 
431                 bool bOverwrite = false;
432                 static const OUStringLiteral sStyleInsertModeOverwrite(u"StyleInsertModeOverwrite");
433                 if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeOverwrite) )
434                 {
435                     aAny = xImportInfo->getPropertyValue(sStyleInsertModeOverwrite);
436                     if( auto b = o3tl::tryAccess<bool>(aAny) )
437                     {
438                         if( *b )
439                             bOverwrite = true;
440                     }
441                 }
442 
443                 setStyleInsertMode( nFamilyMask, bOverwrite );
444             }
445         }
446 
447         // text insert mode?
448         static const OUStringLiteral sTextInsertModeRange(u"TextInsertModeRange");
449         if( xPropertySetInfo->hasPropertyByName(sTextInsertModeRange) )
450         {
451             aAny = xImportInfo->getPropertyValue(sTextInsertModeRange);
452             Reference<XTextRange> xInsertTextRange;
453             if( aAny >>= xInsertTextRange )
454                 setTextInsertMode( xInsertTextRange );
455         }
456 
457         // auto text mode
458         static const OUStringLiteral sAutoTextMode(u"AutoTextMode");
459         if( xPropertySetInfo->hasPropertyByName(sAutoTextMode) )
460         {
461             aAny = xImportInfo->getPropertyValue(sAutoTextMode);
462             if( auto b = o3tl::tryAccess<bool>(aAny) )
463             {
464                 if( *b )
465                     m_bBlock = true;
466             }
467         }
468 
469         // organizer mode
470         static const OUStringLiteral sOrganizerMode(u"OrganizerMode");
471         if( xPropertySetInfo->hasPropertyByName(sOrganizerMode) )
472         {
473             aAny = xImportInfo->getPropertyValue(sOrganizerMode);
474             if( auto b = o3tl::tryAccess<bool>(aAny) )
475             {
476                 if( *b )
477                     m_bOrganizerMode = true;
478             }
479         }
480 
481         // default document properties
482         static const OUStringLiteral sDefSettings(u"DefaultDocumentSettings");
483         if (xPropertySetInfo->hasPropertyByName(sDefSettings))
484         {
485             aAny = xImportInfo->getPropertyValue(sDefSettings);
486             Sequence<PropertyValue> aProps;
487             if (aAny >>= aProps)
488             {
489                 Reference<lang::XMultiServiceFactory> xFac(GetModel(), UNO_QUERY);
490                 Reference<XPropertySet> xProps(
491                     xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY);
492                 Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
493 
494                 if (xProps.is() && xInfo.is())
495                 {
496                     for (const auto& rProp : std::as_const(aProps))
497                     {
498                         if (xInfo->hasPropertyByName(rProp.Name))
499                         {
500                             xProps->setPropertyValue(rProp.Name, rProp.Value);
501                         }
502                     }
503                 }
504             }
505         }
506     }
507 
508     // There only is a text cursor by now if we are in insert mode. In any
509     // other case we have to create one at the start of the document.
510     // We also might change into the insert mode later, so we have to make
511     // sure to first set the insert mode and then create the text import
512     // helper. Otherwise it won't have the insert flag set!
513     OTextCursorHelper *pTextCursor = nullptr;
514     Reference < XTextCursor > xTextCursor;
515     if( HasTextImport() )
516            xTextCursor = GetTextImport()->GetCursor();
517     if( !xTextCursor.is() )
518     {
519         Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
520         Reference < XText > xText = xTextDoc->getText();
521         xTextCursor = xText->createTextCursor();
522         SwCursorShell *pCursorSh = nullptr;
523         SwDoc *pDoc = nullptr;
524         if( SvXMLImportFlags::ALL == getImportFlags() )
525         {
526             pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
527             OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
528             if( !pTextCursor )
529                 return;
530 
531             pDoc = pTextCursor->GetDoc();
532             OSL_ENSURE( pDoc, "SwDoc missing" );
533             if( !pDoc )
534                 return;
535 
536             // Is there an edit shell. If yes, then we are currently inserting
537             // a document. We then have to insert at the current edit shell's
538             // cursor position. That not quite clean code, but there is no other
539             // way currently.
540             pCursorSh = pDoc->GetEditShell();
541         }
542         if( pCursorSh )
543         {
544             const uno::Reference<text::XTextRange> xInsertTextRange(
545                 SwXTextRange::CreateXTextRange(
546                     *pDoc, *pCursorSh->GetCursor()->GetPoint(), nullptr ) );
547             setTextInsertMode( xInsertTextRange );
548             xTextCursor = GetTextImport()->GetCursor();
549             pTextCursor = nullptr;
550         }
551         else
552             GetTextImport()->SetCursor( xTextCursor );
553     }
554 
555     if( !(getImportFlags() & (SvXMLImportFlags::CONTENT|SvXMLImportFlags::MASTERSTYLES)) )
556         return;
557 
558     if( !pTextCursor  )
559         pTextCursor = lcl_xml_GetSwXTextCursor( xTextCursor );
560     OSL_ENSURE( pTextCursor, "SwXTextCursor missing" );
561     if( !pTextCursor )
562         return;
563 
564     SwDoc *pDoc = pTextCursor->GetDoc();
565     OSL_ENSURE( pDoc, "SwDoc missing" );
566     if( !pDoc )
567         return;
568 
569     if (SvXMLImportFlags::ALL == getImportFlags())
570     {
571         // for flat ODF - this is done in SwReader::Read() for package ODF
572         pDoc->SetInReading(true);
573         pDoc->SetInXMLImport(true);
574     }
575 
576     if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
577     {
578         m_pSttNdIdx.reset(new SwNodeIndex( pDoc->GetNodes() ));
579         if( IsInsertMode() )
580         {
581             SwPaM *pPaM = pTextCursor->GetPaM();
582             const SwPosition* pPos = pPaM->GetPoint();
583 
584             // Split once and remember the node that has been split.
585             pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
586             *m_pSttNdIdx = pPos->nNode.GetIndex()-1;
587 
588             // Split again.
589             pDoc->getIDocumentContentOperations().SplitNode( *pPos, false );
590 
591             // Insert all content into the new node
592             pPaM->Move( fnMoveBackward );
593             pDoc->SetTextFormatColl
594                 ( *pPaM, pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, false ) );
595         }
596     }
597 
598     // We need a draw model to be able to set the z order
599     pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); // #i52858# - method name changed
600 
601     // SJ: #i49801# locking the model to disable repaints
602     SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
603     if ( pDrawModel )
604         pDrawModel->setLock(true);
605 
606     if (!GetGraphicStorageHandler().is())
607     {
608         m_xGraphicStorageHandler = SvXMLGraphicHelper::Create(SvXMLGraphicHelperMode::Read);
609         SetGraphicStorageHandler(m_xGraphicStorageHandler);
610     }
611 
612     if( !GetEmbeddedResolver().is() )
613     {
614         SfxObjectShell *pPersist = pDoc->GetPersist();
615         if( pPersist )
616         {
617             m_xEmbeddedResolver = SvXMLEmbeddedObjectHelper::Create(
618                                             *pPersist,
619                                             SvXMLEmbeddedObjectHelperMode::Read );
620             SetEmbeddedResolver( m_xEmbeddedResolver );
621         }
622     }
623 }
624 
endDocument()625 void SwXMLImport::endDocument()
626 {
627     OSL_ENSURE( GetModel().is(), "model missing; maybe startDocument wasn't called?" );
628     if( !GetModel().is() )
629         return;
630 
631     // this method will modify the document directly -> lock SolarMutex
632     SolarMutexGuard aGuard;
633 
634     if (m_xGraphicStorageHandler)
635         m_xGraphicStorageHandler->dispose();
636     m_xGraphicStorageHandler.clear();
637 
638     if( m_xEmbeddedResolver )
639         m_xEmbeddedResolver->dispose();
640     m_xEmbeddedResolver.clear();
641     // Clear the shape import to sort the shapes  (and not in the
642     // destructor that might be called after the import has finished
643     // for Java filters.
644     if( HasShapeImport() )
645         ClearShapeImport();
646 
647     SwDoc *pDoc = nullptr;
648     if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() )
649     {
650         Reference<XUnoTunnel> xCursorTunnel( GetTextImport()->GetCursor(),
651                                               UNO_QUERY);
652         assert(xCursorTunnel.is() && "missing XUnoTunnel for Cursor");
653         OTextCursorHelper *pTextCursor = reinterpret_cast< OTextCursorHelper *>(
654                 sal::static_int_cast< sal_IntPtr >( xCursorTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )));
655         assert(pTextCursor && "SwXTextCursor missing");
656         SwPaM *pPaM = pTextCursor->GetPaM();
657         if( IsInsertMode() && m_pSttNdIdx->GetIndex() )
658         {
659             // If we are in insert mode, join the split node that is in front
660             // of the new content with the first new node. Or in other words:
661             // Revert the first split node.
662             SwTextNode* pTextNode = m_pSttNdIdx->GetNode().GetTextNode();
663             SwNodeIndex aNxtIdx( *m_pSttNdIdx );
664             if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx ) &&
665                 m_pSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() )
666             {
667                 // If the PaM points to the first new node, move the PaM to the
668                 // end of the previous node.
669                 if( pPaM->GetPoint()->nNode == aNxtIdx )
670                 {
671                     pPaM->GetPoint()->nNode = *m_pSttNdIdx;
672                     pPaM->GetPoint()->nContent.Assign( pTextNode,
673                                             pTextNode->GetText().getLength());
674                 }
675 
676 #if OSL_DEBUG_LEVEL > 0
677                 // !!! This should be impossible !!!!
678                 OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 !=
679                                         pPaM->GetBound().nNode.GetIndex(),
680                         "PaM.Bound1 point to new node " );
681                 OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 !=
682                                         pPaM->GetBound( false ).nNode.GetIndex(),
683                         "PaM.Bound2 points to new node" );
684 
685                 if( m_pSttNdIdx->GetIndex()+1 ==
686                                         pPaM->GetBound().nNode.GetIndex() )
687                 {
688                     const sal_Int32 nCntPos =
689                             pPaM->GetBound().nContent.GetIndex();
690                     pPaM->GetBound().nContent.Assign( pTextNode,
691                             pTextNode->GetText().getLength() + nCntPos );
692                 }
693                 if( m_pSttNdIdx->GetIndex()+1 ==
694                                 pPaM->GetBound( false ).nNode.GetIndex() )
695                 {
696                     const sal_Int32 nCntPos =
697                             pPaM->GetBound( false ).nContent.GetIndex();
698                     pPaM->GetBound( false ).nContent.Assign( pTextNode,
699                             pTextNode->GetText().getLength() + nCntPos );
700                 }
701 #endif
702                 // If the first new node isn't empty, convert  the node's text
703                 // attributes into hints. Otherwise, set the new node's
704                 // paragraph style at the previous (empty) node.
705                 SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode();
706                 if (!pTextNode->GetText().isEmpty())
707                     pDelNd->FormatToTextAttr( pTextNode );
708                 else
709                 {
710                     pTextNode->ResetAttr(RES_CHRATR_BEGIN, RES_CHRATR_END);
711                     pTextNode->ChgFormatColl( pDelNd->GetTextColl() );
712                     if (!pDelNd->GetNoCondAttr(RES_PARATR_LIST_ID, /*bInParents=*/false))
713                     {
714                         // MergeListsAtDocumentInsertPosition() will deal with lists below, copy
715                         // paragraph direct formatting otherwise.
716                         pDelNd->CopyCollFormat(*pTextNode);
717                     }
718                 }
719                 pTextNode->JoinNext();
720             }
721         }
722 
723         SwPosition* pPos = pPaM->GetPoint();
724         OSL_ENSURE( !pPos->nContent.GetIndex(), "last paragraph isn't empty" );
725         if( !pPos->nContent.GetIndex() )
726         {
727             SwTextNode* pCurrNd;
728             sal_uLong nNodeIdx = pPos->nNode.GetIndex();
729             pDoc = &pPaM->GetDoc();
730 
731             OSL_ENSURE( pPos->nNode.GetNode().IsContentNode(),
732                         "insert position is not a content node" );
733             if( !IsInsertMode() )
734             {
735                 // If we're not in insert mode, the last node is deleted.
736                 const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
737                 if( pPrev->IsContentNode() ||
738                      ( pPrev->IsEndNode() &&
739                       pPrev->StartOfSectionNode()->IsSectionNode() ) )
740                 {
741                     SwContentNode* pCNd = pPaM->GetContentNode();
742                     if( pCNd && pCNd->StartOfSectionIndex()+2 <
743                         pCNd->EndOfSectionIndex() )
744                     {
745                         pPaM->GetBound().nContent.Assign( nullptr, 0 );
746                         pPaM->GetBound(false).nContent.Assign( nullptr, 0 );
747                         pDoc->GetNodes().Delete( pPaM->GetPoint()->nNode );
748                     }
749                 }
750             }
751             else if( nullptr != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTextNode()) )
752             {
753                 // Id we're in insert mode, the empty node is joined with
754                 // the next and the previous one.
755                 if( pCurrNd->CanJoinNext( &pPos->nNode ))
756                 {
757                     SwTextNode* pNextNd = pPos->nNode.GetNode().GetTextNode();
758                     bool endNodeFound = pDoc->GetNodes()[nNodeIdx-1]->IsEndNode();
759                     SwNode *pLastPar = pDoc->GetNodes()[nNodeIdx -2];
760                     if ( !pLastPar->IsTextNode() ) {
761                         pLastPar = pDoc->GetNodes()[nNodeIdx -1];
762                     }
763                     if ( !endNodeFound && pLastPar->IsTextNode() )
764                     {
765                         pNextNd->ChgFormatColl(pLastPar->GetTextNode()->GetTextColl());
766                     }
767 
768                     pPos->nContent.Assign( pNextNd, 0 );
769                     pPaM->SetMark(); pPaM->DeleteMark();
770                     pNextNd->JoinPrev();
771 
772                     // Remove line break that has been inserted by the import,
773                     // but only if one has been inserted and
774                     // no endNode found to avoid removing section
775                     if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && !endNodeFound &&
776                          *m_pSttNdIdx != pPos->nNode )
777                     {
778                         pNextNd->JoinPrev();
779                     }
780                 }
781                 else if (pCurrNd->GetText().isEmpty())
782                 {
783                     pPos->nContent.Assign( nullptr, 0 );
784                     pPaM->SetMark(); pPaM->DeleteMark();
785                     pDoc->GetNodes().Delete( pPos->nNode );
786                     pPaM->Move( fnMoveBackward );
787                 }
788             }
789 
790             // tdf#113877
791             // when we insert one document with list inside into another one with list at the insert position,
792             // the resulting numbering in these lists is not consequent.
793             //
794             // Main document:
795             //  1. One
796             //  2. Two
797             //  3. Three
798             //  4.                      <-- insert position
799             //
800             // Inserted document:
801             //  1. One
802             //  2. Two
803             //  3. Three
804             //  4.
805             //
806             // Expected result
807             //  1. One
808             //  2. Two
809             //  3. Three
810             //  4. One
811             //  5. Two
812             //  6. Three
813             //  7.
814             //
815             MergeListsAtDocumentInsertPosition(pDoc);
816         }
817     }
818 
819     /* Was called too early. Moved from SwXMLBodyContext_Impl::EndElement */
820 
821     GetTextImport()->RedlineAdjustStartNodeCursor();
822 
823     if( (getImportFlags() & SvXMLImportFlags::CONTENT) ||
824         ((getImportFlags() & SvXMLImportFlags::MASTERSTYLES) && IsStylesOnlyMode()) )
825     {
826         // pDoc might be 0. In this case UpdateTextCollCondition is looking
827         // for it itself.
828         UpdateTextCollConditions( pDoc );
829     }
830 
831     GetTextImport()->ResetCursor();
832 
833     m_pSttNdIdx.reset();
834 
835     // SJ: #i49801# -> now permitting repaints
836     if ( pDoc )
837     {
838         if( getImportFlags() == SvXMLImportFlags::ALL )
839         {
840             // Notify math objects. If we are in the package filter this will
841             // be done by the filter object itself
842             if( IsInsertMode() )
843                 pDoc->PrtOLENotify( false );
844             else if ( pDoc->IsOLEPrtNotifyPending() )
845                 pDoc->PrtOLENotify( true );
846 
847             assert(pDoc->IsInReading());
848             assert(pDoc->IsInXMLImport());
849             pDoc->SetInReading(false);
850             pDoc->SetInXMLImport(false);
851         }
852 
853         SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
854         if ( pDrawModel )
855             pDrawModel->setLock(false);
856     }
857 
858     // #i90243#
859     if ( m_bInititedXForms )
860     {
861         Reference< xforms::XFormsSupplier > xFormsSupp( GetModel(), UNO_QUERY );
862         Reference< XNameAccess > xXForms;
863         if ( xFormsSupp.is() )
864             xXForms = xFormsSupp->getXForms().get();
865 
866         if ( xXForms.is() )
867         {
868             try
869             {
870                 Sequence< beans::PropertyValue > aXFormsSettings;
871 
872                 const OUString& sXFormsSettingsName( GetXMLToken( XML_XFORM_MODEL_SETTINGS ) );
873                 if ( m_xLateInitSettings.is() && m_xLateInitSettings->hasByName( sXFormsSettingsName ) )
874                 {
875                     OSL_VERIFY( m_xLateInitSettings->getByName( sXFormsSettingsName ) >>= aXFormsSettings );
876                     applyXFormsSettings( xXForms, aXFormsSettings );
877                 }
878             }
879             catch( const Exception& )
880             {
881             }
882         }
883     }
884 
885 #if 1
886     if (!pDoc) { pDoc = SwImport::GetDocFromXMLImport(*this); }
887     for (sal_uLong i = 0; i < pDoc->GetNodes().Count(); ++i)
888     {
889         if (SwTableNode *const pTableNode = pDoc->GetNodes()[i]->GetTableNode())
890         {
891             if (!pTableNode->GetTable().IsNewModel()
892                 && pTableNode->GetTable().CanConvertSubtables())
893             {
894                 pTableNode->GetTable().ConvertSubtables();
895             }
896         }
897         // don't skip to the end; nested tables could have subtables too...
898     }
899 #endif
900 
901     // delegate to parent: takes care of error handling
902     SvXMLImport::endDocument();
903     ClearTextImport();
904 }
905 
906 // tdf#113877
907 // when we insert one document with list inside into another one with list at the insert position,
908 // the resulting numbering in these lists is not consequent.
909 //
910 // CASE-1: Main document:
911 //  1. One
912 //  2. Two
913 //  3. Three
914 //  4.                      <-- insert position
915 //
916 // Inserted document:
917 //  1. One
918 //  2. Two
919 //  3. Three
920 //  4.
921 //
922 // Expected result
923 //  1. One
924 //  2. Two
925 //  3. Three
926 //  4. One
927 //  5. Two
928 //  6. Three
929 //  7.
930 //
931 // CASE-2: Main document:
932 //  1. One
933 //  2. Two
934 //  3. Three
935 //  4.                      <-- insert position
936 //
937 // Inserted document:
938 //  A) One
939 //  B) Two
940 //  C) Three
941 //  D)
942 //
943 // Expected result
944 //  1. One
945 //  2. Two
946 //  3. Three
947 //  4. One
948 //  A) Two
949 //  B) Three
950 //  5.
951 //
MergeListsAtDocumentInsertPosition(SwDoc * pDoc)952 void SwXMLImport::MergeListsAtDocumentInsertPosition(SwDoc *pDoc)
953 {
954     // 1. check environment
955     if (! pDoc)
956         return;
957 
958     if (! IsInsertMode() || ! m_pSttNdIdx->GetIndex())
959         return;
960 
961     sal_uLong index = 1;
962 
963     // the last node of the main document where we have inserted a document
964     const SwNodePtr node1 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + 0];
965 
966     // the first node of the inserted document
967     SwNodePtr node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
968 
969     if (! (node1 && node2
970         && (node1->GetNodeType() == node2->GetNodeType())
971         && (node1->IsTextNode() == node2->IsTextNode())
972         ))
973     {
974         // not a text node at insert position
975         return;
976     }
977 
978     // 2. get the first node of the inserted document,
979     // which will be used to detect if inside inserted document a new list was started after the first list
980     const SfxPoolItem* pListId2Initial = nullptr;
981     {
982         SwContentNode* contentNode1 = static_cast<SwContentNode *>(node1);
983         SwContentNode* contentNode2 = static_cast<SwContentNode *>(node2);
984 
985         // check if both lists have the same list properties
986         const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
987         const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
988 
989         if (! pListId1)
990             return;
991         if (! pListId2)
992             return;
993 
994         auto pStringListId1 = dynamic_cast<const SfxStringItem*>(pListId1);
995         assert(pStringListId1);
996         const OUString& sListId1 = pStringListId1->GetValue();
997         auto pStringListId2 = dynamic_cast<const SfxStringItem*>(pListId2);
998         assert(pStringListId2);
999         const OUString& sListId2 = pStringListId2->GetValue();
1000 
1001         const SwList* pList1 = pDoc->getIDocumentListsAccess().getListByName( sListId1 );
1002         const SwList* pList2 = pDoc->getIDocumentListsAccess().getListByName( sListId2 );
1003 
1004         if (! pList1)
1005             return;
1006         if (! pList2)
1007             return;
1008 
1009         const OUString& sDefaultListStyleName1 = pList1->GetDefaultListStyleName();
1010         const OUString& sDefaultListStyleName2 = pList2->GetDefaultListStyleName();
1011 
1012         if (sDefaultListStyleName1 != sDefaultListStyleName2)
1013         {
1014             const SwNumRule* pNumRule1 = pDoc->FindNumRulePtr( sDefaultListStyleName1 );
1015             const SwNumRule* pNumRule2 = pDoc->FindNumRulePtr( sDefaultListStyleName2 );
1016 
1017             if (pNumRule1 && pNumRule2)
1018             {
1019                 // check style of the each list level
1020                 for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1021                 {
1022                     if( pNumRule1->Get( n ) != pNumRule2->Get( n ) )
1023                     {
1024                         return;
1025                     }
1026                 }
1027 
1028                 // our list should be merged
1029                 pListId2Initial = pListId2;
1030             }
1031         }
1032         else
1033         {
1034             // our list should be merged
1035             pListId2Initial = pListId2;
1036         }
1037     }
1038 
1039     if (! pListId2Initial)
1040     {
1041         // two lists have different styles => they should not be merged
1042         return;
1043     }
1044 
1045     // 3. merge two lists
1046     while (
1047         node1 && node2
1048         && (node1->GetNodeType() == node2->GetNodeType())
1049         && (node1->IsTextNode() == node2->IsTextNode())
1050         )
1051     {
1052         SwContentNode* contentNode1 = static_cast<SwContentNode *>( node1 );
1053         SwContentNode* contentNode2 = static_cast<SwContentNode *>( node2 );
1054 
1055         const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( RES_PARATR_LIST_ID, false );
1056         const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( RES_PARATR_LIST_ID, false );
1057 
1058         if (! pListId1)
1059             return;
1060         if (! pListId2)
1061             return;
1062 
1063         if (*pListId2Initial != *pListId2)
1064         {
1065             // no more list items of the first list inside inserted document
1066             return;
1067         }
1068 
1069         // set list style to this list element
1070         contentNode2->SetAttr(*pListId1);
1071 
1072         // get next item
1073         index++;
1074         if (index >= pDoc->GetNodes().Count())
1075         {
1076             // no more items
1077             return;
1078         }
1079 
1080         node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
1081     }
1082 }
1083 
1084 namespace {
1085 
1086 // Locally derive XMLTextShapeImportHelper, so we can take care of the
1087 // form import This is Writer, but not text specific, so it should go
1088 // here!
1089 class SvTextShapeImportHelper : public XMLTextShapeImportHelper
1090 {
1091     // hold own reference form import helper, because the SvxImport
1092     // stored in the superclass, from whom we originally got the
1093     // reference, is already destroyed when we want to use it in the
1094     // destructor
1095     rtl::Reference< ::xmloff::OFormLayerXMLImport > rFormImport;
1096 
1097     // hold reference to the one page (if it exists) for calling startPage()
1098     // and endPage. If !xPage.is(), then this document doesn't have a
1099     // XDrawPage.
1100     Reference<drawing::XDrawPage> xPage;
1101 
1102 public:
1103     explicit SvTextShapeImportHelper(SvXMLImport& rImp);
1104     virtual ~SvTextShapeImportHelper() override;
1105 };
1106 
1107 }
1108 
SvTextShapeImportHelper(SvXMLImport & rImp)1109 SvTextShapeImportHelper::SvTextShapeImportHelper(SvXMLImport& rImp) :
1110     XMLTextShapeImportHelper(rImp)
1111 {
1112     Reference<drawing::XDrawPageSupplier> xSupplier(rImp.GetModel(),UNO_QUERY);
1113     if (xSupplier.is())
1114     {
1115         if (rImp.GetFormImport().is())
1116         {
1117             rImp.GetFormImport()->startPage(xSupplier->getDrawPage());
1118             rFormImport = rImp.GetFormImport();
1119         }
1120 
1121         xPage  = xSupplier->getDrawPage();
1122         XMLShapeImportHelper::startPage( xPage );
1123     }
1124 }
1125 
~SvTextShapeImportHelper()1126 SvTextShapeImportHelper::~SvTextShapeImportHelper()
1127 {
1128     rFormImport->endPage();
1129 
1130     if (xPage.is())
1131     {
1132         XMLShapeImportHelper::endPage(xPage);
1133     }
1134 }
1135 
CreateTextImport()1136 XMLTextImportHelper* SwXMLImport::CreateTextImport()
1137 {
1138     return new SwXMLTextImportHelper( GetModel(), *this, getImportInfo(),
1139                                       IsInsertMode(),
1140                                       IsStylesOnlyMode(),
1141                                       IsBlockMode(), m_bOrganizerMode );
1142 }
1143 
CreateShapeImport()1144 XMLShapeImportHelper* SwXMLImport::CreateShapeImport()
1145 {
1146     return new SvTextShapeImportHelper( *this );
1147 }
1148 
CreateFontDeclsContext()1149 SvXMLImportContext *SwXMLImport::CreateFontDeclsContext()
1150 {
1151     XMLFontStylesContext *pFSContext =
1152             new XMLFontStylesContext( *this, osl_getThreadTextEncoding() );
1153     SetFontDecls( pFSContext );
1154     return pFSContext;
1155 }
1156 
SetViewSettings(const Sequence<PropertyValue> & aViewProps)1157 void SwXMLImport::SetViewSettings(const Sequence < PropertyValue > & aViewProps)
1158 {
1159     if (IsInsertMode() || IsStylesOnlyMode() || IsBlockMode() || m_bOrganizerMode || !GetModel().is() )
1160         return;
1161 
1162     // this method will modify the document directly -> lock SolarMutex
1163     SolarMutexGuard aGuard;
1164 
1165     SwDoc *pDoc = getDoc();
1166     tools::Rectangle aRect;
1167     if( pDoc->GetDocShell() )
1168         aRect = pDoc->GetDocShell()->GetVisArea( ASPECT_CONTENT );
1169         //TODO/LATER: why that cast?!
1170         //aRect = ((SfxInPlaceObject *)pDoc->GetDocShell())->GetVisArea();
1171 
1172     sal_Int64 nTmp = 0;
1173     bool bShowRedlineChanges = false, bBrowseMode = false;
1174     bool bChangeShowRedline = false, bChangeBrowseMode = false;
1175 
1176     //TODO/LATER: why that cast?!
1177     bool bTwip = pDoc->GetDocShell()->GetMapUnit ( ) == MapUnit::MapTwip;
1178     //sal_Bool bTwip = pDoc->GetDocShell()->SfxInPlaceObject::GetMapUnit ( ) == MapUnit::MapTwip;
1179 
1180     for (const PropertyValue& rValue : aViewProps)
1181     {
1182         if ( rValue.Name == "ViewAreaTop" )
1183         {
1184             rValue.Value >>= nTmp;
1185             aRect.setY( static_cast< tools::Long >(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp) );
1186         }
1187         else if ( rValue.Name == "ViewAreaLeft" )
1188         {
1189             rValue.Value >>= nTmp;
1190             aRect.setX( static_cast< tools::Long >(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp) );
1191         }
1192         else if ( rValue.Name == "ViewAreaWidth" )
1193         {
1194             rValue.Value >>= nTmp;
1195             Size aSize( aRect.GetSize() );
1196             aSize.setWidth( static_cast< tools::Long >(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp) );
1197             aRect.SetSize( aSize );
1198         }
1199         else if ( rValue.Name == "ViewAreaHeight" )
1200         {
1201             rValue.Value >>= nTmp;
1202             Size aSize( aRect.GetSize() );
1203             aSize.setHeight( static_cast< tools::Long >(bTwip ? sanitiseMm100ToTwip(nTmp) : nTmp) );
1204             aRect.SetSize( aSize );
1205         }
1206         else if ( rValue.Name == "ShowRedlineChanges" )
1207         {
1208             bShowRedlineChanges = *o3tl::doAccess<bool>(rValue.Value);
1209             bChangeShowRedline = true;
1210         }
1211 // Headers and footers are not displayed in BrowseView anymore
1212         else if ( rValue.Name == "InBrowseMode" )
1213         {
1214             bBrowseMode = *o3tl::doAccess<bool>(rValue.Value);
1215             bChangeBrowseMode = true;
1216         }
1217     }
1218     if( pDoc->GetDocShell() )
1219         pDoc->GetDocShell()->SetVisArea ( aRect );
1220 
1221     if (bChangeBrowseMode)
1222         pDoc->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, bBrowseMode );
1223 
1224     if (bChangeShowRedline)
1225         GetTextImport()->SetShowChanges( bShowRedlineChanges );
1226 }
1227 
1228 // Note: this will be called only if there are OOo elements in settings.xml.
1229 // So if a setting is missing there we can assume that it was written
1230 // by an OOo/LO version that is older than the introduction of the setting!
SetConfigurationSettings(const Sequence<PropertyValue> & aConfigProps)1231 void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aConfigProps)
1232 {
1233     // this method will modify the document directly -> lock SolarMutex
1234     SolarMutexGuard aGuard;
1235 
1236     Reference< lang::XMultiServiceFactory > xFac( GetModel(), UNO_QUERY );
1237     if( !xFac.is() )
1238         return;
1239 
1240     Reference< XPropertySet > xProps( xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY );
1241     if( !xProps.is() )
1242         return;
1243 
1244     Reference< XPropertySetInfo > xInfo( xProps->getPropertySetInfo() );
1245     if( !xInfo.is() )
1246         return;
1247 
1248     std::unordered_set< OUString > aExcludeAlways;
1249     aExcludeAlways.insert("LinkUpdateMode");
1250     // this should contain things that are actually user-settable, via Tools->Options
1251     std::unordered_set< OUString > aExcludeWhenNotLoadingUserSettings {
1252         "ForbiddenCharacters",
1253         "IsKernAsianPunctuation",
1254         "CharacterCompressionType",
1255         "FieldAutoUpdate",
1256         "ChartAutoUpdate",
1257         "AddParaTableSpacing",
1258         "AddParaTableSpacingAtStart",
1259         "PrintAnnotationMode",
1260         "PrintBlackFonts",
1261         "PrintControls",
1262         "PrintDrawings",
1263         "PrintGraphics",
1264         "PrintHiddenText",
1265         "PrintLeftPages",
1266         "PrintPageBackground",
1267         "PrintProspect",
1268         "PrintReversed",
1269         "PrintRightPages",
1270         "PrintFaxName",
1271         "PrintPaperFromSetup",
1272         "PrintTables",
1273         "PrintTextPlaceholder",
1274         "PrintSingleJobs",
1275         "UpdateFromTemplate",
1276         "PrinterIndependentLayout",
1277         "PrintEmptyPages",
1278         "ConsiderTextWrapOnObjPos",
1279         "DoNotJustifyLinesWithManualBreak",
1280         "ProtectForm",
1281         "MsWordCompTrailingBlanks",
1282         "SubtractFlysAnchoredAtFlys",
1283         "EmptyDbFieldHidesPara"
1284     };
1285 
1286     SvtSaveOptions aSaveOpt;
1287     bool bAreUserSettingsFromDocument = aSaveOpt.IsLoadUserSettings();
1288 
1289     // for some properties we don't want to use the application
1290     // default if they're missing. So we watch for them in the loop
1291     // below, and set them if not found
1292     bool bPrinterIndependentLayout = false;
1293     bool bUseOldNumbering = false;
1294     bool bAddExternalLeading = false;
1295     bool bAddParaSpacingToTableCells = false;
1296     bool bAddParaLineSpacingToTableCells = false;
1297     bool bUseFormerLineSpacing = false;
1298     bool bUseFormerObjectPositioning = false;
1299     bool bUseFormerTextWrapping = false;
1300     bool bConsiderWrapOnObjPos = false;
1301     bool bIgnoreFirstLineIndentInNumbering = false;
1302     bool bDoNotJustifyLinesWithManualBreak = false;
1303     bool bDoNotResetParaAttrsForNumFont    = false;
1304     bool bLoadReadonly = false;
1305     bool bDoNotCaptureDrawObjsOnPage( false );
1306     bool bClipAsCharacterAnchoredWriterFlyFrames( false );
1307     bool bUnixForceZeroExtLeading = false;
1308     bool bSmallCapsPercentage66 = false;
1309     bool bTabOverflow = false;
1310     bool bUnbreakableNumberings = false;
1311     bool bClippedPictures = false;
1312     bool bBackgroundParaOverDrawings = false;
1313     bool bTabOverMargin = false;
1314     bool bTabOverMarginValue = false;
1315     bool bPropLineSpacingShrinksFirstLine = false;
1316     bool bSubtractFlysAnchoredAtFlys = false;
1317     bool bEmptyDbFieldHidesPara = false;
1318     bool bCollapseEmptyCellPara = false;
1319 
1320     const PropertyValue* currentDatabaseDataSource = nullptr;
1321     const PropertyValue* currentDatabaseCommand = nullptr;
1322     const PropertyValue* currentDatabaseCommandType = nullptr;
1323     const PropertyValue* embeddedDatabaseName = nullptr;
1324 
1325     for( const PropertyValue& rValue : aConfigProps )
1326     {
1327         bool bSet = aExcludeAlways.find(rValue.Name) == aExcludeAlways.end();
1328         if( bSet && !bAreUserSettingsFromDocument
1329             && (aExcludeWhenNotLoadingUserSettings.find(rValue.Name)
1330                 != aExcludeWhenNotLoadingUserSettings.end()) )
1331         {
1332             bSet = false;
1333         }
1334 
1335         if( bSet )
1336         {
1337             try
1338             {
1339                 if( xInfo->hasPropertyByName( rValue.Name ) )
1340                 {
1341                     if( rValue.Name == "RedlineProtectionKey" )
1342                     {
1343                         Sequence<sal_Int8> aKey;
1344                         rValue.Value >>= aKey;
1345                         GetTextImport()->SetChangesProtectionKey( aKey );
1346                     }
1347                     else
1348                     {
1349                         // HACK: Setting these out of order does not work.
1350                         if( rValue.Name == "CurrentDatabaseDataSource" )
1351                             currentDatabaseDataSource = &rValue;
1352                         else if( rValue.Name == "CurrentDatabaseCommand" )
1353                             currentDatabaseCommand = &rValue;
1354                         else if( rValue.Name == "CurrentDatabaseCommandType" )
1355                             currentDatabaseCommandType = &rValue;
1356                         else if (rValue.Name == "EmbeddedDatabaseName")
1357                             embeddedDatabaseName = &rValue;
1358                         else
1359                             xProps->setPropertyValue( rValue.Name, rValue.Value );
1360                     }
1361                 }
1362 
1363                 // did we find any of the non-default cases?
1364                 if ( rValue.Name == "PrinterIndependentLayout" )
1365                     bPrinterIndependentLayout = true;
1366                 else if ( rValue.Name == "AddExternalLeading" )
1367                     bAddExternalLeading = true;
1368                 else if ( rValue.Name == "AddParaSpacingToTableCells" )
1369                     bAddParaSpacingToTableCells = true;
1370                 else if ( rValue.Name == "AddParaLineSpacingToTableCells" )
1371                     bAddParaLineSpacingToTableCells = true;
1372                 else if ( rValue.Name == "UseFormerLineSpacing" )
1373                     bUseFormerLineSpacing = true;
1374                 else if ( rValue.Name == "UseFormerObjectPositioning" )
1375                     bUseFormerObjectPositioning = true;
1376                 else if ( rValue.Name == "UseFormerTextWrapping" )
1377                     bUseFormerTextWrapping = true;
1378                 else if ( rValue.Name == "UseOldNumbering" )
1379                     bUseOldNumbering = true;
1380                 else if ( rValue.Name == "ConsiderTextWrapOnObjPos" )
1381                     bConsiderWrapOnObjPos = true;
1382                 else if ( rValue.Name == "IgnoreFirstLineIndentInNumbering" )
1383                     bIgnoreFirstLineIndentInNumbering = true;
1384                 else if ( rValue.Name == "DoNotJustifyLinesWithManualBreak" )
1385                     bDoNotJustifyLinesWithManualBreak = true;
1386                 else if ( rValue.Name == "DoNotResetParaAttrsForNumFont" )
1387                     bDoNotResetParaAttrsForNumFont = true;
1388                 else if ( rValue.Name == "LoadReadonly" )
1389                     bLoadReadonly = true;
1390                 else if ( rValue.Name == "DoNotCaptureDrawObjsOnPage" )
1391                     bDoNotCaptureDrawObjsOnPage = true;
1392                 else if ( rValue.Name == "ClipAsCharacterAnchoredWriterFlyFrames" )
1393                     bClipAsCharacterAnchoredWriterFlyFrames = true;
1394                 else if ( rValue.Name == "UnxForceZeroExtLeading" )
1395                     bUnixForceZeroExtLeading = true;
1396                 else if ( rValue.Name == "SmallCapsPercentage66" )
1397                     bSmallCapsPercentage66 = true;
1398                 else if ( rValue.Name == "TabOverflow" )
1399                     bTabOverflow = true;
1400                 else if ( rValue.Name == "UnbreakableNumberings" )
1401                     bUnbreakableNumberings = true;
1402                 else if ( rValue.Name == "ClippedPictures" )
1403                     bClippedPictures = true;
1404                 else if ( rValue.Name == "BackgroundParaOverDrawings" )
1405                     bBackgroundParaOverDrawings = true;
1406                 else if ( rValue.Name == "TabOverMargin" )
1407                 {
1408                     bTabOverMargin = true;
1409                     rValue.Value >>= bTabOverMarginValue;
1410                 }
1411                 else if ( rValue.Name == "PropLineSpacingShrinksFirstLine" )
1412                     bPropLineSpacingShrinksFirstLine = true;
1413                 else if (rValue.Name == "SubtractFlysAnchoredAtFlys")
1414                     bSubtractFlysAnchoredAtFlys = true;
1415                 else if (rValue.Name == "EmptyDbFieldHidesPara")
1416                     bEmptyDbFieldHidesPara = true;
1417                 else if (rValue.Name == "CollapseEmptyCellPara")
1418                     bCollapseEmptyCellPara = true;
1419             }
1420             catch( Exception& )
1421             {
1422                 TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
1423             }
1424         }
1425     }
1426 
1427     try
1428     {
1429         if( currentDatabaseDataSource != nullptr )
1430             xProps->setPropertyValue( currentDatabaseDataSource->Name, currentDatabaseDataSource->Value );
1431         if( currentDatabaseCommand != nullptr )
1432             xProps->setPropertyValue( currentDatabaseCommand->Name, currentDatabaseCommand->Value );
1433         if( currentDatabaseCommandType != nullptr )
1434             xProps->setPropertyValue( currentDatabaseCommandType->Name, currentDatabaseCommandType->Value );
1435         if (embeddedDatabaseName)
1436             xProps->setPropertyValue(embeddedDatabaseName->Name, embeddedDatabaseName->Value);
1437     } catch( Exception& )
1438     {
1439         TOOLS_WARN_EXCEPTION( "sw", "SwXMLImport::SetConfigurationSettings" );
1440     }
1441 
1442     // finally, treat the non-default cases
1443     // introduce boolean, that indicates a document, written by version prior SO8.
1444     // If user settings are not loaded, we can't know if this is an old document. Better to assume no?
1445     const bool bDocumentPriorSO8 = !bConsiderWrapOnObjPos && bAreUserSettingsFromDocument;
1446 
1447     // Use old behaviour if this setting didn't exist, but only if this setting is being read from the document.
1448     // (Obviously the setting doesn't exist if we are explicitly ignoring it, so then stick with program/user defaults)
1449     if(!bPrinterIndependentLayout && bAreUserSettingsFromDocument)
1450     {
1451         xProps->setPropertyValue( "PrinterIndependentLayout", Any(sal_Int16(document::PrinterIndependentLayout::DISABLED)) );
1452     }
1453 
1454     if( ! bAddExternalLeading )
1455     {
1456         xProps->setPropertyValue( "AddExternalLeading", makeAny( false ) );
1457     }
1458 
1459     if( ! bUseFormerLineSpacing )
1460     {
1461         xProps->setPropertyValue( "UseFormerLineSpacing", makeAny( true ) );
1462     }
1463 
1464     if( !bUseFormerObjectPositioning )
1465     {
1466         xProps->setPropertyValue( "UseFormerObjectPositioning", makeAny( true ) );
1467     }
1468 
1469     if( !bUseOldNumbering )
1470     {
1471         xProps->setPropertyValue( "UseOldNumbering", makeAny(true) );
1472     }
1473 
1474     if( !bAddParaSpacingToTableCells )
1475     {
1476         xProps->setPropertyValue( "AddParaSpacingToTableCells",
1477             makeAny( false ) );
1478     }
1479     if (!bAddParaLineSpacingToTableCells)
1480     {
1481         xProps->setPropertyValue("AddParaLineSpacingToTableCells", makeAny(false));
1482     }
1483 
1484     if( !bUseFormerTextWrapping )
1485     {
1486         xProps->setPropertyValue( "UseFormerTextWrapping", makeAny( true ) );
1487     }
1488 
1489     if (!bConsiderWrapOnObjPos && bAreUserSettingsFromDocument)
1490     {
1491         xProps->setPropertyValue( "ConsiderTextWrapOnObjPos", makeAny( false ) );
1492     }
1493 
1494     // #i47448#
1495     // For SO7pp4, part of the 'new numbering' stuff has been backported from
1496     // SO8. Unfortunately, only part of it and by using the same compatibility option
1497     // like in SO8. Therefore documents generated with SO7pp4, containing
1498     // numbered paragraphs with first line indent differ between SO7pp4 and
1499     // SO8. In order to fix this for SO8pp1, I introduce a new compatibility
1500     // flag 'bIgnoreFirstLineIndentInNumbering'. This flag has to be set for all
1501     // documents < SO8, but not for SO8. So if the property is not present, the
1502     // flag will be set to 'true'. SO8 documents surely have the
1503     // 'ConsiderWrapOnObjPos' property set (no matter if 'true' or 'false'),
1504     // therefore the correct condition to set this flag is this:
1505     if( !bIgnoreFirstLineIndentInNumbering && bDocumentPriorSO8 )
1506     {
1507         xProps->setPropertyValue( "IgnoreFirstLineIndentInNumbering",
1508             makeAny( true ) );
1509     }
1510 
1511     // This flag has to be set for all documents < SO8
1512     if ( !bDoNotJustifyLinesWithManualBreak && bDocumentPriorSO8 )
1513     {
1514         xProps->setPropertyValue( "DoNotJustifyLinesWithManualBreak",
1515             makeAny( true ) );
1516     }
1517 
1518     // This flag has to be set for all documents < SO8
1519     if ( !bDoNotResetParaAttrsForNumFont && bDocumentPriorSO8 )
1520     {
1521         xProps->setPropertyValue( "DoNotResetParaAttrsForNumFont",
1522             makeAny( true ) );
1523     }
1524 
1525     if ( !bLoadReadonly )
1526     {
1527         xProps->setPropertyValue( "LoadReadonly", makeAny( false ) );
1528     }
1529 
1530     // This flag has to be set for all documents < SO8
1531     if ( !bDoNotCaptureDrawObjsOnPage && bDocumentPriorSO8 )
1532     {
1533         xProps->setPropertyValue( "DoNotCaptureDrawObjsOnPage",
1534             makeAny( true ) );
1535     }
1536 
1537     // This flag has to be set for all documents < SO8
1538     if ( !bClipAsCharacterAnchoredWriterFlyFrames && bDocumentPriorSO8 )
1539     {
1540         xProps->setPropertyValue( "ClipAsCharacterAnchoredWriterFlyFrames",
1541             makeAny( true ) );
1542     }
1543 
1544     if ( !bUnixForceZeroExtLeading )
1545     {
1546         xProps->setPropertyValue( "UnxForceZeroExtLeading", makeAny( true ) );
1547     }
1548 
1549     // Old LO versions had 66 as the value for small caps percentage, later changed to 80.
1550     // In order to keep backwards compatibility, SmallCapsPercentage66 option is written to .odt
1551     // files, and the default for new documents is 'false'. Files without this option
1552     // are considered to be old files, so set the compatibility option too.
1553     if ( !bSmallCapsPercentage66 )
1554     {
1555         xProps->setPropertyValue( "SmallCapsPercentage66", makeAny( true ) );
1556     }
1557 
1558     if ( !bTabOverflow )
1559     {
1560         xProps->setPropertyValue( "TabOverflow", makeAny( false ) );
1561     }
1562 
1563     if ( !bUnbreakableNumberings )
1564     {
1565         xProps->setPropertyValue( "UnbreakableNumberings", makeAny( false ) );
1566     }
1567 
1568     if ( !bClippedPictures )
1569     {
1570         xProps->setPropertyValue( "ClippedPictures", makeAny( false ) );
1571     }
1572 
1573     if ( !bBackgroundParaOverDrawings )
1574         xProps->setPropertyValue("BackgroundParaOverDrawings", makeAny( false ) );
1575 
1576     if ( !bTabOverMargin )
1577         xProps->setPropertyValue("TabOverMargin", makeAny( false ) );
1578 
1579     if (bTabOverMarginValue)
1580         // Let TabOverMargin imply the new default for
1581         // PrinterIndependentLayout, knowing the first is set by Word import
1582         // filters and Word defaults to our new default as well.
1583         xProps->setPropertyValue(
1584             "PrinterIndependentLayout",
1585             uno::Any(document::PrinterIndependentLayout::HIGH_RESOLUTION));
1586 
1587     if (!bPropLineSpacingShrinksFirstLine)
1588         xProps->setPropertyValue("PropLineSpacingShrinksFirstLine", makeAny(false));
1589 
1590     if (!bSubtractFlysAnchoredAtFlys && bAreUserSettingsFromDocument)
1591         xProps->setPropertyValue("SubtractFlysAnchoredAtFlys", makeAny(true));
1592 
1593     if (!bEmptyDbFieldHidesPara && bAreUserSettingsFromDocument)
1594         xProps->setPropertyValue("EmptyDbFieldHidesPara", makeAny(false));
1595 
1596     if (!bCollapseEmptyCellPara)
1597         xProps->setPropertyValue("CollapseEmptyCellPara", makeAny(false));
1598 
1599     SwDoc *pDoc = getDoc();
1600     SfxPrinter *pPrinter = pDoc->getIDocumentDeviceAccess().getPrinter( false );
1601     if( pPrinter )
1602     {
1603         // If the printer is known, then the OLE objects will
1604         // already have correct sizes, and we don't have to call
1605         // PrtOLENotify again. Otherwise we have to call it.
1606         // The flag might be set from setting the printer, so it
1607         // it is required to clear it.
1608         pDoc->SetOLEPrtNotifyPending( !pPrinter->IsKnown() );
1609     }
1610 }
1611 
SetDocumentSpecificSettings(const OUString & _rSettingsGroupName,const Sequence<PropertyValue> & _rSettings)1612 void SwXMLImport::SetDocumentSpecificSettings(
1613     const OUString& _rSettingsGroupName,
1614     const Sequence< PropertyValue>& _rSettings )
1615 {
1616     // the only doc-specific settings group we know so far are the XForms settings
1617     if ( !IsXMLToken( _rSettingsGroupName, XML_XFORM_MODEL_SETTINGS ) )
1618         return;
1619 
1620     // preserve the settings for a later iteration - we are currently reading the settings.xml,
1621     // the content.xml will be read later, by another instance of SwXMLImport
1622     OSL_ENSURE( m_xLateInitSettings.is(), "SwXMLImport::SetDocumentSpecificSettings: no storage for those settings!" );
1623     if ( !m_xLateInitSettings.is() )
1624         return;
1625 
1626     try
1627     {
1628         if ( m_xLateInitSettings->hasByName( _rSettingsGroupName ) )
1629         {
1630             m_xLateInitSettings->replaceByName( _rSettingsGroupName, makeAny( _rSettings ) );
1631             OSL_FAIL( "SwXMLImport::SetDocumentSpecificSettings: already have settings for this model!" );
1632         }
1633         else
1634             m_xLateInitSettings->insertByName( _rSettingsGroupName, makeAny( _rSettings ) );
1635     }
1636     catch( const Exception& )
1637     {
1638     }
1639 }
1640 
initialize(const Sequence<Any> & aArguments)1641 void SwXMLImport::initialize(
1642     const Sequence<Any>& aArguments )
1643 {
1644     // delegate to super class
1645     SvXMLImport::initialize(aArguments);
1646 
1647     // we are only looking for a NamedValue "LateInitSettings"
1648     for(const auto& rArgument : aArguments)
1649     {
1650         beans::NamedValue aNamedValue;
1651         if ( rArgument >>= aNamedValue )
1652         {
1653             if (aNamedValue.Name == "LateInitSettings")
1654             {
1655                 OSL_VERIFY( aNamedValue.Value >>= m_xLateInitSettings );
1656             }
1657         }
1658     }
1659 }
1660 
GetDocFromXMLImport(SvXMLImport const & rImport)1661 SwDoc* SwImport::GetDocFromXMLImport( SvXMLImport const & rImport )
1662 {
1663     auto pTextDoc = comphelper::getUnoTunnelImplementation<SwXTextDocument>(rImport.GetModel());
1664     assert( pTextDoc );
1665     assert( pTextDoc->GetDocShell() );
1666     SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
1667     OSL_ENSURE( pDoc, "Where is my document?" );
1668     return pDoc;
1669 }
1670 
initXForms()1671 void SwXMLImport::initXForms()
1672 {
1673     // obtain SwDoc
1674     auto pXTextDocument = comphelper::getUnoTunnelImplementation<SwXTextDocument>(GetModel());
1675     if( pXTextDocument == nullptr )
1676         return;
1677 
1678     SwDoc *pDoc = pXTextDocument->GetDocShell()->GetDoc();
1679 
1680     // init XForms (if not already done)
1681     // (no default model, since we'll load the models)
1682     if( ! pDoc->isXForms() )
1683         pDoc->initXForms( false );
1684 
1685     m_bInititedXForms = true;
1686 }
1687 
getDoc()1688 SwDoc* SwXMLImport::getDoc()
1689 {
1690     if( m_pDoc != nullptr )
1691         return m_pDoc;
1692     Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY );
1693     Reference < XText > xText = xTextDoc->getText();
1694     Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY);
1695     assert( xTextTunnel.is());
1696     SwXText *pText = reinterpret_cast< SwXText *>(
1697             sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() )));
1698     assert( pText != nullptr );
1699     m_pDoc = pText->GetDoc();
1700     assert( m_pDoc != nullptr );
1701     return m_pDoc;
1702 }
1703 
getDoc() const1704 const SwDoc* SwXMLImport::getDoc() const
1705 {
1706     return const_cast< SwXMLImport* >( this )->getDoc();
1707 }
1708 
1709 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 &)1710 com_sun_star_comp_Writer_XMLOasisImporter_get_implementation(css::uno::XComponentContext* context,
1711         css::uno::Sequence<css::uno::Any> const &)
1712 {
1713     return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisImporter",
1714                 SvXMLImportFlags::ALL));
1715 }
1716 
1717 
1718 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 &)1719 com_sun_star_comp_Writer_XMLOasisStylesImporter_get_implementation(css::uno::XComponentContext* context,
1720         css::uno::Sequence<css::uno::Any> const &)
1721 {
1722     return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisStylesImporter",
1723                 SvXMLImportFlags::STYLES | SvXMLImportFlags::MASTERSTYLES | SvXMLImportFlags::AUTOSTYLES |
1724                 SvXMLImportFlags::FONTDECLS));
1725 }
1726 
1727 
1728 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 &)1729 com_sun_star_comp_Writer_XMLOasisContentImporter_get_implementation(css::uno::XComponentContext* context,
1730         css::uno::Sequence<css::uno::Any> const &)
1731 {
1732     return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisContentImporter",
1733                 SvXMLImportFlags::CONTENT | SvXMLImportFlags::SCRIPTS | SvXMLImportFlags::AUTOSTYLES |
1734                 SvXMLImportFlags::FONTDECLS));
1735 }
1736 
1737 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 &)1738 com_sun_star_comp_Writer_XMLOasisMetaImporter_get_implementation(css::uno::XComponentContext* context,
1739         css::uno::Sequence<css::uno::Any> const &)
1740 {
1741     return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisMetaImporter",
1742                 SvXMLImportFlags::META));
1743 }
1744 
1745 
1746 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 &)1747 com_sun_star_comp_Writer_XMLOasisSettingsImporter_get_implementation(css::uno::XComponentContext* context,
1748         css::uno::Sequence<css::uno::Any> const &)
1749 {
1750     return cppu::acquire(new SwXMLImport(context, "com.sun.star.comp.Writer.XMLOasisSettingsImporter",
1751                 SvXMLImportFlags::SETTINGS));
1752 }
1753 
TestImportFODT(SvStream & rStream)1754 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODT(SvStream &rStream)
1755 {
1756     SwGlobals::ensure();
1757 
1758     SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
1759     xDocSh->DoInitNew();
1760     uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1761 
1762     uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1763     uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1764     uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.XmlFilterAdaptor"), uno::UNO_SET_THROW);
1765 
1766     css::uno::Sequence<OUString> aUserData
1767     {
1768         "com.sun.star.comp.filter.OdfFlatXml",
1769         "",
1770         "com.sun.star.comp.Writer.XMLOasisImporter",
1771         "com.sun.star.comp.Writer.XMLOasisExporter",
1772         "",
1773         "",
1774         "true"
1775     };
1776     uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
1777     {
1778         { "UserData", uno::Any(aUserData) },
1779     }));
1780     css::uno::Sequence<uno::Any> aOuterArgs(1);
1781     aOuterArgs[0] <<= aAdaptorArgs;
1782 
1783     uno::Reference<lang::XInitialization> xInit(xInterface, uno::UNO_QUERY_THROW);
1784     xInit->initialize(aOuterArgs);
1785 
1786     uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
1787     uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1788     {
1789         { "InputStream", uno::Any(xStream) },
1790         { "URL", uno::Any(OUString("private:stream")) },
1791     }));
1792     xImporter->setTargetDocument(xModel);
1793 
1794     uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
1795     //SetLoading hack because the document properties will be re-initted
1796     //by the xml filter and during the init, while it's considered uninitialized,
1797     //setting a property will inform the document it's modified, which attempts
1798     //to update the properties, which throws cause the properties are uninitialized
1799     xDocSh->SetLoading(SfxLoadedFlags::NONE);
1800     bool ret = xFilter->filter(aArgs);
1801     xDocSh->SetLoading(SfxLoadedFlags::ALL);
1802 
1803     xDocSh->DoClose();
1804 
1805     return ret;
1806 }
1807 
TestImportDOCX(SvStream & rStream)1808 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportDOCX(SvStream &rStream)
1809 {
1810     SwGlobals::ensure();
1811 
1812     SfxObjectShellLock xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL));
1813     xDocSh->DoInitNew();
1814     uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
1815 
1816     uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1817     uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
1818 
1819     uno::Reference<document::XFilter> xFilter(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_QUERY_THROW);
1820 
1821     uno::Reference<document::XImporter> xImporter(xFilter, uno::UNO_QUERY_THROW);
1822     uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1823     {
1824         { "InputStream", uno::makeAny(xStream) },
1825         { "InputMode", uno::makeAny(true) },
1826     }));
1827     xImporter->setTargetDocument(xModel);
1828 
1829     //SetLoading hack because the document properties will be re-initted
1830     //by the xml filter and during the init, while it's considered uninitialized,
1831     //setting a property will inform the document it's modified, which attempts
1832     //to update the properties, which throws cause the properties are uninitialized
1833     xDocSh->SetLoading(SfxLoadedFlags::NONE);
1834     bool ret = false;
1835     try
1836     {
1837         ret = xFilter->filter(aArgs);
1838     }
1839     catch (...)
1840     {
1841     }
1842     xDocSh->SetLoading(SfxLoadedFlags::ALL);
1843 
1844     xDocSh->DoClose();
1845 
1846     return ret;
1847 }
1848 
1849 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1850