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 <memory>
21 #include <unosection.hxx>
22 
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
25 #include <com/sun/star/text/SectionFileLink.hpp>
26 
27 #include <comphelper/interfacecontainer2.hxx>
28 #include <cppuhelper/exc_hlp.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 
31 #include <cmdid.h>
32 #include <hintids.hxx>
33 #include <svl/urihelper.hxx>
34 #include <svl/listener.hxx>
35 #include <editeng/brushitem.hxx>
36 #include <editeng/xmlcnitm.hxx>
37 #include <sfx2/linkmgr.hxx>
38 #include <sfx2/lnkbase.hxx>
39 #include <osl/mutex.hxx>
40 #include <osl/diagnose.h>
41 #include <vcl/svapp.hxx>
42 #include <fmtclds.hxx>
43 #include <unotextrange.hxx>
44 #include <TextCursorHelper.hxx>
45 #include <unoport.hxx>
46 #include <redline.hxx>
47 #include <unomap.hxx>
48 #include <section.hxx>
49 #include <doc.hxx>
50 #include <IDocumentRedlineAccess.hxx>
51 #include <IDocumentUndoRedo.hxx>
52 #include <docsh.hxx>
53 #include <sfx2/docfile.hxx>
54 #include <docary.hxx>
55 #include <swundo.hxx>
56 #include <tox.hxx>
57 #include <unoidx.hxx>
58 #include <doctxm.hxx>
59 #include <fmtftntx.hxx>
60 #include <fmtclbl.hxx>
61 #include <editeng/frmdiritem.hxx>
62 #include <fmtcntnt.hxx>
63 #include <editeng/lrspitem.hxx>
64 #include <comphelper/servicehelper.hxx>
65 #include <comphelper/string.hxx>
66 
67 using namespace ::com::sun::star;
68 
69 namespace {
70 
71 struct SwTextSectionProperties_Impl
72 {
73     uno::Sequence<sal_Int8> m_Password;
74     OUString  m_sCondition;
75     OUString  m_sLinkFileName;
76     OUString  m_sSectionFilter;
77     OUString  m_sSectionRegion;
78 
79     std::unique_ptr<SwFormatCol>                 m_pColItem;
80     std::unique_ptr<SvxBrushItem>             m_pBrushItem;
81     std::unique_ptr<SwFormatFootnoteAtTextEnd>         m_pFootnoteItem;
82     std::unique_ptr<SwFormatEndAtTextEnd>         m_pEndItem;
83     std::unique_ptr<SvXMLAttrContainerItem> m_pXMLAttr;
84     std::unique_ptr<SwFormatNoBalancedColumns> m_pNoBalanceItem;
85     std::unique_ptr<SvxFrameDirectionItem>    m_pFrameDirItem;
86     std::unique_ptr<SvxLRSpaceItem>           m_pLRSpaceItem;
87 
88     bool m_bDDE;
89     bool m_bHidden;
90     bool m_bCondHidden;
91     bool m_bProtect;
92     bool m_bEditInReadonly;
93     bool m_bUpdateType;
94 
SwTextSectionProperties_Impl__anon81e1440a0111::SwTextSectionProperties_Impl95     SwTextSectionProperties_Impl()
96         : m_bDDE(false)
97         , m_bHidden(false)
98         , m_bCondHidden(false)
99         , m_bProtect(false)
100         , m_bEditInReadonly(false)
101         , m_bUpdateType(true)
102     {
103     }
104 
105 };
106 
107 }
108 
109 class SwXTextSection::Impl
110     : public SvtListener
111 {
112 private:
113     ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
114 
115 public:
116     SwXTextSection &            m_rThis;
117     uno::WeakReference<uno::XInterface> m_wThis;
118     const SfxItemPropertySet &  m_rPropSet;
119     ::comphelper::OInterfaceContainerHelper2 m_EventListeners;
120     const bool                  m_bIndexHeader;
121     bool                        m_bIsDescriptor;
122     OUString             m_sName;
123     std::unique_ptr<SwTextSectionProperties_Impl> m_pProps;
124     SwSectionFormat* m_pFormat;
125 
Impl(SwXTextSection & rThis,SwSectionFormat * const pFormat,const bool bIndexHeader)126     Impl(   SwXTextSection& rThis,
127             SwSectionFormat* const pFormat, const bool bIndexHeader)
128         : SvtListener()
129         , m_rThis(rThis)
130         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_SECTION))
131         , m_EventListeners(m_Mutex)
132         , m_bIndexHeader(bIndexHeader)
133         , m_bIsDescriptor(nullptr == pFormat)
134         , m_pProps(pFormat ? nullptr : new SwTextSectionProperties_Impl())
135         , m_pFormat(pFormat)
136     {
137         if(m_pFormat)
138             StartListening(m_pFormat->GetNotifier());
139     }
140 
Attach(SwSectionFormat * pFormat)141     void Attach(SwSectionFormat* pFormat)
142     {
143         EndListeningAll();
144         StartListening(pFormat->GetNotifier());
145         m_pFormat = pFormat;
146     }
147 
GetSectionFormat() const148     SwSectionFormat* GetSectionFormat() const
149         { return m_pFormat; }
150 
GetSectionFormatOrThrow() const151     SwSectionFormat & GetSectionFormatOrThrow() const {
152         SwSectionFormat *const pFormat( GetSectionFormat() );
153         if (!pFormat) {
154             throw uno::RuntimeException("SwXTextSection: disposed or invalid", nullptr);
155         }
156         return *pFormat;
157     }
158 
159     /// @throws beans::UnknownPropertyException
160     /// @throws beans::PropertyVetoException,
161     /// @throws lang::IllegalArgumentException
162     /// @throws lang::WrappedTargetException,
163     /// @throws uno::RuntimeException
164     void SetPropertyValues_Impl(
165             const uno::Sequence< OUString >& rPropertyNames,
166             const uno::Sequence< uno::Any >& aValues);
167     /// @throws beans::UnknownPropertyException
168     /// @throws lang::WrappedTargetException,
169     /// @throws uno::RuntimeException
170     uno::Sequence< uno::Any >
171         GetPropertyValues_Impl(
172             const uno::Sequence< OUString >& rPropertyNames);
173     virtual void Notify(const SfxHint& rHint) override;
174 };
175 
Notify(const SfxHint & rHint)176 void SwXTextSection::Impl::Notify(const SfxHint& rHint)
177 {
178     if(rHint.GetId() == SfxHintId::Dying)
179     {
180         m_pFormat = nullptr;
181         uno::Reference<uno::XInterface> const xThis(m_wThis);
182         if (!xThis.is())
183         {   // fdo#72695: if UNO object is already dead, don't revive it with event
184             return;
185         }
186         lang::EventObject const ev(xThis);
187         m_EventListeners.disposeAndClear(ev);
188     }
189 }
190 
GetFormat() const191 SwSectionFormat * SwXTextSection::GetFormat() const
192 {
193     return m_pImpl->GetSectionFormat();
194 }
195 
196 uno::Reference< text::XTextSection >
CreateXTextSection(SwSectionFormat * const pFormat,const bool bIndexHeader)197 SwXTextSection::CreateXTextSection(
198         SwSectionFormat *const pFormat, const bool bIndexHeader)
199 {
200     // re-use existing SwXTextSection
201     // #i105557#: do not iterate over the registered clients: race condition
202     uno::Reference< text::XTextSection > xSection;
203     if (pFormat)
204     {
205         xSection.set(pFormat->GetXTextSection());
206     }
207     if ( !xSection.is() )
208     {
209         rtl::Reference<SwXTextSection> pNew = new SwXTextSection(pFormat, bIndexHeader);
210         xSection.set(pNew);
211         if (pFormat)
212         {
213             pFormat->SetXTextSection(xSection);
214         }
215         // need a permanent Reference to initialize m_wThis
216         pNew->m_pImpl->m_wThis = xSection;
217     }
218     return xSection;
219 }
220 
SwXTextSection(SwSectionFormat * const pFormat,const bool bIndexHeader)221 SwXTextSection::SwXTextSection(
222         SwSectionFormat *const pFormat, const bool bIndexHeader)
223     : m_pImpl( new SwXTextSection::Impl(*this, pFormat, bIndexHeader) )
224 {
225 }
226 
~SwXTextSection()227 SwXTextSection::~SwXTextSection()
228 {
229 }
230 
getUnoTunnelId()231 const uno::Sequence< sal_Int8 > & SwXTextSection::getUnoTunnelId()
232 {
233     static const UnoTunnelIdInit theSwXTextSectionUnoTunnelId;
234     return theSwXTextSectionUnoTunnelId.getSeq();
235 }
236 
237 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)238 SwXTextSection::getSomething(const uno::Sequence< sal_Int8 >& rId)
239 {
240     return ::sw::UnoTunnelImpl<SwXTextSection>(rId, this);
241 }
242 
243 uno::Reference< text::XTextSection > SAL_CALL
getParentSection()244 SwXTextSection::getParentSection()
245 {
246     SolarMutexGuard aGuard;
247 
248     SwSectionFormat & rSectionFormat( m_pImpl->GetSectionFormatOrThrow() );
249 
250     SwSectionFormat *const pParentFormat = rSectionFormat.GetParent();
251     const uno::Reference< text::XTextSection > xRet =
252         pParentFormat ? CreateXTextSection(pParentFormat) : nullptr;
253     return xRet;
254 }
255 
256 uno::Sequence< uno::Reference< text::XTextSection > > SAL_CALL
getChildSections()257 SwXTextSection::getChildSections()
258 {
259     SolarMutexGuard aGuard;
260 
261     SwSectionFormat & rSectionFormat( m_pImpl->GetSectionFormatOrThrow() );
262 
263     SwSections aChildren;
264     rSectionFormat.GetChildSections(aChildren, SectionSort::Not, false);
265     uno::Sequence<uno::Reference<text::XTextSection> > aSeq(aChildren.size());
266     uno::Reference< text::XTextSection > * pArray = aSeq.getArray();
267     for (size_t i = 0; i < aChildren.size(); ++i)
268     {
269         SwSectionFormat *const pChild = aChildren[i]->GetFormat();
270         pArray[i] = CreateXTextSection(pChild);
271     }
272     return aSeq;
273 }
274 
275 void SAL_CALL
attach(const uno::Reference<text::XTextRange> & xTextRange)276 SwXTextSection::attach(const uno::Reference< text::XTextRange > & xTextRange)
277 {
278     SolarMutexGuard g;
279 
280     if (!m_pImpl->m_bIsDescriptor)
281     {
282         throw uno::RuntimeException();
283     }
284 
285     uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
286     SwXTextRange* pRange = nullptr;
287     OTextCursorHelper* pCursor = nullptr;
288     if(xRangeTunnel.is())
289     {
290         pRange  = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
291         pCursor =
292             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
293     }
294 
295     SwDoc *const pDoc =
296         pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
297     if (!pDoc)
298     {
299         throw lang::IllegalArgumentException();
300     }
301 
302     SwUnoInternalPaM aPam(*pDoc);
303     // this has to return true now
304     ::sw::XTextRangeToSwPaM(aPam, xTextRange);
305     UnoActionContext aCont(pDoc);
306     pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSSECTION, nullptr );
307 
308     if (m_pImpl->m_sName.isEmpty())
309     {
310         m_pImpl->m_sName = "TextSection";
311     }
312     SectionType eType(SectionType::FileLink);
313     if( m_pImpl->m_pProps->m_bDDE )
314         eType = SectionType::DdeLink;
315     else if( m_pImpl->m_pProps->m_sLinkFileName.isEmpty() && m_pImpl->m_pProps->m_sSectionRegion.isEmpty() )
316         eType = SectionType::Content;
317     // index header section?
318     if (m_pImpl->m_bIndexHeader)
319     {
320         // caller wants an index header section, but will only
321         // give him one if a) we are inside an index, and b) said
322         // index doesn't yet have a header section.
323         const SwTOXBase* pBase = SwDoc::GetCurTOX(*aPam.Start());
324 
325         // are we inside an index?
326         if (pBase)
327         {
328             // get all child sections
329             SwSections aSectionsArr;
330             static_cast<const SwTOXBaseSection*>(pBase)->GetFormat()->
331                 GetChildSections(aSectionsArr);
332 
333             // and search for current header section
334             const size_t nCount = aSectionsArr.size();
335             bool bHeaderPresent = false;
336             for(size_t i = 0; i < nCount; ++i)
337             {
338                 if (aSectionsArr[i]->GetType() == SectionType::ToxHeader)
339                     bHeaderPresent = true;
340             }
341             if (! bHeaderPresent)
342             {
343                 eType = SectionType::ToxHeader;
344             }
345         }
346     }
347 
348     SwSectionData aSect(eType, pDoc->GetUniqueSectionName(&m_pImpl->m_sName));
349     aSect.SetCondition(m_pImpl->m_pProps->m_sCondition);
350     aSect.SetLinkFileName(m_pImpl->m_pProps->m_sLinkFileName +
351         OUStringChar(sfx2::cTokenSeparator) +
352         m_pImpl->m_pProps->m_sSectionFilter +
353         OUStringChar(sfx2::cTokenSeparator) +
354         m_pImpl->m_pProps->m_sSectionRegion);
355 
356     aSect.SetHidden(m_pImpl->m_pProps->m_bHidden);
357     aSect.SetProtectFlag(m_pImpl->m_pProps->m_bProtect);
358     aSect.SetEditInReadonlyFlag(m_pImpl->m_pProps->m_bEditInReadonly);
359 
360     SfxItemSet aSet(
361         pDoc->GetAttrPool(),
362         svl::Items<
363             RES_LR_SPACE, RES_LR_SPACE,
364             RES_BACKGROUND, RES_BACKGROUND,
365             RES_COL, RES_COL,
366             RES_FTN_AT_TXTEND, RES_FRAMEDIR,
367             RES_UNKNOWNATR_CONTAINER,RES_UNKNOWNATR_CONTAINER>{});
368     if (m_pImpl->m_pProps->m_pBrushItem)
369     {
370         aSet.Put(*m_pImpl->m_pProps->m_pBrushItem);
371     }
372     if (m_pImpl->m_pProps->m_pColItem)
373     {
374         aSet.Put(*m_pImpl->m_pProps->m_pColItem);
375     }
376     if (m_pImpl->m_pProps->m_pFootnoteItem)
377     {
378         aSet.Put(*m_pImpl->m_pProps->m_pFootnoteItem);
379     }
380     if (m_pImpl->m_pProps->m_pEndItem)
381     {
382         aSet.Put(*m_pImpl->m_pProps->m_pEndItem);
383     }
384     if (m_pImpl->m_pProps->m_pXMLAttr)
385     {
386         aSet.Put(*m_pImpl->m_pProps->m_pXMLAttr);
387     }
388     if (m_pImpl->m_pProps->m_pNoBalanceItem)
389     {
390         aSet.Put(*m_pImpl->m_pProps->m_pNoBalanceItem);
391     }
392     if (m_pImpl->m_pProps->m_pFrameDirItem)
393     {
394         aSet.Put(*m_pImpl->m_pProps->m_pFrameDirItem);
395     }
396     if (m_pImpl->m_pProps->m_pLRSpaceItem)
397     {
398         aSet.Put(*m_pImpl->m_pProps->m_pLRSpaceItem);
399     }
400     // section password
401     if (m_pImpl->m_pProps->m_Password.hasElements())
402     {
403         aSect.SetPassword(m_pImpl->m_pProps->m_Password);
404     }
405 
406     SwSection *const pRet =
407         pDoc->InsertSwSection( aPam, aSect, nullptr, aSet.Count() ? &aSet : nullptr );
408     if (!pRet) // fdo#42450 text range could partially overlap existing section
409     {
410         // shouldn't have created an undo object yet
411         pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSSECTION, nullptr );
412         throw lang::IllegalArgumentException(
413                 "SwXTextSection::attach(): invalid TextRange",
414                 static_cast< ::cppu::OWeakObject*>(this), 0);
415     }
416     m_pImpl->Attach(pRet->GetFormat());
417     pRet->GetFormat()->SetXObject(static_cast< ::cppu::OWeakObject*>(this));
418 
419     // XML import must hide sections depending on their old
420     //         condition status
421     if (!m_pImpl->m_pProps->m_sCondition.isEmpty())
422     {
423         pRet->SetCondHidden(m_pImpl->m_pProps->m_bCondHidden);
424     }
425 
426     // set update type if DDE link (and connect, if necessary)
427     if (m_pImpl->m_pProps->m_bDDE)
428     {
429         if (! pRet->IsConnected())
430         {
431             pRet->CreateLink(LinkCreateType::Connect);
432         }
433         pRet->SetUpdateType( m_pImpl->m_pProps->m_bUpdateType ?
434                 SfxLinkUpdateMode::ALWAYS : SfxLinkUpdateMode::ONCALL );
435     }
436 
437     // end the Undo bracketing here
438     pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSSECTION, nullptr );
439     m_pImpl->m_pProps.reset();
440     m_pImpl->m_bIsDescriptor = false;
441 }
442 
443 uno::Reference< text::XTextRange > SAL_CALL
getAnchor()444 SwXTextSection::getAnchor()
445 {
446     SolarMutexGuard aGuard;
447 
448     uno::Reference< text::XTextRange >  xRet;
449     SwSectionFormat *const pSectFormat = m_pImpl->GetSectionFormat();
450     if(pSectFormat)
451     {
452         const SwNodeIndex* pIdx;
453         if( nullptr != ( pSectFormat->GetSection() ) &&
454             nullptr != ( pIdx = pSectFormat->GetContent().GetContentIdx() ) &&
455             pIdx->GetNode().GetNodes().IsDocNodes() )
456         {
457             bool isMoveIntoTable(false);
458             SwPaM aPaM(*pIdx);
459             aPaM.Move( fnMoveForward, GoInContent );
460             assert(pIdx->GetNode().IsSectionNode());
461             if (aPaM.GetPoint()->nNode.GetNode().FindTableNode() != pIdx->GetNode().FindTableNode()
462                 || aPaM.GetPoint()->nNode.GetNode().FindSectionNode() != &pIdx->GetNode())
463             {
464                 isMoveIntoTable = true;
465             }
466 
467             const SwEndNode* pEndNode = pIdx->GetNode().EndOfSectionNode();
468             SwPaM aEnd(*pEndNode);
469             aEnd.Move( fnMoveBackward, GoInContent );
470             if (aEnd.GetPoint()->nNode.GetNode().FindTableNode() != pIdx->GetNode().FindTableNode()
471                 || aEnd.GetPoint()->nNode.GetNode().FindSectionNode() != &pIdx->GetNode())
472             {
473                 isMoveIntoTable = true;
474             }
475             if (isMoveIntoTable)
476             {
477                 uno::Reference<text::XText> const xParentText(
478                     ::sw::CreateParentXText(*pSectFormat->GetDoc(), SwPosition(*pIdx)));
479                 xRet = new SwXTextRange(*pSectFormat);
480             }
481             else // for compatibility, keep the old way in this case
482             {
483                 xRet = SwXTextRange::CreateXTextRange(*pSectFormat->GetDoc(),
484                     *aPaM.Start(), aEnd.Start());
485             }
486         }
487     }
488     return xRet;
489 }
490 
dispose()491 void SAL_CALL SwXTextSection::dispose()
492 {
493     SolarMutexGuard aGuard;
494 
495     SwSectionFormat *const pSectFormat = m_pImpl->GetSectionFormat();
496     if (pSectFormat)
497     {
498         pSectFormat->GetDoc()->DelSectionFormat( pSectFormat );
499     }
500 }
501 
addEventListener(const uno::Reference<lang::XEventListener> & xListener)502 void SAL_CALL SwXTextSection::addEventListener(
503         const uno::Reference< lang::XEventListener > & xListener)
504 {
505     // no need to lock here as m_pImpl is const and container threadsafe
506     m_pImpl->m_EventListeners.addInterface(xListener);
507 }
508 
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)509 void SAL_CALL SwXTextSection::removeEventListener(
510         const uno::Reference< lang::XEventListener > & xListener)
511 {
512     // no need to lock here as m_pImpl is const and container threadsafe
513     m_pImpl->m_EventListeners.removeInterface(xListener);
514 }
515 
516 uno::Reference< beans::XPropertySetInfo > SAL_CALL
getPropertySetInfo()517 SwXTextSection::getPropertySetInfo()
518 {
519     SolarMutexGuard g;
520     return m_pImpl->m_rPropSet.getPropertySetInfo();
521 }
522 
523 static void
lcl_UpdateLinkType(SwSection & rSection,bool const bLinkUpdateAlways)524 lcl_UpdateLinkType(SwSection & rSection, bool const bLinkUpdateAlways)
525 {
526     if (rSection.GetType() == SectionType::DdeLink)
527     {
528         // set update type; needs an established link
529         if (!rSection.IsConnected())
530         {
531             rSection.CreateLink(LinkCreateType::Connect);
532         }
533         rSection.SetUpdateType( bLinkUpdateAlways
534             ? SfxLinkUpdateMode::ALWAYS : SfxLinkUpdateMode::ONCALL );
535     }
536 }
537 
538 static void
lcl_UpdateSection(SwSectionFormat * const pFormat,std::unique_ptr<SwSectionData> const & pSectionData,std::unique_ptr<SfxItemSet> const & pItemSet,bool const bLinkModeChanged,bool const bLinkUpdateAlways=true)539 lcl_UpdateSection(SwSectionFormat *const pFormat,
540     std::unique_ptr<SwSectionData> const& pSectionData,
541     std::unique_ptr<SfxItemSet> const& pItemSet,
542     bool const bLinkModeChanged, bool const bLinkUpdateAlways = true)
543 {
544     if (!pFormat)
545         return;
546 
547     SwSection & rSection = *pFormat->GetSection();
548     SwDoc *const pDoc = pFormat->GetDoc();
549     SwSectionFormats const& rFormats = pDoc->GetSections();
550     UnoActionContext aContext(pDoc);
551     for (size_t i = 0; i < rFormats.size(); ++i)
552     {
553         if (rFormats[i]->GetSection()->GetSectionName()
554                 == rSection.GetSectionName())
555         {
556             pDoc->UpdateSection(i, *pSectionData, pItemSet.get(),
557                     pDoc->IsInReading());
558             {
559                 // temporarily remove actions to allow cursor update
560                 // TODO: why? no table cursor here!
561                 UnoActionRemoveContext aRemoveContext( pDoc );
562             }
563 
564             if (bLinkModeChanged)
565             {
566                 lcl_UpdateLinkType(rSection, bLinkUpdateAlways);
567             }
568             // section found and processed: break from loop
569             break;
570         }
571     }
572 }
573 
SetPropertyValues_Impl(const uno::Sequence<OUString> & rPropertyNames,const uno::Sequence<uno::Any> & rValues)574 void SwXTextSection::Impl::SetPropertyValues_Impl(
575     const uno::Sequence< OUString >& rPropertyNames,
576     const uno::Sequence< uno::Any >& rValues)
577 {
578     if(rPropertyNames.getLength() != rValues.getLength())
579     {
580         throw lang::IllegalArgumentException();
581     }
582     SwSectionFormat *const pFormat = GetSectionFormat();
583     if (!pFormat && !m_bIsDescriptor)
584     {
585         throw uno::RuntimeException();
586     }
587 
588     std::unique_ptr<SwSectionData> const pSectionData(
589         pFormat ? new SwSectionData(*pFormat->GetSection()) : nullptr);
590 
591     OUString const*const pPropertyNames = rPropertyNames.getConstArray();
592     uno::Any const*const pValues = rValues.getConstArray();
593     std::unique_ptr<SfxItemSet> pItemSet;
594     bool bLinkModeChanged = false;
595     bool bLinkMode = false;
596 
597     for (sal_Int32 nProperty = 0; nProperty < rPropertyNames.getLength();
598          nProperty++)
599     {
600         SfxItemPropertyMapEntry const*const pEntry =
601             m_rPropSet.getPropertyMap().getByName(pPropertyNames[nProperty]);
602         if (!pEntry)
603         {
604             throw beans::UnknownPropertyException(
605                 "Unknown property: " + pPropertyNames[nProperty],
606                 static_cast<cppu::OWeakObject *>(& m_rThis));
607         }
608         if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
609         {
610             throw beans::PropertyVetoException(
611                 "Property is read-only: " + pPropertyNames[nProperty],
612                 static_cast<cppu::OWeakObject *>(& m_rThis));
613         }
614         switch (pEntry->nWID)
615         {
616             case WID_SECT_CONDITION:
617             {
618                 OUString uTmp;
619                 pValues[nProperty] >>= uTmp;
620                 if (m_bIsDescriptor)
621                 {
622                     m_pProps->m_sCondition = uTmp;
623                 }
624                 else
625                 {
626                     pSectionData->SetCondition(uTmp);
627                 }
628             }
629             break;
630             case WID_SECT_DDE_TYPE:
631             case WID_SECT_DDE_FILE:
632             case WID_SECT_DDE_ELEMENT:
633             {
634                 OUString sTmp;
635                 pValues[nProperty] >>= sTmp;
636                 if (m_bIsDescriptor)
637                 {
638                     if (!m_pProps->m_bDDE)
639                     {
640                         m_pProps->m_sLinkFileName =
641                             OUStringChar(sfx2::cTokenSeparator) + OUStringChar(sfx2::cTokenSeparator);
642                         m_pProps->m_bDDE = true;
643                     }
644                     m_pProps->m_sLinkFileName = comphelper::string::setToken(
645                         m_pProps->m_sLinkFileName,
646                         pEntry->nWID - WID_SECT_DDE_TYPE, sfx2::cTokenSeparator, sTmp);
647                 }
648                 else
649                 {
650                     OUString sLinkFileName(pSectionData->GetLinkFileName());
651                     if (pSectionData->GetType() != SectionType::DdeLink)
652                     {
653                         sLinkFileName = OUStringChar(sfx2::cTokenSeparator) + OUStringChar(sfx2::cTokenSeparator);
654                         pSectionData->SetType(SectionType::DdeLink);
655                     }
656                     sLinkFileName = comphelper::string::setToken(sLinkFileName,
657                         pEntry->nWID - WID_SECT_DDE_TYPE,
658                             sfx2::cTokenSeparator, sTmp);
659                     pSectionData->SetLinkFileName(sLinkFileName);
660                 }
661             }
662             break;
663             case WID_SECT_DDE_AUTOUPDATE:
664             {
665                 bool bVal(false);
666                 if (!(pValues[nProperty] >>= bVal))
667                 {
668                     throw lang::IllegalArgumentException();
669                 }
670                 if (m_bIsDescriptor)
671                 {
672                     m_pProps->m_bUpdateType = bVal;
673                 }
674                 else
675                 {
676                     bLinkModeChanged = true;
677                     bLinkMode = bVal;
678                 }
679             }
680             break;
681             case WID_SECT_LINK:
682             {
683                 text::SectionFileLink aLink;
684                 if (!(pValues[nProperty] >>= aLink))
685                 {
686                     throw lang::IllegalArgumentException();
687                 }
688                 if (m_bIsDescriptor)
689                 {
690                     m_pProps->m_bDDE = false;
691                     m_pProps->m_sLinkFileName = aLink.FileURL;
692                     m_pProps->m_sSectionFilter = aLink.FilterName;
693                 }
694                 else
695                 {
696                     if (pSectionData->GetType() != SectionType::FileLink &&
697                         !aLink.FileURL.isEmpty())
698                     {
699                         pSectionData->SetType(SectionType::FileLink);
700                     }
701                     const OUString sTmp(!aLink.FileURL.isEmpty()
702                         ? URIHelper::SmartRel2Abs(
703                             pFormat->GetDoc()->GetDocShell()->GetMedium()->GetURLObject(),
704                             aLink.FileURL, URIHelper::GetMaybeFileHdl())
705                         : OUString());
706                     const OUString sFileName(
707                         sTmp + OUStringChar(sfx2::cTokenSeparator) +
708                         aLink.FilterName + OUStringChar(sfx2::cTokenSeparator) +
709                         pSectionData->GetLinkFileName().getToken(2, sfx2::cTokenSeparator));
710                     pSectionData->SetLinkFileName(sFileName);
711                     if (sFileName.getLength() < 3)
712                     {
713                         pSectionData->SetType(SectionType::Content);
714                     }
715                 }
716             }
717             break;
718             case WID_SECT_REGION:
719             {
720                 OUString sLink;
721                 pValues[nProperty] >>= sLink;
722                 if (m_bIsDescriptor)
723                 {
724                     m_pProps->m_bDDE = false;
725                     m_pProps->m_sSectionRegion = sLink;
726                 }
727                 else
728                 {
729                     if (pSectionData->GetType() != SectionType::FileLink &&
730                         !sLink.isEmpty())
731                     {
732                         pSectionData->SetType(SectionType::FileLink);
733                     }
734                     OUString sSectLink(pSectionData->GetLinkFileName());
735                     for (sal_Int32 i = comphelper::string::getTokenCount(sSectLink, sfx2::cTokenSeparator);
736                          i < 3; ++i)
737                     {
738                         sSectLink += OUStringChar(sfx2::cTokenSeparator);
739                     }
740                     sSectLink = comphelper::string::setToken(sSectLink, 2, sfx2::cTokenSeparator, sLink);
741                     pSectionData->SetLinkFileName(sSectLink);
742                     if (sSectLink.getLength() < 3)
743                     {
744                         pSectionData->SetType(SectionType::Content);
745                     }
746                 }
747             }
748             break;
749             case WID_SECT_VISIBLE:
750             {
751                 bool bVal(false);
752                 if (!(pValues[nProperty] >>= bVal))
753                 {
754                     throw lang::IllegalArgumentException();
755                 }
756                 if (m_bIsDescriptor)
757                 {
758                     m_pProps->m_bHidden = !bVal;
759                 }
760                 else
761                 {
762                     pSectionData->SetHidden(!bVal);
763                 }
764             }
765             break;
766             case WID_SECT_CURRENTLY_VISIBLE:
767             {
768                 bool bVal(false);
769                 if (!(pValues[nProperty] >>= bVal))
770                 {
771                     throw lang::IllegalArgumentException();
772                 }
773                 if (m_bIsDescriptor)
774                 {
775                     m_pProps->m_bCondHidden = !bVal;
776                 }
777                 else
778                 {
779                     if (!pSectionData->GetCondition().isEmpty())
780                     {
781                         pSectionData->SetCondHidden(!bVal);
782                     }
783                 }
784             }
785             break;
786             case WID_SECT_PROTECTED:
787             {
788                 bool bVal(false);
789                 if (!(pValues[nProperty] >>= bVal))
790                 {
791                     throw lang::IllegalArgumentException();
792                 }
793                 if (m_bIsDescriptor)
794                 {
795                     m_pProps->m_bProtect = bVal;
796                 }
797                 else
798                 {
799                     pSectionData->SetProtectFlag(bVal);
800                 }
801             }
802             break;
803             case WID_SECT_EDIT_IN_READONLY:
804             {
805                 bool bVal(false);
806                 if (!(pValues[nProperty] >>= bVal))
807                 {
808                     throw lang::IllegalArgumentException();
809                 }
810                 if (m_bIsDescriptor)
811                 {
812                     m_pProps->m_bEditInReadonly = bVal;
813                 }
814                 else
815                 {
816                     pSectionData->SetEditInReadonlyFlag(bVal);
817                 }
818             }
819             break;
820             case WID_SECT_PASSWORD:
821             {
822                 uno::Sequence<sal_Int8> aSeq;
823                 pValues[nProperty] >>= aSeq;
824                 if (m_bIsDescriptor)
825                 {
826                     m_pProps->m_Password = aSeq;
827                 }
828                 else
829                 {
830                     pSectionData->SetPassword(aSeq);
831                 }
832             }
833             break;
834             default:
835             {
836                 if (pFormat)
837                 {
838                     const SfxItemSet& rOldAttrSet = pFormat->GetAttrSet();
839                     pItemSet.reset( new SfxItemSet(*rOldAttrSet.GetPool(), {{pEntry->nWID, pEntry->nWID}}));
840                     pItemSet->Put(rOldAttrSet);
841                     m_rPropSet.setPropertyValue(*pEntry,
842                             pValues[nProperty], *pItemSet);
843                 }
844                 else
845                 {
846                     SfxPoolItem* pPutItem = nullptr;
847                     if (RES_COL == pEntry->nWID)
848                     {
849                         if (!m_pProps->m_pColItem)
850                         {
851                             m_pProps->m_pColItem.reset(new SwFormatCol);
852                         }
853                         pPutItem = m_pProps->m_pColItem.get();
854                     }
855                     else if (RES_BACKGROUND == pEntry->nWID)
856                     {
857                         if (!m_pProps->m_pBrushItem)
858                         {
859                             m_pProps->m_pBrushItem.reset(
860                                 new SvxBrushItem(RES_BACKGROUND));
861                         }
862                         pPutItem = m_pProps->m_pBrushItem.get();
863                     }
864                     else if (RES_FTN_AT_TXTEND == pEntry->nWID)
865                     {
866                         if (!m_pProps->m_pFootnoteItem)
867                         {
868                             m_pProps->m_pFootnoteItem.reset(new SwFormatFootnoteAtTextEnd);
869                         }
870                         pPutItem = m_pProps->m_pFootnoteItem.get();
871                     }
872                     else if (RES_END_AT_TXTEND == pEntry->nWID)
873                     {
874                         if (!m_pProps->m_pEndItem)
875                         {
876                             m_pProps->m_pEndItem.reset(new SwFormatEndAtTextEnd);
877                         }
878                         pPutItem = m_pProps->m_pEndItem.get();
879                     }
880                     else if (RES_UNKNOWNATR_CONTAINER== pEntry->nWID)
881                     {
882                         if (!m_pProps->m_pXMLAttr)
883                         {
884                             m_pProps->m_pXMLAttr.reset(
885                                 new SvXMLAttrContainerItem(
886                                     RES_UNKNOWNATR_CONTAINER));
887                         }
888                         pPutItem = m_pProps->m_pXMLAttr.get();
889                     }
890                     else if (RES_COLUMNBALANCE== pEntry->nWID)
891                     {
892                         if (!m_pProps->m_pNoBalanceItem)
893                         {
894                             m_pProps->m_pNoBalanceItem.reset(
895                                 new SwFormatNoBalancedColumns(true));
896                         }
897                         pPutItem = m_pProps->m_pNoBalanceItem.get();
898                     }
899                     else if (RES_FRAMEDIR == pEntry->nWID)
900                     {
901                         if (!m_pProps->m_pFrameDirItem)
902                         {
903                             m_pProps->m_pFrameDirItem.reset(
904                                 new SvxFrameDirectionItem(
905                                 SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));
906                         }
907                         pPutItem = m_pProps->m_pFrameDirItem.get();
908                     }
909                     else if (RES_LR_SPACE == pEntry->nWID)
910                     {
911                         if (!m_pProps->m_pLRSpaceItem)
912                         {
913                             m_pProps->m_pLRSpaceItem.reset(
914                                 new SvxLRSpaceItem( RES_LR_SPACE ));
915                         }
916                         pPutItem = m_pProps->m_pLRSpaceItem.get();
917                     }
918                     if (pPutItem)
919                     {
920                         pPutItem->PutValue(pValues[nProperty],
921                                 pEntry->nMemberId);
922                     }
923                 }
924             }
925         }
926     }
927 
928     lcl_UpdateSection(pFormat, pSectionData, pItemSet, bLinkModeChanged,
929         bLinkMode);
930 }
931 
932 void SAL_CALL
setPropertyValues(const uno::Sequence<OUString> & rPropertyNames,const uno::Sequence<uno::Any> & rValues)933 SwXTextSection::setPropertyValues(
934     const uno::Sequence< OUString >& rPropertyNames,
935     const uno::Sequence< uno::Any >& rValues)
936 {
937     SolarMutexGuard aGuard;
938 
939     // workaround for bad designed API
940     try
941     {
942         m_pImpl->SetPropertyValues_Impl( rPropertyNames, rValues );
943     }
944     catch (const beans::UnknownPropertyException &rException)
945     {
946         // wrap the original (here not allowed) exception in
947         // a WrappedTargetException that gets thrown instead.
948         lang::WrappedTargetException aWExc;
949         aWExc.TargetException <<= rException;
950         throw aWExc;
951     }
952 }
953 
setPropertyValue(const OUString & rPropertyName,const uno::Any & rValue)954 void SwXTextSection::setPropertyValue(
955     const OUString& rPropertyName, const uno::Any& rValue)
956 {
957     SolarMutexGuard aGuard;
958 
959     uno::Sequence< OUString > aPropertyNames { rPropertyName };
960     uno::Sequence< uno::Any > aValues(1);
961     aValues.getArray()[0] = rValue;
962     m_pImpl->SetPropertyValues_Impl( aPropertyNames, aValues );
963 }
964 
965 uno::Sequence< uno::Any >
GetPropertyValues_Impl(const uno::Sequence<OUString> & rPropertyNames)966 SwXTextSection::Impl::GetPropertyValues_Impl(
967         const uno::Sequence< OUString > & rPropertyNames )
968 {
969     SwSectionFormat *const pFormat = GetSectionFormat();
970     if (!pFormat && !m_bIsDescriptor)
971     {
972         throw uno::RuntimeException( "non-descriptor section without format");
973     }
974 
975     uno::Sequence< uno::Any > aRet(rPropertyNames.getLength());
976     uno::Any* pRet = aRet.getArray();
977     SwSection *const pSect = pFormat ? pFormat->GetSection() : nullptr;
978     const OUString* pPropertyNames = rPropertyNames.getConstArray();
979 
980     for (sal_Int32 nProperty = 0; nProperty < rPropertyNames.getLength();
981         nProperty++)
982     {
983         SfxItemPropertyMapEntry const*const pEntry =
984             m_rPropSet.getPropertyMap().getByName(pPropertyNames[nProperty]);
985         if (!pEntry)
986         {
987             throw beans::UnknownPropertyException(
988                 "Unknown property: " + pPropertyNames[nProperty],
989                 static_cast<cppu::OWeakObject *>(& m_rThis));
990         }
991         switch(pEntry->nWID)
992         {
993             case WID_SECT_CONDITION:
994             {
995                 const OUString uTmp( m_bIsDescriptor
996                     ? m_pProps->m_sCondition
997                     : pSect->GetCondition());
998                 pRet[nProperty] <<= uTmp;
999             }
1000             break;
1001             case WID_SECT_DDE_TYPE:
1002             case WID_SECT_DDE_FILE:
1003             case WID_SECT_DDE_ELEMENT:
1004             {
1005                 OUString sRet;
1006                 if (m_bIsDescriptor)
1007                 {
1008                     if (m_pProps->m_bDDE)
1009                     {
1010                         sRet = m_pProps->m_sLinkFileName;
1011                     }
1012                 }
1013                 else if (SectionType::DdeLink == pSect->GetType())
1014                 {
1015                     sRet = pSect->GetLinkFileName();
1016                 }
1017                 pRet[nProperty] <<= sRet.getToken(pEntry->nWID - WID_SECT_DDE_TYPE,
1018                     sfx2::cTokenSeparator);
1019             }
1020             break;
1021             case WID_SECT_DDE_AUTOUPDATE:
1022             {
1023                 // GetUpdateType() returns .._ALWAYS or .._ONCALL
1024                 if (pSect && pSect->IsLinkType() && pSect->IsConnected())  // #i73247#
1025                 {
1026                     const bool bTemp =
1027                         (pSect->GetUpdateType() == SfxLinkUpdateMode::ALWAYS);
1028                     pRet[nProperty] <<= bTemp;
1029                 }
1030             }
1031             break;
1032             case WID_SECT_LINK     :
1033             {
1034                 text::SectionFileLink aLink;
1035                 if (m_bIsDescriptor)
1036                 {
1037                     if (!m_pProps->m_bDDE)
1038                     {
1039                         aLink.FileURL = m_pProps->m_sLinkFileName;
1040                         aLink.FilterName = m_pProps->m_sSectionFilter;
1041                     }
1042                 }
1043                 else if (SectionType::FileLink == pSect->GetType())
1044                 {
1045                     const OUString& sRet( pSect->GetLinkFileName() );
1046                     sal_Int32 nIndex(0);
1047                     aLink.FileURL =
1048                         sRet.getToken(0, sfx2::cTokenSeparator, nIndex);
1049                     aLink.FilterName =
1050                         sRet.getToken(0, sfx2::cTokenSeparator, nIndex);
1051                 }
1052                 pRet[nProperty] <<= aLink;
1053             }
1054             break;
1055             case WID_SECT_REGION :
1056             {
1057                 OUString sRet;
1058                 if (m_bIsDescriptor)
1059                 {
1060                     sRet = m_pProps->m_sSectionRegion;
1061                 }
1062                 else if (SectionType::FileLink == pSect->GetType())
1063                 {
1064                     sRet = pSect->GetLinkFileName().getToken(2,
1065                             sfx2::cTokenSeparator);
1066                 }
1067                 pRet[nProperty] <<= sRet;
1068             }
1069             break;
1070             case WID_SECT_VISIBLE   :
1071             {
1072                 const bool bTemp = m_bIsDescriptor
1073                     ? !m_pProps->m_bHidden : !pSect->IsHidden();
1074                 pRet[nProperty] <<= bTemp;
1075             }
1076             break;
1077             case WID_SECT_CURRENTLY_VISIBLE:
1078             {
1079                 const bool bTemp = m_bIsDescriptor
1080                     ? !m_pProps->m_bCondHidden : !pSect->IsCondHidden();
1081                 pRet[nProperty] <<= bTemp;
1082             }
1083             break;
1084             case WID_SECT_PROTECTED:
1085             {
1086                 const bool bTemp = m_bIsDescriptor
1087                     ? m_pProps->m_bProtect : pSect->IsProtect();
1088                 pRet[nProperty] <<= bTemp;
1089             }
1090             break;
1091             case WID_SECT_EDIT_IN_READONLY:
1092             {
1093                 const bool bTemp = m_bIsDescriptor
1094                     ? m_pProps->m_bEditInReadonly : pSect->IsEditInReadonly();
1095                 pRet[nProperty] <<= bTemp;
1096             }
1097             break;
1098             case  FN_PARAM_LINK_DISPLAY_NAME:
1099             {
1100                 if (pFormat)
1101                 {
1102                     pRet[nProperty] <<= pFormat->GetSection()->GetSectionName();
1103                 }
1104             }
1105             break;
1106             case WID_SECT_DOCUMENT_INDEX:
1107             {
1108                 // search enclosing index
1109                 SwSection* pEnclosingSection = pSect;
1110                 while ((pEnclosingSection != nullptr) &&
1111                        (SectionType::ToxContent != pEnclosingSection->GetType()))
1112                 {
1113                     pEnclosingSection = pEnclosingSection->GetParent();
1114                 }
1115                 SwTOXBaseSection* const pTOXBaseSect = pEnclosingSection ?
1116                     dynamic_cast<SwTOXBaseSection*>( pEnclosingSection ) : nullptr;
1117                 if (pTOXBaseSect)
1118                 {
1119                     // convert section to TOXBase and get SwXDocumentIndex
1120                     const uno::Reference<text::XDocumentIndex> xIndex =
1121                         SwXDocumentIndex::CreateXDocumentIndex(
1122                             *pTOXBaseSect->GetFormat()->GetDoc(), pTOXBaseSect);
1123                     pRet[nProperty] <<= xIndex;
1124                 }
1125                 // else: no enclosing index found -> empty return value
1126             }
1127             break;
1128             case WID_SECT_IS_GLOBAL_DOC_SECTION:
1129             {
1130                 const bool bRet = pFormat && (nullptr != pFormat->GetGlobalDocSection());
1131                 pRet[nProperty] <<= bRet;
1132             }
1133             break;
1134             case  FN_UNO_ANCHOR_TYPES:
1135             case  FN_UNO_TEXT_WRAP:
1136             case  FN_UNO_ANCHOR_TYPE:
1137                 ::sw::GetDefaultTextContentValue(
1138                         pRet[nProperty], u"", pEntry->nWID);
1139             break;
1140             case FN_UNO_REDLINE_NODE_START:
1141             case FN_UNO_REDLINE_NODE_END:
1142             {
1143                 if (!pFormat)
1144                     break;      // #i73247#
1145                 SwNode* pSectNode = pFormat->GetSectionNode();
1146                 if (FN_UNO_REDLINE_NODE_END == pEntry->nWID)
1147                 {
1148                     pSectNode = pSectNode->EndOfSectionNode();
1149                 }
1150                 const SwRedlineTable& rRedTable =
1151                     pFormat->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
1152                 for (SwRangeRedline* pRedline : rRedTable)
1153                 {
1154                     const SwNode& rRedPointNode = pRedline->GetNode();
1155                     const SwNode& rRedMarkNode = pRedline->GetNode(false);
1156                     if ((&rRedPointNode == pSectNode) ||
1157                         (&rRedMarkNode == pSectNode))
1158                     {
1159                         const SwNode& rStartOfRedline =
1160                             (SwNodeIndex(rRedPointNode) <=
1161                              SwNodeIndex(rRedMarkNode))
1162                                  ? rRedPointNode : rRedMarkNode;
1163                         const bool bIsStart = (&rStartOfRedline == pSectNode);
1164                         pRet[nProperty] <<=
1165                             SwXRedlinePortion::CreateRedlineProperties(
1166                                     *pRedline, bIsStart);
1167                         break;
1168                     }
1169                 }
1170             }
1171             break;
1172             case WID_SECT_PASSWORD:
1173             {
1174                 pRet[nProperty] <<= m_bIsDescriptor
1175                     ? m_pProps->m_Password : pSect->GetPassword();
1176             }
1177             break;
1178             default:
1179             {
1180                 if (pFormat)
1181                 {
1182                     m_rPropSet.getPropertyValue(*pEntry,
1183                             pFormat->GetAttrSet(), pRet[nProperty]);
1184                 }
1185                 else
1186                 {
1187                     const SfxPoolItem* pQueryItem = nullptr;
1188                     if (RES_COL == pEntry->nWID)
1189                     {
1190                         if (!m_pProps->m_pColItem)
1191                         {
1192                             m_pProps->m_pColItem.reset(new SwFormatCol);
1193                         }
1194                         pQueryItem = m_pProps->m_pColItem.get();
1195                     }
1196                     else if (RES_BACKGROUND == pEntry->nWID)
1197                     {
1198                         if (!m_pProps->m_pBrushItem)
1199                         {
1200                             m_pProps->m_pBrushItem.reset(
1201                                 new SvxBrushItem(RES_BACKGROUND));
1202                         }
1203                         pQueryItem = m_pProps->m_pBrushItem.get();
1204                     }
1205                     else if (RES_FTN_AT_TXTEND == pEntry->nWID)
1206                     {
1207                         if (!m_pProps->m_pFootnoteItem)
1208                         {
1209                             m_pProps->m_pFootnoteItem.reset(new SwFormatFootnoteAtTextEnd);
1210                         }
1211                         pQueryItem = m_pProps->m_pFootnoteItem.get();
1212                     }
1213                     else if (RES_END_AT_TXTEND == pEntry->nWID)
1214                     {
1215                         if (!m_pProps->m_pEndItem)
1216                         {
1217                             m_pProps->m_pEndItem.reset(new SwFormatEndAtTextEnd);
1218                         }
1219                         pQueryItem = m_pProps->m_pEndItem.get();
1220                     }
1221                     else if (RES_UNKNOWNATR_CONTAINER== pEntry->nWID)
1222                     {
1223                         if (!m_pProps->m_pXMLAttr)
1224                         {
1225                             m_pProps->m_pXMLAttr.reset(
1226                                 new SvXMLAttrContainerItem);
1227                         }
1228                         pQueryItem = m_pProps->m_pXMLAttr.get();
1229                     }
1230                     else if (RES_COLUMNBALANCE== pEntry->nWID)
1231                     {
1232                         if (!m_pProps->m_pNoBalanceItem)
1233                         {
1234                             m_pProps->m_pNoBalanceItem.reset(
1235                                 new SwFormatNoBalancedColumns);
1236                         }
1237                         pQueryItem = m_pProps->m_pNoBalanceItem.get();
1238                     }
1239                     else if (RES_FRAMEDIR == pEntry->nWID)
1240                     {
1241                         if (!m_pProps->m_pFrameDirItem)
1242                         {
1243                             m_pProps->m_pFrameDirItem.reset(
1244                                 new SvxFrameDirectionItem(
1245                                     SvxFrameDirection::Environment, RES_FRAMEDIR));
1246                         }
1247                         pQueryItem = m_pProps->m_pFrameDirItem.get();
1248                     }
1249                     else if (RES_LR_SPACE == pEntry->nWID)
1250                     {
1251                         if (!m_pProps->m_pLRSpaceItem)
1252                         {
1253                             m_pProps->m_pLRSpaceItem.reset(
1254                                 new SvxLRSpaceItem( RES_LR_SPACE ));
1255                         }
1256                         pQueryItem = m_pProps->m_pLRSpaceItem.get();
1257                     }
1258                     if (pQueryItem)
1259                     {
1260                         pQueryItem->QueryValue(pRet[nProperty],
1261                                 pEntry->nMemberId);
1262                     }
1263                 }
1264             }
1265         }
1266     }
1267     return aRet;
1268 }
1269 
1270 uno::Sequence< uno::Any > SAL_CALL
getPropertyValues(const uno::Sequence<OUString> & rPropertyNames)1271 SwXTextSection::getPropertyValues(
1272     const uno::Sequence< OUString >& rPropertyNames)
1273 {
1274     SolarMutexGuard aGuard;
1275     uno::Sequence< uno::Any > aValues;
1276 
1277     // workaround for bad designed API
1278     try
1279     {
1280         aValues = m_pImpl->GetPropertyValues_Impl( rPropertyNames );
1281     }
1282     catch (beans::UnknownPropertyException &)
1283     {
1284         css::uno::Any anyEx = cppu::getCaughtException();
1285         throw lang::WrappedTargetRuntimeException("Unknown property exception caught",
1286                 static_cast < cppu::OWeakObject * > ( this ), anyEx );
1287     }
1288     catch (lang::WrappedTargetException &)
1289     {
1290         css::uno::Any anyEx = cppu::getCaughtException();
1291         throw lang::WrappedTargetRuntimeException("WrappedTargetException caught",
1292                 static_cast < cppu::OWeakObject * > ( this ), anyEx );
1293     }
1294 
1295     return aValues;
1296 }
1297 
1298 uno::Any SAL_CALL
getPropertyValue(const OUString & rPropertyName)1299 SwXTextSection::getPropertyValue(const OUString& rPropertyName)
1300 {
1301     SolarMutexGuard aGuard;
1302 
1303     uno::Sequence< OUString > aPropertyNames { rPropertyName };
1304     return m_pImpl->GetPropertyValues_Impl(aPropertyNames).getConstArray()[0];
1305 }
1306 
addPropertiesChangeListener(const uno::Sequence<OUString> &,const uno::Reference<beans::XPropertiesChangeListener> &)1307 void SAL_CALL SwXTextSection::addPropertiesChangeListener(
1308     const uno::Sequence< OUString >& /*aPropertyNames*/,
1309     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
1310 {
1311     OSL_FAIL("SwXTextSection::addPropertiesChangeListener(): not implemented");
1312 }
1313 
removePropertiesChangeListener(const uno::Reference<beans::XPropertiesChangeListener> &)1314 void SAL_CALL SwXTextSection::removePropertiesChangeListener(
1315     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
1316 {
1317     OSL_FAIL("SwXTextSection::removePropertiesChangeListener(): not implemented");
1318 }
1319 
firePropertiesChangeEvent(const uno::Sequence<OUString> &,const uno::Reference<beans::XPropertiesChangeListener> &)1320 void SAL_CALL SwXTextSection::firePropertiesChangeEvent(
1321     const uno::Sequence< OUString >& /*aPropertyNames*/,
1322     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
1323 {
1324     OSL_FAIL("SwXTextSection::firePropertiesChangeEvent(): not implemented");
1325 }
1326 
1327 void SAL_CALL
addPropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)1328 SwXTextSection::addPropertyChangeListener(
1329         const OUString& /*rPropertyName*/,
1330         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1331 {
1332     OSL_FAIL("SwXTextSection::addPropertyChangeListener(): not implemented");
1333 }
1334 
1335 void SAL_CALL
removePropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)1336 SwXTextSection::removePropertyChangeListener(
1337         const OUString& /*rPropertyName*/,
1338         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1339 {
1340     OSL_FAIL("SwXTextSection::removePropertyChangeListener(): not implemented");
1341 }
1342 
1343 void SAL_CALL
addVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)1344 SwXTextSection::addVetoableChangeListener(
1345         const OUString& /*rPropertyName*/,
1346         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1347 {
1348     OSL_FAIL("SwXTextSection::addVetoableChangeListener(): not implemented");
1349 }
1350 
1351 void SAL_CALL
removeVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)1352 SwXTextSection::removeVetoableChangeListener(
1353         const OUString& /*rPropertyName*/,
1354         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1355 {
1356     OSL_FAIL("SwXTextSection::removeVetoableChangeListener(): not implemented");
1357 }
1358 
1359 beans::PropertyState SAL_CALL
getPropertyState(const OUString & rPropertyName)1360 SwXTextSection::getPropertyState(const OUString& rPropertyName)
1361 {
1362     SolarMutexGuard aGuard;
1363 
1364     uno::Sequence< OUString > aNames { rPropertyName };
1365     return getPropertyStates(aNames).getConstArray()[0];
1366 }
1367 
1368 uno::Sequence< beans::PropertyState > SAL_CALL
getPropertyStates(const uno::Sequence<OUString> & rPropertyNames)1369 SwXTextSection::getPropertyStates(
1370         const uno::Sequence< OUString >& rPropertyNames)
1371 {
1372     SolarMutexGuard aGuard;
1373 
1374     SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1375     if (!pFormat && !m_pImpl->m_bIsDescriptor)
1376     {
1377         throw uno::RuntimeException();
1378     }
1379 
1380     uno::Sequence< beans::PropertyState > aStates(rPropertyNames.getLength());
1381     beans::PropertyState *const pStates = aStates.getArray();
1382     const OUString* pNames = rPropertyNames.getConstArray();
1383     for (sal_Int32 i = 0; i < rPropertyNames.getLength(); i++)
1384     {
1385         pStates[i] = beans::PropertyState_DEFAULT_VALUE;
1386         SfxItemPropertyMapEntry const*const pEntry =
1387             m_pImpl->m_rPropSet.getPropertyMap().getByName( pNames[i]);
1388         if (!pEntry)
1389         {
1390             throw beans::UnknownPropertyException(
1391                 "Unknown property: " + pNames[i],
1392                 static_cast< cppu::OWeakObject* >(this));
1393         }
1394         switch (pEntry->nWID)
1395         {
1396             case WID_SECT_CONDITION:
1397             case WID_SECT_DDE_TYPE:
1398             case WID_SECT_DDE_FILE:
1399             case WID_SECT_DDE_ELEMENT:
1400             case WID_SECT_DDE_AUTOUPDATE:
1401             case WID_SECT_LINK:
1402             case WID_SECT_REGION :
1403             case WID_SECT_VISIBLE:
1404             case WID_SECT_PROTECTED:
1405             case WID_SECT_EDIT_IN_READONLY:
1406             case  FN_PARAM_LINK_DISPLAY_NAME:
1407             case  FN_UNO_ANCHOR_TYPES:
1408             case  FN_UNO_TEXT_WRAP:
1409             case  FN_UNO_ANCHOR_TYPE:
1410                 pStates[i] = beans::PropertyState_DIRECT_VALUE;
1411             break;
1412             default:
1413             {
1414                 if (pFormat)
1415                 {
1416                     pStates[i] = m_pImpl->m_rPropSet.getPropertyState(
1417                                     pNames[i], pFormat->GetAttrSet());
1418                 }
1419                 else
1420                 {
1421                     if (RES_COL == pEntry->nWID)
1422                     {
1423                         if (!m_pImpl->m_pProps->m_pColItem)
1424                         {
1425                             pStates[i] = beans::PropertyState_DEFAULT_VALUE;
1426                         }
1427                         else
1428                         {
1429                             pStates[i] = beans::PropertyState_DIRECT_VALUE;
1430                         }
1431                     }
1432                     else
1433                     {
1434                         if (!m_pImpl->m_pProps->m_pBrushItem)
1435                         {
1436                             pStates[i] = beans::PropertyState_DEFAULT_VALUE;
1437                         }
1438                         else
1439                         {
1440                             pStates[i] = beans::PropertyState_DIRECT_VALUE;
1441                         }
1442                     }
1443                 }
1444             }
1445         }
1446     }
1447     return aStates;
1448 }
1449 
1450 void SAL_CALL
setPropertyToDefault(const OUString & rPropertyName)1451 SwXTextSection::setPropertyToDefault(const OUString& rPropertyName)
1452 {
1453     SolarMutexGuard aGuard;
1454 
1455     SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1456     if (!pFormat && !m_pImpl->m_bIsDescriptor)
1457     {
1458         throw uno::RuntimeException();
1459     }
1460 
1461     SfxItemPropertyMapEntry const*const pEntry =
1462         m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
1463     if (!pEntry)
1464     {
1465         throw beans::UnknownPropertyException(
1466             "Unknown property: " + rPropertyName,
1467             static_cast< cppu::OWeakObject* >(this));
1468     }
1469     if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
1470     {
1471         throw uno::RuntimeException(
1472             "Property is read-only: " + rPropertyName,
1473             static_cast<cppu::OWeakObject *>(this));
1474     }
1475 
1476     std::unique_ptr<SwSectionData> const pSectionData(
1477         pFormat ? new SwSectionData(*pFormat->GetSection()) : nullptr);
1478 
1479     std::unique_ptr<SfxItemSet> pNewAttrSet;
1480     bool bLinkModeChanged = false;
1481 
1482     switch (pEntry->nWID)
1483     {
1484         case WID_SECT_CONDITION:
1485         {
1486             if (m_pImpl->m_bIsDescriptor)
1487             {
1488                 m_pImpl->m_pProps->m_sCondition.clear();
1489             }
1490             else
1491             {
1492                 pSectionData->SetCondition(OUString());
1493             }
1494         }
1495         break;
1496         case WID_SECT_DDE_TYPE      :
1497         case WID_SECT_DDE_FILE      :
1498         case WID_SECT_DDE_ELEMENT   :
1499         case WID_SECT_LINK     :
1500         case WID_SECT_REGION :
1501             if (m_pImpl->m_bIsDescriptor)
1502             {
1503                 m_pImpl->m_pProps->m_bDDE = false;
1504                 m_pImpl->m_pProps->m_sLinkFileName.clear();
1505                 m_pImpl->m_pProps->m_sSectionRegion.clear();
1506                 m_pImpl->m_pProps->m_sSectionFilter.clear();
1507             }
1508             else
1509             {
1510                 pSectionData->SetType(SectionType::Content);
1511             }
1512         break;
1513         case WID_SECT_DDE_AUTOUPDATE:
1514             if (m_pImpl->m_bIsDescriptor)
1515             {
1516                 m_pImpl->m_pProps->m_bUpdateType = true;
1517             }
1518             else
1519             {
1520                 bLinkModeChanged = true;
1521             }
1522         break;
1523         case WID_SECT_VISIBLE   :
1524         {
1525             if (m_pImpl->m_bIsDescriptor)
1526             {
1527                 m_pImpl->m_pProps->m_bHidden = false;
1528             }
1529             else
1530             {
1531                 pSectionData->SetHidden(false);
1532             }
1533         }
1534         break;
1535         case WID_SECT_PROTECTED:
1536         {
1537             if (m_pImpl->m_bIsDescriptor)
1538             {
1539                 m_pImpl->m_pProps->m_bProtect = false;
1540             }
1541             else
1542             {
1543                 pSectionData->SetProtectFlag(false);
1544             }
1545         }
1546         break;
1547         case WID_SECT_EDIT_IN_READONLY:
1548         {
1549             if (m_pImpl->m_bIsDescriptor)
1550             {
1551                 m_pImpl->m_pProps->m_bEditInReadonly = false;
1552             }
1553             else
1554             {
1555                 pSectionData->SetEditInReadonlyFlag(false);
1556             }
1557         }
1558         break;
1559 
1560         case  FN_UNO_ANCHOR_TYPES:
1561         case  FN_UNO_TEXT_WRAP:
1562         case  FN_UNO_ANCHOR_TYPE:
1563         break;
1564         default:
1565         {
1566             if (SfxItemPool::IsWhich(pEntry->nWID))
1567             {
1568                 if (pFormat)
1569                 {
1570                     const SfxItemSet& rOldAttrSet = pFormat->GetAttrSet();
1571                     pNewAttrSet.reset( new SfxItemSet(*rOldAttrSet.GetPool(), {{pEntry->nWID, pEntry->nWID}}));
1572                     pNewAttrSet->ClearItem(pEntry->nWID);
1573                 }
1574                 else
1575                 {
1576                     if (RES_COL == pEntry->nWID)
1577                     {
1578                         m_pImpl->m_pProps->m_pColItem.reset();
1579                     }
1580                     else if (RES_BACKGROUND == pEntry->nWID)
1581                     {
1582                         m_pImpl->m_pProps->m_pBrushItem.reset();
1583                     }
1584                 }
1585             }
1586         }
1587     }
1588 
1589     lcl_UpdateSection(pFormat, pSectionData, pNewAttrSet, bLinkModeChanged);
1590 }
1591 
1592 uno::Any SAL_CALL
getPropertyDefault(const OUString & rPropertyName)1593 SwXTextSection::getPropertyDefault(const OUString& rPropertyName)
1594 {
1595     SolarMutexGuard aGuard;
1596 
1597     uno::Any aRet;
1598     SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1599     SfxItemPropertyMapEntry const*const pEntry =
1600         m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
1601     if (!pEntry)
1602     {
1603         throw beans::UnknownPropertyException(
1604             "Unknown property: " + rPropertyName,
1605             static_cast<cppu::OWeakObject *>(this));
1606     }
1607 
1608     switch(pEntry->nWID)
1609     {
1610         case WID_SECT_CONDITION:
1611         case WID_SECT_DDE_TYPE      :
1612         case WID_SECT_DDE_FILE      :
1613         case WID_SECT_DDE_ELEMENT   :
1614         case WID_SECT_REGION :
1615         case FN_PARAM_LINK_DISPLAY_NAME:
1616             aRet <<= OUString();
1617         break;
1618         case WID_SECT_LINK     :
1619             aRet <<= text::SectionFileLink();
1620         break;
1621         case WID_SECT_DDE_AUTOUPDATE:
1622         case WID_SECT_VISIBLE   :
1623             aRet <<= true;
1624         break;
1625         case WID_SECT_PROTECTED:
1626         case WID_SECT_EDIT_IN_READONLY:
1627             aRet <<= false;
1628         break;
1629         case  FN_UNO_ANCHOR_TYPES:
1630         case  FN_UNO_TEXT_WRAP:
1631         case  FN_UNO_ANCHOR_TYPE:
1632             ::sw::GetDefaultTextContentValue(aRet, u"", pEntry->nWID);
1633         break;
1634         default:
1635         if(pFormat && SfxItemPool::IsWhich(pEntry->nWID))
1636         {
1637             SwDoc *const pDoc = pFormat->GetDoc();
1638             const SfxPoolItem& rDefItem =
1639                 pDoc->GetAttrPool().GetDefaultItem(pEntry->nWID);
1640             rDefItem.QueryValue(aRet, pEntry->nMemberId);
1641         }
1642     }
1643     return aRet;
1644 }
1645 
getName()1646 OUString SAL_CALL SwXTextSection::getName()
1647 {
1648     SolarMutexGuard aGuard;
1649 
1650     OUString sRet;
1651     SwSectionFormat const*const pFormat = m_pImpl->GetSectionFormat();
1652     if(pFormat)
1653     {
1654         sRet = pFormat->GetSection()->GetSectionName();
1655     }
1656     else if (m_pImpl->m_bIsDescriptor)
1657     {
1658         sRet = m_pImpl->m_sName;
1659     }
1660     else
1661     {
1662         throw uno::RuntimeException();
1663     }
1664     return sRet;
1665 }
1666 
setName(const OUString & rName)1667 void SAL_CALL SwXTextSection::setName(const OUString& rName)
1668 {
1669     SolarMutexGuard aGuard;
1670 
1671     SwSectionFormat *const pFormat = m_pImpl->GetSectionFormat();
1672     if(pFormat)
1673     {
1674         SwSection *const pSect = pFormat->GetSection();
1675         SwSectionData aSection(*pSect);
1676         aSection.SetSectionName(rName);
1677 
1678         const SwSectionFormats& rFormats = pFormat->GetDoc()->GetSections();
1679         size_t nApplyPos = SIZE_MAX;
1680         for( size_t i = 0; i < rFormats.size(); ++i )
1681         {
1682             if(rFormats[i]->GetSection() == pSect)
1683             {
1684                 nApplyPos = i;
1685             }
1686             else if (rName == rFormats[i]->GetSection()->GetSectionName())
1687             {
1688                 throw uno::RuntimeException();
1689             }
1690         }
1691         if (nApplyPos != SIZE_MAX)
1692         {
1693             {
1694                 UnoActionContext aContext(pFormat->GetDoc());
1695                 pFormat->GetDoc()->UpdateSection(nApplyPos, aSection);
1696             }
1697             {
1698                 // temporarily remove actions to allow cursor update
1699                 // TODO: why? no table cursor here!
1700                 UnoActionRemoveContext aRemoveContext( pFormat->GetDoc() );
1701             }
1702         }
1703     }
1704     else if (m_pImpl->m_bIsDescriptor)
1705     {
1706         m_pImpl->m_sName = rName;
1707     }
1708     else
1709     {
1710         throw uno::RuntimeException();
1711     }
1712 }
1713 
1714 OUString SAL_CALL
getImplementationName()1715 SwXTextSection::getImplementationName()
1716 {
1717     return "SwXTextSection";
1718 }
1719 
supportsService(const OUString & rServiceName)1720 sal_Bool SAL_CALL SwXTextSection::supportsService(const OUString& rServiceName)
1721 {
1722     return cppu::supportsService(this, rServiceName);
1723 }
1724 
1725 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()1726 SwXTextSection::getSupportedServiceNames()
1727 {
1728     return {
1729         "com.sun.star.text.TextContent",
1730         "com.sun.star.text.TextSection",
1731         "com.sun.star.document.LinkTarget"
1732     };
1733 }
1734 
1735 // MetadatableMixin
GetCoreObject()1736 ::sfx2::Metadatable* SwXTextSection::GetCoreObject()
1737 {
1738     SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1739     return pSectionFormat;
1740 }
1741 
GetModel()1742 uno::Reference<frame::XModel> SwXTextSection::GetModel()
1743 {
1744     SwSectionFormat *const pSectionFormat( m_pImpl->GetSectionFormat() );
1745     if (pSectionFormat)
1746     {
1747         SwDocShell const*const pShell( pSectionFormat->GetDoc()->GetDocShell() );
1748         return pShell ? pShell->GetModel() : nullptr;
1749     }
1750     return nullptr;
1751 }
1752 
1753 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1754