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