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