xref: /core/sw/source/uibase/uno/unotxdoc.cxx (revision c2bcbd36)
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 <officecfg/Office/Common.hxx>
22 #include <comphelper/string.hxx>
23 #include <AnnotationWin.hxx>
24 #include <o3tl/any.hxx>
25 #include <utility>
26 #include <vcl/virdev.hxx>
27 #include <vcl/sysdata.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/print.hxx>
30 #include <sfx2/bindings.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/lokhelper.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/printer.hxx>
35 #include <toolkit/helper/vclunohelper.hxx>
36 #include <toolkit/awt/vclxdevice.hxx>
37 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
38 #include <sfx2/lokcomponenthelpers.hxx>
39 #include <sfx2/ipclient.hxx>
40 #include <editeng/svxacorr.hxx>
41 #include <editeng/acorrcfg.hxx>
42 #include <cmdid.h>
43 #include <swtypes.hxx>
44 #include <wdocsh.hxx>
45 #include <wrtsh.hxx>
46 #include <pview.hxx>
47 #include <viewsh.hxx>
48 #include <pvprtdat.hxx>
49 #include <printdata.hxx>
50 #include <pagefrm.hxx>
51 #include <rootfrm.hxx>
52 #include <svl/stritem.hxx>
53 #include <unotxdoc.hxx>
54 #include <svl/numformat.hxx>
55 #include <svl/numuno.hxx>
56 #include <fldbas.hxx>
57 #include <unomap.hxx>
58 #include <unotextbodyhf.hxx>
59 #include <unotextrange.hxx>
60 #include <unotextcursor.hxx>
61 #include <unosett.hxx>
62 #include <unocoll.hxx>
63 #include <unoredlines.hxx>
64 #include <unosrch.hxx>
65 #include <sfx2/request.hxx>
66 #include <sfx2/objsh.hxx>
67 #include <unoprnms.hxx>
68 #include <unostyle.hxx>
69 #include <unodraw.hxx>
70 #include <svl/eitem.hxx>
71 #include <unotools/datetime.hxx>
72 #include <unocrsr.hxx>
73 #include <unofieldcoll.hxx>
74 #include <unoidxcoll.hxx>
75 #include <unocrsrhelper.hxx>
76 #include <globdoc.hxx>
77 #include <viewopt.hxx>
78 #include <unochart.hxx>
79 #include <charatr.hxx>
80 #include <svx/xmleohlp.hxx>
81 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
82 #include <com/sun/star/lang/DisposedException.hpp>
83 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
84 #include <com/sun/star/lang/NoSupportException.hpp>
85 #include <com/sun/star/beans/PropertyAttribute.hpp>
86 #include <com/sun/star/beans/XFastPropertySet.hpp>
87 #include <com/sun/star/beans/XPropertyAccess.hpp>
88 #include <com/sun/star/document/RedlineDisplayType.hpp>
89 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
90 #include <com/sun/star/frame/XController.hpp>
91 #include <com/sun/star/frame/XFrame.hpp>
92 #include <com/sun/star/script/XInvocation.hpp>
93 #include <com/sun/star/view/XSelectionSupplier.hpp>
94 #include <sfx2/linkmgr.hxx>
95 #include <svx/unofill.hxx>
96 #include <swmodule.hxx>
97 #include <docstat.hxx>
98 #include <modcfg.hxx>
99 #include <ndtxt.hxx>
100 #include <strings.hrc>
101 #include <bitmaps.hlst>
102 #include "unodefaults.hxx"
103 #include "SwXDocumentSettings.hxx"
104 #include <doc.hxx>
105 #include <IDocumentSettingAccess.hxx>
106 #include <IDocumentDeviceAccess.hxx>
107 #include <IDocumentDrawModelAccess.hxx>
108 #include <IDocumentChartDataProviderAccess.hxx>
109 #include <IDocumentLinksAdministration.hxx>
110 #include <IDocumentRedlineAccess.hxx>
111 #include <IDocumentFieldsAccess.hxx>
112 #include <IDocumentStatistics.hxx>
113 #include <IDocumentStylePoolAccess.hxx>
114 #include <IDocumentState.hxx>
115 #include <drawdoc.hxx>
116 #include <SwStyleNameMapper.hxx>
117 #include <osl/file.hxx>
118 #include <comphelper/lok.hxx>
119 #include <comphelper/propertyvalue.hxx>
120 #include <comphelper/storagehelper.hxx>
121 #include <cppuhelper/supportsservice.hxx>
122 #include <sfx2/dispatch.hxx>
123 #include <swruler.hxx>
124 #include <docufld.hxx>
125 
126 #include <EnhancedPDFExportHelper.hxx>
127 #include <numrule.hxx>
128 
129 #include <editeng/langitem.hxx>
130 #include <docary.hxx>
131 #include <i18nlangtag/languagetag.hxx>
132 #include <i18nutil/searchopt.hxx>
133 
134 #include <charfmt.hxx>
135 #include <fmtcol.hxx>
136 #include <istyleaccess.hxx>
137 
138 #include <swatrset.hxx>
139 #include <view.hxx>
140 #include <viscrs.hxx>
141 #include <srcview.hxx>
142 #include <edtwin.hxx>
143 #include <swdtflvr.hxx>
144 #include <PostItMgr.hxx>
145 
146 #include <svtools/langtab.hxx>
147 #include <map>
148 #include <set>
149 #include <vector>
150 
151 #include <editeng/eeitem.hxx>
152 #include <editeng/editeng.hxx>
153 #include <editeng/editview.hxx>
154 #include <svx/svdoutl.hxx>
155 #include <svx/svdview.hxx>
156 #include <comphelper/interfacecontainer4.hxx>
157 #include <comphelper/servicehelper.hxx>
158 #include <memory>
159 #include <redline.hxx>
160 #include <DocumentRedlineManager.hxx>
161 #include <xmloff/odffields.hxx>
162 #include <tools/json_writer.hxx>
163 #include <tools/UnitConversion.hxx>
164 
165 #include <svx/svdpage.hxx>
166 #include <o3tl/string_view.hxx>
167 #include <comphelper/sequenceashashmap.hxx>
168 
169 #include <IDocumentOutlineNodes.hxx>
170 #include <SearchResultLocator.hxx>
171 #include <textcontentcontrol.hxx>
172 #include <unocontentcontrol.hxx>
173 
174 using namespace ::com::sun::star;
175 using namespace ::com::sun::star::text;
176 using namespace ::com::sun::star::i18n;
177 using namespace ::com::sun::star::uno;
178 using namespace ::com::sun::star::beans;
179 using namespace ::com::sun::star::lang;
180 using namespace ::com::sun::star::container;
181 using namespace ::com::sun::star::document;
182 using ::osl::FileBase;
183 
184 static std::unique_ptr<SwPrintUIOptions> lcl_GetPrintUIOptions(
185     SwDocShell * pDocShell,
186     const SfxViewShell * pView )
187 {
188     if (!pDocShell)
189         return nullptr;
190 
191     const bool bWebDoc      = nullptr != dynamic_cast< const SwWebDocShell * >(pDocShell);
192     const bool bSwSrcView   = nullptr != dynamic_cast< const SwSrcView * >(pView);
193     const SwView * pSwView = dynamic_cast< const SwView * >(pView);
194     const bool bHasSelection    = pSwView && pSwView->HasSelection( false );  // check for any selection, not just text selection
195     const bool bHasPostIts      = sw_GetPostIts(pDocShell->GetDoc()->getIDocumentFieldsAccess(), nullptr);
196 
197     // get default values to use in dialog from documents SwPrintData
198     const SwPrintData &rPrintData = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrintData();
199 
200     // Get current page number
201     sal_uInt16 nCurrentPage = 1;
202     const SwWrtShell* pSh = pDocShell->GetWrtShell();
203     const SwRootFrame *pFrame = nullptr;
204     if (pSh)
205     {
206         SwPaM* pShellCursor = pSh->GetCursor();
207         nCurrentPage = pShellCursor->GetPageNum();
208         pFrame = pSh->GetLayout();
209     }
210     else if (!bSwSrcView)
211     {
212         const SwPagePreview* pPreview = dynamic_cast< const SwPagePreview* >(pView);
213         OSL_ENSURE(pPreview, "Unexpected type of the view shell");
214         if (pPreview)
215         {
216             nCurrentPage = pPreview->GetSelectedPage();
217             pFrame = pPreview->GetViewShell()->GetLayout();
218         }
219     }
220 
221     // If blanks are skipped, account for them in initial page range value
222     if (pFrame && !rPrintData.IsPrintEmptyPages())
223     {
224         sal_uInt16 nMax = nCurrentPage;
225         const SwPageFrame *pPage = dynamic_cast<const SwPageFrame*>(pFrame->Lower());
226         while (pPage && nMax-- > 0)
227         {
228             if (pPage->getFrameArea().Height() == 0)
229                 nCurrentPage--;
230             pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
231         }
232     }
233     return std::make_unique<SwPrintUIOptions>( nCurrentPage, bWebDoc, bSwSrcView, bHasSelection, bHasPostIts, rPrintData );
234 }
235 
236 static SwTextFormatColl *lcl_GetParaStyle(const OUString& rCollName, SwDoc& rDoc)
237 {
238     SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( rCollName );
239     if( !pColl )
240     {
241         const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(
242             rCollName, SwGetPoolIdFromName::TxtColl );
243         if( USHRT_MAX != nId )
244             pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( nId );
245     }
246     return pColl;
247 }
248 
249 static void lcl_DisposeView( SfxViewFrame* pToClose, SwDocShell const * pDocShell )
250 {
251     // check if the view frame still exists
252     SfxViewFrame* pFound = SfxViewFrame::GetFirst( pDocShell, false );
253     while(pFound)
254     {
255         if( pFound == pToClose)
256         {
257             pToClose->DoClose();
258             break;
259         }
260         pFound = SfxViewFrame::GetNext( *pFound, pDocShell, false );
261     }
262 }
263 
264 class SwXTextDocument::Impl
265 {
266 public:
267     std::mutex m_Mutex; // just for OInterfaceContainerHelper4
268     ::comphelper::OInterfaceContainerHelper4<css::util::XRefreshListener> m_RefreshListeners;
269 };
270 
271 const Sequence< sal_Int8 > & SwXTextDocument::getUnoTunnelId()
272 {
273     static const comphelper::UnoIdInit theSwXTextDocumentUnoTunnelId;
274     return theSwXTextDocumentUnoTunnelId.getSeq();
275 }
276 
277 sal_Int64 SAL_CALL SwXTextDocument::getSomething( const Sequence< sal_Int8 >& rId )
278 {
279     if( comphelper::isUnoTunnelId<SwXTextDocument>(rId) )
280     {
281         return comphelper::getSomething_cast(this);
282     }
283     if( comphelper::isUnoTunnelId<SfxObjectShell>(rId) )
284     {
285         return comphelper::getSomething_cast(m_pDocShell);
286     }
287 
288     sal_Int64 nRet = SfxBaseModel::getSomething( rId );
289     if (nRet)
290         return nRet;
291 
292     GetNumberFormatter();
293     if (!m_xNumFormatAgg.is()) // may happen if not valid or no SwDoc
294         return 0;
295     Any aNumTunnel = m_xNumFormatAgg->queryAggregation(cppu::UnoType<XUnoTunnel>::get());
296     Reference<XUnoTunnel> xNumTunnel;
297     aNumTunnel >>= xNumTunnel;
298     return (xNumTunnel.is()) ? xNumTunnel->getSomething(rId) : 0;
299 }
300 
301 Any SAL_CALL SwXTextDocument::queryInterface( const uno::Type& rType )
302 {
303     Any aRet = SwXTextDocumentBaseClass::queryInterface(rType);
304     if ( !aRet.hasValue() )
305         aRet = SfxBaseModel::queryInterface(rType);
306     if ( !aRet.hasValue() &&
307         rType == cppu::UnoType<lang::XMultiServiceFactory>::get())
308     {
309         Reference<lang::XMultiServiceFactory> xTmp = this;
310         aRet <<= xTmp;
311     }
312     if ( !aRet.hasValue() &&
313         rType == cppu::UnoType<tiledrendering::XTiledRenderable>::get())
314     {
315         Reference<tiledrendering::XTiledRenderable> xTmp = this;
316         aRet <<= xTmp;
317     }
318 
319     if ( !aRet.hasValue()
320         && rType != cppu::UnoType<css::document::XDocumentEventBroadcaster>::get()
321         && rType != cppu::UnoType<css::frame::XController>::get()
322         && rType != cppu::UnoType<css::frame::XFrame>::get()
323         && rType != cppu::UnoType<css::script::XInvocation>::get()
324         && rType != cppu::UnoType<css::beans::XFastPropertySet>::get()
325         && rType != cppu::UnoType<css::awt::XWindow>::get())
326     {
327         GetNumberFormatter();
328         if(m_xNumFormatAgg.is())
329             aRet = m_xNumFormatAgg->queryAggregation(rType);
330     }
331     return aRet;
332 }
333 
334 void SAL_CALL SwXTextDocument::acquire()noexcept
335 {
336     SfxBaseModel::acquire();
337 }
338 
339 void SAL_CALL SwXTextDocument::release()noexcept
340 {
341     SfxBaseModel::release();
342 }
343 
344 Sequence< uno::Type > SAL_CALL SwXTextDocument::getTypes()
345 {
346     Sequence< uno::Type > aNumTypes;
347     GetNumberFormatter();
348     if(m_xNumFormatAgg.is())
349     {
350         const uno::Type& rProvType = cppu::UnoType<XTypeProvider>::get();
351         Any aNumProv = m_xNumFormatAgg->queryAggregation(rProvType);
352         Reference<XTypeProvider> xNumProv;
353         if(aNumProv >>= xNumProv)
354         {
355             aNumTypes = xNumProv->getTypes();
356         }
357     }
358     return comphelper::concatSequences(
359             SfxBaseModel::getTypes(),
360             SwXTextDocumentBaseClass::getTypes(),
361             aNumTypes,
362             Sequence {
363                 cppu::UnoType<lang::XMultiServiceFactory>::get(),
364                 cppu::UnoType<tiledrendering::XTiledRenderable>::get()});
365 }
366 
367 SwXTextDocument::SwXTextDocument(SwDocShell* pShell)
368     : SwXTextDocumentBaseClass(pShell)
369     , m_pImpl(new Impl)
370     ,
371     m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_DOCUMENT)),
372     m_pDocShell(pShell),
373     m_bObjectValid(pShell != nullptr),
374     m_pHiddenViewFrame(nullptr),
375     // #i117783#
376     m_bApplyPagePrintSettingsFromXPagePrintable( false )
377 {
378 }
379 
380 SdrModel& SwXTextDocument::getSdrModelFromUnoModel() const
381 {
382     OSL_ENSURE(m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(), "No SdrModel in SwDoc, should not happen");
383     return *m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
384 }
385 
386 SwXTextDocument::~SwXTextDocument()
387 {
388     InitNewDoc();
389     if(m_xNumFormatAgg.is())
390     {
391         Reference< XInterface >  x0;
392         m_xNumFormatAgg->setDelegator(x0);
393         m_xNumFormatAgg = nullptr;
394     }
395     m_pPrintUIOptions.reset();
396     if (m_pRenderData && m_pRenderData->IsViewOptionAdjust())
397     {   // rhbz#827695: this can happen if the last page is not printed
398         // the SwViewShell has been deleted already by SwView::~SwView
399         // FIXME: replace this awful implementation of XRenderable with
400         // something less insane that has its own view
401         m_pRenderData->ViewOptionAdjustCrashPreventionKludge();
402     }
403     m_pRenderData.reset();
404 }
405 
406 SwXDocumentPropertyHelper * SwXTextDocument::GetPropertyHelper ()
407 {
408     if(!mxPropertyHelper.is())
409     {
410         mxPropertyHelper = new SwXDocumentPropertyHelper(*m_pDocShell->GetDoc());
411     }
412     return mxPropertyHelper.get();
413 }
414 
415 void SwXTextDocument::GetNumberFormatter()
416 {
417     if(!IsValid())
418         return;
419 
420     if(!m_xNumFormatAgg.is())
421     {
422         if ( m_pDocShell->GetDoc() )
423         {
424             rtl::Reference<SvNumberFormatsSupplierObj> pNumFormat = new SvNumberFormatsSupplierObj(
425                                 m_pDocShell->GetDoc()->GetNumberFormatter());
426             m_xNumFormatAgg = pNumFormat;
427         }
428         if(m_xNumFormatAgg.is())
429             m_xNumFormatAgg->setDelegator(static_cast<cppu::OWeakObject*>(static_cast<SwXTextDocumentBaseClass*>(this)));
430     }
431     else
432     {
433         const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
434         Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
435         Reference< XUnoTunnel > xNumTunnel;
436         aNumTunnel >>= xNumTunnel;
437         SvNumberFormatsSupplierObj* pNumFormat
438             = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
439         OSL_ENSURE(pNumFormat, "No number formatter available");
440         if (pNumFormat && !pNumFormat->GetNumberFormatter())
441             pNumFormat->SetNumberFormatter(m_pDocShell->GetDoc()->GetNumberFormatter());
442     }
443 }
444 
445 Reference< XText >  SwXTextDocument::getText()
446 {
447     return getBodyText();
448 }
449 
450 rtl::Reference< SwXBodyText > SwXTextDocument::getBodyText()
451 {
452     SolarMutexGuard aGuard;
453     if(!IsValid())
454         throw DisposedException("", static_cast< XTextDocument* >(this));
455     if(!m_xBodyText.is())
456     {
457         m_xBodyText = new SwXBodyText(m_pDocShell->GetDoc());
458     }
459     return m_xBodyText;
460 }
461 
462 void SwXTextDocument::reformat()
463 {
464     SolarMutexGuard aGuard;
465     if(!IsValid())
466         throw DisposedException("", static_cast< XTextDocument* >(this));
467 }
468 
469 void SwXTextDocument::lockControllers()
470 {
471     SolarMutexGuard aGuard;
472     if(!IsValid())
473         throw DisposedException("", static_cast< XTextDocument* >(this));
474 
475     maActionArr.emplace_front(new UnoActionContext(m_pDocShell->GetDoc()));
476 }
477 
478 void SwXTextDocument::unlockControllers()
479 {
480     SolarMutexGuard aGuard;
481     if(maActionArr.empty())
482         throw RuntimeException("Nothing to unlock");
483 
484     maActionArr.pop_front();
485 }
486 
487 sal_Bool SwXTextDocument::hasControllersLocked()
488 {
489     SolarMutexGuard aGuard;
490     return !maActionArr.empty();
491 }
492 
493 Reference< frame::XController >  SwXTextDocument::getCurrentController()
494 {
495     return SfxBaseModel::getCurrentController();
496 }
497 
498 void SwXTextDocument::setCurrentController(const Reference< frame::XController > & xController)
499 {
500     SfxBaseModel::setCurrentController(xController);
501 }
502 
503 Reference< XInterface >  SwXTextDocument::getCurrentSelection()
504 {
505     SolarMutexGuard aGuard;
506     Reference< XInterface >  xRef;
507     if(IsValid())
508     {
509         SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>));
510         while(pView && pView->GetObjectShell() != m_pDocShell)
511         {
512             pView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>));
513         }
514         if(pView)
515         {
516             Any aRef = pView->GetUNOObject()->getSelection();
517             aRef >>= xRef;
518         }
519     }
520     return xRef;
521 }
522 
523 sal_Bool SwXTextDocument::attachResource(const OUString& aURL, const Sequence< beans::PropertyValue >& aArgs)
524 {
525     return SfxBaseModel::attachResource(aURL, aArgs);
526 }
527 
528 OUString SwXTextDocument::getURL()
529 {
530     return SfxBaseModel::getURL();
531 }
532 
533 Sequence< beans::PropertyValue > SwXTextDocument::getArgs()
534 {
535     return SfxBaseModel::getArgs();
536 }
537 
538 void SwXTextDocument::connectController(const Reference< frame::XController > & xController)
539 {
540     SfxBaseModel::connectController(xController);
541 }
542 
543 void SwXTextDocument::disconnectController(const Reference< frame::XController > & xController)
544 {
545     SfxBaseModel::disconnectController(xController);
546 }
547 
548 void SwXTextDocument::dispose()
549 {
550     // Delete UnoActionContexts before deleting the SwDoc, as the first has unowned pointers to the
551     // second.
552     maActionArr.clear();
553 
554     SfxBaseModel::dispose();
555 }
556 
557 void SwXTextDocument::close( sal_Bool bDeliverOwnership )
558 {
559     if(m_pDocShell)
560     {
561         uno::Sequence< uno::Any > aArgs;
562         m_pDocShell->CallAutomationDocumentEventSinks( "Close", aArgs );
563     }
564     SolarMutexGuard aGuard;
565     if(IsValid() && m_pHiddenViewFrame)
566         lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell);
567     SfxBaseModel::close(bDeliverOwnership);
568 }
569 
570 void SwXTextDocument::addEventListener(const Reference< lang::XEventListener > & aListener)
571 {
572     SfxBaseModel::addEventListener(aListener);
573 }
574 
575 void SwXTextDocument::removeEventListener(const Reference< lang::XEventListener > & aListener)
576 {
577     SfxBaseModel::removeEventListener(aListener);
578 }
579 
580 Reference< XPropertySet > SwXTextDocument::getLineNumberingProperties()
581 {
582     SolarMutexGuard aGuard;
583     if(!IsValid())
584         throw DisposedException("", static_cast< XTextDocument* >(this));
585 
586     if(!mxXLineNumberingProperties.is())
587     {
588         mxXLineNumberingProperties = new SwXLineNumberingProperties(m_pDocShell->GetDoc());
589     }
590     return mxXLineNumberingProperties;
591 }
592 
593 Reference< XIndexReplace >  SwXTextDocument::getChapterNumberingRules()
594 {
595     SolarMutexGuard aGuard;
596     if(!IsValid())
597         throw DisposedException("", static_cast< XTextDocument* >(this));
598     if(!mxXChapterNumbering.is())
599     {
600         mxXChapterNumbering = new SwXChapterNumbering(*m_pDocShell);
601     }
602     return mxXChapterNumbering;
603 }
604 
605 Reference< XIndexAccess >  SwXTextDocument::getNumberingRules()
606 {
607     SolarMutexGuard aGuard;
608     if(!IsValid())
609         throw DisposedException("", static_cast< XTextDocument* >(this));
610     if(!mxXNumberingRules.is() )
611     {
612         mxXNumberingRules = new SwXNumberingRulesCollection( m_pDocShell->GetDoc() );
613     }
614     return mxXNumberingRules;
615 }
616 
617 Reference< XIndexAccess >  SwXTextDocument::getFootnotes()
618 {
619     SolarMutexGuard aGuard;
620     if(!IsValid())
621         throw DisposedException("", static_cast< XTextDocument* >(this));
622     if(!mxXFootnotes.is())
623     {
624         mxXFootnotes = new SwXFootnotes(false, m_pDocShell->GetDoc());
625     }
626     return mxXFootnotes;
627 }
628 
629 Reference< XPropertySet >  SAL_CALL
630         SwXTextDocument::getFootnoteSettings()
631 {
632     SolarMutexGuard aGuard;
633     if(!IsValid())
634         throw DisposedException("", static_cast< XTextDocument* >(this));
635     if(!mxXFootnoteSettings.is())
636     {
637         mxXFootnoteSettings = new SwXFootnoteProperties(m_pDocShell->GetDoc());
638     }
639     return mxXFootnoteSettings;
640 }
641 
642 Reference< XIndexAccess >  SwXTextDocument::getEndnotes()
643 {
644     SolarMutexGuard aGuard;
645     if(!IsValid())
646         throw DisposedException("", static_cast< XTextDocument* >(this));
647     if(!mxXEndnotes.is())
648     {
649         mxXEndnotes = new SwXFootnotes(true, m_pDocShell->GetDoc());
650     }
651     return mxXEndnotes;
652 }
653 
654 Reference< XPropertySet >  SwXTextDocument::getEndnoteSettings()
655 {
656     SolarMutexGuard aGuard;
657     if(!IsValid())
658         throw DisposedException("", static_cast< XTextDocument* >(this));
659     if(!mxXEndnoteSettings.is())
660     {
661         mxXEndnoteSettings = new SwXEndnoteProperties(m_pDocShell->GetDoc());
662     }
663     return mxXEndnoteSettings;
664 }
665 
666 Reference< XIndexAccess >  SwXTextDocument::getContentControls()
667 {
668     SolarMutexGuard aGuard;
669     if(!IsValid())
670         throw DisposedException("", static_cast< XTextDocument* >(this));
671     if(!mxXContentControls.is())
672     {
673         mxXContentControls = new SwXContentControls(m_pDocShell->GetDoc());
674     }
675     return mxXContentControls;
676 }
677 
678 Reference< util::XReplaceDescriptor >  SwXTextDocument::createReplaceDescriptor()
679 {
680     return new SwXTextSearch;
681 }
682 
683 SwUnoCursor* SwXTextDocument::CreateCursorForSearch(Reference< XTextCursor > & xCursor)
684 {
685     getText();
686     XText *const pText = m_xBodyText.get();
687     SwXBodyText* pBText = static_cast<SwXBodyText*>(pText);
688     rtl::Reference<SwXTextCursor> pXTextCursor = pBText->CreateTextCursor(true);
689     xCursor.set( static_cast<text::XWordCursor*>(pXTextCursor.get()) );
690 
691     auto& rUnoCursor(pXTextCursor->GetCursor());
692     rUnoCursor.SetRemainInSection(false);
693     return &rUnoCursor;
694 }
695 
696 sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > & xDesc)
697 {
698     SolarMutexGuard aGuard;
699     Reference< XUnoTunnel > xDescTunnel(xDesc, UNO_QUERY_THROW);
700     SwXTextSearch* pSearch;
701     if (!IsValid() || !(pSearch = comphelper::getFromUnoTunnel<SwXTextSearch>(xDescTunnel)))
702         throw DisposedException("", static_cast< XTextDocument* >(this));
703 
704     Reference< XTextCursor >  xCursor;
705     auto pUnoCursor(CreateCursorForSearch(xCursor));
706     int eRanges(FindRanges::InBody|FindRanges::InSelAll);
707 
708     i18nutil::SearchOptions2 aSearchOpt;
709     pSearch->FillSearchOptions( aSearchOpt );
710 
711     SwDocPositions eStart = pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start;
712     SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End;
713 
714     // Search should take place anywhere
715     pUnoCursor->SetRemainInSection(false);
716     sal_Int32 nResult;
717     UnoActionContext aContext(m_pDocShell->GetDoc());
718     //try attribute search first
719     if(pSearch->HasSearchAttributes()||pSearch->HasReplaceAttributes())
720     {
721         SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1,
722                             RES_PARATR_BEGIN, RES_PARATR_END-1,
723                             RES_FRMATR_BEGIN, RES_FRMATR_END-1>  aSearch(m_pDocShell->GetDoc()->GetAttrPool());
724         SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1,
725                             RES_PARATR_BEGIN, RES_PARATR_END-1,
726                             RES_FRMATR_BEGIN, RES_FRMATR_END-1>  aReplace(m_pDocShell->GetDoc()->GetAttrPool());
727         pSearch->FillSearchItemSet(aSearch);
728         pSearch->FillReplaceItemSet(aReplace);
729         bool bCancel;
730         nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles,
731                     eStart, eEnd, bCancel,
732                     static_cast<FindRanges>(eRanges),
733                     !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr,
734                     &aReplace );
735     }
736     else if(pSearch->m_bStyles)
737     {
738         SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc());
739         SwTextFormatColl *pReplaceColl = lcl_GetParaStyle(pSearch->m_sReplaceText, pUnoCursor->GetDoc());
740 
741         bool bCancel;
742         nResult = pUnoCursor->FindFormat(*pSearchColl,
743                     eStart, eEnd, bCancel,
744                     static_cast<FindRanges>(eRanges), pReplaceColl );
745 
746     }
747     else
748     {
749         //todo/mba: assuming that notes should be omitted
750         bool bCancel;
751         nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/,
752             eStart, eEnd, bCancel,
753             static_cast<FindRanges>(eRanges),
754             true );
755     }
756     return nResult;
757 
758 }
759 
760 Reference< util::XSearchDescriptor >  SwXTextDocument::createSearchDescriptor()
761 {
762     return new SwXTextSearch;
763 }
764 
765 // Used for findAll/First/Next
766 
767 SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > & xDesc,
768                                      Reference< XTextCursor > & xCursor,
769                                      bool bAll,
770                                      sal_Int32& nResult,
771                                      Reference< XInterface > const & xLastResult)
772 {
773     const auto pSearch = comphelper::getFromUnoTunnel<SwXTextSearch>(xDesc);
774     if(!IsValid() || !pSearch)
775         return nullptr;
776 
777     auto pUnoCursor(CreateCursorForSearch(xCursor));
778 
779     bool bParentInExtra = false;
780     if(xLastResult.is())
781     {
782         Reference<XUnoTunnel> xCursorTunnel( xLastResult, UNO_QUERY);
783         OTextCursorHelper* pPosCursor = comphelper::getFromUnoTunnel<OTextCursorHelper>(xCursorTunnel);
784         SwPaM* pCursor = pPosCursor ? pPosCursor->GetPaM() : nullptr;
785         if(pCursor)
786         {
787             *pUnoCursor->GetPoint() = *pCursor->End();
788             pUnoCursor->DeleteMark();
789         }
790         else
791         {
792             SwXTextRange* pRange = comphelper::getFromUnoTunnel<SwXTextRange>(xCursorTunnel);
793             if(!pRange)
794                 return nullptr;
795             pRange->GetPositions(*pUnoCursor);
796             if(pUnoCursor->HasMark())
797             {
798                 if(*pUnoCursor->GetPoint() < *pUnoCursor->GetMark())
799                     pUnoCursor->Exchange();
800                 pUnoCursor->DeleteMark();
801             }
802         }
803         const SwNode& rRangeNode = pUnoCursor->GetPointNode();
804         bParentInExtra = rRangeNode.FindFlyStartNode() ||
805                             rRangeNode.FindFootnoteStartNode() ||
806                             rRangeNode.FindHeaderStartNode() ||
807                             rRangeNode.FindFooterStartNode() ;
808     }
809 
810     i18nutil::SearchOptions2 aSearchOpt;
811     pSearch->FillSearchOptions( aSearchOpt );
812 
813 /**
814  * The following combinations are allowed:
815  *  - Search in the body:                   -> FindRanges::InBody
816  *  - Search all in the body:               -> FindRanges::InBodyOnly | FindRanges::InSelAll
817  *  - Search in selections: one / all       -> FindRanges::InSel  [ | FindRanges::InSelAll ]
818  *  - Search outside the body: one / all    -> FindRanges::InOther [ | FindRanges::InSelAll ]
819  *  - Search everywhere all:                -> FindRanges::InSelAll
820  */
821     FindRanges eRanges(FindRanges::InBody);
822     if(bParentInExtra)
823         eRanges = FindRanges::InOther;
824     if(bAll) //always - everywhere?
825         eRanges = FindRanges::InSelAll;
826     SwDocPositions eStart = !bAll ? SwDocPositions::Curr : pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start;
827     SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End;
828 
829     nResult = 0;
830     for (int nSearchProc = 0; nSearchProc < 2; ++nSearchProc)
831     {
832         //try attribute search first
833         if(pSearch->HasSearchAttributes())
834         {
835             SfxItemSetFixed<
836                     RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
837                     RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT,
838                     RES_PARATR_BEGIN, RES_PARATR_END - 1,
839                     RES_FRMATR_BEGIN, RES_FRMATR_END - 1>
840                  aSearch( m_pDocShell->GetDoc()->GetAttrPool() );
841             pSearch->FillSearchItemSet(aSearch);
842             bool bCancel;
843             nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles,
844                         eStart, eEnd, bCancel,
845                         eRanges,
846                         !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr );
847         }
848         else if(pSearch->m_bStyles)
849         {
850             SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc());
851             //pSearch->sReplaceText
852             SwTextFormatColl *pReplaceColl = nullptr;
853             bool bCancel;
854             nResult = pUnoCursor->FindFormat(*pSearchColl,
855                         eStart, eEnd, bCancel,
856                         eRanges, pReplaceColl );
857         }
858         else
859         {
860             //todo/mba: assuming that notes should be omitted
861             bool bCancel;
862             nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/,
863                     eStart, eEnd, bCancel,
864                     eRanges );
865         }
866         if(nResult || (eRanges&(FindRanges::InSelAll|FindRanges::InOther)))
867             break;
868         //second step - find in other
869         eRanges = FindRanges::InOther;
870     }
871     return pUnoCursor;
872 }
873 
874 Reference< XIndexAccess >
875     SwXTextDocument::findAll(const Reference< util::XSearchDescriptor > & xDesc)
876 {
877     SolarMutexGuard aGuard;
878     Reference< XInterface >  xTmp;
879     sal_Int32 nResult = 0;
880     Reference< XTextCursor >  xCursor;
881     auto pResultCursor(FindAny(xDesc, xCursor, true, nResult, xTmp));
882     if(!pResultCursor)
883         throw RuntimeException("No result cursor");
884     Reference< XIndexAccess >  xRet = SwXTextRanges::Create( nResult ? &(*pResultCursor) : nullptr );
885     return xRet;
886 }
887 
888 Reference< XInterface >  SwXTextDocument::findFirst(const Reference< util::XSearchDescriptor > & xDesc)
889 {
890     SolarMutexGuard aGuard;
891     Reference< XInterface >  xTmp;
892     sal_Int32 nResult = 0;
893     Reference< XTextCursor >  xCursor;
894     auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xTmp));
895     if(!pResultCursor)
896         throw RuntimeException("No result cursor");
897     Reference< XInterface >  xRet;
898     if(nResult)
899     {
900         const uno::Reference< text::XText >  xParent =
901             ::sw::CreateParentXText(*m_pDocShell->GetDoc(),
902                     *pResultCursor->GetPoint());
903         xRet = *new SwXTextCursor(xParent, *pResultCursor);
904     }
905     return xRet;
906 }
907 
908 Reference< XInterface >  SwXTextDocument::findNext(const Reference< XInterface > & xStartAt,
909             const Reference< util::XSearchDescriptor > & xDesc)
910 {
911     SolarMutexGuard aGuard;
912     sal_Int32 nResult = 0;
913     Reference< XTextCursor >  xCursor;
914     if(!xStartAt.is())
915         throw RuntimeException("xStartAt missing");
916     auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xStartAt));
917     if(!pResultCursor)
918         throw RuntimeException("No result cursor");
919     Reference< XInterface >  xRet;
920     if(nResult)
921     {
922         const uno::Reference< text::XText >  xParent =
923             ::sw::CreateParentXText(*m_pDocShell->GetDoc(),
924                     *pResultCursor->GetPoint());
925 
926         xRet = *new SwXTextCursor(xParent, *pResultCursor);
927     }
928     return xRet;
929 }
930 
931 Sequence< beans::PropertyValue > SwXTextDocument::getPagePrintSettings()
932 {
933     SolarMutexGuard aGuard;
934     Sequence< beans::PropertyValue > aSeq(9);
935     if(!IsValid())
936         throw DisposedException("", static_cast< XTextDocument* >(this));
937 
938     beans::PropertyValue* pArray = aSeq.getArray();
939     SwPagePreviewPrtData aData;
940     const SwPagePreviewPrtData* pData = m_pDocShell->GetDoc()->GetPreviewPrtData();
941     if(pData)
942         aData = *pData;
943     Any aVal;
944     aVal <<= static_cast<sal_Int16>(aData.GetRow());
945     pArray[0] = beans::PropertyValue("PageRows", -1, aVal, PropertyState_DIRECT_VALUE);
946     aVal <<= static_cast<sal_Int16>(aData.GetCol());
947     pArray[1] = beans::PropertyValue("PageColumns", -1, aVal, PropertyState_DIRECT_VALUE);
948     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetLeftSpace()));
949     pArray[2] = beans::PropertyValue("LeftMargin", -1, aVal, PropertyState_DIRECT_VALUE);
950     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetRightSpace()));
951     pArray[3] = beans::PropertyValue("RightMargin", -1, aVal, PropertyState_DIRECT_VALUE);
952     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetTopSpace()));
953     pArray[4] = beans::PropertyValue("TopMargin", -1, aVal, PropertyState_DIRECT_VALUE);
954     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetBottomSpace()));
955     pArray[5] = beans::PropertyValue("BottomMargin", -1, aVal, PropertyState_DIRECT_VALUE);
956     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetHorzSpace()));
957     pArray[6] = beans::PropertyValue("HoriMargin", -1, aVal, PropertyState_DIRECT_VALUE);
958     aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetVertSpace()));
959     pArray[7] = beans::PropertyValue("VertMargin", -1, aVal, PropertyState_DIRECT_VALUE);
960     aVal <<= aData.GetLandscape();
961     pArray[8] = beans::PropertyValue("IsLandscape", -1, aVal, PropertyState_DIRECT_VALUE);
962 
963     return aSeq;
964 }
965 
966 static sal_uInt32 lcl_Any_To_ULONG(const Any& rValue, bool& bException)
967 {
968     bException = false;
969     TypeClass eType = rValue.getValueType().getTypeClass();
970 
971     sal_uInt32 nRet = 0;
972     if( eType == TypeClass_UNSIGNED_LONG )
973         rValue >>= nRet;
974     else
975     {
976          sal_Int32 nVal=0;
977          bException = !(rValue >>= nVal);
978          if( !bException )
979             nRet = static_cast<sal_uInt32>(nVal);
980     }
981 
982     return nRet;
983 }
984 
985 static OUString lcl_CreateOutlineString(const size_t nIndex, const SwDoc* pDoc)
986 {
987     OUStringBuffer sEntry;
988     const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds();
989     const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule();
990     const SwTextNode * pTextNd = rOutlineNodes[ nIndex ]->GetTextNode();
991     SwNumberTree::tNumberVector aNumVector = pTextNd->GetNumberVector();
992     if( pOutlRule && pTextNd->GetNumRule())
993         for( int nLevel = 0;
994              nLevel <= pTextNd->GetActualListLevel();
995              nLevel++ )
996         {
997             tools::Long nVal = aNumVector[nLevel];
998             nVal ++;
999             nVal -= pOutlRule->Get(nLevel).GetStart();
1000             sEntry.append( nVal );
1001             sEntry.append(".");
1002         }
1003     OUString sOutlineText = pDoc->getIDocumentOutlineNodes().getOutlineText(
1004                 nIndex, pDoc->GetDocShell()->GetWrtShell()->GetLayout(), false);
1005     sEntry.append(sOutlineText);
1006     return sEntry.makeStringAndClear();
1007 }
1008 
1009 void SwXTextDocument::setPagePrintSettings(const Sequence< beans::PropertyValue >& aSettings)
1010 {
1011     SolarMutexGuard aGuard;
1012     if(!IsValid())
1013         throw DisposedException("", static_cast< XTextDocument* >(this));
1014 
1015     SwPagePreviewPrtData aData;
1016     //if only a few properties are coming, then use the current settings
1017     const SwPagePreviewPrtData* pData = m_pDocShell->GetDoc()->GetPreviewPrtData();
1018     if(pData)
1019         aData = *pData;
1020     for(const beans::PropertyValue& rProperty : aSettings)
1021     {
1022         OUString sName = rProperty.Name;
1023         const Any& rVal = rProperty.Value;
1024         bool bException;
1025         sal_uInt32 nVal = lcl_Any_To_ULONG(rVal, bException);
1026         if( sName == "PageRows" )
1027         {
1028             if(!nVal || nVal > 0xff)
1029                 throw RuntimeException("Invalid value");
1030             aData.SetRow(static_cast<sal_uInt8>(nVal));
1031         }
1032         else if(sName == "PageColumns")
1033         {
1034             if(!nVal  || nVal > 0xff)
1035                 throw RuntimeException("Invalid value");
1036             aData.SetCol(static_cast<sal_uInt8>(nVal));
1037         }
1038         else if(sName == "LeftMargin")
1039         {
1040             aData.SetLeftSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1041         }
1042         else if(sName == "RightMargin")
1043         {
1044             aData.SetRightSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1045         }
1046         else if(sName == "TopMargin")
1047         {
1048             aData.SetTopSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1049         }
1050         else if(sName == "BottomMargin")
1051         {
1052             aData.SetBottomSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1053         }
1054         else if(sName == "HoriMargin")
1055         {
1056             aData.SetHorzSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1057         }
1058         else if(sName == "VertMargin")
1059         {
1060             aData.SetVertSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
1061         }
1062         else if(sName == "IsLandscape")
1063         {
1064             auto b = o3tl::tryAccess<bool>(rVal);
1065             bException = !b;
1066             if (b)
1067             {
1068                 aData.SetLandscape(*b);
1069             }
1070         }
1071         else
1072             bException = true;
1073         if(bException)
1074             throw RuntimeException();
1075     }
1076     m_pDocShell->GetDoc()->SetPreviewPrtData(&aData);
1077 
1078 }
1079 
1080 void SwXTextDocument::printPages(const Sequence< beans::PropertyValue >& xOptions)
1081 {
1082     SolarMutexGuard aGuard;
1083     if(!IsValid())
1084         throw DisposedException("", static_cast< XTextDocument* >(this));
1085 
1086     SfxViewFrame* pFrame = SfxViewFrame::LoadHiddenDocument( *m_pDocShell, SfxInterfaceId(7) );
1087     SfxRequest aReq(FN_PRINT_PAGEPREVIEW, SfxCallMode::SYNCHRON,
1088                                 m_pDocShell->GetDoc()->GetAttrPool());
1089     aReq.AppendItem(SfxBoolItem(FN_PRINT_PAGEPREVIEW, true));
1090 
1091     for ( const beans::PropertyValue &rProp : xOptions )
1092     {
1093         // get Property-Value from options
1094         Any aValue( rProp.Value );
1095 
1096         // FileName-Property?
1097         if ( rProp.Name == UNO_NAME_FILE_NAME )
1098         {
1099             OUString sFileURL;
1100             if ( rProp.Value >>= sFileURL )
1101             {
1102                 // Convert the File URL into a system dependent path, as the SalPrinter expects
1103                 OUString sSystemPath;
1104                 FileBase::getSystemPathFromFileURL ( sFileURL, sSystemPath );
1105                 aReq.AppendItem(SfxStringItem( SID_FILE_NAME, sSystemPath ) );
1106             }
1107             else if ( rProp.Value.getValueType() != cppu::UnoType<void>::get() )
1108                 throw IllegalArgumentException();
1109         }
1110 
1111         // CopyCount-Property
1112         else if ( rProp.Name == UNO_NAME_COPY_COUNT )
1113         {
1114             sal_Int32 nCopies = 0;
1115             aValue >>= nCopies;
1116             aReq.AppendItem(SfxInt16Item( SID_PRINT_COPIES, static_cast<sal_Int16>(nCopies) ) );
1117         }
1118 
1119         // Collate-Property
1120         else if ( rProp.Name == UNO_NAME_COLLATE )
1121         {
1122             auto b = o3tl::tryAccess<bool>(rProp.Value);
1123             if ( !b )
1124                 throw IllegalArgumentException();
1125             aReq.AppendItem(SfxBoolItem( SID_PRINT_COLLATE, *b ) );
1126 
1127         }
1128 
1129         // Sort-Property
1130         else if ( rProp.Name == UNO_NAME_SORT )
1131         {
1132             auto b = o3tl::tryAccess<bool>(rProp.Value);
1133             if ( !b )
1134                 throw IllegalArgumentException();
1135 
1136             aReq.AppendItem(SfxBoolItem( SID_PRINT_SORT, *b ) );
1137         }
1138 
1139         // Pages-Property
1140         else if ( rProp.Name == UNO_NAME_PAGES )
1141         {
1142             OUString sTmp;
1143             if ( !(rProp.Value >>= sTmp) )
1144                 throw IllegalArgumentException();
1145 
1146             aReq.AppendItem( SfxStringItem( SID_PRINT_PAGES, sTmp ) );
1147 
1148         }
1149     }
1150 
1151     // #i117783#
1152     m_bApplyPagePrintSettingsFromXPagePrintable = true;
1153     pFrame->GetViewShell()->ExecuteSlot(aReq);
1154     // Frame close
1155     pFrame->DoClose();
1156 
1157 }
1158 
1159 Reference< XNameAccess >  SwXTextDocument::getReferenceMarks()
1160 {
1161     SolarMutexGuard aGuard;
1162     if(!IsValid())
1163         throw DisposedException("", static_cast< XTextDocument* >(this));
1164     if(!mxXReferenceMarks.is())
1165     {
1166         mxXReferenceMarks = new SwXReferenceMarks(m_pDocShell->GetDoc());
1167     }
1168     return mxXReferenceMarks;
1169 }
1170 
1171 Reference< XEnumerationAccess >  SwXTextDocument::getTextFields()
1172 {
1173     SolarMutexGuard aGuard;
1174     if(!IsValid())
1175         throw DisposedException("", static_cast< XTextDocument* >(this));
1176     if(!mxXTextFieldTypes.is())
1177     {
1178         mxXTextFieldTypes = new SwXTextFieldTypes(m_pDocShell->GetDoc());
1179     }
1180     return mxXTextFieldTypes;
1181 }
1182 
1183 Reference< XNameAccess >  SwXTextDocument::getTextFieldMasters()
1184 {
1185     SolarMutexGuard aGuard;
1186     if(!IsValid())
1187         throw DisposedException("", static_cast< XTextDocument* >(this));
1188     if(!mxXTextFieldMasters.is())
1189     {
1190         mxXTextFieldMasters = new SwXTextFieldMasters(m_pDocShell->GetDoc());
1191     }
1192     return mxXTextFieldMasters;
1193 }
1194 
1195 Reference< XNameAccess >  SwXTextDocument::getEmbeddedObjects()
1196 {
1197     SolarMutexGuard aGuard;
1198     if(!IsValid())
1199         throw DisposedException("", static_cast< XTextDocument* >(this));
1200     if(!mxXEmbeddedObjects.is())
1201     {
1202         mxXEmbeddedObjects = new SwXTextEmbeddedObjects(m_pDocShell->GetDoc());
1203     }
1204     return mxXEmbeddedObjects;
1205 }
1206 
1207 Reference< XNameAccess >  SwXTextDocument::getBookmarks()
1208 {
1209     SolarMutexGuard aGuard;
1210     if(!IsValid())
1211         throw DisposedException("", static_cast< XTextDocument* >(this));
1212     if(!mxXBookmarks.is())
1213     {
1214         mxXBookmarks = new SwXBookmarks(m_pDocShell->GetDoc());
1215     }
1216     return mxXBookmarks;
1217 }
1218 
1219 Reference< XNameAccess >  SwXTextDocument::getTextSections()
1220 {
1221     SolarMutexGuard aGuard;
1222     if(!IsValid())
1223         throw DisposedException("", static_cast< XTextDocument* >(this));
1224     if(!mxXTextSections.is())
1225     {
1226         mxXTextSections = new SwXTextSections(m_pDocShell->GetDoc());
1227     }
1228     return mxXTextSections;
1229 }
1230 
1231 Reference< XNameAccess >  SwXTextDocument::getTextTables()
1232 {
1233     SolarMutexGuard aGuard;
1234     if(!IsValid())
1235         throw DisposedException("", static_cast< XTextDocument* >(this));
1236     if(!mxXTextTables.is())
1237     {
1238         mxXTextTables = new SwXTextTables(m_pDocShell->GetDoc());
1239     }
1240     return mxXTextTables;
1241 }
1242 
1243 Reference< XNameAccess >  SwXTextDocument::getGraphicObjects()
1244 {
1245     SolarMutexGuard aGuard;
1246     if(!IsValid())
1247         throw DisposedException("", static_cast< XTextDocument* >(this));
1248     if(!mxXGraphicObjects.is())
1249     {
1250         mxXGraphicObjects = new SwXTextGraphicObjects(m_pDocShell->GetDoc());
1251     }
1252     return mxXGraphicObjects;
1253 }
1254 
1255 Reference< XNameAccess >  SwXTextDocument::getTextFrames()
1256 {
1257     SolarMutexGuard aGuard;
1258     if(!IsValid())
1259         throw DisposedException("", static_cast< XTextDocument* >(this));
1260     if(!mxXTextFrames.is())
1261     {
1262         mxXTextFrames = new SwXTextFrames(m_pDocShell->GetDoc());
1263     }
1264     return mxXTextFrames;
1265 }
1266 
1267 Reference< XNameAccess >  SwXTextDocument::getStyleFamilies()
1268 {
1269     SolarMutexGuard aGuard;
1270     if(!IsValid())
1271         throw DisposedException("", static_cast< XTextDocument* >(this));
1272     if(!mxXStyleFamilies.is())
1273     {
1274         mxXStyleFamilies = new SwXStyleFamilies(*m_pDocShell);
1275     }
1276     return mxXStyleFamilies;
1277 }
1278 
1279 uno::Reference< style::XAutoStyles > SwXTextDocument::getAutoStyles(  )
1280 {
1281     SolarMutexGuard aGuard;
1282     if(!IsValid())
1283         throw DisposedException("", static_cast< XTextDocument* >(this));
1284     if(!mxXAutoStyles.is())
1285     {
1286         mxXAutoStyles = new SwXAutoStyles(*m_pDocShell);
1287     }
1288     return mxXAutoStyles;
1289 
1290 }
1291 
1292 Reference< drawing::XDrawPage >  SwXTextDocument::getDrawPage()
1293 {
1294     SolarMutexGuard aGuard;
1295     if(!IsValid())
1296         throw DisposedException("", static_cast< XTextDocument* >(this));
1297     if(!m_xDrawPage.is())
1298     {
1299         SwDoc* pDoc = m_pDocShell->GetDoc();
1300         // #i52858#
1301         SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel();
1302         SdrPage* pPage = pModel->GetPage( 0 );
1303         m_xDrawPage = new SwFmDrawPage(pDoc, pPage);
1304     }
1305     return m_xDrawPage;
1306 }
1307 
1308 namespace {
1309 
1310 class SwDrawPagesObj : public cppu::WeakImplHelper<
1311     css::drawing::XDrawPages,
1312     css::lang::XServiceInfo>
1313 {
1314 private:
1315     css::uno::Reference< css::drawing::XDrawPageSupplier > m_xDoc;
1316 public:
1317     SwDrawPagesObj(css::uno::Reference< css::drawing::XDrawPageSupplier > xDoc) : m_xDoc(std::move(xDoc)) {}
1318 
1319     // XDrawPages
1320     virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL
1321         insertNewByIndex(sal_Int32 /*nIndex*/) override { throw css::lang::NoSupportException(); }
1322 
1323     virtual void SAL_CALL remove(const css::uno::Reference< css::drawing::XDrawPage >& /*xPage*/) override
1324     {
1325         throw css::lang::NoSupportException();
1326     }
1327 
1328     // XIndexAccess
1329     virtual sal_Int32 SAL_CALL getCount() override { return 1; }
1330 
1331     virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
1332     {
1333         if (Index != 0)
1334             throw css::lang::IndexOutOfBoundsException("Writer documents have only one DrawPage!");
1335         return css::uno::Any(m_xDoc->getDrawPage());
1336     }
1337 
1338     // XElementAccess
1339     virtual css::uno::Type SAL_CALL getElementType() override
1340     {
1341         return cppu::UnoType<drawing::XDrawPage>::get();
1342     }
1343 
1344     virtual sal_Bool SAL_CALL hasElements() override { return true; }
1345 
1346     // XServiceInfo
1347     virtual OUString SAL_CALL getImplementationName() override
1348     {
1349         return "SwDrawPagesObj";
1350     }
1351 
1352     virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override
1353     {
1354         return cppu::supportsService(this, ServiceName);
1355     }
1356 
1357     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
1358     {
1359         return { "com.sun.star.drawing.DrawPages" };
1360     }
1361 };
1362 
1363 }
1364 
1365 // XDrawPagesSupplier
1366 
1367 uno::Reference<drawing::XDrawPages> SAL_CALL SwXTextDocument::getDrawPages()
1368 {
1369     SolarMutexGuard aGuard;
1370     return new SwDrawPagesObj(this);
1371 }
1372 
1373 void SwXTextDocument::Invalidate()
1374 {
1375     m_bObjectValid = false;
1376     if(m_xNumFormatAgg.is())
1377     {
1378         const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
1379         Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
1380         Reference< XUnoTunnel > xNumTunnel;
1381         aNumTunnel >>= xNumTunnel;
1382         SvNumberFormatsSupplierObj* pNumFormat
1383             = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
1384         OSL_ENSURE(pNumFormat, "No number formatter available");
1385         if (pNumFormat)
1386             pNumFormat->SetNumberFormatter(nullptr);
1387         OSL_ENSURE(pNumFormat, "No number formatter available");
1388     }
1389     InitNewDoc();
1390     m_pDocShell = nullptr;
1391     lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this));
1392     std::unique_lock aGuard(m_pImpl->m_Mutex);
1393     m_pImpl->m_RefreshListeners.disposeAndClear(aGuard, ev);
1394 }
1395 
1396 void SwXTextDocument::Reactivate(SwDocShell* pNewDocShell)
1397 {
1398     if(m_pDocShell && m_pDocShell != pNewDocShell)
1399         Invalidate();
1400     m_pDocShell = pNewDocShell;
1401     m_bObjectValid = true;
1402 }
1403 
1404 void    SwXTextDocument::InitNewDoc()
1405 {
1406     // first invalidate all collections, then delete references and Set to zero
1407     if(mxXTextTables.is())
1408     {
1409         XNameAccess* pTables = mxXTextTables.get();
1410         static_cast<SwXTextTables*>(pTables)->Invalidate();
1411         mxXTextTables.clear();
1412     }
1413 
1414     if(mxXTextFrames.is())
1415     {
1416         XNameAccess* pFrames = mxXTextFrames.get();
1417         static_cast<SwXTextFrames*>(pFrames)->Invalidate();
1418         mxXTextFrames.clear();
1419     }
1420 
1421     if(mxXGraphicObjects.is())
1422     {
1423         XNameAccess* pFrames = mxXGraphicObjects.get();
1424         static_cast<SwXTextGraphicObjects*>(pFrames)->Invalidate();
1425         mxXGraphicObjects.clear();
1426     }
1427 
1428     if(mxXEmbeddedObjects.is())
1429     {
1430         XNameAccess* pOLE = mxXEmbeddedObjects.get();
1431         static_cast<SwXTextEmbeddedObjects*>(pOLE)->Invalidate();
1432         mxXEmbeddedObjects.clear();
1433     }
1434 
1435     m_xBodyText = nullptr;
1436 
1437     if(m_xNumFormatAgg.is())
1438     {
1439         const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
1440         Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
1441         Reference< XUnoTunnel > xNumTunnel;
1442         aNumTunnel >>= xNumTunnel;
1443         SvNumberFormatsSupplierObj* pNumFormat
1444             = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
1445         OSL_ENSURE(pNumFormat, "No number formatter available");
1446         if (pNumFormat)
1447             pNumFormat->SetNumberFormatter(nullptr);
1448     }
1449 
1450     if(mxXTextFieldTypes.is())
1451     {
1452         XEnumerationAccess* pT = mxXTextFieldTypes.get();
1453         static_cast<SwXTextFieldTypes*>(pT)->Invalidate();
1454         mxXTextFieldTypes.clear();
1455     }
1456 
1457     if(mxXTextFieldMasters.is())
1458     {
1459         XNameAccess* pT = mxXTextFieldMasters.get();
1460         static_cast<SwXTextFieldMasters*>(pT)->Invalidate();
1461         mxXTextFieldMasters.clear();
1462     }
1463 
1464     if(mxXTextSections.is())
1465     {
1466         XNameAccess* pSect = mxXTextSections.get();
1467         static_cast<SwXTextSections*>(pSect)->Invalidate();
1468         mxXTextSections.clear();
1469     }
1470 
1471     if(m_xDrawPage.is())
1472     {
1473         // #i91798#, #i91895#
1474         // dispose XDrawPage here. We are the owner and know that it is no longer in a valid condition.
1475         Reference<XComponent>(static_cast<cppu::OWeakObject*>(m_xDrawPage.get()), UNO_QUERY_THROW)->dispose();
1476         m_xDrawPage->InvalidateSwDoc();
1477         m_xDrawPage.clear();
1478     }
1479 
1480     if ( mxXNumberingRules.is() )
1481     {
1482         XIndexAccess* pNum = mxXNumberingRules.get();
1483         static_cast<SwXNumberingRulesCollection*>(pNum)->Invalidate();
1484         mxXNumberingRules.clear();
1485     }
1486 
1487     if(mxXFootnotes.is())
1488     {
1489         XIndexAccess* pFootnote = mxXFootnotes.get();
1490         static_cast<SwXFootnotes*>(pFootnote)->Invalidate();
1491         mxXFootnotes.clear();
1492     }
1493 
1494     if(mxXEndnotes.is())
1495     {
1496         XIndexAccess* pFootnote = mxXEndnotes.get();
1497         static_cast<SwXFootnotes*>(pFootnote)->Invalidate();
1498         mxXEndnotes.clear();
1499     }
1500 
1501     if(mxXContentControls.is())
1502     {
1503         XIndexAccess* pContentControls = mxXContentControls.get();
1504         static_cast<SwXContentControls*>(pContentControls)->Invalidate();
1505         mxXContentControls.clear();
1506     }
1507 
1508     if(mxXDocumentIndexes.is())
1509     {
1510         XIndexAccess* pIdxs = mxXDocumentIndexes.get();
1511         static_cast<SwXDocumentIndexes*>(pIdxs)->Invalidate();
1512         mxXDocumentIndexes.clear();
1513     }
1514 
1515     if(mxXStyleFamilies.is())
1516     {
1517         XNameAccess* pStyles = mxXStyleFamilies.get();
1518         static_cast<SwXStyleFamilies*>(pStyles)->Invalidate();
1519         mxXStyleFamilies.clear();
1520     }
1521     if(mxXAutoStyles.is())
1522     {
1523         XNameAccess* pStyles = mxXAutoStyles.get();
1524         static_cast<SwXAutoStyles*>(pStyles)->Invalidate();
1525         mxXAutoStyles.clear();
1526     }
1527 
1528     if(mxXBookmarks.is())
1529     {
1530         XNameAccess* pBm = mxXBookmarks.get();
1531         static_cast<SwXBookmarks*>(pBm)->Invalidate();
1532         mxXBookmarks.clear();
1533     }
1534 
1535     if(mxXChapterNumbering.is())
1536     {
1537         XIndexReplace* pCh = mxXChapterNumbering.get();
1538         static_cast<SwXChapterNumbering*>(pCh)->Invalidate();
1539         mxXChapterNumbering.clear();
1540     }
1541 
1542     if(mxXFootnoteSettings.is())
1543     {
1544         XPropertySet* pFntSet = mxXFootnoteSettings.get();
1545         static_cast<SwXFootnoteProperties*>(pFntSet)->Invalidate();
1546         mxXFootnoteSettings.clear();
1547     }
1548 
1549     if(mxXEndnoteSettings.is())
1550     {
1551         XPropertySet* pEndSet = mxXEndnoteSettings.get();
1552         static_cast<SwXEndnoteProperties*>(pEndSet)->Invalidate();
1553         mxXEndnoteSettings.clear();
1554     }
1555 
1556     if(mxXLineNumberingProperties.is())
1557     {
1558         XPropertySet* pLine = mxXLineNumberingProperties.get();
1559         static_cast<SwXLineNumberingProperties*>(pLine)->Invalidate();
1560         mxXLineNumberingProperties.clear();
1561     }
1562     if(mxXReferenceMarks.is())
1563     {
1564         XNameAccess* pMarks = mxXReferenceMarks.get();
1565         static_cast<SwXReferenceMarks*>(pMarks)->Invalidate();
1566         mxXReferenceMarks.clear();
1567     }
1568     if(mxLinkTargetSupplier.is())
1569     {
1570         XNameAccess* pAccess = mxLinkTargetSupplier.get();
1571         static_cast<SwXLinkTargetSupplier*>(pAccess)->Invalidate();
1572         mxLinkTargetSupplier.clear();
1573     }
1574     if(mxXRedlines.is())
1575     {
1576         XEnumerationAccess* pMarks = mxXRedlines.get();
1577         static_cast<SwXRedlines*>(pMarks)->Invalidate();
1578         mxXRedlines.clear();
1579     }
1580     if(mxPropertyHelper.is())
1581     {
1582         mxPropertyHelper->Invalidate();
1583         mxPropertyHelper.clear();
1584     }
1585 }
1586 
1587 css::uno::Reference<css::uno::XInterface> SwXTextDocument::create(
1588     OUString const & rServiceName,
1589     css::uno::Sequence<css::uno::Any> const * arguments)
1590 {
1591     SolarMutexGuard aGuard;
1592     if (!IsValid())
1593         throw DisposedException("", static_cast< XTextDocument* >(this));
1594 
1595     const SwServiceType nType = SwXServiceProvider::GetProviderType(rServiceName);
1596     if (nType != SwServiceType::Invalid)
1597     {
1598         return SwXServiceProvider::MakeInstance(nType, *m_pDocShell->GetDoc());
1599     }
1600     if (rServiceName == "com.sun.star.drawing.DashTable")
1601     {
1602         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Dash);
1603     }
1604     if (rServiceName == "com.sun.star.drawing.GradientTable")
1605     {
1606         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Gradient);
1607     }
1608     if (rServiceName == "com.sun.star.drawing.HatchTable")
1609     {
1610         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Hatch);
1611     }
1612     if (rServiceName == "com.sun.star.drawing.BitmapTable")
1613     {
1614         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Bitmap);
1615     }
1616     if (rServiceName == "com.sun.star.drawing.TransparencyGradientTable")
1617     {
1618         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::TransGradient);
1619     }
1620     if (rServiceName == "com.sun.star.drawing.MarkerTable")
1621     {
1622         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Marker);
1623     }
1624     if (rServiceName == "com.sun.star.drawing.Defaults")
1625     {
1626         return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Defaults);
1627     }
1628     if (rServiceName == "com.sun.star.document.Settings")
1629     {
1630         return Reference<XInterface>(*new SwXDocumentSettings(this));
1631     }
1632     if (rServiceName == "com.sun.star.document.ImportEmbeddedObjectResolver")
1633     {
1634         return static_cast<cppu::OWeakObject *>(
1635             new SvXMLEmbeddedObjectHelper(
1636                 *m_pDocShell, SvXMLEmbeddedObjectHelperMode::Read));
1637     }
1638     if (rServiceName == "com.sun.star.text.DocumentSettings")
1639     {
1640         return Reference<XInterface>(*new SwXDocumentSettings(this));
1641     }
1642     if (rServiceName == "com.sun.star.chart2.data.DataProvider")
1643     {
1644         return Reference<XInterface>(
1645             static_cast<chart2::data::XDataProvider *>(
1646                 m_pDocShell->getIDocumentChartDataProviderAccess().
1647                 GetChartDataProvider()));
1648     }
1649     if (!rServiceName.startsWith("com.sun.star.")
1650         || rServiceName.endsWith(".OLE2Shape"))
1651     {
1652         // We do not want to insert OLE2 Shapes (e.g.,
1653         // "com.sun.star.drawing.OLE2Shape", ...) like this (by creating them
1654         // with the documents factory and adding the shapes to the draw page);
1655         // for inserting OLE objects the proper way is to use
1656         // "com.sun.star.text.TextEmbeddedObject":
1657         throw ServiceNotRegisteredException();
1658     }
1659     // The XML import is allowed to create instances of
1660     // "com.sun.star.drawing.OLE2Shape"; thus, a temporary service name is
1661     // introduced to make this possible:
1662     OUString aTmpServiceName(rServiceName);
1663     if (rServiceName == "com.sun.star.drawing.temporaryForXMLImportOLE2Shape")
1664     {
1665         aTmpServiceName = "com.sun.star.drawing.OLE2Shape";
1666     }
1667     Reference<XInterface> xTmp(
1668         arguments == nullptr
1669         ? SvxFmMSFactory::createInstance(aTmpServiceName)
1670         : SvxFmMSFactory::createInstanceWithArguments(
1671             aTmpServiceName, *arguments));
1672     if (rServiceName == "com.sun.star.drawing.GroupShape"
1673         || rServiceName == "com.sun.star.drawing.Shape3DSceneObject")
1674     {
1675         return *new SwXGroupShape(xTmp, m_pDocShell->GetDoc());
1676     }
1677     if (rServiceName.startsWith("com.sun.star.drawing."))
1678     {
1679         return *new SwXShape(xTmp, m_pDocShell->GetDoc());
1680     }
1681     return xTmp;
1682 }
1683 
1684 Reference< XInterface >  SwXTextDocument::createInstance(const OUString& rServiceName)
1685 {
1686     return create(rServiceName, nullptr);
1687 }
1688 
1689 Reference< XInterface >  SwXTextDocument::createInstanceWithArguments(
1690         const OUString& ServiceSpecifier,
1691         const Sequence< Any >& Arguments)
1692 {
1693     return create(ServiceSpecifier, &Arguments);
1694 }
1695 
1696 Sequence< OUString > SwXTextDocument::getAvailableServiceNames()
1697 {
1698     static Sequence< OUString > aServices;
1699     if ( !aServices.hasElements() )
1700     {
1701         Sequence< OUString > aRet =  SvxFmMSFactory::getAvailableServiceNames();
1702         auto i = comphelper::findValue(aRet, "com.sun.star.drawing.OLE2Shape");
1703         if (i != -1)
1704         {
1705             auto nLength = aRet.getLength();
1706             aRet.getArray()[i] = aRet[nLength - 1];
1707             aRet.realloc( nLength - 1 );
1708         }
1709         Sequence< OUString > aOwn = SwXServiceProvider::GetAllServiceNames();
1710         aServices = comphelper::concatSequences(aRet, aOwn);
1711     }
1712 
1713     return aServices;
1714 }
1715 
1716 OUString SwXTextDocument::getImplementationName()
1717 {
1718     return "SwXTextDocument";
1719     /* // Matching the .component information:
1720        return dynamic_cast<SwGlobalDocShell*>( pDocShell ) != nullptr
1721            ? OUString("com.sun.star.comp.Writer.GlobalDocument")
1722            : dynamic_cast<SwWebDocShell*>( pDocShell ) != nullptr
1723            ? OUString("com.sun.star.comp.Writer.WebDocument")
1724            : OUString("com.sun.star.comp.Writer.TextDocument");
1725     */
1726 }
1727 
1728 sal_Bool SwXTextDocument::supportsService(const OUString& rServiceName)
1729 {
1730     return cppu::supportsService(this, rServiceName);
1731 }
1732 
1733 Sequence< OUString > SwXTextDocument::getSupportedServiceNames()
1734 {
1735     bool bWebDoc    = (dynamic_cast<SwWebDocShell*>(    m_pDocShell) !=  nullptr );
1736     bool bGlobalDoc = (dynamic_cast<SwGlobalDocShell*>( m_pDocShell) !=  nullptr );
1737     bool bTextDoc   = (!bWebDoc && !bGlobalDoc);
1738 
1739     Sequence< OUString > aRet (3);
1740     OUString* pArray = aRet.getArray();
1741 
1742     pArray[0] = "com.sun.star.document.OfficeDocument";
1743     pArray[1] = "com.sun.star.text.GenericTextDocument";
1744 
1745     if (bTextDoc)
1746         pArray[2] = "com.sun.star.text.TextDocument";
1747     else if (bWebDoc)
1748         pArray[2] = "com.sun.star.text.WebDocument";
1749     else if (bGlobalDoc)
1750         pArray[2] = "com.sun.star.text.GlobalDocument";
1751 
1752     return aRet;
1753 }
1754 
1755 Reference< XIndexAccess >  SwXTextDocument::getDocumentIndexes()
1756 {
1757     SolarMutexGuard aGuard;
1758     if(!IsValid())
1759         throw DisposedException("", static_cast< XTextDocument* >(this));
1760 
1761     if(!mxXDocumentIndexes.is())
1762     {
1763         mxXDocumentIndexes = new SwXDocumentIndexes(m_pDocShell->GetDoc());
1764     }
1765     return mxXDocumentIndexes;
1766 }
1767 
1768 Reference< XPropertySetInfo >  SwXTextDocument::getPropertySetInfo()
1769 {
1770     static Reference< XPropertySetInfo >  xRet = m_pPropSet->getPropertySetInfo();
1771     return xRet;
1772 }
1773 
1774 void SwXTextDocument::setPropertyValue(const OUString& rPropertyName, const Any& aValue)
1775 {
1776     SolarMutexGuard aGuard;
1777     if(!IsValid())
1778         throw DisposedException("", static_cast< XTextDocument* >(this));
1779 
1780     const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
1781 
1782     if(!pEntry)
1783         throw UnknownPropertyException(rPropertyName);
1784     if(pEntry->nFlags & PropertyAttribute::READONLY)
1785         throw PropertyVetoException();
1786     switch(pEntry->nWID)
1787     {
1788         case  WID_DOC_CHAR_COUNT     :
1789         case  WID_DOC_PARA_COUNT     :
1790         case  WID_DOC_WORD_COUNT     :
1791             throw RuntimeException(
1792                 "bad WID",
1793                 static_cast< cppu::OWeakObject * >(
1794                     static_cast< SwXTextDocumentBaseClass * >(this)));
1795         case  WID_DOC_WORD_SEPARATOR :
1796         {
1797             OUString sDelim;
1798             aValue >>= sDelim;
1799             SW_MOD()->GetModuleConfig()->SetWordDelimiter(sDelim);
1800         }
1801         break;
1802         case WID_DOC_CHANGES_RECORD:
1803         case WID_DOC_CHANGES_SHOW:
1804         {
1805             bool bSet = *o3tl::doAccess<bool>(aValue);
1806             RedlineFlags eMode = m_pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
1807             if(WID_DOC_CHANGES_SHOW == pEntry->nWID)
1808             {
1809                 eMode |= RedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete);
1810                 if( !bSet )
1811                     m_pDocShell->GetDoc()->GetDocumentRedlineManager().SetHideRedlines(true);
1812             }
1813             else if(WID_DOC_CHANGES_RECORD == pEntry->nWID)
1814             {
1815                 eMode = bSet ? eMode|RedlineFlags::On : eMode&~RedlineFlags::On;
1816             }
1817             m_pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eMode );
1818         }
1819         break;
1820         case  WID_DOC_CHANGES_PASSWORD:
1821         {
1822             Sequence <sal_Int8> aNew;
1823             if(aValue >>= aNew)
1824             {
1825                 SwDoc* pDoc = m_pDocShell->GetDoc();
1826                 pDoc->getIDocumentRedlineAccess().SetRedlinePassword(aNew);
1827                 if(aNew.hasElements())
1828                 {
1829                     RedlineFlags eMode = pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
1830                     eMode |= RedlineFlags::On;
1831                     pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eMode );
1832                 }
1833             }
1834         }
1835         break;
1836         case WID_DOC_AUTO_MARK_URL :
1837         {
1838             OUString sURL;
1839             aValue >>= sURL;
1840             m_pDocShell->GetDoc()->SetTOIAutoMarkURL(sURL);
1841         }
1842         break;
1843         case WID_DOC_HIDE_TIPS :
1844             SW_MOD()->GetModuleConfig()->SetHideFieldTips(*o3tl::doAccess<bool>(aValue));
1845         break;
1846         case WID_DOC_REDLINE_DISPLAY:
1847         {
1848             RedlineFlags eRedMode = m_pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
1849             eRedMode = eRedMode & (~RedlineFlags::ShowMask);
1850             sal_Int16 nSet = 0;
1851             aValue >>= nSet;
1852             switch(nSet)
1853             {
1854                 case RedlineDisplayType::NONE: break;
1855                 case RedlineDisplayType::INSERTED: eRedMode |= RedlineFlags::ShowInsert; break;
1856                 case RedlineDisplayType::REMOVED: eRedMode |= RedlineFlags::ShowDelete;  break;
1857                 case RedlineDisplayType::
1858                         INSERTED_AND_REMOVED: eRedMode |= RedlineFlags::ShowInsert|RedlineFlags::ShowDelete;
1859                 break;
1860                 default: throw IllegalArgumentException();
1861             }
1862             m_pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags(eRedMode);
1863         }
1864         break;
1865         case WID_DOC_TWO_DIGIT_YEAR:
1866         {
1867             sal_Int16 nYear = 0;
1868             aValue >>= nYear;
1869             SfxRequest aRequest ( SID_ATTR_YEAR2000, SfxCallMode::SLOT, m_pDocShell->GetDoc()->GetAttrPool());
1870             aRequest.AppendItem(SfxUInt16Item( SID_ATTR_YEAR2000, static_cast < sal_uInt16 > ( nYear ) ) );
1871             m_pDocShell->Execute ( aRequest );
1872         }
1873         break;
1874         case WID_DOC_AUTOMATIC_CONTROL_FOCUS:
1875         {
1876             SwDrawModel * pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1877             bool bAuto = *o3tl::doAccess<bool>(aValue);
1878 
1879             if ( nullptr != pDrawDoc )
1880                 pDrawDoc->SetAutoControlFocus( bAuto );
1881             else if (bAuto)
1882             {
1883                 // if setting to true, and we don't have an
1884                 // SdrModel, then we are changing the default and
1885                 // must thus create an SdrModel, if we don't have an
1886                 // SdrModel and we are leaving the default at false,
1887                 // we don't need to make an SdrModel and can do nothing
1888                 // #i52858# - method name changed
1889                 pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel();
1890                 pDrawDoc->SetAutoControlFocus ( bAuto );
1891             }
1892         }
1893         break;
1894         case WID_DOC_APPLY_FORM_DESIGN_MODE:
1895         {
1896             SwDrawModel * pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1897             bool bMode = *o3tl::doAccess<bool>(aValue);
1898 
1899             if ( nullptr != pDrawDoc )
1900                 pDrawDoc->SetOpenInDesignMode( bMode );
1901             else if (!bMode)
1902             {
1903                 // if setting to false, and we don't have an
1904                 // SdrModel, then we are changing the default and
1905                 // must thus create an SdrModel, if we don't have an
1906                 // SdrModel and we are leaving the default at true,
1907                 // we don't need to make an SdrModel and can do
1908                 // nothing
1909                 // #i52858# - method name changed
1910                 pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel();
1911                 pDrawDoc->SetOpenInDesignMode ( bMode );
1912             }
1913         }
1914         break;
1915         // #i42634# New property to set the bInReading
1916         // flag at the document, used during binary import
1917         case WID_DOC_LOCK_UPDATES :
1918         {
1919             SwDoc* pDoc = m_pDocShell->GetDoc();
1920             bool bBool (false);
1921             if( aValue >>= bBool )
1922             {
1923               pDoc->SetInReading( bBool );
1924             }
1925         }
1926         break;
1927         case WID_DOC_WRITERFILTER:
1928         {
1929             SwDoc* pDoc = m_pDocShell->GetDoc();
1930             bool bBool = {};
1931             if (aValue >>= bBool)
1932             { // HACK: writerfilter has to use API to set this :(
1933                 bool bOld = pDoc->IsInWriterfilterImport();
1934                 pDoc->SetInWriterfilterImport(bBool);
1935                 if (bOld && !bBool)
1936                 {
1937                     pDoc->getIDocumentFieldsAccess().SetFieldsDirty(false, nullptr, SwNodeOffset(0));
1938                 }
1939             }
1940         }
1941         break;
1942         case WID_DOC_BUILDID:
1943             aValue >>= maBuildId;
1944         break;
1945 
1946         case WID_DOC_DEFAULT_PAGE_MODE:
1947         {
1948             bool bDefaultPageMode( false );
1949             aValue >>= bDefaultPageMode;
1950             m_pDocShell->GetDoc()->SetDefaultPageMode( bDefaultPageMode );
1951         }
1952         break;
1953         case WID_DOC_INTEROP_GRAB_BAG:
1954              setGrabBagItem(aValue);
1955         break;
1956 
1957         default:
1958         {
1959             const SfxPoolItem& rItem = m_pDocShell->GetDoc()->GetDefault(pEntry->nWID);
1960             std::unique_ptr<SfxPoolItem> pNewItem(rItem.Clone());
1961             pNewItem->PutValue(aValue, pEntry->nMemberId);
1962             m_pDocShell->GetDoc()->SetDefault(*pNewItem);
1963         }
1964     }
1965 }
1966 
1967 Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName)
1968 {
1969     SolarMutexGuard aGuard;
1970     if(!IsValid())
1971         throw DisposedException("", static_cast< XTextDocument* >(this));
1972 
1973     const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
1974 
1975     if(!pEntry)
1976         throw UnknownPropertyException(rPropertyName);
1977     Any aAny;
1978     switch(pEntry->nWID)
1979     {
1980         case WID_DOC_ISTEMPLATEID    :
1981             aAny <<= m_pDocShell->IsTemplate();
1982             break;
1983         case  WID_DOC_CHAR_COUNT     :
1984         case  WID_DOC_PARA_COUNT     :
1985         case  WID_DOC_WORD_COUNT     :
1986         {
1987             const SwDocStat& rStat(m_pDocShell->GetDoc()->getIDocumentStatistics().GetUpdatedDocStat( false, true ));
1988             sal_Int32 nValue;
1989             switch(pEntry->nWID)
1990             {
1991                 case  WID_DOC_CHAR_COUNT     :nValue = rStat.nChar;break;
1992                 case  WID_DOC_PARA_COUNT     :nValue = rStat.nPara;break;
1993                 case  WID_DOC_WORD_COUNT     :nValue = rStat.nWord;break;
1994             }
1995             aAny <<= nValue;
1996         }
1997         break;
1998         case  WID_DOC_WORD_SEPARATOR :
1999         {
2000             aAny <<= SW_MOD()->GetDocStatWordDelim();
2001         }
2002         break;
2003         case WID_DOC_CHANGES_RECORD:
2004         case WID_DOC_CHANGES_SHOW:
2005         {
2006             const RedlineFlags eMode = m_pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
2007             bool bSet = false;
2008             if(WID_DOC_CHANGES_SHOW == pEntry->nWID)
2009             {
2010                 bSet = IDocumentRedlineAccess::IsShowChanges(eMode);
2011             }
2012             else if(WID_DOC_CHANGES_RECORD == pEntry->nWID)
2013             {
2014                 bSet = bool(eMode & RedlineFlags::On);
2015             }
2016             aAny <<= bSet;
2017         }
2018         break;
2019         case  WID_DOC_CHANGES_PASSWORD:
2020         {
2021             SwDoc* pDoc = m_pDocShell->GetDoc();
2022             aAny <<= pDoc->getIDocumentRedlineAccess().GetRedlinePassword();
2023         }
2024         break;
2025         case WID_DOC_AUTO_MARK_URL :
2026             aAny <<= m_pDocShell->GetDoc()->GetTOIAutoMarkURL();
2027         break;
2028         case WID_DOC_HIDE_TIPS :
2029             aAny <<= SW_MOD()->GetModuleConfig()->IsHideFieldTips();
2030         break;
2031         case WID_DOC_REDLINE_DISPLAY:
2032         {
2033             RedlineFlags eRedMode = m_pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
2034             eRedMode = eRedMode & RedlineFlags::ShowMask;
2035             sal_Int16 nRet = RedlineDisplayType::NONE;
2036             if(RedlineFlags::ShowInsert == eRedMode)
2037                 nRet = RedlineDisplayType::INSERTED;
2038             else if(RedlineFlags::ShowDelete == eRedMode)
2039                 nRet = RedlineDisplayType::REMOVED;
2040             else if(RedlineFlags::ShowMask == eRedMode)
2041                 nRet = RedlineDisplayType::INSERTED_AND_REMOVED;
2042             aAny <<= nRet;
2043         }
2044         break;
2045         case WID_DOC_FORBIDDEN_CHARS:
2046         {
2047             GetPropertyHelper();
2048             Reference<XForbiddenCharacters> xRet = mxPropertyHelper;
2049             aAny <<= xRet;
2050         }
2051         break;
2052         case WID_DOC_TWO_DIGIT_YEAR:
2053         {
2054             aAny <<= static_cast < sal_Int16 > (m_pDocShell->GetDoc()->GetNumberFormatter ()->GetYear2000());
2055         }
2056         break;
2057         case WID_DOC_AUTOMATIC_CONTROL_FOCUS:
2058         {
2059             SwDrawModel * pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
2060             bool bAuto;
2061             if ( nullptr != pDrawDoc )
2062                 bAuto = pDrawDoc->GetAutoControlFocus();
2063             else
2064                 bAuto = false;
2065             aAny <<= bAuto;
2066         }
2067         break;
2068         case WID_DOC_APPLY_FORM_DESIGN_MODE:
2069         {
2070             SwDrawModel * pDrawDoc = m_pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
2071             bool bMode;
2072             if ( nullptr != pDrawDoc )
2073                 bMode = pDrawDoc->GetOpenInDesignMode();
2074             else
2075                 bMode = true;
2076             aAny <<= bMode;
2077         }
2078         break;
2079         case WID_DOC_BASIC_LIBRARIES:
2080             aAny <<= m_pDocShell->GetBasicContainer();
2081         break;
2082         case WID_DOC_DIALOG_LIBRARIES:
2083             aAny <<= m_pDocShell->GetDialogContainer();
2084         break;
2085         case WID_DOC_VBA_DOCOBJ:
2086         {
2087             /* #i111553# This property provides the name of the constant that
2088                will be used to store this model in the global Basic manager.
2089                That constant will be equivalent to 'ThisComponent' but for
2090                each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
2091                constant can co-exist, as required by VBA. */
2092             aAny <<= OUString( "ThisWordDoc" );
2093         }
2094         break;
2095         case WID_DOC_RUNTIME_UID:
2096             aAny <<= getRuntimeUID();
2097         break;
2098         case WID_DOC_LOCK_UPDATES :
2099             aAny <<= m_pDocShell->GetDoc()->IsInReading();
2100         break;
2101         case WID_DOC_BUILDID:
2102             aAny <<= maBuildId;
2103         break;
2104         case WID_DOC_HAS_VALID_SIGNATURES:
2105             aAny <<= hasValidSignatures();
2106         break;
2107         case WID_DOC_INTEROP_GRAB_BAG:
2108              getGrabBagItem(aAny);
2109         break;
2110 
2111         default:
2112         {
2113             const SfxPoolItem& rItem = m_pDocShell->GetDoc()->GetDefault(pEntry->nWID);
2114             rItem.QueryValue(aAny, pEntry->nMemberId);
2115         }
2116     }
2117     return aAny;
2118 }
2119 
2120 void SwXTextDocument::addPropertyChangeListener(const OUString& /*PropertyName*/,
2121     const Reference< XPropertyChangeListener > & /*aListener*/)
2122 {
2123     OSL_FAIL("not implemented");
2124 }
2125 
2126 void SwXTextDocument::removePropertyChangeListener(const OUString& /*PropertyName*/,
2127     const Reference< XPropertyChangeListener > & /*aListener*/)
2128 {
2129     OSL_FAIL("not implemented");
2130 }
2131 
2132 void SwXTextDocument::addVetoableChangeListener(const OUString& /*PropertyName*/,
2133     const Reference< XVetoableChangeListener > & /*aListener*/)
2134 {
2135     OSL_FAIL("not implemented");
2136 }
2137 
2138 void SwXTextDocument::removeVetoableChangeListener(const OUString& /*PropertyName*/,
2139                         const Reference< XVetoableChangeListener > & /*aListener*/)
2140 {
2141     OSL_FAIL("not implemented");
2142 }
2143 
2144 Reference< XNameAccess >  SwXTextDocument::getLinks()
2145 {
2146     if(!mxLinkTargetSupplier.is())
2147     {
2148         mxLinkTargetSupplier = new SwXLinkTargetSupplier(*this);
2149     }
2150     return mxLinkTargetSupplier;
2151 }
2152 
2153 Reference< XEnumerationAccess > SwXTextDocument::getRedlines(  )
2154 {
2155     if(!mxXRedlines.is())
2156     {
2157         mxXRedlines = new SwXRedlines(m_pDocShell->GetDoc());
2158     }
2159     return mxXRedlines;
2160 }
2161 
2162 void SwXTextDocument::NotifyRefreshListeners()
2163 {
2164     // why does SwBaseShell not just call refresh? maybe because it's rSh is
2165     // (sometimes) a different shell than GetWrtShell()?
2166     lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this));
2167     std::unique_lock aGuard(m_pImpl->m_Mutex);
2168     m_pImpl->m_RefreshListeners.notifyEach(aGuard,
2169             & util::XRefreshListener::refreshed, ev);
2170 }
2171 
2172 void SwXTextDocument::refresh()
2173 {
2174     SolarMutexGuard aGuard;
2175     if(!IsValid())
2176         throw DisposedException("", static_cast< XTextDocument* >(this));
2177 
2178     SwViewShell *pViewShell = m_pDocShell->GetWrtShell();
2179     NotifyRefreshListeners();
2180     if(pViewShell)
2181         pViewShell->Reformat();
2182 }
2183 
2184 void SAL_CALL SwXTextDocument::addRefreshListener(
2185         const Reference<util::XRefreshListener> & xListener)
2186 {
2187     if (xListener)
2188     {
2189         std::unique_lock aGuard(m_pImpl->m_Mutex);
2190         m_pImpl->m_RefreshListeners.addInterface(aGuard, xListener);
2191     }
2192 }
2193 
2194 void SAL_CALL SwXTextDocument::removeRefreshListener(
2195         const Reference<util::XRefreshListener> & xListener)
2196 {
2197     if (xListener)
2198     {
2199         std::unique_lock aGuard(m_pImpl->m_Mutex);
2200         m_pImpl->m_RefreshListeners.removeInterface(aGuard, xListener);
2201     }
2202 }
2203 
2204 void SwXTextDocument::updateLinks(  )
2205 {
2206     SolarMutexGuard aGuard;
2207     if(!IsValid())
2208         throw DisposedException("", static_cast< XTextDocument* >(this));
2209 
2210     SwDoc* pDoc = m_pDocShell->GetDoc();
2211     sfx2::LinkManager& rLnkMan = pDoc->getIDocumentLinksAdministration().GetLinkManager();
2212     if( !rLnkMan.GetLinks().empty() )
2213     {
2214         UnoActionContext aAction(pDoc);
2215         rLnkMan.UpdateAllLinks( false, true, nullptr );
2216     }
2217 }
2218 
2219 //XPropertyState
2220 PropertyState SAL_CALL SwXTextDocument::getPropertyState( const OUString& rPropertyName )
2221 {
2222     SolarMutexGuard aGuard;
2223     if(!IsValid())
2224         throw DisposedException("", static_cast< XTextDocument* >(this));
2225 
2226     const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
2227     if(!pEntry)
2228         throw UnknownPropertyException(rPropertyName);
2229     return PropertyState_DIRECT_VALUE;
2230 }
2231 
2232 Sequence< PropertyState > SAL_CALL SwXTextDocument::getPropertyStates( const Sequence< OUString >& rPropertyNames )
2233 {
2234     const sal_Int32 nCount = rPropertyNames.getLength();
2235     Sequence < PropertyState > aRet ( nCount );
2236 
2237     std::transform(rPropertyNames.begin(), rPropertyNames.end(), aRet.getArray(),
2238         [this](const OUString& rName) -> PropertyState { return getPropertyState(rName); });
2239 
2240     return aRet;
2241 }
2242 
2243 void SAL_CALL SwXTextDocument::setPropertyToDefault( const OUString& rPropertyName )
2244 {
2245     SolarMutexGuard aGuard;
2246     if(!IsValid())
2247         throw DisposedException("", static_cast< XTextDocument* >(this));
2248 
2249     const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
2250     if(!pEntry)
2251         throw UnknownPropertyException(rPropertyName);
2252     switch(pEntry->nWID)
2253     {
2254         case 0:default:break;
2255     }
2256 }
2257 
2258 Any SAL_CALL SwXTextDocument::getPropertyDefault( const OUString& rPropertyName )
2259 {
2260     SolarMutexGuard aGuard;
2261     if(!IsValid())
2262         throw DisposedException("", static_cast< XTextDocument* >(this));
2263 
2264     const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
2265     if(!pEntry)
2266         throw UnknownPropertyException(rPropertyName);
2267     Any aAny;
2268     switch(pEntry->nWID)
2269     {
2270         case 0:default:break;
2271     }
2272     return aAny;
2273 }
2274 
2275 static VclPtr< OutputDevice > lcl_GetOutputDevice( const SwPrintUIOptions &rPrintUIOptions )
2276 {
2277     VclPtr< OutputDevice > pOut;
2278 
2279     uno::Any aAny( rPrintUIOptions.getValue( "RenderDevice" ));
2280     uno::Reference< awt::XDevice >  xRenderDevice;
2281     aAny >>= xRenderDevice;
2282     if (xRenderDevice.is())
2283     {
2284         VCLXDevice*     pDevice = comphelper::getFromUnoTunnel<VCLXDevice>( xRenderDevice );
2285         pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >();
2286     }
2287 
2288     return pOut;
2289 }
2290 
2291 static bool lcl_SeqHasProperty(
2292     const uno::Sequence< beans::PropertyValue >& rOptions,
2293     const char *pPropName )
2294 {
2295     return std::any_of(rOptions.begin(), rOptions.end(),
2296         [&pPropName](const beans::PropertyValue& rProp) {
2297             return rProp.Name.equalsAscii( pPropName ); });
2298 }
2299 
2300 static bool lcl_GetBoolProperty(
2301     const uno::Sequence< beans::PropertyValue >& rOptions,
2302     const char *pPropName )
2303 {
2304     bool bRes = false;
2305     auto pOption = std::find_if(rOptions.begin(), rOptions.end(),
2306         [&pPropName](const beans::PropertyValue& rProp) {
2307             return rProp.Name.equalsAscii( pPropName ); });
2308     if (pOption != rOptions.end())
2309         pOption->Value >>= bRes;
2310     return bRes;
2311 }
2312 
2313 SfxViewShell * SwXTextDocument::GetRenderView(
2314     bool &rbIsSwSrcView,
2315     const uno::Sequence< beans::PropertyValue >& rOptions,
2316     bool bIsPDFExport )
2317 {
2318     // get view shell to use
2319     SfxViewShell *pView = nullptr;
2320     if (bIsPDFExport)
2321         pView = GuessViewShell( rbIsSwSrcView );
2322     else
2323     {
2324         uno::Any aTmp;
2325         auto pOption = std::find_if(rOptions.begin(), rOptions.end(),
2326             [](const beans::PropertyValue& rProp) { return rProp.Name == "View"; });
2327         if (pOption != rOptions.end())
2328             aTmp = pOption->Value;
2329 
2330         uno::Reference< frame::XController > xController;
2331         if (aTmp >>= xController)
2332         {
2333             OSL_ENSURE( xController.is(), "controller is empty!" );
2334             pView = GuessViewShell( rbIsSwSrcView, xController );
2335         }
2336     }
2337     return pView;
2338 }
2339 
2340 /*
2341  *  GetRenderDoc:
2342  *  returns the document to be rendered, usually this will be the 'regular'
2343  *  document but in case of PDF export of (multi-)selection it will
2344  *  be a temporary document that gets created if not already done.
2345  *  The rpView variable will be set (if not already done) to the used
2346  *  SfxViewShell.
2347 */
2348 SwDoc * SwXTextDocument::GetRenderDoc(
2349     SfxViewShell *&rpView,
2350     const uno::Any& rSelection,
2351     bool bIsPDFExport )
2352 {
2353     SwDoc *pDoc = nullptr;
2354 
2355     uno::Reference< frame::XModel > xModel;
2356     rSelection >>= xModel;
2357     if (xModel == m_pDocShell->GetModel())
2358         pDoc = m_pDocShell->GetDoc();
2359     else
2360     {
2361         OSL_ENSURE( !xModel.is(), "unexpected model found" );
2362 
2363         if (rSelection.hasValue())     // is anything selected ?
2364         {
2365             // this part should only be called when a temporary document needs to be created,
2366             // for example for PDF export or printing of (multi-)selection only.
2367 
2368             if (!rpView)
2369             {
2370                 bool bIsSwSrcView = false;
2371                 // aside from maybe PDF export the view should always have been provided!
2372                 OSL_ENSURE( bIsPDFExport, "view is missing, guessing one..." );
2373 
2374                 rpView = GuessViewShell( bIsSwSrcView );
2375             }
2376             OSL_ENSURE( rpView, "SwViewShell missing" );
2377             // the view shell should be SwView for documents PDF export.
2378             // for the page preview no selection should be possible
2379             // (the export dialog does not allow for this option)
2380             if (auto pSwView = dynamic_cast<SwView *>( rpView ))
2381             {
2382                 if (!m_pRenderData)
2383                 {
2384                     OSL_FAIL("GetRenderDoc: no renderdata");
2385                     return nullptr;
2386                 }
2387                 SfxObjectShellLock xDocSh(m_pRenderData->GetTempDocShell());
2388                 if (!xDocSh.Is())
2389                 {
2390                     xDocSh = pSwView->CreateTmpSelectionDoc();
2391                     m_pRenderData->SetTempDocShell(xDocSh);
2392                 }
2393                 if (xDocSh.Is())
2394                 {
2395                     pDoc = static_cast<SwDocShell*>(&xDocSh)->GetDoc();
2396                     rpView = pDoc->GetDocShell()->GetView();
2397                 }
2398             }
2399             else
2400             {
2401                 OSL_FAIL("unexpected SwViewShell" );
2402             }
2403         }
2404     }
2405     return pDoc;
2406 }
2407 
2408 static void lcl_SavePrintUIOptionsToDocumentPrintData(
2409     SwDoc &rDoc,
2410     const SwPrintUIOptions &rPrintUIOptions,
2411     bool bIsPDFEXport )
2412 {
2413     SwPrintData aDocPrintData( rDoc.getIDocumentDeviceAccess().getPrintData() );
2414 
2415     aDocPrintData.SetPrintGraphic( rPrintUIOptions.IsPrintGraphics() );
2416     aDocPrintData.SetPrintTable( true ); // for now it was decided that tables should always be printed
2417     aDocPrintData.SetPrintDraw( rPrintUIOptions.IsPrintDrawings() );
2418     aDocPrintData.SetPrintControl( rPrintUIOptions.IsPrintFormControls() );
2419     aDocPrintData.SetPrintLeftPage( rPrintUIOptions.IsPrintLeftPages() );
2420     aDocPrintData.SetPrintRightPage( rPrintUIOptions.IsPrintRightPages() );
2421     aDocPrintData.SetPrintReverse( false ); /*handled by print dialog now*/
2422     aDocPrintData.SetPaperFromSetup( rPrintUIOptions.IsPaperFromSetup() );
2423     aDocPrintData.SetPrintEmptyPages( rPrintUIOptions.IsPrintEmptyPages( bIsPDFEXport ) );
2424     aDocPrintData.SetPrintPostIts( rPrintUIOptions.GetPrintPostItsType() );
2425     aDocPrintData.SetPrintProspect( rPrintUIOptions.IsPrintProspect() );
2426     aDocPrintData.SetPrintProspect_RTL( rPrintUIOptions.IsPrintProspectRTL() );
2427     aDocPrintData.SetPrintPageBackground( rPrintUIOptions.IsPrintPageBackground() );
2428     aDocPrintData.SetPrintBlackFont( rPrintUIOptions.IsPrintWithBlackTextColor() );
2429     // aDocPrintData.SetPrintSingleJobs( b ); handled by File/Print dialog itself
2430     // arDocPrintData.SetFaxName( s ); n/a in File/Print dialog
2431     aDocPrintData.SetPrintHiddenText( rPrintUIOptions.IsPrintHiddenText() );
2432     aDocPrintData.SetPrintTextPlaceholder( rPrintUIOptions.IsPrintTextPlaceholders() );
2433 
2434     rDoc.getIDocumentDeviceAccess().setPrintData( aDocPrintData );
2435 }
2436 
2437 sal_Int32 SAL_CALL SwXTextDocument::getRendererCount(
2438         const uno::Any& rSelection,
2439         const uno::Sequence< beans::PropertyValue >& rxOptions )
2440 {
2441     SolarMutexGuard aGuard;
2442     if(!IsValid())
2443     {
2444         throw DisposedException( OUString(),
2445                 static_cast< XTextDocument* >(this) );
2446     }
2447 
2448     const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" );
2449     bool bIsSwSrcView = false;
2450     SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
2451 
2452     if (!bIsSwSrcView && !m_pRenderData)
2453         m_pRenderData.reset(new SwRenderData);
2454     if (!m_pPrintUIOptions)
2455         m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
2456     bool bFormat = m_pPrintUIOptions->processPropertiesAndCheckFormat( rxOptions );
2457 
2458     SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
2459     OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
2460     if (!pDoc || !pView)
2461         return 0;
2462 
2463     // save current UI options from the print dialog for the next call to that dialog
2464     lcl_SavePrintUIOptionsToDocumentPrintData( *pDoc, *m_pPrintUIOptions, bIsPDFExport );
2465 
2466     sal_Int32 nRet = 0;
2467     if (bIsSwSrcView)
2468     {
2469         SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView);
2470         VclPtr< OutputDevice> pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
2471         nRet = rSwSrcView.PrintSource( pOutDev, 1 /* dummy */, true /* get page count only */ );
2472     }
2473     else
2474     {
2475         SwDocShell *pRenderDocShell = pDoc->GetDocShell();
2476 
2477         // TODO/mba: we really need a generic way to get the SwViewShell!
2478         SwViewShell* pViewShell = nullptr;
2479         SwView* pSwView = dynamic_cast<SwView*>( pView );
2480         if ( pSwView )
2481         {
2482             pViewShell = pSwView->GetWrtShellPtr();
2483         }
2484         else
2485         {
2486             if ( bIsPDFExport && bFormat )
2487             {
2488                 //create a hidden view to be able to export as PDF also in print preview
2489                 //pView and pSwView are not changed intentionally!
2490                 m_pHiddenViewFrame = SfxViewFrame::LoadHiddenDocument( *pRenderDocShell, SFX_INTERFACE_SFXDOCSH );
2491                 pViewShell = static_cast<SwView*>(m_pHiddenViewFrame->GetViewShell())->GetWrtShellPtr();
2492             }
2493             else
2494                 pViewShell = static_cast<SwPagePreview*>(pView)->GetViewShell();
2495         }
2496 
2497         if (!pViewShell || !pViewShell->GetLayout())
2498             return 0;
2499 
2500         if (bFormat)
2501         {
2502             // #i38289
2503             if( pViewShell->GetViewOptions()->getBrowseMode() ||
2504                 pViewShell->GetViewOptions()->IsWhitespaceHidden() )
2505             {
2506                 SwViewOption aOpt( *pViewShell->GetViewOptions() );
2507                 aOpt.setBrowseMode( false );
2508                 aOpt.SetHideWhitespaceMode( false );
2509                 pViewShell->ApplyViewOptions( aOpt );
2510                 if (pSwView)
2511                 {
2512                     pSwView->RecheckBrowseMode();
2513                 }
2514             }
2515 
2516             // reformatting the document for printing will show the changes in the view
2517             // which is likely to produce many unwanted and not nice to view actions.
2518             // We don't want that! Thus we disable updating of the view.
2519             pViewShell->StartAction();
2520 
2521             if (pSwView)
2522             {
2523                 if (m_pRenderData && m_pRenderData->NeedNewViewOptionAdjust( *pViewShell ) )
2524                     m_pRenderData->ViewOptionAdjustStop();
2525                 if (m_pRenderData && !m_pRenderData->IsViewOptionAdjust())
2526                 {
2527                     m_pRenderData->ViewOptionAdjustStart(
2528                         *pViewShell, *pViewShell->GetViewOptions() );
2529                 }
2530             }
2531 
2532             m_pRenderData->MakeSwPrtOptions( pRenderDocShell,
2533                     m_pPrintUIOptions.get(), bIsPDFExport );
2534 
2535             if (pSwView)
2536             {
2537                 // PDF export should not make use of the SwPrtOptions
2538                 const SwPrintData *pPrtOptions = bIsPDFExport
2539                     ? nullptr : m_pRenderData->GetSwPrtOptions();
2540                 bool setShowPlaceHoldersInPDF = false;
2541                 if(bIsPDFExport)
2542                     setShowPlaceHoldersInPDF = lcl_GetBoolProperty( rxOptions, "ExportPlaceholders" );
2543                 m_pRenderData->ViewOptionAdjust( pPrtOptions, setShowPlaceHoldersInPDF );
2544             }
2545 
2546             // since printing now also use the API for PDF export this option
2547             // should be set for printing as well ...
2548             pViewShell->SetPDFExportOption( true );
2549 
2550             // there is some redundancy between those two function calls, but right now
2551             // there is no time to sort this out.
2552             //TODO: check what exactly needs to be done and make just one function for that
2553             pViewShell->CalcLayout();
2554 
2555             // #122919# Force field update before PDF export, but after layout init (tdf#121962)
2556             bool bStateChanged = false;
2557             // check configuration: shall update of printing information in DocInfo set the document to "modified"?
2558             if (pRenderDocShell->IsEnableSetModified() && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
2559             {
2560                 pRenderDocShell->EnableSetModified( false );
2561                 bStateChanged = true;
2562             }
2563             pViewShell->SwViewShell::UpdateFields(true);
2564             if( bStateChanged )
2565                 pRenderDocShell->EnableSetModified();
2566 
2567             pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() );
2568 
2569             pViewShell->SetPDFExportOption( false );
2570 
2571             // enable view again
2572             pViewShell->EndAction();
2573         }
2574 
2575         const sal_Int32 nPageCount = pViewShell->GetPageCount();
2576 
2577         // get number of pages to be rendered
2578 
2579         const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
2580         if (bPrintProspect)
2581         {
2582             SwDoc::CalculatePagePairsForProspectPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, nPageCount );
2583             nRet = m_pRenderData->GetPagePairsForProspectPrinting().size();
2584         }
2585         else
2586         {
2587             const SwPostItMode nPostItMode = static_cast<SwPostItMode>( m_pPrintUIOptions->getIntValue( "PrintAnnotationMode", 0 ) );
2588             if (nPostItMode != SwPostItMode::NONE)
2589             {
2590                 VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
2591                 m_pRenderData->CreatePostItData(*pDoc, pViewShell->GetViewOptions(), pOutDev);
2592             }
2593 
2594             // get set of valid document pages (according to the current settings)
2595             // and their start frames
2596             SwDoc::CalculatePagesForPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, bIsPDFExport, nPageCount );
2597 
2598             if (nPostItMode != SwPostItMode::NONE)
2599             {
2600                 SwDoc::UpdatePagesForPrintingWithPostItData( *m_pRenderData,
2601                         *m_pPrintUIOptions, nPageCount );
2602             }
2603 
2604             nRet = m_pRenderData->GetPagesToPrint().size();
2605         }
2606     }
2607     OSL_ENSURE( nRet >= 0, "negative number of pages???" );
2608     // tdf#144989 the layout is complete now - prevent DoIdleJobs() from
2609     // messing it up, particulary SwDocUpdateField::MakeFieldList_() unhiding
2610     // sections
2611     pDoc->getIDocumentTimerAccess().BlockIdling();
2612 
2613     return nRet;
2614 }
2615 
2616 uno::Sequence< beans::PropertyValue > SAL_CALL SwXTextDocument::getRenderer(
2617         sal_Int32 nRenderer,
2618         const uno::Any& rSelection,
2619         const uno::Sequence< beans::PropertyValue >& rxOptions )
2620 {
2621     SolarMutexGuard aGuard;
2622     if(!IsValid())
2623     {
2624         throw DisposedException("", static_cast< XTextDocument* >(this));
2625     }
2626 
2627     const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" );
2628     bool bIsSwSrcView = false;
2629     SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
2630 
2631     // m_pRenderData should NOT be created here!
2632     // That should only be done in getRendererCount. If this function is called before
2633     // getRendererCount was called then the caller will probably just retrieve the extra UI options
2634     // and is not interested in getting valid information about the other data that would
2635     // otherwise be provided here!
2636 //    if( ! m_pRenderData )
2637 //        m_pRenderData = new SwRenderData;
2638     if (!m_pPrintUIOptions)
2639         m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
2640     m_pPrintUIOptions->processProperties( rxOptions );
2641     const bool bPrintProspect    = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
2642     const bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport );
2643     const bool bPrintPaperFromSetup = m_pPrintUIOptions->getBoolValue( "PrintPaperFromSetup" );
2644 
2645     SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
2646     OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
2647     if (!pDoc || !pView)
2648         return uno::Sequence< beans::PropertyValue >();
2649 
2650     // due to #110067# (document page count changes sometimes during
2651     // PDF export/printing) we can not check for the upper bound properly.
2652     // Thus instead of throwing the exception we silently return.
2653     if (0 > nRenderer)
2654         throw IllegalArgumentException();
2655 
2656     // TODO/mba: we really need a generic way to get the SwViewShell!
2657     SwViewShell* pVwSh = nullptr;
2658     SwView* pSwView = dynamic_cast<SwView*>( pView );
2659     if ( pSwView )
2660         pVwSh = pSwView->GetWrtShellPtr();
2661     else
2662         pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell();
2663 
2664     sal_Int32 nMaxRenderer = 0;
2665     if (!bIsSwSrcView && m_pRenderData)
2666     {
2667         OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" );
2668         nMaxRenderer = bPrintProspect?
2669             m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 :
2670             m_pRenderData->GetPagesToPrint().size() - 1;
2671     }
2672     // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print
2673     // we obmit checking of the upper bound in this case.
2674     if (!bIsSwSrcView && m_pRenderData && nRenderer > nMaxRenderer)
2675         return uno::Sequence< beans::PropertyValue >();
2676 
2677     uno::Sequence< beans::PropertyValue > aRenderer;
2678     if (m_pRenderData)
2679     {
2680         // #i114210#
2681         // determine the correct page number from the renderer index
2682         // #i114875
2683         // consider brochure print
2684         const sal_Int32 nPage = bPrintProspect
2685                              ? nRenderer + 1
2686                              : m_pRenderData->GetPagesToPrint()[ nRenderer ];
2687 
2688         // get paper tray to use ...
2689         sal_Int32 nPrinterPaperTray = -1;
2690         if (! bPrintPaperFromSetup)
2691         {
2692             // ... from individual page style (see the page tab in Format/Page dialog)
2693             const std::map< sal_Int32, sal_Int32 > &rPaperTrays = m_pRenderData->GetPrinterPaperTrays();
2694             std::map< sal_Int32, sal_Int32 >::const_iterator aIt( rPaperTrays.find( nPage ) );
2695             if (aIt != rPaperTrays.end())
2696                 nPrinterPaperTray = aIt->second;
2697         }
2698 
2699         awt::Size aPageSize;
2700         awt::Point aPagePos;
2701         awt::Size aPreferredPageSize;
2702         Size aTmpSize;
2703         if (bIsSwSrcView || bPrintProspect)
2704         {
2705             // for printing of HTML source code and prospect printing we should use
2706             // the printers paper size since
2707             // a) HTML source view has no page size
2708             // b) prospect printing has a different page size from the documents page
2709             //    since two document pages will get rendered on one printer page
2710 
2711             // since PageIncludesNonprintableArea will be set to true we can return the
2712             // printers paper size here.
2713             // Sometimes 'getRenderer' is only called to get "ExtraPrintUIOptions", in this
2714             // case we won't get an OutputDevice here, but then the caller also has no need
2715             // for the correct PageSize right now...
2716             VclPtr< Printer > pPrinter = dynamic_cast< Printer * >(lcl_GetOutputDevice( *m_pPrintUIOptions ).get());
2717             if (pPrinter)
2718             {
2719                 // HTML source view and prospect adapt to the printer's paper size
2720                 aTmpSize = pPrinter->GetPaperSize();
2721                 aTmpSize = OutputDevice::LogicToLogic( aTmpSize,
2722                             pPrinter->GetMapMode(), MapMode( MapUnit::Map100thMM ));
2723                 aPageSize = awt::Size( aTmpSize.Width(), aTmpSize.Height() );
2724                 #if 0
2725                 // #i115048# it seems users didn't like getting double the formatted page size
2726                 // revert to "old" behavior scaling to the current paper size of the printer
2727                 if (bPrintProspect)
2728                 {
2729                     // we just state what output size we would need
2730                     // which may cause vcl to set that page size on the printer
2731                     // (if available and not overridden by the user)
2732                     aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages );
2733                     aPreferredPageSize = awt::Size ( convertTwipToMm100( 2 * aTmpSize.Width() ),
2734                                                      convertTwipToMm100( aTmpSize.Height() ));
2735                 }
2736                 #else
2737                 if( bPrintProspect )
2738                 {
2739                     // just switch to an appropriate portrait/landscape format
2740                     // FIXME: brochure printing with landscape pages puts the
2741                     // pages next to each other, so landscape is currently always
2742                     // the better choice
2743                     if( aPageSize.Width < aPageSize.Height )
2744                     {
2745                         aPreferredPageSize.Width = aPageSize.Height;
2746                         aPreferredPageSize.Height = aPageSize.Width;
2747                     }
2748                 }
2749                 #endif
2750             }
2751         }
2752         else
2753         {
2754             aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages );
2755             aPageSize = awt::Size ( convertTwipToMm100( aTmpSize.Width() ),
2756                                     convertTwipToMm100( aTmpSize.Height() ));
2757             Point aPoint = pVwSh->GetPagePos(nPage);
2758             aPagePos = awt::Point(convertTwipToMm100(aPoint.X()), convertTwipToMm100(aPoint.Y()));
2759         }
2760 
2761         sal_Int32 nLen = 3;
2762         aRenderer = { comphelper::makePropertyValue("PageSize", aPageSize),
2763                       comphelper::makePropertyValue("PageIncludesNonprintableArea", true),
2764                       comphelper::makePropertyValue("PagePos", aPagePos) };
2765         if (aPreferredPageSize.Width && aPreferredPageSize.Height)
2766         {
2767             ++nLen;
2768             aRenderer.realloc( nLen );
2769             auto pRenderer = aRenderer.getArray();
2770             pRenderer[ nLen - 1 ].Name  = "PreferredPageSize";
2771             pRenderer[ nLen - 1 ].Value <<= aPreferredPageSize;
2772         }
2773         if (nPrinterPaperTray >= 0)
2774         {
2775             ++nLen;
2776             aRenderer.realloc( nLen );
2777             auto pRenderer = aRenderer.getArray();
2778             pRenderer[ nLen - 1 ].Name  = "PrinterPaperTray";
2779             pRenderer[ nLen - 1 ].Value <<= nPrinterPaperTray;
2780         }
2781     }
2782 
2783     // #i117783#
2784     if ( m_bApplyPagePrintSettingsFromXPagePrintable )
2785     {
2786         const SwPagePreviewPrtData* pPagePrintSettings =
2787                                         m_pDocShell->GetDoc()->GetPreviewPrtData();
2788         if ( pPagePrintSettings &&
2789              ( pPagePrintSettings->GetRow() > 1 ||
2790                pPagePrintSettings->GetCol() > 1 ) )
2791         {
2792             // extend render data by page print settings attributes
2793             sal_Int32 nLen = aRenderer.getLength();
2794             const sal_Int32 nRenderDataIdxStart = nLen;
2795             nLen += 9;
2796             aRenderer.realloc( nLen );
2797             auto pRenderer = aRenderer.getArray();
2798             // put page print settings attribute into render data
2799             const sal_Int32 nRow = pPagePrintSettings->GetRow();
2800             pRenderer[ nRenderDataIdxStart + 0 ].Name  = "NUpRows";
2801             pRenderer[ nRenderDataIdxStart + 0 ].Value <<= std::max<sal_Int32>( nRow, 1);
2802             const sal_Int32 nCol = pPagePrintSettings->GetCol();
2803             pRenderer[ nRenderDataIdxStart + 1 ].Name  = "NUpColumns";
2804             pRenderer[ nRenderDataIdxStart + 1 ].Value <<= std::max<sal_Int32>( nCol, 1);
2805             pRenderer[ nRenderDataIdxStart + 2 ].Name  = "NUpPageMarginLeft";
2806             pRenderer[ nRenderDataIdxStart + 2 ].Value <<= pPagePrintSettings->GetLeftSpace();
2807             pRenderer[ nRenderDataIdxStart + 3 ].Name  = "NUpPageMarginRight";
2808             pRenderer[ nRenderDataIdxStart + 3 ].Value <<= pPagePrintSettings->GetRightSpace();
2809             pRenderer[ nRenderDataIdxStart + 4 ].Name  = "NUpPageMarginTop";
2810             pRenderer[ nRenderDataIdxStart + 4 ].Value <<= pPagePrintSettings->GetTopSpace();
2811             pRenderer[ nRenderDataIdxStart + 5 ].Name  = "NUpPageMarginBottom";
2812             pRenderer[ nRenderDataIdxStart + 5 ].Value <<= pPagePrintSettings->GetBottomSpace();
2813             pRenderer[ nRenderDataIdxStart + 6 ].Name  = "NUpHorizontalSpacing";
2814             pRenderer[ nRenderDataIdxStart + 6 ].Value <<= pPagePrintSettings->GetHorzSpace();
2815             pRenderer[ nRenderDataIdxStart + 7 ].Name  = "NUpVerticalSpacing";
2816             pRenderer[ nRenderDataIdxStart + 7 ].Value <<= pPagePrintSettings->GetVertSpace();
2817             {
2818                 Printer* pPrinter = m_pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrinter( false );
2819                 if ( pPrinter )
2820                 {
2821                     awt::Size aNewPageSize;
2822                     const Size aPageSize = pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM ) );
2823                     aNewPageSize = awt::Size( aPageSize.Width(), aPageSize.Height() );
2824                     if ( ( pPagePrintSettings->GetLandscape() &&
2825                            aPageSize.Width() < aPageSize.Height() ) ||
2826                          ( !pPagePrintSettings->GetLandscape() &&
2827                            aPageSize.Width() > aPageSize.Height() ) )
2828                     {
2829                         aNewPageSize = awt::Size( aPageSize.Height(), aPageSize.Width() );
2830                     }
2831                     pRenderer[ nRenderDataIdxStart + 8 ].Name  = "NUpPaperSize";
2832                     pRenderer[ nRenderDataIdxStart + 8 ].Value <<= aNewPageSize;
2833                 }
2834             }
2835         }
2836 
2837         m_bApplyPagePrintSettingsFromXPagePrintable = false;
2838     }
2839 
2840     m_pPrintUIOptions->appendPrintUIOptions( aRenderer );
2841 
2842     return aRenderer;
2843 }
2844 
2845 SfxViewShell * SwXTextDocument::GuessViewShell(
2846     /* out */ bool &rbIsSwSrcView,
2847     const uno::Reference< css::frame::XController >& rController )
2848 {
2849     // #130810# SfxViewShell::Current() / SfxViewShell::GetObjectShell()
2850     // must not be used (see comment from MBA)
2851 
2852     SfxViewShell    *pView = nullptr;
2853     SwView          *pSwView = nullptr;
2854     SwPagePreview   *pSwPagePreview = nullptr;
2855     SwSrcView       *pSwSrcView = nullptr;
2856     SfxViewFrame    *pFrame = SfxViewFrame::GetFirst( m_pDocShell, false );
2857 
2858     // look for the view shell with the same controller in use,
2859     // otherwise look for a suitable view, preferably a SwView,
2860     // if that one is not found use a SwPagePreview if found.
2861     while (pFrame)
2862     {
2863         pView = pFrame->GetViewShell();
2864         pSwView = dynamic_cast< SwView * >(pView);
2865         pSwSrcView = dynamic_cast< SwSrcView * >(pView);
2866         if (!pSwPagePreview)
2867             pSwPagePreview = dynamic_cast< SwPagePreview * >(pView);
2868         if (rController.is())
2869         {
2870             if (pView && pView->GetController() == rController)
2871                 break;
2872         }
2873         else if (pSwView || pSwSrcView)
2874             break;
2875         pFrame = SfxViewFrame::GetNext( *pFrame, m_pDocShell,  false );
2876     }
2877 
2878     OSL_ENSURE( pSwView || pSwPagePreview || pSwSrcView, "failed to get view shell" );
2879     if (pView)
2880         rbIsSwSrcView = pSwSrcView != nullptr;
2881     return pView;
2882 }
2883 
2884 void SAL_CALL SwXTextDocument::render(
2885         sal_Int32 nRenderer,
2886         const uno::Any& rSelection,
2887         const uno::Sequence< beans::PropertyValue >& rxOptions )
2888 {
2889     SolarMutexGuard aGuard;
2890     if(!IsValid())
2891     {
2892         throw DisposedException( OUString(),
2893                 static_cast< XTextDocument* >(this) );
2894     }
2895 
2896     // due to #110067# (document page count changes sometimes during
2897     // PDF export/printing) we can not check for the upper bound properly.
2898     // Thus instead of throwing the exception we silently return.
2899     if (0 > nRenderer)
2900         throw IllegalArgumentException();
2901 
2902     // tdf#135244: prevent jumping to cursor at any temporary modification
2903     auto aLock = m_pDocShell->LockAllViews();
2904 
2905     const bool bHasPDFExtOutDevData = lcl_SeqHasProperty( rxOptions, "HasPDFExtOutDevData" );
2906     const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ) || bHasPDFExtOutDevData;
2907     bool bIsSwSrcView = false;
2908     SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
2909 
2910     OSL_ENSURE( m_pRenderData, "data should have been created already in getRendererCount..." );
2911     OSL_ENSURE( m_pPrintUIOptions, "data should have been created already in getRendererCount..." );
2912     if (!bIsSwSrcView && !m_pRenderData)
2913         m_pRenderData.reset(new SwRenderData);
2914     if (!m_pPrintUIOptions)
2915         m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
2916     m_pPrintUIOptions->processProperties( rxOptions );
2917     const bool bPrintProspect   = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
2918     const bool bLastPage        = m_pPrintUIOptions->getBoolValue( "IsLastPage" );
2919 
2920     SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
2921     OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
2922     if (pDoc && pView)
2923     {
2924         sal_Int32 nMaxRenderer = 0;
2925         if (!bIsSwSrcView)
2926         {
2927             OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" );
2928             nMaxRenderer = bPrintProspect?
2929                 m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 :
2930                 m_pRenderData->GetPagesToPrint().size() - 1;
2931         }
2932         // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print
2933         // we obmit checking of the upper bound in this case.
2934         if (bIsSwSrcView || nRenderer <= nMaxRenderer)
2935         {
2936             if (bIsSwSrcView)
2937             {
2938                 SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView);
2939                 VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
2940                 rSwSrcView.PrintSource(pOutDev, nRenderer + 1, false);
2941             }
2942             else
2943             {
2944                 // the view shell should be SwView for documents PDF export
2945                 // or SwPagePreview for PDF export of the page preview
2946                 SwViewShell* pVwSh = nullptr;
2947                 // TODO/mba: we really need a generic way to get the SwViewShell!
2948                 const SwView* pSwView = dynamic_cast<const SwView*>(pView);
2949                 if (pSwView)
2950                     pVwSh = pSwView->GetWrtShellPtr();
2951                 else
2952                     pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell();
2953 
2954                 // get output device to use
2955                 VclPtr< OutputDevice > pOut = lcl_GetOutputDevice( *m_pPrintUIOptions );
2956 
2957                 if(pVwSh && pOut && m_pRenderData->HasSwPrtOptions())
2958                 {
2959                     const OUString aPageRange  = m_pPrintUIOptions->getStringValue( "PageRange" );
2960                     const bool bFirstPage           = m_pPrintUIOptions->getBoolValue( "IsFirstPage" );
2961                     bool bIsSkipEmptyPages          = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport );
2962 
2963                     OSL_ENSURE((pSwView && m_pRenderData->IsViewOptionAdjust())
2964                             || (!pSwView && !m_pRenderData->IsViewOptionAdjust()),
2965                             "SwView / SwViewOptionAdjust_Impl availability mismatch" );
2966 
2967                     // since printing now also use the API for PDF export this option
2968                     // should be set for printing as well ...
2969                     pVwSh->SetPDFExportOption( true );
2970 
2971                     // #i12836# enhanced pdf export
2972 
2973                     // First, we have to export hyperlinks, notes, and outline to pdf.
2974                     // During this process, additional information required for tagging
2975                     // the pdf file are collected, which are evaluated during painting.
2976 
2977                     SwWrtShell* pWrtShell = pSwView ? pSwView->GetWrtShellPtr() : nullptr;
2978 
2979                     SwPrintData rSwPrtOptions = *m_pRenderData->GetSwPrtOptions();
2980 
2981                     if (bIsPDFExport && (bFirstPage || bHasPDFExtOutDevData) && pWrtShell)
2982                     {
2983                         rSwPrtOptions.SetPrintPostIts(
2984                             lcl_GetBoolProperty(rxOptions, "ExportNotesInMargin")
2985                                 ? SwPostItMode::InMargins
2986                                 : SwPostItMode::NONE);
2987                         SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, false, rSwPrtOptions );
2988                     }
2989 
2990                     if (bPrintProspect)
2991                         pVwSh->PrintProspect( pOut, rSwPrtOptions, nRenderer );
2992                     else    // normal printing and PDF export
2993                         pVwSh->PrintOrPDFExport( pOut, rSwPrtOptions, nRenderer, bIsPDFExport );
2994 
2995                     // #i35176#
2996 
2997                     // After printing the last page, we take care for the links coming
2998                     // from the EditEngine. The links are generated during the painting
2999                     // process, but the destinations are still missing.
3000 
3001                     if (bIsPDFExport && bLastPage && pWrtShell)
3002                     {
3003                         SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, true, rSwPrtOptions );
3004                     }
3005 
3006                     pVwSh->SetPDFExportOption( false );
3007 
3008                     // last page to be rendered? (not necessarily the last page of the document)
3009                     // -> do clean-up of data
3010                     if (bLastPage)
3011                     {
3012                         // #i96167# haggai: delete ViewOptionsAdjust here because it makes use
3013                         // of the shell, which might get destroyed in lcl_DisposeView!
3014                         if (m_pRenderData->IsViewOptionAdjust())
3015                             m_pRenderData->ViewOptionAdjustStop();
3016 
3017                         if (m_pRenderData->HasPostItData())
3018                             m_pRenderData->DeletePostItData();
3019                         if (m_pHiddenViewFrame)
3020                         {
3021                             lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell );
3022                             m_pHiddenViewFrame = nullptr;
3023 
3024                             // prevent crash described in #i108805
3025                             SwDocShell *pRenderDocShell = pDoc->GetDocShell();
3026                             SfxItemSet *pSet = pRenderDocShell->GetMedium()->GetItemSet();
3027                             pSet->Put( SfxBoolItem( SID_HIDDEN, false ) );
3028 
3029                         }
3030                     }
3031                 }
3032             }
3033         }
3034     }
3035     if( bLastPage )
3036     {
3037         // tdf#144989 enable DoIdleJobs() again after last page
3038         pDoc->getIDocumentTimerAccess().UnblockIdling();
3039         m_pRenderData.reset();
3040         m_pPrintUIOptions.reset();
3041     }
3042 }
3043 
3044 // xforms::XFormsSupplier
3045 Reference<XNameContainer> SAL_CALL SwXTextDocument::getXForms()
3046 {
3047     SolarMutexGuard aGuard;
3048     if ( !m_pDocShell )
3049         throw DisposedException( OUString(), static_cast< XTextDocument* >( this ) );
3050     SwDoc* pDoc = m_pDocShell->GetDoc();
3051     return pDoc->getXForms();
3052 }
3053 
3054 uno::Reference< text::XFlatParagraphIterator > SAL_CALL SwXTextDocument::getFlatParagraphIterator(::sal_Int32 nTextMarkupType, sal_Bool bAutomatic)
3055 {
3056     SolarMutexGuard aGuard;
3057     if (!IsValid())
3058     {
3059         throw DisposedException("SwXTextDocument not valid",
3060                 static_cast<XTextDocument*>(this));
3061     }
3062 
3063     return SwUnoCursorHelper::CreateFlatParagraphIterator(
3064             *m_pDocShell->GetDoc(), nTextMarkupType, bAutomatic);
3065 }
3066 
3067 uno::Reference< util::XCloneable > SwXTextDocument::createClone(  )
3068 {
3069     SolarMutexGuard aGuard;
3070     if(!IsValid())
3071         throw DisposedException("", static_cast< XTextDocument* >(this));
3072 
3073     // create a new document - hidden - copy the storage and return it
3074     // SfxObjectShellRef is used here, since the model should control object lifetime after creation
3075     // and thus SfxObjectShellLock is not allowed here
3076     // the model holds reference to the shell, so the shell will not destructed at the end of method
3077     SfxObjectShellRef pShell = m_pDocShell->GetDoc()->CreateCopy(false, false);
3078     uno::Reference< frame::XModel > xNewModel = pShell->GetModel();
3079     uno::Reference< embed::XStorage > xNewStorage = ::comphelper::OStorageHelper::GetTemporaryStorage( );
3080     uno::Sequence< beans::PropertyValue > aTempMediaDescriptor;
3081     storeToStorage( xNewStorage, aTempMediaDescriptor );
3082     uno::Reference< document::XStorageBasedDocument > xStorageDoc( xNewModel, uno::UNO_QUERY );
3083     xStorageDoc->loadFromStorage( xNewStorage, aTempMediaDescriptor );
3084     return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY );
3085 }
3086 
3087 void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener)
3088 {
3089     SolarMutexGuard aGuard;
3090 
3091     if (IsValid() && xListener.is())
3092         m_pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener);
3093 }
3094 
3095 void SwXTextDocument::removePasteEventListener(
3096     const uno::Reference<text::XPasteListener>& xListener)
3097 {
3098     SolarMutexGuard aGuard;
3099 
3100     if (IsValid() && xListener.is())
3101         m_pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener);
3102 }
3103 
3104 void SwXTextDocument::paintTile( VirtualDevice &rDevice,
3105                                  int nOutputWidth, int nOutputHeight,
3106                                  int nTilePosX, int nTilePosY,
3107                                  tools::Long nTileWidth, tools::Long nTileHeight )
3108 {
3109     SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
3110     pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight,
3111                           nTilePosX, nTilePosY, nTileWidth, nTileHeight);
3112 
3113     LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
3114                                          nTilePosX, nTilePosY, nTileWidth, nTileHeight);
3115 }
3116 
3117 Size SwXTextDocument::getDocumentSize()
3118 {
3119     SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
3120     Size aDocSize = pViewShell->GetDocSize();
3121 
3122     return Size(aDocSize.Width()  + 2 * DOCUMENTBORDER,
3123                 aDocSize.Height() + 2 * DOCUMENTBORDER);
3124 }
3125 
3126 void SwXTextDocument::setPart(int nPart, bool /*bAllowChangeFocus*/)
3127 {
3128     SolarMutexGuard aGuard;
3129 
3130     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3131     if (!pWrtShell)
3132         return;
3133 
3134     pWrtShell->GotoPage(nPart + 1, true);
3135 }
3136 
3137 int SwXTextDocument::getParts()
3138 {
3139     SolarMutexGuard aGuard;
3140 
3141     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3142     if (!pWrtShell)
3143         return 0;
3144 
3145     return pWrtShell->GetPageCnt();
3146 }
3147 
3148 OUString SwXTextDocument::getPartPageRectangles()
3149 {
3150     SolarMutexGuard aGuard;
3151 
3152     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3153     if (!pWrtShell)
3154         return OUString();
3155 
3156     return pWrtShell->getPageRectangles();
3157 }
3158 
3159 void SwXTextDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
3160 {
3161     SolarMutexGuard aGuard;
3162 
3163     SwView* pView = m_pDocShell->GetView();
3164     if (pView)
3165         pView->GetEditWin().SetClipboard(xClipboard);
3166 }
3167 
3168 bool SwXTextDocument::isMimeTypeSupported()
3169 {
3170     SolarMutexGuard aGuard;
3171 
3172     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3173     if (!pWrtShell)
3174         return false;
3175 
3176     TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&pWrtShell->GetView().GetEditWin()));
3177     if (SdrView* pSdrView = pWrtShell->GetDrawView())
3178     {
3179         if (pSdrView->GetTextEditObject())
3180             // Editing shape text
3181             return EditEngine::HasValidData(aDataHelper.GetTransferable());
3182     }
3183 
3184     return aDataHelper.GetXTransferable().is() && SwTransferable::IsPaste(*pWrtShell, aDataHelper);
3185 }
3186 
3187 void SwXTextDocument::setClientVisibleArea(const tools::Rectangle& rRectangle)
3188 {
3189     if (SwView* pView = m_pDocShell->GetView())
3190     {
3191         // set the PgUp/PgDown offset
3192         pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3);
3193     }
3194 
3195     if (SwViewShell* pViewShell = m_pDocShell->GetWrtShell())
3196     {
3197         pViewShell->setLOKVisibleArea(rRectangle);
3198     }
3199 }
3200 
3201 void SwXTextDocument::setClientZoom(int nTilePixelWidth_, int /*nTilePixelHeight_*/,
3202                                     int nTileTwipWidth_, int /*nTileTwipHeight_*/)
3203 {
3204     // Here we set the zoom value as it has been set by the user in the client.
3205     // This value is used in postMouseEvent and setGraphicSelection methods
3206     // for in place chart editing. We assume that x and y scale is roughly
3207     // the same.
3208     SfxInPlaceClient* pIPClient = m_pDocShell->GetView()->GetIPClient();
3209     if (!pIPClient)
3210         return;
3211 
3212     SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
3213     double fScale = 100.0 * nTilePixelWidth_ / nTileTwipWidth_
3214                     * o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::twip);
3215     SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
3216     if (aOption.GetZoom() != fScale)
3217     {
3218         aOption.SetZoom(fScale);
3219         pWrtViewShell->ApplyViewOptions(aOption);
3220 
3221         // Changing the zoom value doesn't always trigger the updating of
3222         // the client ole object area, so we call it directly.
3223         pIPClient->VisAreaChanged();
3224     }
3225 }
3226 
3227 PointerStyle SwXTextDocument::getPointer()
3228 {
3229     SolarMutexGuard aGuard;
3230 
3231     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3232     if (!pWrtShell)
3233         return PointerStyle::Arrow;
3234 
3235     return pWrtShell->GetView().GetEditWin().GetPointer();
3236 }
3237 
3238 void SwXTextDocument::getTrackedChanges(tools::JsonWriter& rJson)
3239 {
3240     auto redlinesNode = rJson.startArray("redlines");
3241 
3242     // Disable since usability is very low beyond some small number of changes.
3243     static bool bDisableRedlineComments = getenv("DISABLE_REDLINE") != nullptr;
3244     if (bDisableRedlineComments)
3245         return;
3246 
3247     const SwRedlineTable& rRedlineTable
3248         = m_pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
3249     for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
3250     {
3251         auto redlineNode = rJson.startStruct();
3252         rJson.put("index", rRedlineTable[i]->GetId());
3253         rJson.put("author", rRedlineTable[i]->GetAuthorString(1));
3254         rJson.put("type", SwRedlineTypeToOUString(
3255                                        rRedlineTable[i]->GetRedlineData().GetType()));
3256         rJson.put("comment",
3257                            rRedlineTable[i]->GetRedlineData().GetComment());
3258         rJson.put("description", rRedlineTable[i]->GetDescr());
3259         OUString sDateTime = utl::toISO8601(
3260             rRedlineTable[i]->GetRedlineData().GetTimeStamp().GetUNODateTime());
3261         rJson.put("dateTime", sDateTime);
3262 
3263         SwContentNode* pContentNd = rRedlineTable[i]->GetPointContentNode();
3264         SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current());
3265         if (pView && pContentNd)
3266         {
3267             SwShellCursor aCursor(pView->GetWrtShell(), *(rRedlineTable[i]->Start()));
3268             aCursor.SetMark();
3269             aCursor.GetMark()->Assign(*pContentNd, rRedlineTable[i]->End()->GetContentIndex());
3270 
3271             aCursor.FillRects();
3272 
3273             SwRects* pRects(&aCursor);
3274             std::vector<OString> aRects;
3275             for (const SwRect& rNextRect : *pRects)
3276                 aRects.push_back(rNextRect.SVRect().toString());
3277 
3278             const OString sRects = comphelper::string::join("; ", aRects);
3279             rJson.put("textRange", sRects);
3280         }
3281     }
3282 }
3283 
3284 void SwXTextDocument::getTrackedChangeAuthors(tools::JsonWriter& rJsonWriter)
3285 {
3286     SW_MOD()->GetRedlineAuthorInfo(rJsonWriter);
3287 }
3288 
3289 void SwXTextDocument::getRulerState(tools::JsonWriter& rJsonWriter)
3290 {
3291     SwView* pView = m_pDocShell->GetView();
3292     dynamic_cast<SwCommentRuler&>(pView->GetHRuler()).CreateJsonNotification(rJsonWriter);
3293 }
3294 
3295 void SwXTextDocument::getPostIts(tools::JsonWriter& rJsonWriter)
3296 {
3297     SolarMutexGuard aGuard;
3298     auto commentsNode = rJsonWriter.startArray("comments");
3299     for (auto const& sidebarItem : *m_pDocShell->GetView()->GetPostItMgr())
3300     {
3301         sw::annotation::SwAnnotationWin* pWin = sidebarItem->mpPostIt.get();
3302 
3303         if (!pWin)
3304         {
3305             continue;
3306         }
3307 
3308         const SwPostItField* pField = pWin->GetPostItField();
3309         const SwRect& aRect = pWin->GetAnchorRect();
3310         tools::Rectangle aSVRect(aRect.Pos().getX(),
3311                                 aRect.Pos().getY(),
3312                                 aRect.Pos().getX() + aRect.SSize().Width(),
3313                                 aRect.Pos().getY() + aRect.SSize().Height());
3314 
3315         if (!sidebarItem->maLayoutInfo.mPositionFromCommentAnchor)
3316         {
3317             // Comments on frames: anchor position is the corner position, not the whole frame.
3318             aSVRect.SetSize(Size(0, 0));
3319         }
3320 
3321         std::vector<OString> aRects;
3322         for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges())
3323         {
3324             const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight());
3325             aRects.push_back(rect.SVRect().toString());
3326         }
3327         const OString sRects = comphelper::string::join("; ", aRects);
3328 
3329         auto commentNode = rJsonWriter.startStruct();
3330         rJsonWriter.put("id", pField->GetPostItId());
3331         rJsonWriter.put("parent", pWin->CalcParent());
3332         rJsonWriter.put("author", pField->GetPar1());
3333         rJsonWriter.put("text", pField->GetPar2());
3334         rJsonWriter.put("resolved", pField->GetResolved() ? "true" : "false");
3335         rJsonWriter.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime()));
3336         rJsonWriter.put("anchorPos", aSVRect.toString());
3337         rJsonWriter.put("textRange", sRects);
3338     }
3339 }
3340 
3341 void SwXTextDocument::executeFromFieldEvent(const StringMap& aArguments)
3342 {
3343     auto aIter = aArguments.find("type");
3344     if (aIter == aArguments.end() || aIter->second != "drop-down")
3345         return;
3346 
3347     aIter = aArguments.find("cmd");
3348     if (aIter == aArguments.end() || aIter->second != "selected")
3349         return;
3350 
3351     aIter = aArguments.find("data");
3352     if (aIter == aArguments.end())
3353         return;
3354 
3355     sal_Int32 nSelection = aIter->second.toInt32();
3356     SwPosition aPos(*m_pDocShell->GetWrtShell()->GetCursor()->GetPoint());
3357     sw::mark::IFieldmark* pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getFieldmarkFor(aPos);
3358     if ( !pFieldBM )
3359     {
3360         aPos.AdjustContent(-1);
3361         pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getFieldmarkFor(aPos);
3362     }
3363     if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN)
3364     {
3365         if (nSelection >= 0)
3366         {
3367             (*pFieldBM->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= nSelection;
3368             pFieldBM->Invalidate();
3369             m_pDocShell->GetWrtShell()->SetModified();
3370             m_pDocShell->GetView()->GetEditWin().LogicInvalidate(nullptr);
3371         }
3372     }
3373 }
3374 
3375 std::vector<basegfx::B2DRange>
3376 SwXTextDocument::getSearchResultRectangles(const char* pPayload)
3377 {
3378     SwDoc* pDoc = m_pDocShell->GetDoc();
3379     if (!pDoc)
3380         return std::vector<basegfx::B2DRange>();
3381 
3382     sw::search::SearchResultLocator aLocator(pDoc);
3383     sw::search::LocationResult aResult = aLocator.findForPayload(pPayload);
3384     if (aResult.mbFound)
3385     {
3386         return aResult.maRectangles;
3387     }
3388     return std::vector<basegfx::B2DRange>();
3389 }
3390 
3391 namespace
3392 {
3393 inline constexpr OUStringLiteral SELECTED_DATE_FORMAT = u"YYYY-MM-DD";
3394 }
3395 
3396 void SwXTextDocument::executeContentControlEvent(const StringMap& rArguments)
3397 {
3398     auto it = rArguments.find("type");
3399     if (it == rArguments.end())
3400     {
3401         return;
3402     }
3403 
3404     if (it->second == "drop-down")
3405     {
3406         SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3407         const SwPosition* pStart = pWrtShell->GetCursor()->Start();
3408         SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
3409         if (!pTextNode)
3410         {
3411             return;
3412         }
3413 
3414         SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(),
3415                                                      RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
3416         if (!pAttr)
3417         {
3418             return;
3419         }
3420 
3421         auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
3422         const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
3423         std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
3424         if (!pContentControl->GetComboBox() && !pContentControl->GetDropDown())
3425         {
3426             return;
3427         }
3428 
3429         it = rArguments.find("selected");
3430         if (it == rArguments.end())
3431         {
3432             return;
3433         }
3434 
3435         sal_Int32 nSelection = it->second.toInt32();
3436         pContentControl->SetSelectedListItem(nSelection);
3437         pWrtShell->GotoContentControl(rFormatContentControl);
3438     }
3439     else if (it->second == "picture")
3440     {
3441         it = rArguments.find("changed");
3442         if (it == rArguments.end())
3443         {
3444             return;
3445         }
3446 
3447         SwView* pView = m_pDocShell->GetView();
3448         if (!pView)
3449         {
3450             return;
3451         }
3452 
3453         // The current placeholder is selected, so this will replace, not insert.
3454         SfxStringItem aItem(SID_INSERT_GRAPHIC, it->second);
3455         pView->GetViewFrame()->GetDispatcher()->ExecuteList(SID_CHANGE_PICTURE,
3456                                                             SfxCallMode::SYNCHRON, { &aItem });
3457     }
3458     else if (it->second == "date")
3459     {
3460         SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3461         const SwPosition* pStart = pWrtShell->GetCursor()->Start();
3462         SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
3463         if (!pTextNode)
3464         {
3465             return;
3466         }
3467 
3468         SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(),
3469                                                      RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
3470         if (!pAttr)
3471         {
3472             return;
3473         }
3474 
3475         auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
3476         const SwFormatContentControl& rFormatContentControl
3477             = pTextContentControl->GetContentControl();
3478         std::shared_ptr<SwContentControl> pContentControl
3479             = rFormatContentControl.GetContentControl();
3480         if (!pContentControl->GetDate())
3481         {
3482             return;
3483         }
3484 
3485         it = rArguments.find("selected");
3486         if (it == rArguments.end())
3487         {
3488             return;
3489         }
3490 
3491         OUString aSelectedDate = it->second.replaceAll("T00:00:00Z", "");
3492         SwDoc& rDoc = pTextNode->GetDoc();
3493         SvNumberFormatter* pNumberFormatter = rDoc.GetNumberFormatter();
3494         sal_uInt32 nFormat
3495             = pNumberFormatter->GetEntryKey(SELECTED_DATE_FORMAT, LANGUAGE_ENGLISH_US);
3496         if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
3497         {
3498             sal_Int32 nCheckPos = 0;
3499             SvNumFormatType nType;
3500             OUString sFormat = SELECTED_DATE_FORMAT;
3501             pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat, LANGUAGE_ENGLISH_US);
3502         }
3503 
3504         if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
3505         {
3506             return;
3507         }
3508 
3509         double dCurrentDate = 0;
3510         pNumberFormatter->IsNumberFormat(aSelectedDate, nFormat, dCurrentDate);
3511         pContentControl->SetSelectedDate(dCurrentDate);
3512         pWrtShell->GotoContentControl(rFormatContentControl);
3513     }
3514 }
3515 
3516 int SwXTextDocument::getPart()
3517 {
3518     SolarMutexGuard aGuard;
3519 
3520     SwView* pView = m_pDocShell->GetView();
3521     if (!pView)
3522         return 0;
3523 
3524     return pView->getPart();
3525 }
3526 
3527 OUString SwXTextDocument::getPartName(int nPart)
3528 {
3529     return SwResId(STR_PAGE) + OUString::number(nPart + 1);
3530 }
3531 
3532 OUString SwXTextDocument::getPartHash(int nPart)
3533 {
3534     OUString sPart(SwResId(STR_PAGE) + OUString::number(nPart + 1));
3535 
3536     return OUString::number(sPart.hashCode());
3537 }
3538 
3539 VclPtr<vcl::Window> SwXTextDocument::getDocWindow()
3540 {
3541     SolarMutexGuard aGuard;
3542     SwView* pView = m_pDocShell->GetView();
3543     if (!pView)
3544         return {};
3545 
3546     if (VclPtr<vcl::Window> pWindow = SfxLokHelper::getInPlaceDocWindow(pView))
3547         return pWindow;
3548 
3549     return &(pView->GetEditWin());
3550 }
3551 
3552 void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
3553 {
3554     SolarMutexGuard aGuard;
3555 
3556     SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
3557 
3558     SwView* pView = m_pDocShell->GetView();
3559     if (!pView)
3560         return;
3561 
3562     pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true);
3563 
3564     // Tiled rendering defaults.
3565     SwViewOption aViewOption(*pViewShell->GetViewOptions());
3566     aViewOption.SetHardBlank(false);
3567 
3568     // Disable field shadings: the result would depend on the cursor position.
3569     SwViewOption::SetAppearanceFlag(ViewOptFlags::FieldShadings, false);
3570 
3571     for (const beans::PropertyValue& rValue : rArguments)
3572     {
3573         if (rValue.Name == ".uno:HideWhitespace" && rValue.Value.has<bool>())
3574             aViewOption.SetHideWhitespaceMode(rValue.Value.get<bool>());
3575         else if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>())
3576             SwViewOption::SetAppearanceFlag(ViewOptFlags::Shadow , rValue.Value.get<bool>());
3577         else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>())
3578         {
3579             // Store the author name in the view.
3580             pView->SetRedlineAuthor(rValue.Value.get<OUString>());
3581             // Let the actual author name pick up the value from the current
3582             // view, which would normally happen only during the next view
3583             // switch.
3584             m_pDocShell->SetView(pView);
3585         }
3586         else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
3587             aViewOption.SetOnlineSpell(rValue.Value.get<bool>());
3588     }
3589 
3590     // Set the initial zoom value to 1; usually it is set in setClientZoom and
3591     // SwViewShell::PaintTile; zoom value is used for chart in place
3592     // editing, see postMouseEvent and setGraphicSelection methods.
3593     aViewOption.SetZoom(1 * 100);
3594 
3595     aViewOption.SetPostIts(comphelper::LibreOfficeKit::isTiledAnnotations());
3596     pViewShell->ApplyViewOptions(aViewOption);
3597 
3598     // position the pages again after setting view options. Eg: if postit
3599     // rendering is false, then there would be no sidebar, so width of the
3600     // document needs to be adjusted
3601     pViewShell->GetLayout()->CheckViewLayout( pViewShell->GetViewOptions(), nullptr );
3602 
3603     // Disable map mode, so that it's possible to send mouse event coordinates
3604     // directly in twips.
3605     SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
3606     rEditWin.EnableMapMode(false);
3607 
3608     // when the "This document may contain formatting or content that cannot
3609     // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
3610     // causing 'Save' being disabled; so let's always save to the original
3611     // format
3612     auto xChanges = comphelper::ConfigurationChanges::create();
3613     officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
3614     xChanges->commit();
3615 
3616     // disable word auto-completion suggestions, the tooltips are not visible,
3617     // and the editeng-like auto-completion is annoying
3618     SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags().bAutoCompleteWords = false;
3619 
3620     // don't change the whitespace at the beginning of paragraphs, this is
3621     // annoying when taking minutes without further formatting
3622     SwEditShell::GetAutoFormatFlags()->bAFormatByInpDelSpacesAtSttEnd = false;
3623 }
3624 
3625 void SwXTextDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
3626 {
3627     SolarMutexGuard aGuard;
3628     SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
3629 }
3630 
3631 void SwXTextDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
3632 {
3633     SolarMutexGuard aGuard;
3634 
3635     SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
3636     if (!pWrtViewShell)
3637     {
3638         return;
3639     }
3640 
3641     SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
3642     double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip);
3643 
3644     if (SfxLokHelper::testInPlaceComponentMouseEventHit(
3645             m_pDocShell->GetView(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale))
3646         return;
3647 
3648     SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
3649     LokMouseEventData aMouseEventData(nType, Point(nX, nY), nCount,
3650                                       MouseEventModifiers::SIMPLECLICK,
3651                                       nButtons, nModifier);
3652     SfxLokHelper::postMouseEventAsync(&rEditWin, aMouseEventData);
3653 }
3654 
3655 void SwXTextDocument::setTextSelection(int nType, int nX, int nY)
3656 {
3657     SolarMutexGuard aGuard;
3658 
3659     SfxViewShell* pViewShell = m_pDocShell->GetView();
3660     LokChartHelper aChartHelper(pViewShell);
3661     if (aChartHelper.setTextSelection(nType, nX, nY))
3662         return;
3663 
3664     SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
3665     switch (nType)
3666     {
3667     case LOK_SETTEXTSELECTION_START:
3668         rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false);
3669         break;
3670     case LOK_SETTEXTSELECTION_END:
3671         rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false);
3672         break;
3673     case LOK_SETTEXTSELECTION_RESET:
3674         rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true);
3675         break;
3676     default:
3677         assert(false);
3678         break;
3679     }
3680 }
3681 
3682 uno::Reference<datatransfer::XTransferable> SwXTextDocument::getSelection()
3683 {
3684     SolarMutexGuard aGuard;
3685 
3686     uno::Reference<datatransfer::XTransferable> xTransferable;
3687 
3688     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3689     if (SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr)
3690     {
3691         if (pSdrView->GetTextEditObject())
3692         {
3693             // Editing shape text
3694             EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
3695             xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection());
3696         }
3697     }
3698 
3699     if (SwPostItMgr* pPostItMgr = m_pDocShell->GetView()->GetPostItMgr())
3700     {
3701         if (sw::annotation::SwAnnotationWin* pWin = pPostItMgr->GetActiveSidebarWin())
3702         {
3703             // Editing postit text.
3704             EditView& rEditView = pWin->GetOutlinerView()->GetEditView();
3705             xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection());
3706         }
3707     }
3708 
3709     if (!xTransferable.is() && pWrtShell)
3710         xTransferable = new SwTransferable(*pWrtShell);
3711 
3712     return xTransferable;
3713 }
3714 
3715 void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY)
3716 {
3717     SolarMutexGuard aGuard;
3718 
3719     SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
3720     SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
3721     double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip);
3722 
3723     SfxViewShell* pViewShell = m_pDocShell->GetView();
3724     LokChartHelper aChartHelper(pViewShell);
3725     if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
3726         return;
3727 
3728     SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
3729     switch (nType)
3730     {
3731     case LOK_SETGRAPHICSELECTION_START:
3732         rEditWin.SetGraphicTwipPosition(/*bStart=*/true, Point(nX, nY));
3733         break;
3734     case LOK_SETGRAPHICSELECTION_END:
3735         rEditWin.SetGraphicTwipPosition(/*bStart=*/false, Point(nX, nY));
3736         break;
3737     default:
3738         assert(false);
3739         break;
3740     }
3741 }
3742 
3743 void SwXTextDocument::resetSelection()
3744 {
3745     SolarMutexGuard aGuard;
3746 
3747     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
3748     pWrtShell->ResetSelect(nullptr, false);
3749 }
3750 
3751 void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight )
3752 {
3753     SystemGraphicsData aData;
3754     aData.nSize = sizeof(SystemGraphicsData);
3755     #if defined(_WIN32)
3756     sal_Int64 nWindowHandle;
3757     Parent >>= nWindowHandle;
3758     aData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
3759     ScopedVclPtrInstance<VirtualDevice> xDevice(aData, Size(1, 1), DeviceFormat::DEFAULT);
3760     paintTile(*xDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight);
3761     #else
3762     // TODO: support other platforms
3763     (void)Parent;
3764     (void)nOutputWidth;
3765     (void)nOutputHeight;
3766     (void)nTilePosX;
3767     (void)nTilePosY;
3768     (void)nTileWidth;
3769     (void)nTileHeight;
3770     #endif
3771 }
3772 
3773 /**
3774  * retrieve languages already used in current document
3775  */
3776 uno::Sequence< lang::Locale > SAL_CALL SwXTextDocument::getDocumentLanguages(
3777         ::sal_Int16 nScriptTypes,
3778         ::sal_Int16 nMaxCount )
3779 {
3780     SolarMutexGuard aGuard;
3781 
3782     // possible canonical values for nScriptTypes
3783     // any bit wise combination is allowed
3784     const sal_Int16 nLatin   = 0x001;
3785     const sal_Int16 nAsian   = 0x002;
3786     const sal_Int16 nComplex = 0x004;
3787 
3788     // script types for which to get the languages
3789     const bool bLatin   = 0 != (nScriptTypes & nLatin);
3790     const bool bAsian   = 0 != (nScriptTypes & nAsian);
3791     const bool bComplex = 0 != (nScriptTypes & nComplex);
3792 
3793     if (nScriptTypes < nLatin || nScriptTypes > (nLatin | nAsian | nComplex))
3794         throw IllegalArgumentException("nScriptTypes ranges from 1 to 7!", Reference< XInterface >(), 1);
3795     if (!m_pDocShell)
3796         throw DisposedException();
3797     SwDoc* pDoc = m_pDocShell->GetDoc();
3798 
3799     // avoid duplicate values
3800     std::set< LanguageType > aAllLangs;
3801 
3802     //USER STYLES
3803 
3804     const SwCharFormats *pFormats = pDoc->GetCharFormats();
3805     for(size_t i = 0; i < pFormats->size(); ++i)
3806     {
3807         const SwAttrSet &rAttrSet = (*pFormats)[i]->GetAttrSet();
3808         LanguageType nLang = LANGUAGE_DONTKNOW;
3809         if (bLatin)
3810         {
3811             nLang = rAttrSet.GetLanguage( false ).GetLanguage();
3812             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3813                 aAllLangs.insert( nLang );
3814         }
3815         if (bAsian)
3816         {
3817             nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage();
3818             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3819                 aAllLangs.insert( nLang );
3820         }
3821         if (bComplex)
3822         {
3823             nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage();
3824             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3825                 aAllLangs.insert( nLang );
3826         }
3827     }
3828 
3829     const SwTextFormatColls *pColls = pDoc->GetTextFormatColls();
3830     for (size_t i = 0; i < pColls->size(); ++i)
3831     {
3832         const SwAttrSet &rAttrSet = (*pColls)[i]->GetAttrSet();
3833         LanguageType nLang = LANGUAGE_DONTKNOW;
3834         if (bLatin)
3835         {
3836             nLang = rAttrSet.GetLanguage( false ).GetLanguage();
3837             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3838                 aAllLangs.insert( nLang );
3839         }
3840         if (bAsian)
3841         {
3842             nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage();
3843             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3844                 aAllLangs.insert( nLang );
3845         }
3846         if (bComplex)
3847         {
3848             nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage();
3849             if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3850                 aAllLangs.insert( nLang );
3851         }
3852     }
3853 
3854     //AUTO STYLES
3855     const IStyleAccess::SwAutoStyleFamily aFam[2] =
3856     {
3857       IStyleAccess::AUTO_STYLE_CHAR,
3858       IStyleAccess::AUTO_STYLE_PARA
3859     };
3860     for (IStyleAccess::SwAutoStyleFamily i : aFam)
3861     {
3862         std::vector< std::shared_ptr<SfxItemSet> > rStyles;
3863         pDoc->GetIStyleAccess().getAllStyles(rStyles, i);
3864         while (!rStyles.empty())
3865         {
3866             std::shared_ptr<SfxItemSet> pStyle = rStyles.back();
3867             rStyles.pop_back();
3868             const SfxItemSet *pSet = pStyle.get();
3869 
3870             LanguageType nLang = LANGUAGE_DONTKNOW;
3871             if (bLatin)
3872             {
3873                 assert(pSet);
3874                 nLang = pSet->Get( RES_CHRATR_LANGUAGE, false ).GetLanguage();
3875                 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3876                     aAllLangs.insert( nLang );
3877             }
3878             if (bAsian)
3879             {
3880                 assert(pSet);
3881                 nLang = pSet->Get( RES_CHRATR_CJK_LANGUAGE, false ).GetLanguage();
3882                 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3883                     aAllLangs.insert( nLang );
3884             }
3885             if (bComplex)
3886             {
3887                 assert(pSet);
3888                 nLang = pSet->Get( RES_CHRATR_CTL_LANGUAGE, false ).GetLanguage();
3889                 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3890                     aAllLangs.insert( nLang );
3891             }
3892         }
3893     }
3894 
3895     //TODO/mba: it's a strange concept that a view is needed to retrieve core data
3896     SwWrtShell *pWrtSh = m_pDocShell->GetWrtShell();
3897     SdrView *pSdrView = pWrtSh->GetDrawView();
3898 
3899     if( pSdrView )
3900     {
3901         SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
3902         if(pOutliner)
3903         {
3904             EditEngine& rEditEng = const_cast<EditEngine&>(pOutliner->GetEditEngine());
3905             sal_Int32 nParCount = pOutliner->GetParagraphCount();
3906             for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
3907             {
3908                 //every paragraph
3909                 std::vector<sal_Int32> aPortions;
3910                 rEditEng.GetPortions( nPar, aPortions );
3911 
3912                 for ( size_t nPos = aPortions.size(); nPos; )
3913                 {
3914                     //every position
3915                     --nPos;
3916                     sal_Int32 nEnd = aPortions[ nPos ];
3917                     sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0;
3918                     ESelection aSelection( nPar, nStart, nPar, nEnd );
3919                     SfxItemSet aAttr = rEditEng.GetAttribs( aSelection );
3920 
3921                     LanguageType nLang = LANGUAGE_DONTKNOW;
3922                     if (bLatin)
3923                     {
3924                         nLang = aAttr.Get( EE_CHAR_LANGUAGE, false ).GetLanguage();
3925                         if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3926                             aAllLangs.insert( nLang );
3927                     }
3928                     if (bAsian)
3929                     {
3930                         nLang = aAttr.Get( EE_CHAR_LANGUAGE_CJK, false ).GetLanguage();
3931                         if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3932                             aAllLangs.insert( nLang );
3933                     }
3934                     if (bComplex)
3935                     {
3936                         nLang = aAttr.Get( EE_CHAR_LANGUAGE_CTL, false ).GetLanguage();
3937                         if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3938                             aAllLangs.insert( nLang );
3939                     }
3940                 }
3941             }
3942         }
3943     }
3944     // less than nMaxCount languages
3945     if (nMaxCount > static_cast< sal_Int16 >( aAllLangs.size() ))
3946         nMaxCount = static_cast< sal_Int16 >( aAllLangs.size() );
3947 
3948     // build return value
3949     uno::Sequence< lang::Locale > aLanguages( nMaxCount );
3950     lang::Locale* pLanguage = aLanguages.getArray();
3951     if (nMaxCount > 0)
3952     {
3953         sal_Int32 nCount = 0;
3954         for (const auto& rLang : aAllLangs)
3955         {
3956             if (nCount >= nMaxCount)
3957                 break;
3958             if (LANGUAGE_NONE != rLang)
3959             {
3960                 pLanguage[nCount] = LanguageTag::convertToLocale( rLang );
3961                 pLanguage[nCount].Language = SvtLanguageTable::GetLanguageString( rLang );
3962                 nCount += 1;
3963             }
3964         }
3965     }
3966 
3967     return aLanguages;
3968 }
3969 
3970 SwXLinkTargetSupplier::SwXLinkTargetSupplier(SwXTextDocument& rxDoc) :
3971     m_pxDoc(&rxDoc)
3972 {
3973     m_sTables     = SwResId(STR_CONTENT_TYPE_TABLE);
3974     m_sFrames     = SwResId(STR_CONTENT_TYPE_FRAME);
3975     m_sGraphics   = SwResId(STR_CONTENT_TYPE_GRAPHIC);
3976     m_sOLEs       = SwResId(STR_CONTENT_TYPE_OLE);
3977     m_sSections   = SwResId(STR_CONTENT_TYPE_REGION);
3978     m_sOutlines   = SwResId(STR_CONTENT_TYPE_OUTLINE);
3979     m_sBookmarks  = SwResId(STR_CONTENT_TYPE_BOOKMARK);
3980     m_sDrawingObjects = SwResId(STR_CONTENT_TYPE_DRAWOBJECT);
3981 }
3982 
3983 SwXLinkTargetSupplier::~SwXLinkTargetSupplier()
3984 {
3985 }
3986 
3987 Any SwXLinkTargetSupplier::getByName(const OUString& rName)
3988 {
3989     Any aRet;
3990     if(!m_pxDoc)
3991         throw RuntimeException("No document available");
3992     OUString sSuffix("|");
3993     if(rName == m_sTables)
3994     {
3995         sSuffix += "table";
3996 
3997         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
3998                                         m_pxDoc->getTextTables(), rName, sSuffix );
3999         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4000     }
4001     else if(rName == m_sFrames)
4002     {
4003         sSuffix += "frame";
4004         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
4005                                         m_pxDoc->getTextFrames(), rName, sSuffix );
4006         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4007     }
4008     else if(rName == m_sSections)
4009     {
4010         sSuffix += "region";
4011         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
4012                                         m_pxDoc->getTextSections(), rName, sSuffix );
4013         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4014     }
4015     else if(rName == m_sGraphics)
4016     {
4017         sSuffix += "graphic";
4018         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
4019                                         m_pxDoc->getGraphicObjects(), rName, sSuffix );
4020         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4021     }
4022     else if(rName == m_sOLEs)
4023     {
4024         sSuffix += "ole";
4025         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
4026                                         m_pxDoc->getEmbeddedObjects(), rName, sSuffix );
4027         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4028     }
4029     else if(rName == m_sOutlines)
4030     {
4031         sSuffix += "outline";
4032         Reference< XNameAccess >  xTables = new SwXLinkNameAccessWrapper(
4033                                         *m_pxDoc, rName, sSuffix );
4034         aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
4035     }
4036     else if(rName == m_sBookmarks)
4037     {
4038         sSuffix.clear();
4039         Reference< XNameAccess >  xBkms = new SwXLinkNameAccessWrapper(
4040                                         m_pxDoc->getBookmarks(), rName, sSuffix );
4041         aRet <<= Reference< XPropertySet >(xBkms, UNO_QUERY);
4042     }
4043     else if(rName == m_sDrawingObjects)
4044     {
4045         sSuffix += "drawingobject";
4046         Reference<XNameAccess> xDrawingObjects = new SwXLinkNameAccessWrapper(
4047                     *m_pxDoc, rName, sSuffix);
4048         aRet <<= Reference<XPropertySet>(xDrawingObjects, UNO_QUERY);
4049     }
4050     else
4051         throw NoSuchElementException();
4052     return aRet;
4053 }
4054 
4055 Sequence< OUString > SwXLinkTargetSupplier::getElementNames()
4056 {
4057     return { m_sTables,
4058              m_sFrames,
4059              m_sGraphics,
4060              m_sOLEs,
4061              m_sSections,
4062              m_sOutlines,
4063              m_sBookmarks,
4064              m_sDrawingObjects };
4065 }
4066 
4067 sal_Bool SwXLinkTargetSupplier::hasByName(const OUString& rName)
4068 {
4069     if( rName == m_sTables  ||
4070         rName == m_sFrames  ||
4071         rName == m_sGraphics||
4072         rName == m_sOLEs   ||
4073         rName == m_sSections ||
4074         rName == m_sOutlines ||
4075         rName == m_sBookmarks ||
4076         rName == m_sDrawingObjects )
4077         return true;
4078     return false;
4079 }
4080 
4081 uno::Type  SwXLinkTargetSupplier::getElementType()
4082 {
4083     return cppu::UnoType<XPropertySet>::get();
4084 
4085 }
4086 
4087 sal_Bool SwXLinkTargetSupplier::hasElements()
4088 {
4089     return nullptr != m_pxDoc;
4090 }
4091 
4092 OUString SwXLinkTargetSupplier::getImplementationName()
4093 {
4094     return "SwXLinkTargetSupplier";
4095 }
4096 
4097 sal_Bool SwXLinkTargetSupplier::supportsService(const OUString& rServiceName)
4098 {
4099     return cppu::supportsService(this, rServiceName);
4100 }
4101 
4102 Sequence< OUString > SwXLinkTargetSupplier::getSupportedServiceNames()
4103 {
4104     Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" };
4105     return aRet;
4106 }
4107 
4108 SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(
4109             Reference< XNameAccess > const & xAccess, OUString aLinkDisplayName, OUString sSuffix ) :
4110     m_xRealAccess(xAccess),
4111     m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
4112     m_sLinkSuffix(std::move(sSuffix)),
4113     m_sLinkDisplayName(std::move(aLinkDisplayName)),
4114     m_pxDoc(nullptr)
4115 {
4116 }
4117 
4118 SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(SwXTextDocument& rxDoc,
4119             OUString aLinkDisplayName, OUString sSuffix) :
4120     m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
4121     m_sLinkSuffix(std::move(sSuffix)),
4122     m_sLinkDisplayName(std::move(aLinkDisplayName)),
4123     m_pxDoc(&rxDoc)
4124 {
4125 }
4126 
4127 SwXLinkNameAccessWrapper::~SwXLinkNameAccessWrapper()
4128 {
4129 }
4130 
4131 Any SwXLinkNameAccessWrapper::getByName(const OUString& rName)
4132 {
4133     Any aRet;
4134     bool bFound = false;
4135     //cut link extension and call the real NameAccess
4136     OUString sParam = rName;
4137     OUString sSuffix(m_sLinkSuffix);
4138     if(sParam.getLength() > sSuffix.getLength() )
4139     {
4140         std::u16string_view sCmp = sParam.subView(sParam.getLength() - sSuffix.getLength(),
4141                                                     sSuffix.getLength());
4142         if(sCmp == sSuffix)
4143         {
4144             if(m_pxDoc)
4145             {
4146                 sParam = sParam.copy(0, sParam.getLength() - sSuffix.getLength());
4147                 if(!m_pxDoc->GetDocShell())
4148                     throw RuntimeException("No document shell available");
4149                 SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
4150 
4151                 if (sSuffix == "|outline")
4152                 {
4153                     const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size();
4154 
4155                     for (size_t i = 0; i < nOutlineCount && !bFound; ++i)
4156                     {
4157                         if(sParam == lcl_CreateOutlineString(i, pDoc))
4158                         {
4159                             OUString sOutlineText =
4160                                     pDoc->getIDocumentOutlineNodes().getOutlineText(
4161                                         i, pDoc->GetDocShell()->GetWrtShell()->GetLayout());
4162                             sal_Int32 nOutlineLevel = pDoc->getIDocumentOutlineNodes().getOutlineLevel(i);
4163                             Reference<XPropertySet> xOutline =
4164                                     new SwXOutlineTarget(sParam, sOutlineText, nOutlineLevel);
4165                             aRet <<= xOutline;
4166                             bFound = true;
4167                         }
4168                     }
4169                 }
4170                 else if (sSuffix == "|drawingobject")
4171                 {
4172                     SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
4173                     if (pModel)
4174                     {
4175                         SdrPage* pPage = pModel->GetPage(0);
4176                         for (size_t i = 0; i < pPage->GetObjCount() && !bFound; ++i)
4177                         {
4178                             SdrObject* pObj = pPage->GetObj(i);
4179                             if (sParam == pObj->GetName())
4180                             {
4181                                 Reference<XPropertySet> xDrawingObject = new SwXDrawingObjectTarget(sParam);
4182                                 aRet <<= xDrawingObject;
4183                                 bFound = true;
4184                             }
4185                         }
4186                     }
4187                 }
4188             }
4189             else
4190             {
4191                 aRet = m_xRealAccess->getByName(sParam.copy(0, sParam.getLength() - sSuffix.getLength()));
4192                 Reference< XInterface > xInt;
4193                 if(!(aRet >>= xInt))
4194                     throw RuntimeException("Could not retrieve property");
4195                 Reference< XPropertySet >  xProp(xInt, UNO_QUERY);
4196                 aRet <<= xProp;
4197                 bFound = true;
4198             }
4199         }
4200     }
4201     if(!bFound)
4202         throw NoSuchElementException();
4203     return aRet;
4204 }
4205 
4206 Sequence< OUString > SwXLinkNameAccessWrapper::getElementNames()
4207 {
4208     Sequence< OUString > aRet;
4209     if(m_pxDoc)
4210     {
4211         if(!m_pxDoc->GetDocShell())
4212             throw RuntimeException("No document shell available");
4213         SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
4214         if (m_sLinkSuffix == "|outline")
4215         {
4216             const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds();
4217             const size_t nOutlineCount = rOutlineNodes.size();
4218             aRet.realloc(nOutlineCount);
4219             OUString* pResArr = aRet.getArray();
4220             for (size_t i = 0; i < nOutlineCount; ++i)
4221             {
4222                 OUString sEntry = lcl_CreateOutlineString(i, pDoc) + "|outline";
4223                 pResArr[i] = sEntry;
4224             }
4225         }
4226         else if (m_sLinkSuffix == "|drawingobject")
4227         {
4228             SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
4229             if(pModel)
4230             {
4231                 SdrPage* pPage = pModel->GetPage(0);
4232                 const size_t nObjCount = pPage->GetObjCount();
4233                 aRet.realloc(nObjCount);
4234                 OUString* pResArr = aRet.getArray();
4235                 auto j = 0;
4236                 for (size_t i = 0; i < nObjCount; ++i)
4237                 {
4238                     SdrObject* pObj = pPage->GetObj(i);
4239                     if (!pObj->GetName().isEmpty())
4240                         pResArr[j++] = pObj->GetName() + "|drawingobject";
4241                 }
4242             }
4243         }
4244     }
4245     else
4246     {
4247         const Sequence< OUString > aOrg = m_xRealAccess->getElementNames();
4248         aRet.realloc(aOrg.getLength());
4249         std::transform(aOrg.begin(), aOrg.end(), aRet.getArray(),
4250             [this](const OUString& rOrg) -> OUString { return rOrg + m_sLinkSuffix; });
4251     }
4252     return aRet;
4253 }
4254 
4255 sal_Bool SwXLinkNameAccessWrapper::hasByName(const OUString& rName)
4256 {
4257     bool bRet = false;
4258     OUString sParam(rName);
4259     if(sParam.getLength() > m_sLinkSuffix.getLength() )
4260     {
4261         std::u16string_view sCmp = sParam.subView(sParam.getLength() - m_sLinkSuffix.getLength(),
4262                                                     m_sLinkSuffix.getLength());
4263         if(sCmp == m_sLinkSuffix)
4264         {
4265             sParam = sParam.copy(0, sParam.getLength() - m_sLinkSuffix.getLength());
4266             if(m_pxDoc)
4267             {
4268                 if(!m_pxDoc->GetDocShell())
4269                     throw RuntimeException("No document shell available");
4270                 SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
4271                 if (m_sLinkSuffix == "|outline")
4272                 {
4273                     const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size();
4274 
4275                     for (size_t i = 0; i < nOutlineCount && !bRet; ++i)
4276                     {
4277                         if(sParam == lcl_CreateOutlineString(i, pDoc))
4278                         {
4279                             bRet = true;
4280                         }
4281                     }
4282                 }
4283                 else if (m_sLinkSuffix == "|drawingobject")
4284                 {
4285                     SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
4286                     if (pModel)
4287                     {
4288                         SdrPage* pPage = pModel->GetPage(0);
4289                         const size_t nObjCount = pPage->GetObjCount();
4290                         for (size_t i = 0; i < nObjCount && !bRet; ++i)
4291                         {
4292                             if (sParam == pPage->GetObj(i)->GetName())
4293                                 bRet = true;
4294                         }
4295                     }
4296                 }
4297             }
4298             else
4299             {
4300                 bRet = m_xRealAccess->hasByName(sParam);
4301             }
4302         }
4303     }
4304     return bRet;
4305 }
4306 
4307 uno::Type  SwXLinkNameAccessWrapper::getElementType()
4308 {
4309     return cppu::UnoType<XPropertySet>::get();
4310 }
4311 
4312 sal_Bool SwXLinkNameAccessWrapper::hasElements()
4313 {
4314     bool bRet = false;
4315     if(m_pxDoc)
4316     {
4317         OSL_FAIL("not implemented");
4318     }
4319     else
4320     {
4321         bRet = m_xRealAccess->hasElements();
4322     }
4323     return bRet;
4324 }
4325 
4326 Reference< XPropertySetInfo >  SwXLinkNameAccessWrapper::getPropertySetInfo()
4327 {
4328     static Reference< XPropertySetInfo >  xRet = m_pPropSet->getPropertySetInfo();
4329     return xRet;
4330 }
4331 
4332 void SwXLinkNameAccessWrapper::setPropertyValue(
4333     const OUString& rPropName, const Any& )
4334 {
4335     throw UnknownPropertyException(rPropName);
4336 }
4337 
4338 static Any lcl_GetDisplayBitmap(std::u16string_view sLinkSuffix)
4339 {
4340     Any aRet;
4341     if(!sLinkSuffix.empty())
4342         sLinkSuffix = sLinkSuffix.substr(1);
4343     OUString sImgId;
4344 
4345     if(sLinkSuffix == u"outline")
4346         sImgId = RID_BMP_NAVI_OUTLINE;
4347     else if(sLinkSuffix == u"table")
4348         sImgId = RID_BMP_NAVI_TABLE;
4349     else if(sLinkSuffix == u"frame")
4350         sImgId = RID_BMP_NAVI_FRAME;
4351     else if(sLinkSuffix == u"graphic")
4352         sImgId = RID_BMP_NAVI_GRAPHIC;
4353     else if(sLinkSuffix == u"ole")
4354         sImgId = RID_BMP_NAVI_OLE;
4355     else if(sLinkSuffix.empty())
4356         sImgId = RID_BMP_NAVI_BOOKMARK;
4357     else if(sLinkSuffix == u"region")
4358         sImgId = RID_BMP_NAVI_REGION;
4359     else if(sLinkSuffix == u"drawingobject")
4360         sImgId = RID_BMP_NAVI_DRAWOBJECT;
4361 
4362     if (!sImgId.isEmpty())
4363     {
4364         aRet <<= VCLUnoHelper::CreateBitmap(BitmapEx(sImgId));
4365     }
4366     return aRet;
4367 }
4368 
4369 Any SwXLinkNameAccessWrapper::getPropertyValue(const OUString& rPropertyName)
4370 {
4371     Any aRet;
4372     if( rPropertyName == UNO_LINK_DISPLAY_NAME )
4373     {
4374         aRet <<= m_sLinkDisplayName;
4375     }
4376     else if( rPropertyName == UNO_LINK_DISPLAY_BITMAP )
4377     {
4378         aRet = lcl_GetDisplayBitmap(m_sLinkSuffix);
4379     }
4380     else
4381         throw UnknownPropertyException(rPropertyName);
4382     return aRet;
4383 }
4384 
4385 void SwXLinkNameAccessWrapper::addPropertyChangeListener(
4386     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4387 {}
4388 
4389 void SwXLinkNameAccessWrapper::removePropertyChangeListener(
4390     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4391 {}
4392 
4393 void SwXLinkNameAccessWrapper::addVetoableChangeListener(
4394     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4395 {}
4396 
4397 void SwXLinkNameAccessWrapper::removeVetoableChangeListener(
4398     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4399 {}
4400 
4401 Reference< XNameAccess >  SwXLinkNameAccessWrapper::getLinks()
4402 {
4403     return this;
4404 }
4405 
4406 OUString SwXLinkNameAccessWrapper::getImplementationName()
4407 {
4408     return "SwXLinkNameAccessWrapper";
4409 }
4410 
4411 sal_Bool SwXLinkNameAccessWrapper::supportsService(const OUString& rServiceName)
4412 {
4413     return cppu::supportsService(this, rServiceName);
4414 }
4415 
4416 Sequence< OUString > SwXLinkNameAccessWrapper::getSupportedServiceNames()
4417 {
4418     Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" };
4419     return aRet;
4420 }
4421 
4422 SwXOutlineTarget::SwXOutlineTarget(OUString aOutlineText, OUString aActualText,
4423                                    const sal_Int32 nOutlineLevel) :
4424     m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
4425     m_sOutlineText(std::move(aOutlineText)),
4426     m_sActualText(std::move(aActualText)),
4427     m_nOutlineLevel(nOutlineLevel)
4428 {
4429 }
4430 
4431 SwXOutlineTarget::~SwXOutlineTarget()
4432 {
4433 }
4434 
4435 Reference< XPropertySetInfo >  SwXOutlineTarget::getPropertySetInfo()
4436 {
4437     static Reference< XPropertySetInfo >  xRet = m_pPropSet->getPropertySetInfo();
4438     return xRet;
4439 }
4440 
4441 void SwXOutlineTarget::setPropertyValue(
4442     const OUString& rPropertyName, const Any& /*aValue*/)
4443 {
4444     throw UnknownPropertyException(rPropertyName);
4445 }
4446 
4447 Any SwXOutlineTarget::getPropertyValue(const OUString& rPropertyName)
4448 {
4449     if (rPropertyName != UNO_LINK_DISPLAY_NAME && rPropertyName != "ActualOutlineName" &&
4450             rPropertyName != "OutlineLevel")
4451         throw UnknownPropertyException(rPropertyName);
4452 
4453     if (rPropertyName == "ActualOutlineName")
4454         return Any(m_sActualText);
4455 
4456     if (rPropertyName == "OutlineLevel")
4457         return Any(m_nOutlineLevel);
4458 
4459     return Any(m_sOutlineText);
4460 }
4461 
4462 void SwXOutlineTarget::addPropertyChangeListener(
4463     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4464 {
4465 }
4466 
4467 void SwXOutlineTarget::removePropertyChangeListener(
4468     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4469 {
4470 }
4471 
4472 void SwXOutlineTarget::addVetoableChangeListener(
4473     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4474 {
4475 }
4476 
4477 void SwXOutlineTarget::removeVetoableChangeListener(
4478     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4479 {
4480 }
4481 
4482 OUString SwXOutlineTarget::getImplementationName()
4483 {
4484     return "SwXOutlineTarget";
4485 }
4486 
4487 sal_Bool SwXOutlineTarget::supportsService(const OUString& ServiceName)
4488 {
4489     return cppu::supportsService(this, ServiceName);
4490 }
4491 
4492 Sequence< OUString > SwXOutlineTarget::getSupportedServiceNames()
4493 {
4494     Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" };
4495 
4496     return aRet;
4497 }
4498 
4499 SwXDrawingObjectTarget::SwXDrawingObjectTarget(OUString aDrawingObjectText) :
4500     m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
4501     m_sDrawingObjectText(std::move(aDrawingObjectText))
4502 {
4503 }
4504 
4505 SwXDrawingObjectTarget::~SwXDrawingObjectTarget()
4506 {
4507 }
4508 
4509 Reference< XPropertySetInfo >  SwXDrawingObjectTarget::getPropertySetInfo()
4510 {
4511     static Reference< XPropertySetInfo >  xRet = m_pPropSet->getPropertySetInfo();
4512     return xRet;
4513 }
4514 
4515 void SwXDrawingObjectTarget::setPropertyValue(
4516     const OUString& rPropertyName, const Any& /*aValue*/)
4517 {
4518     throw UnknownPropertyException(rPropertyName);
4519 }
4520 
4521 Any SwXDrawingObjectTarget::getPropertyValue(const OUString& rPropertyName)
4522 {
4523     if(rPropertyName != UNO_LINK_DISPLAY_NAME)
4524         throw UnknownPropertyException(rPropertyName);
4525 
4526     return Any(m_sDrawingObjectText);
4527 }
4528 
4529 void SwXDrawingObjectTarget::addPropertyChangeListener(
4530     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4531 {
4532 }
4533 
4534 void SwXDrawingObjectTarget::removePropertyChangeListener(
4535     const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
4536 {
4537 }
4538 
4539 void SwXDrawingObjectTarget::addVetoableChangeListener(
4540     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4541 {
4542 }
4543 
4544 void SwXDrawingObjectTarget::removeVetoableChangeListener(
4545     const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
4546 {
4547 }
4548 
4549 OUString SwXDrawingObjectTarget::getImplementationName()
4550 {
4551     return "SwXDrawingObjectTarget";
4552 }
4553 
4554 sal_Bool SwXDrawingObjectTarget::supportsService(const OUString& ServiceName)
4555 {
4556     return cppu::supportsService(this, ServiceName);
4557 }
4558 
4559 Sequence< OUString > SwXDrawingObjectTarget::getSupportedServiceNames()
4560 {
4561     Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" };
4562 
4563     return aRet;
4564 }
4565 
4566 SwXDocumentPropertyHelper::SwXDocumentPropertyHelper(SwDoc& rDoc) :
4567 SvxUnoForbiddenCharsTable ( rDoc.getIDocumentSettingAccess().getForbiddenCharacterTable() )
4568 ,m_pDoc(&rDoc)
4569 {
4570 }
4571 
4572 SwXDocumentPropertyHelper::~SwXDocumentPropertyHelper()
4573 {
4574 }
4575 
4576 Reference<XInterface> SwXDocumentPropertyHelper::GetDrawTable(SwCreateDrawTable nWhich)
4577 {
4578     Reference<XInterface> xRet;
4579     if(m_pDoc)
4580     {
4581         switch(nWhich)
4582         {
4583             // #i52858#
4584             // assure that Draw model is created, if it doesn't exist.
4585             case SwCreateDrawTable::Dash         :
4586                 if(!m_xDashTable.is())
4587                     m_xDashTable = SvxUnoDashTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4588                 xRet = m_xDashTable;
4589             break;
4590             case SwCreateDrawTable::Gradient     :
4591                 if(!m_xGradientTable.is())
4592                     m_xGradientTable = SvxUnoGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4593                 xRet = m_xGradientTable;
4594             break;
4595             case SwCreateDrawTable::Hatch        :
4596                 if(!m_xHatchTable.is())
4597                     m_xHatchTable = SvxUnoHatchTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4598                 xRet = m_xHatchTable;
4599             break;
4600             case SwCreateDrawTable::Bitmap       :
4601                 if(!m_xBitmapTable.is())
4602                     m_xBitmapTable = SvxUnoBitmapTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4603                 xRet = m_xBitmapTable;
4604             break;
4605             case SwCreateDrawTable::TransGradient:
4606                 if(!m_xTransGradientTable.is())
4607                     m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4608                 xRet = m_xTransGradientTable;
4609             break;
4610             case SwCreateDrawTable::Marker       :
4611                 if(!m_xMarkerTable.is())
4612                     m_xMarkerTable = SvxUnoMarkerTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
4613                 xRet = m_xMarkerTable;
4614             break;
4615             case  SwCreateDrawTable::Defaults:
4616                 if(!m_xDrawDefaults.is())
4617                     m_xDrawDefaults = static_cast<cppu::OWeakObject*>(new SwSvxUnoDrawPool(*m_pDoc));
4618                 xRet = m_xDrawDefaults;
4619             break;
4620 #if OSL_DEBUG_LEVEL > 0
4621             default: OSL_FAIL("which table?");
4622 #endif
4623         }
4624     }
4625     return xRet;
4626 }
4627 
4628 void SwXDocumentPropertyHelper::Invalidate()
4629 {
4630     m_xDashTable = nullptr;
4631     m_xGradientTable = nullptr;
4632     m_xHatchTable = nullptr;
4633     m_xBitmapTable = nullptr;
4634     m_xTransGradientTable = nullptr;
4635     m_xMarkerTable = nullptr;
4636     m_xDrawDefaults = nullptr;
4637     m_pDoc = nullptr;
4638     SvxUnoForbiddenCharsTable::mxForbiddenChars.reset();
4639 }
4640 
4641 void SwXDocumentPropertyHelper::onChange()
4642 {
4643     if(m_pDoc)
4644        m_pDoc->getIDocumentState().SetModified();
4645 }
4646 
4647 SwViewOptionAdjust_Impl::SwViewOptionAdjust_Impl(
4648             SwViewShell& rSh, const SwViewOption &rViewOptions)
4649     : m_pShell(&rSh)
4650     , m_aOldViewOptions( rViewOptions )
4651 {
4652 }
4653 
4654 SwViewOptionAdjust_Impl::~SwViewOptionAdjust_Impl()
4655 {
4656     if (m_pShell)
4657     {
4658         m_pShell->ApplyViewOptions( m_aOldViewOptions );
4659     }
4660 }
4661 
4662 void
4663 SwViewOptionAdjust_Impl::AdjustViewOptions(SwPrintData const*const pPrtOptions, bool setShowPlaceHoldersInPDF)
4664 {
4665     // to avoid unnecessary reformatting the view options related to the content
4666     // below should only change if necessary, that is if respective content is present
4667     const bool bContainsHiddenChars         = m_pShell->GetDoc()->ContainsHiddenChars();
4668     const SwFieldType* pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText );
4669     const bool bContainsHiddenFields        = pFieldType && pFieldType->HasWriterListeners();
4670     pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenPara );
4671     const bool bContainsHiddenParagraphs    = pFieldType && pFieldType->HasWriterListeners();
4672     pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::JumpEdit );
4673     const bool bContainsPlaceHolders        = pFieldType && pFieldType->HasWriterListeners();
4674     const bool bContainsFields              = m_pShell->IsAnyFieldInDoc();
4675 
4676     SwViewOption aRenderViewOptions( m_aOldViewOptions );
4677 
4678     // disable anything in the view that should not be printed (or exported to PDF) by default
4679     // (see also dialog "Tools/Options - StarOffice Writer - Formatting Aids"
4680     // in section "Display of ...")
4681     aRenderViewOptions.SetParagraph( false );             // paragraph end
4682     aRenderViewOptions.SetSoftHyph( false );              // aka custom hyphens
4683     aRenderViewOptions.SetBlank( false );                 // spaces
4684     aRenderViewOptions.SetHardBlank( false );             // non-breaking spaces
4685     aRenderViewOptions.SetTab( false );                   // tabs
4686     aRenderViewOptions.SetShowBookmarks( false );         // bookmarks
4687     aRenderViewOptions.SetLineBreak( false );             // breaks (type 1)
4688     aRenderViewOptions.SetPageBreak( false );             // breaks (type 2)
4689     aRenderViewOptions.SetColumnBreak( false );           // breaks (type 3)
4690     bool bVal = pPrtOptions && pPrtOptions->m_bPrintHiddenText;
4691     if (bContainsHiddenChars)
4692         aRenderViewOptions.SetShowHiddenChar( bVal );     // hidden text
4693     if (bContainsHiddenFields)
4694         aRenderViewOptions.SetShowHiddenField( bVal );
4695     if (bContainsHiddenParagraphs)
4696         aRenderViewOptions.SetShowHiddenPara( bVal );
4697 
4698     if (bContainsPlaceHolders)
4699     {
4700         // should always be printed in PDF export!
4701         bVal = !pPrtOptions ? setShowPlaceHoldersInPDF : pPrtOptions->m_bPrintTextPlaceholder;
4702         aRenderViewOptions.SetShowPlaceHolderFields( bVal );
4703     }
4704 
4705     if (bContainsFields)
4706         aRenderViewOptions.SetFieldName( false );
4707 
4708     // we need to set this flag in order to get to see the visible effect of
4709     // some of the above settings (needed for correct rendering)
4710     aRenderViewOptions.SetViewMetaChars( true );
4711 
4712     if (m_aOldViewOptions != aRenderViewOptions)  // check if reformatting is necessary
4713     {
4714         aRenderViewOptions.SetPrinting( pPrtOptions != nullptr );
4715         m_pShell->ApplyViewOptions( aRenderViewOptions );
4716     }
4717 }
4718 
4719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4720