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