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 <unoparagraph.hxx>
21 
22 #include <comphelper/interfacecontainer2.hxx>
23 #include <cppuhelper/exc_hlp.hxx>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <osl/diagnose.h>
26 #include <tools/diagnose_ex.h>
27 
28 #include <cmdid.h>
29 #include <unomid.h>
30 #include <unoparaframeenum.hxx>
31 #include <unotext.hxx>
32 #include <unotextrange.hxx>
33 #include <unoport.hxx>
34 #include <unomap.hxx>
35 #include <unocrsr.hxx>
36 #include <unoprnms.hxx>
37 #include <unocrsrhelper.hxx>
38 #include <doc.hxx>
39 #include <ndtxt.hxx>
40 #include <osl/mutex.hxx>
41 #include <vcl/svapp.hxx>
42 #include <docsh.hxx>
43 #include <swunohelper.hxx>
44 
45 #include <com/sun/star/beans/SetPropertyTolerantFailed.hpp>
46 #include <com/sun/star/beans/GetPropertyTolerantResult.hpp>
47 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
48 #include <com/sun/star/beans/PropertyAttribute.hpp>
49 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
50 #include <com/sun/star/text/WrapTextMode.hpp>
51 #include <com/sun/star/text/TextContentAnchorType.hpp>
52 
53 #include <com/sun/star/drawing/BitmapMode.hpp>
54 #include <comphelper/servicehelper.hxx>
55 #include <editeng/unoipset.hxx>
56 #include <svl/listener.hxx>
57 #include <svx/unobrushitemhelper.hxx>
58 #include <svx/xflbmtit.hxx>
59 #include <svx/xflbstit.hxx>
60 
61 using namespace ::com::sun::star;
62 
63 namespace {
64 
65 class SwParaSelection
66 {
67     SwCursor & m_rCursor;
68 public:
69     explicit SwParaSelection(SwCursor & rCursor);
70     ~SwParaSelection();
71 };
72 
73 }
74 
SwParaSelection(SwCursor & rCursor)75 SwParaSelection::SwParaSelection(SwCursor & rCursor)
76     : m_rCursor(rCursor)
77 {
78     if (m_rCursor.HasMark())
79     {
80         m_rCursor.DeleteMark();
81     }
82     // is it at the start?
83     if (m_rCursor.GetPoint()->nContent != 0)
84     {
85         m_rCursor.MovePara(GoCurrPara, fnParaStart);
86     }
87     // or at the end already?
88     if (m_rCursor.GetPoint()->nContent != m_rCursor.GetContentNode()->Len())
89     {
90         m_rCursor.SetMark();
91         m_rCursor.MovePara(GoCurrPara, fnParaEnd);
92     }
93 }
94 
~SwParaSelection()95 SwParaSelection::~SwParaSelection()
96 {
97     if (m_rCursor.GetPoint()->nContent != 0)
98     {
99         m_rCursor.DeleteMark();
100         m_rCursor.MovePara(GoCurrPara, fnParaStart);
101     }
102 }
103 
104 /// @throws beans::UnknownPropertyException
105 /// @throws uno::RuntimeException
106 static beans::PropertyState lcl_SwXParagraph_getPropertyState(
107                             const SwTextNode& rTextNode,
108                             const SwAttrSet** ppSet,
109                             const SfxItemPropertyMapEntry& rEntry,
110                             bool &rAttrSetFetched );
111 
112 class SwXParagraph::Impl
113     : public SvtListener
114 {
115 private:
116     ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
117 
118 public:
119     SwXParagraph& m_rThis;
120     uno::WeakReference<uno::XInterface> m_wThis;
121     ::comphelper::OInterfaceContainerHelper2 m_EventListeners;
122     SfxItemPropertySet const& m_rPropSet;
123     bool m_bIsDescriptor;
124     sal_Int32 m_nSelectionStartPos;
125     sal_Int32 m_nSelectionEndPos;
126     OUString m_sText;
127     uno::Reference<text::XText> m_xParentText;
128     SwTextNode* m_pTextNode;
129 
Impl(SwXParagraph & rThis,SwTextNode * const pTextNode=nullptr,uno::Reference<text::XText> const & xParent=nullptr,const sal_Int32 nSelStart=-1,const sal_Int32 nSelEnd=-1)130     Impl(SwXParagraph& rThis,
131             SwTextNode* const pTextNode = nullptr, uno::Reference<text::XText> const& xParent = nullptr,
132             const sal_Int32 nSelStart = -1, const sal_Int32 nSelEnd = -1)
133         : m_rThis(rThis)
134         , m_EventListeners(m_Mutex)
135         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH))
136         , m_bIsDescriptor(nullptr == pTextNode)
137         , m_nSelectionStartPos(nSelStart)
138         , m_nSelectionEndPos(nSelEnd)
139         , m_xParentText(xParent)
140         , m_pTextNode(pTextNode)
141     {
142         m_pTextNode && StartListening(m_pTextNode->GetNotifier());
143     }
144 
GetTextNode()145     SwTextNode* GetTextNode() {
146         return m_pTextNode;
147     }
148 
GetTextNodeOrThrow()149     SwTextNode& GetTextNodeOrThrow() {
150         if (!m_pTextNode) {
151             throw uno::RuntimeException("SwXParagraph: disposed or invalid", nullptr);
152         }
153         return *m_pTextNode;
154     }
155 
IsDescriptor() const156     bool IsDescriptor() const { return m_bIsDescriptor; }
157 
158     /// @throws beans::UnknownPropertyException
159     /// @throws beans::PropertyVetoException
160     /// @throws lang::IllegalArgumentException
161     /// @throws lang::WrappedTargetException
162     /// @throws uno::RuntimeException
163     void SetPropertyValues_Impl(
164             const uno::Sequence< OUString >& rPropertyNames,
165             const uno::Sequence< uno::Any >& rValues);
166 
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 
174     /// @throws uno::RuntimeException
175     void GetSinglePropertyValue_Impl(
176         const SfxItemPropertyMapEntry& rEntry,
177         const SfxItemSet& rSet,
178         uno::Any& rAny ) const;
179 
180     /// @throws uno::RuntimeException
181     uno::Sequence< beans::GetDirectPropertyTolerantResult >
182         GetPropertyValuesTolerant_Impl(
183             const uno::Sequence< OUString >& rPropertyNames,
184             bool bDirectValuesOnly);
185 protected:
186     virtual void Notify(const SfxHint& rHint) override;
187 
188 };
189 
Notify(const SfxHint & rHint)190 void SwXParagraph::Impl::Notify(const SfxHint& rHint)
191 {
192     if(rHint.GetId() == SfxHintId::Dying)
193     {
194         m_pTextNode = nullptr;
195         uno::Reference<uno::XInterface> const xThis(m_wThis);
196         if (!xThis.is())
197         {   // fdo#72695: if UNO object is already dead, don't revive it with event
198             return;
199         }
200         lang::EventObject const ev(xThis);
201         m_EventListeners.disposeAndClear(ev);
202     }
203 }
204 
SwXParagraph()205 SwXParagraph::SwXParagraph()
206     : m_pImpl( new SwXParagraph::Impl(*this) )
207 {
208 }
209 
SwXParagraph(uno::Reference<text::XText> const & xParent,SwTextNode & rTextNode,const sal_Int32 nSelStart,const sal_Int32 nSelEnd)210 SwXParagraph::SwXParagraph(
211         uno::Reference< text::XText > const & xParent,
212         SwTextNode & rTextNode,
213         const sal_Int32 nSelStart, const sal_Int32 nSelEnd)
214     : m_pImpl(
215         new SwXParagraph::Impl(*this, &rTextNode, xParent, nSelStart, nSelEnd))
216 {
217 }
218 
~SwXParagraph()219 SwXParagraph::~SwXParagraph()
220 {
221 }
222 
GetTextNode() const223 const SwTextNode * SwXParagraph::GetTextNode() const
224 {
225     return m_pImpl->GetTextNode();
226 }
227 
IsDescriptor() const228 bool SwXParagraph::IsDescriptor() const
229 {
230     return m_pImpl->IsDescriptor();
231 }
232 
233 uno::Reference<text::XTextContent>
CreateXParagraph(SwDoc & rDoc,SwTextNode * const pTextNode,uno::Reference<text::XText> const & i_xParent,const sal_Int32 nSelStart,const sal_Int32 nSelEnd)234 SwXParagraph::CreateXParagraph(SwDoc & rDoc, SwTextNode *const pTextNode,
235         uno::Reference< text::XText> const& i_xParent,
236         const sal_Int32 nSelStart, const sal_Int32 nSelEnd)
237 {
238     // re-use existing SwXParagraph
239     // #i105557#: do not iterate over the registered clients: race condition
240     uno::Reference<text::XTextContent> xParagraph;
241     if (pTextNode && (-1 == nSelStart) && (-1 == nSelEnd))
242     {   // only use cache if no selection!
243         xParagraph.set(pTextNode->GetXParagraph());
244     }
245     if (xParagraph.is())
246     {
247         return xParagraph;
248     }
249 
250     // create new SwXParagraph
251     uno::Reference<text::XText> xParentText(i_xParent);
252     if (!xParentText.is() && pTextNode)
253     {
254         SwPosition Pos(*pTextNode);
255         xParentText.set(::sw::CreateParentXText( rDoc, Pos ));
256     }
257     SwXParagraph *const pXPara( pTextNode
258             ? new SwXParagraph(xParentText, *pTextNode, nSelStart, nSelEnd)
259             : new SwXParagraph);
260     // this is why the constructor is private: need to acquire pXPara here
261     xParagraph.set(pXPara);
262     // in order to initialize the weak pointer cache in the core object
263     if (pTextNode && (-1 == nSelStart) && (-1 == nSelEnd))
264     {
265         pTextNode->SetXParagraph(xParagraph);
266     }
267     // need a permanent Reference to initialize m_wThis
268     pXPara->m_pImpl->m_wThis = xParagraph;
269     return xParagraph;
270 }
271 
SelectPaM(SwPaM & rPaM)272 bool SwXParagraph::SelectPaM(SwPaM & rPaM)
273 {
274     SwTextNode const*const pTextNode( GetTextNode() );
275 
276     if (!pTextNode)
277     {
278         return false;
279     }
280 
281     *rPaM.GetPoint() = SwPosition( *pTextNode );
282     // set selection to the whole paragraph
283     rPaM.SetMark();
284     rPaM.GetMark()->nContent = pTextNode->GetText().getLength();
285     return true;
286 }
287 
getUnoTunnelId()288 const uno::Sequence< sal_Int8 > & SwXParagraph::getUnoTunnelId()
289 {
290     static const UnoTunnelIdInit theSwXParagraphUnoTunnelId;
291     return theSwXParagraphUnoTunnelId.getSeq();
292 }
293 
294 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)295 SwXParagraph::getSomething(const uno::Sequence< sal_Int8 >& rId)
296 {
297     return ::sw::UnoTunnelImpl<SwXParagraph>(rId, this);
298 }
299 
300 OUString SAL_CALL
getImplementationName()301 SwXParagraph::getImplementationName()
302 {
303     return "SwXParagraph";
304 }
305 
306 sal_Bool SAL_CALL
supportsService(const OUString & rServiceName)307 SwXParagraph::supportsService(const OUString& rServiceName)
308 {
309     return cppu::supportsService(this, rServiceName);
310 }
311 
312 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()313 SwXParagraph::getSupportedServiceNames()
314 {
315     return {
316         "com.sun.star.text.TextContent",
317         "com.sun.star.text.Paragraph",
318         "com.sun.star.style.CharacterProperties",
319         "com.sun.star.style.CharacterPropertiesAsian",
320         "com.sun.star.style.CharacterPropertiesComplex",
321         "com.sun.star.style.ParagraphProperties",
322         "com.sun.star.style.ParagraphPropertiesAsian",
323         "com.sun.star.style.ParagraphPropertiesComplex"
324     };
325 }
326 
327 void
attachToText(SwXText & rParent,SwTextNode & rTextNode)328 SwXParagraph::attachToText(SwXText & rParent, SwTextNode & rTextNode)
329 {
330     OSL_ENSURE(m_pImpl->m_bIsDescriptor, "Paragraph is not a descriptor");
331     if (!m_pImpl->m_bIsDescriptor)
332         return;
333 
334     m_pImpl->m_bIsDescriptor = false;
335     m_pImpl->EndListeningAll();
336     m_pImpl->StartListening(rTextNode.GetNotifier());
337     rTextNode.SetXParagraph(uno::Reference<text::XTextContent>(this));
338     m_pImpl->m_xParentText = &rParent;
339     if (!m_pImpl->m_sText.isEmpty())
340     {
341         try { setString(m_pImpl->m_sText); }
342         catch(...){}
343         m_pImpl->m_sText.clear();
344     }
345 }
346 
347 uno::Reference< beans::XPropertySetInfo > SAL_CALL
getPropertySetInfo()348 SwXParagraph::getPropertySetInfo()
349 {
350     SolarMutexGuard g;
351 
352     static uno::Reference< beans::XPropertySetInfo > xRef =
353         m_pImpl->m_rPropSet.getPropertySetInfo();
354     return xRef;
355 }
356 
357 void SAL_CALL
setPropertyValue(const OUString & rPropertyName,const uno::Any & rValue)358 SwXParagraph::setPropertyValue(const OUString& rPropertyName,
359         const uno::Any& rValue)
360 {
361     SolarMutexGuard aGuard;
362     uno::Sequence<OUString> aPropertyNames { rPropertyName };
363     uno::Sequence<uno::Any> aValues(1);
364     aValues.getArray()[0] = rValue;
365     m_pImpl->SetPropertyValues_Impl( aPropertyNames, aValues );
366 }
367 
368 uno::Any
getPropertyValue(const OUString & rPropertyName)369 SwXParagraph::getPropertyValue(const OUString& rPropertyName)
370 {
371     SolarMutexGuard aGuard;
372     uno::Sequence<OUString> aPropertyNames { rPropertyName };
373     const uno::Sequence< uno::Any > aRet =
374         m_pImpl->GetPropertyValues_Impl(aPropertyNames);
375     return aRet.getConstArray()[0];
376 }
377 
SetPropertyValues_Impl(const uno::Sequence<OUString> & rPropertyNames,const uno::Sequence<uno::Any> & rValues)378 void SwXParagraph::Impl::SetPropertyValues_Impl(
379     const uno::Sequence< OUString >& rPropertyNames,
380     const uno::Sequence< uno::Any >& rValues )
381 {
382     SwTextNode & rTextNode(GetTextNodeOrThrow());
383 
384     SwPosition aPos( rTextNode );
385     SwCursor aCursor( aPos, nullptr );
386     const OUString* pPropertyNames = rPropertyNames.getConstArray();
387     const uno::Any* pValues = rValues.getConstArray();
388     const SfxItemPropertyMap &rMap = m_rPropSet.getPropertyMap();
389     SwParaSelection aParaSel( aCursor );
390 
391     uno::Sequence< beans::PropertyValue > aValues( rPropertyNames.getLength() );
392     for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
393     {
394         SfxItemPropertyMapEntry const*const pEntry =
395             rMap.getByName( pPropertyNames[nProp] );
396         if (!pEntry)
397         {
398             throw beans::UnknownPropertyException(
399                 "Unknown property: " + pPropertyNames[nProp],
400                 static_cast< cppu::OWeakObject * >(&m_rThis));
401         }
402         if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
403         {
404             throw beans::PropertyVetoException(
405                 "Property is read-only: " + pPropertyNames[nProp],
406                 static_cast< cppu::OWeakObject * >(&m_rThis));
407         }
408         aValues[nProp].Name = pPropertyNames[nProp];
409         aValues[nProp].Value = pValues[nProp];
410     }
411     SwUnoCursorHelper::SetPropertyValues(aCursor, m_rPropSet, aValues);
412 }
413 
setPropertyValues(const uno::Sequence<OUString> & rPropertyNames,const uno::Sequence<uno::Any> & rValues)414 void SAL_CALL SwXParagraph::setPropertyValues(
415     const uno::Sequence< OUString >& rPropertyNames,
416     const uno::Sequence< uno::Any >& rValues )
417 {
418     SolarMutexGuard aGuard;
419 
420     // workaround for bad designed API
421     try
422     {
423         m_pImpl->SetPropertyValues_Impl( rPropertyNames, rValues );
424     }
425     catch (const beans::UnknownPropertyException &rException)
426     {
427         // wrap the original (here not allowed) exception in
428         // a lang::WrappedTargetException that gets thrown instead.
429         lang::WrappedTargetException aWExc;
430         aWExc.TargetException <<= rException;
431         throw aWExc;
432     }
433 }
434 
435 // Support for DrawingLayer FillStyles for GetPropertyValue() usages
GetSinglePropertyValue_Impl(const SfxItemPropertyMapEntry & rEntry,const SfxItemSet & rSet,uno::Any & rAny) const436 void SwXParagraph::Impl::GetSinglePropertyValue_Impl(
437     const SfxItemPropertyMapEntry& rEntry,
438     const SfxItemSet& rSet,
439     uno::Any& rAny ) const
440 {
441     bool bDone(false);
442 
443     switch(rEntry.nWID)
444     {
445         case RES_BACKGROUND:
446         {
447             const std::unique_ptr<SvxBrushItem> aOriginalBrushItem(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND));
448 
449             if(!aOriginalBrushItem->QueryValue(rAny, rEntry.nMemberId))
450             {
451                 OSL_ENSURE(false, "Error getting attribute from RES_BACKGROUND (!)");
452             }
453 
454             bDone = true;
455             break;
456         }
457         case OWN_ATTR_FILLBMP_MODE:
458         {
459             if (rSet.Get(XATTR_FILLBMP_TILE).GetValue())
460             {
461                 rAny <<= drawing::BitmapMode_REPEAT;
462             }
463             else if (rSet.Get(XATTR_FILLBMP_STRETCH).GetValue())
464             {
465                 rAny <<= drawing::BitmapMode_STRETCH;
466             }
467             else
468             {
469                 rAny <<= drawing::BitmapMode_NO_REPEAT;
470             }
471 
472             bDone = true;
473             break;
474         }
475         default: break;
476     }
477 
478     if(bDone)
479         return;
480 
481     // fallback to standard get value implementation used before this helper was created
482     m_rPropSet.getPropertyValue(rEntry, rSet, rAny);
483 
484     if(rEntry.aType == cppu::UnoType<sal_Int16>::get() && rEntry.aType != rAny.getValueType())
485     {
486         // since the sfx uInt16 item now exports a sal_Int32, we may have to fix this here
487         sal_Int32 nValue(0);
488 
489         if (rAny >>= nValue)
490         {
491             rAny <<= static_cast<sal_Int16>(nValue);
492         }
493     }
494 
495     // check for needed metric translation
496     if(!(rEntry.nMoreFlags & PropertyMoreFlags::METRIC_ITEM))
497         return;
498 
499     bool bDoIt(true);
500 
501     if(XATTR_FILLBMP_SIZEX == rEntry.nWID || XATTR_FILLBMP_SIZEY == rEntry.nWID)
502     {
503         // exception: If these ItemTypes are used, do not convert when these are negative
504         // since this means they are intended as percent values
505         sal_Int32 nValue = 0;
506 
507         if(rAny >>= nValue)
508         {
509             bDoIt = nValue > 0;
510         }
511     }
512 
513     if(bDoIt)
514     {
515         const MapUnit eMapUnit(rSet.GetPool()->GetMetric(rEntry.nWID));
516 
517         if(eMapUnit != MapUnit::Map100thMM)
518         {
519             SvxUnoConvertToMM(eMapUnit, rAny);
520         }
521     }
522 }
523 
GetPropertyValues_Impl(const uno::Sequence<OUString> & rPropertyNames)524 uno::Sequence< uno::Any > SwXParagraph::Impl::GetPropertyValues_Impl(
525         const uno::Sequence< OUString > & rPropertyNames )
526 {
527     SwTextNode & rTextNode(GetTextNodeOrThrow());
528 
529     uno::Sequence< uno::Any > aValues(rPropertyNames.getLength());
530     SwPosition aPos( rTextNode );
531     SwPaM aPam( aPos );
532     uno::Any* pValues = aValues.getArray();
533     const OUString* pPropertyNames = rPropertyNames.getConstArray();
534     const SfxItemPropertyMap &rMap = m_rPropSet.getPropertyMap();
535     const SwAttrSet& rAttrSet( rTextNode.GetSwAttrSet() );
536     for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
537     {
538         SfxItemPropertyMapEntry const*const pEntry =
539             rMap.getByName( pPropertyNames[nProp] );
540         if (!pEntry)
541         {
542             throw beans::UnknownPropertyException(
543                 "Unknown property: " + pPropertyNames[nProp],
544                 static_cast< cppu::OWeakObject * >(&m_rThis));
545         }
546         if (! ::sw::GetDefaultTextContentValue(
547                 pValues[nProp], pPropertyNames[nProp], pEntry->nWID))
548         {
549             beans::PropertyState eTemp;
550             const bool bDone = SwUnoCursorHelper::getCursorPropertyValue(
551                 *pEntry, aPam, &(pValues[nProp]), eTemp, &rTextNode );
552             if (!bDone)
553             {
554                 GetSinglePropertyValue_Impl(*pEntry, rAttrSet, pValues[nProp]);
555             }
556         }
557     }
558     return aValues;
559 }
560 
561 uno::Sequence< uno::Any > SAL_CALL
getPropertyValues(const uno::Sequence<OUString> & rPropertyNames)562 SwXParagraph::getPropertyValues(const uno::Sequence< OUString >& rPropertyNames)
563 {
564     SolarMutexGuard aGuard;
565     uno::Sequence< uno::Any > aValues;
566 
567     // workaround for bad designed API
568     try
569     {
570         aValues = m_pImpl->GetPropertyValues_Impl( rPropertyNames );
571     }
572     catch (beans::UnknownPropertyException &)
573     {
574         css::uno::Any anyEx = cppu::getCaughtException();
575         throw css::lang::WrappedTargetRuntimeException("Unknown property exception caught",
576                 static_cast < cppu::OWeakObject * > ( this ), anyEx );
577     }
578     catch (lang::WrappedTargetException &)
579     {
580         css::uno::Any anyEx = cppu::getCaughtException();
581         throw css::lang::WrappedTargetRuntimeException("WrappedTargetException caught",
582                 static_cast < cppu::OWeakObject * > ( this ), anyEx );
583     }
584 
585     return aValues;
586 }
587 
addPropertiesChangeListener(const uno::Sequence<OUString> &,const uno::Reference<beans::XPropertiesChangeListener> &)588 void SAL_CALL SwXParagraph::addPropertiesChangeListener(
589     const uno::Sequence< OUString >& /*aPropertyNames*/,
590     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
591 {
592     OSL_FAIL("SwXParagraph::addPropertiesChangeListener(): not implemented");
593 }
594 
removePropertiesChangeListener(const uno::Reference<beans::XPropertiesChangeListener> &)595 void SAL_CALL SwXParagraph::removePropertiesChangeListener(
596     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
597 {
598     OSL_FAIL("SwXParagraph::removePropertiesChangeListener(): not implemented");
599 }
600 
firePropertiesChangeEvent(const uno::Sequence<OUString> &,const uno::Reference<beans::XPropertiesChangeListener> &)601 void SAL_CALL SwXParagraph::firePropertiesChangeEvent(
602     const uno::Sequence< OUString >& /*aPropertyNames*/,
603     const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
604 {
605     OSL_FAIL("SwXParagraph::firePropertiesChangeEvent(): not implemented");
606 }
607 
608 /* disabled for #i46921# */
609 
610 uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL
setPropertyValuesTolerant(const uno::Sequence<OUString> & rPropertyNames,const uno::Sequence<uno::Any> & rValues)611 SwXParagraph::setPropertyValuesTolerant(
612         const uno::Sequence< OUString >& rPropertyNames,
613         const uno::Sequence< uno::Any >& rValues )
614 {
615     SolarMutexGuard aGuard;
616 
617     if (rPropertyNames.getLength() != rValues.getLength())
618     {
619         throw lang::IllegalArgumentException();
620     }
621 
622     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
623 
624     //SwNode& rTextNode = pUnoCursor->GetPoint()->nNode.GetNode();
625     //const SwAttrSet& rAttrSet = static_cast<SwTextNode&>(rTextNode).GetSwAttrSet();
626     //sal_uInt16 nAttrCount = rAttrSet.Count();
627 
628     const sal_Int32 nProps = rPropertyNames.getLength();
629     const OUString *pProp = rPropertyNames.getConstArray();
630 
631     //sal_Int32 nVals = rValues.getLength();
632     const uno::Any *pValue = rValues.getConstArray();
633 
634     sal_Int32 nFailed = 0;
635     uno::Sequence< beans::SetPropertyTolerantFailed > aFailed( nProps );
636     beans::SetPropertyTolerantFailed *pFailed = aFailed.getArray();
637 
638     // get entry to start with
639     const SfxItemPropertyMap &rPropMap =
640         m_pImpl->m_rPropSet.getPropertyMap();
641 
642     SwPosition aPos( rTextNode );
643     SwCursor aCursor( aPos, nullptr );
644     SwParaSelection aParaSel( aCursor );
645     for (sal_Int32 i = 0;  i < nProps;  ++i)
646     {
647         try
648         {
649             pFailed[ nFailed ].Name = pProp[i];
650 
651             SfxItemPropertyMapEntry const*const pEntry =
652                 rPropMap.getByName( pProp[i] );
653             if (!pEntry)
654             {
655                 pFailed[ nFailed++ ].Result  =
656                     beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
657             }
658             else
659             {
660                 // set property value
661                 // (compare to SwXParagraph::setPropertyValues)
662                 if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
663                 {
664                     pFailed[ nFailed++ ].Result  =
665                         beans::TolerantPropertySetResultType::PROPERTY_VETO;
666                 }
667                 else
668                 {
669                     SwUnoCursorHelper::SetPropertyValue(
670                         aCursor, m_pImpl->m_rPropSet, pProp[i], pValue[i]);
671                 }
672             }
673         }
674         catch (beans::UnknownPropertyException &)
675         {
676             // should not occur because property was searched for before
677             TOOLS_WARN_EXCEPTION( "sw", "unexpected exception caught" );
678             pFailed[ nFailed++ ].Result =
679                 beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
680         }
681         catch (lang::IllegalArgumentException &)
682         {
683             pFailed[ nFailed++ ].Result =
684                 beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
685         }
686         catch (beans::PropertyVetoException &)
687         {
688             pFailed[ nFailed++ ].Result =
689                 beans::TolerantPropertySetResultType::PROPERTY_VETO;
690         }
691         catch (lang::WrappedTargetException &)
692         {
693             pFailed[ nFailed++ ].Result =
694                 beans::TolerantPropertySetResultType::WRAPPED_TARGET;
695         }
696     }
697 
698     aFailed.realloc( nFailed );
699     return aFailed;
700 }
701 
702 uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL
getPropertyValuesTolerant(const uno::Sequence<OUString> & rPropertyNames)703 SwXParagraph::getPropertyValuesTolerant(
704         const uno::Sequence< OUString >& rPropertyNames )
705 {
706     SolarMutexGuard aGuard;
707 
708     uno::Sequence< beans::GetDirectPropertyTolerantResult > aTmpRes(
709         m_pImpl->GetPropertyValuesTolerant_Impl( rPropertyNames, false ) );
710 
711     // copy temporary result to final result type
712     const sal_Int32 nLen = aTmpRes.getLength();
713     uno::Sequence< beans::GetPropertyTolerantResult > aRes( nLen );
714     std::copy(aTmpRes.begin(), aTmpRes.end(), aRes.begin());
715     return aRes;
716 }
717 
718 uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL
getDirectPropertyValuesTolerant(const uno::Sequence<OUString> & rPropertyNames)719 SwXParagraph::getDirectPropertyValuesTolerant(
720         const uno::Sequence< OUString >& rPropertyNames )
721 {
722     SolarMutexGuard aGuard;
723 
724     return m_pImpl->GetPropertyValuesTolerant_Impl( rPropertyNames, true );
725 }
726 
727 uno::Sequence< beans::GetDirectPropertyTolerantResult >
GetPropertyValuesTolerant_Impl(const uno::Sequence<OUString> & rPropertyNames,bool bDirectValuesOnly)728 SwXParagraph::Impl::GetPropertyValuesTolerant_Impl(
729         const uno::Sequence< OUString >& rPropertyNames,
730         bool bDirectValuesOnly )
731 {
732     SolarMutexGuard aGuard;
733 
734     SwTextNode & rTextNode(GetTextNodeOrThrow());
735 
736     // #i46786# Use SwAttrSet pointer for determining the state.
737     //          Use the value SwAttrSet (from the paragraph OR the style)
738     //          for determining the actual value(s).
739     const SwAttrSet* pAttrSet = rTextNode.GetpSwAttrSet();
740     const SwAttrSet& rValueAttrSet = rTextNode.GetSwAttrSet();
741 
742     sal_Int32 nProps = rPropertyNames.getLength();
743 
744     uno::Sequence< beans::GetDirectPropertyTolerantResult > aResult( nProps );
745     beans::GetDirectPropertyTolerantResult *pResult = aResult.getArray();
746     sal_Int32 nIdx = 0;
747 
748     // get entry to start with
749     const SfxItemPropertyMap &rPropMap = m_rPropSet.getPropertyMap();
750 
751     for (const OUString& rProp : rPropertyNames)
752     {
753         OSL_ENSURE( nIdx < nProps, "index out of bounds" );
754         beans::GetDirectPropertyTolerantResult &rResult = pResult[nIdx];
755 
756         try
757         {
758             rResult.Name = rProp;
759 
760             SfxItemPropertyMapEntry const*const pEntry =
761                 rPropMap.getByName( rProp );
762             if (!pEntry)  // property available?
763             {
764                 rResult.Result =
765                     beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
766             }
767             else
768             {
769                 // get property state
770                 // (compare to SwXParagraph::getPropertyState)
771                 bool bAttrSetFetched = true;
772                 beans::PropertyState eState = lcl_SwXParagraph_getPropertyState(
773                             rTextNode, &pAttrSet, *pEntry, bAttrSetFetched );
774                 rResult.State  = eState;
775 
776                 rResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_FAILURE;
777                 if (!bDirectValuesOnly ||
778                     (beans::PropertyState_DIRECT_VALUE == eState))
779                 {
780                     // get property value
781                     // (compare to SwXParagraph::getPropertyValue(s))
782                     uno::Any aValue;
783                     if (! ::sw::GetDefaultTextContentValue(
784                                 aValue, rProp, pEntry->nWID ) )
785                     {
786                         SwPosition aPos( rTextNode );
787                         SwPaM aPam( aPos );
788                         // handle properties that are not part of the attribute
789                         // and thus only pretended to be paragraph attributes
790                         beans::PropertyState eTemp;
791                         const bool bDone =
792                             SwUnoCursorHelper::getCursorPropertyValue(
793                                     *pEntry, aPam, &aValue, eTemp, &rTextNode );
794 
795                         // if not found try the real paragraph attributes...
796                         if (!bDone)
797                         {
798                             GetSinglePropertyValue_Impl(*pEntry, rValueAttrSet, aValue);
799                         }
800                     }
801 
802                     rResult.Value  = aValue;
803                     rResult.Result = beans::TolerantPropertySetResultType::SUCCESS;
804 
805                     nIdx++;
806                 }
807                 // this assertion should never occur!
808                 OSL_ENSURE( nIdx < 1  ||  pResult[nIdx - 1].Result != beans::TolerantPropertySetResultType::UNKNOWN_FAILURE,
809                         "unknown failure while retrieving property" );
810 
811             }
812         }
813         catch (beans::UnknownPropertyException &)
814         {
815             // should not occur because property was searched for before
816             TOOLS_WARN_EXCEPTION( "sw", "unexpected exception caught" );
817             rResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
818         }
819         catch (lang::IllegalArgumentException &)
820         {
821             rResult.Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
822         }
823         catch (beans::PropertyVetoException &)
824         {
825             rResult.Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
826         }
827         catch (lang::WrappedTargetException &)
828         {
829             rResult.Result = beans::TolerantPropertySetResultType::WRAPPED_TARGET;
830         }
831     }
832 
833     // resize to actually used size
834     aResult.realloc( nIdx );
835 
836     return aResult;
837 }
838 
GetDefaultTextContentValue(uno::Any & rAny,std::u16string_view rPropertyName,sal_uInt16 nWID)839 bool ::sw::GetDefaultTextContentValue(
840         uno::Any& rAny, std::u16string_view rPropertyName, sal_uInt16 nWID)
841 {
842     if(!nWID)
843     {
844         if(rPropertyName == u"" UNO_NAME_ANCHOR_TYPE)
845             nWID = FN_UNO_ANCHOR_TYPE;
846         else if(rPropertyName == u"" UNO_NAME_ANCHOR_TYPES)
847             nWID = FN_UNO_ANCHOR_TYPES;
848         else if(rPropertyName == u"" UNO_NAME_TEXT_WRAP)
849             nWID = FN_UNO_TEXT_WRAP;
850         else
851             return false;
852     }
853 
854     switch(nWID)
855     {
856         case FN_UNO_TEXT_WRAP:  rAny <<= text::WrapTextMode_NONE; break;
857         case FN_UNO_ANCHOR_TYPE: rAny <<= text::TextContentAnchorType_AT_PARAGRAPH; break;
858         case FN_UNO_ANCHOR_TYPES:
859         {   uno::Sequence<text::TextContentAnchorType> aTypes { text::TextContentAnchorType_AT_PARAGRAPH };
860             rAny <<= aTypes;
861         }
862         break;
863         default:
864             return false;
865     }
866     return true;
867 }
868 
869 void SAL_CALL
addPropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)870 SwXParagraph::addPropertyChangeListener(
871         const OUString& /*rPropertyName*/,
872         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
873 {
874     OSL_FAIL("SwXParagraph::addPropertyChangeListener(): not implemented");
875 }
876 
877 void SAL_CALL
removePropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)878 SwXParagraph::removePropertyChangeListener(
879         const OUString& /*rPropertyName*/,
880         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
881 {
882     OSL_FAIL("SwXParagraph::removePropertyChangeListener(): not implemented");
883 }
884 
885 void SAL_CALL
addVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)886 SwXParagraph::addVetoableChangeListener(
887         const OUString& /*rPropertyName*/,
888         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
889 {
890     OSL_FAIL("SwXParagraph::addVetoableChangeListener(): not implemented");
891 }
892 
893 void SAL_CALL
removeVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)894 SwXParagraph::removeVetoableChangeListener(
895         const OUString& /*rPropertyName*/,
896         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
897 {
898     OSL_FAIL("SwXParagraph::removeVetoableChangeListener(): not implemented");
899 }
900 
lcl_SwXParagraph_getPropertyState(const SwTextNode & rTextNode,const SwAttrSet ** ppSet,const SfxItemPropertyMapEntry & rEntry,bool & rAttrSetFetched)901 static beans::PropertyState lcl_SwXParagraph_getPropertyState(
902     const SwTextNode& rTextNode,
903     const SwAttrSet** ppSet,
904     const SfxItemPropertyMapEntry& rEntry,
905     bool &rAttrSetFetched)
906 {
907     beans::PropertyState eRet(beans::PropertyState_DEFAULT_VALUE);
908 
909     if(!(*ppSet) && !rAttrSetFetched)
910     {
911         (*ppSet) = rTextNode.GetpSwAttrSet();
912         rAttrSetFetched = true;
913     }
914 
915     SwPosition aPos(rTextNode);
916     SwPaM aPam(aPos);
917     bool bDone(false);
918 
919     switch(rEntry.nWID)
920     {
921         case FN_UNO_NUM_RULES:
922         {
923             // if numbering is set, return it; else do nothing
924             SwUnoCursorHelper::getNumberingProperty(aPam,eRet,nullptr);
925             bDone = true;
926             break;
927         }
928         case FN_UNO_ANCHOR_TYPES:
929         {
930             bDone = true;
931             break;
932         }
933         case RES_ANCHOR:
934         {
935             bDone = (MID_SURROUND_SURROUNDTYPE == rEntry.nMemberId);
936             break;
937         }
938         case RES_SURROUND:
939         {
940             bDone = (MID_ANCHOR_ANCHORTYPE == rEntry.nMemberId);
941             break;
942         }
943         case FN_UNO_PARA_STYLE:
944         case FN_UNO_PARA_CONDITIONAL_STYLE_NAME:
945         {
946             SwFormatColl* pFormat = SwUnoCursorHelper::GetCurTextFormatColl(aPam,rEntry.nWID == FN_UNO_PARA_CONDITIONAL_STYLE_NAME);
947             eRet = pFormat ? beans::PropertyState_DIRECT_VALUE : beans::PropertyState_AMBIGUOUS_VALUE;
948             bDone = true;
949             break;
950         }
951         case FN_UNO_PAGE_STYLE:
952         {
953             OUString sVal;
954             SwUnoCursorHelper::GetCurPageStyle( aPam, sVal );
955             eRet = !sVal.isEmpty() ? beans::PropertyState_DIRECT_VALUE
956                               : beans::PropertyState_AMBIGUOUS_VALUE;
957             bDone = true;
958             break;
959         }
960 
961         // DrawingLayer PropertyStyle support
962         case OWN_ATTR_FILLBMP_MODE:
963         {
964             if(*ppSet)
965             {
966                 if(SfxItemState::SET == (*ppSet)->GetItemState(XATTR_FILLBMP_STRETCH, false)
967                     || SfxItemState::SET == (*ppSet)->GetItemState(XATTR_FILLBMP_TILE, false))
968                 {
969                     eRet = beans::PropertyState_DIRECT_VALUE;
970                 }
971                 else
972                 {
973                     eRet = beans::PropertyState_AMBIGUOUS_VALUE;
974                 }
975 
976                 bDone = true;
977             }
978             break;
979         }
980         case RES_BACKGROUND:
981         {
982             if(*ppSet)
983             {
984                 if (SWUnoHelper::needToMapFillItemsToSvxBrushItemTypes(**ppSet,
985                         rEntry.nMemberId))
986                 {
987                     eRet = beans::PropertyState_DIRECT_VALUE;
988                 }
989                 bDone = true;
990             }
991             break;
992         }
993     }
994 
995     if(!bDone)
996     {
997         if((*ppSet) && SfxItemState::SET == (*ppSet)->GetItemState(rEntry.nWID, false))
998         {
999             eRet = beans::PropertyState_DIRECT_VALUE;
1000         }
1001     }
1002 
1003     return eRet;
1004 }
1005 
1006 beans::PropertyState SAL_CALL
getPropertyState(const OUString & rPropertyName)1007 SwXParagraph::getPropertyState(const OUString& rPropertyName)
1008 {
1009     SolarMutexGuard aGuard;
1010 
1011     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1012 
1013     const SwAttrSet* pSet = nullptr;
1014     SfxItemPropertyMapEntry const*const pEntry =
1015         m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
1016     if (!pEntry)
1017     {
1018         throw beans::UnknownPropertyException(
1019             "Unknown property: " + rPropertyName,
1020             static_cast<cppu::OWeakObject *>(this));
1021     }
1022     bool bDummy = false;
1023     const beans::PropertyState eRet =
1024         lcl_SwXParagraph_getPropertyState(rTextNode, &pSet, *pEntry, bDummy);
1025     return eRet;
1026 }
1027 
1028 uno::Sequence< beans::PropertyState > SAL_CALL
getPropertyStates(const uno::Sequence<OUString> & PropertyNames)1029 SwXParagraph::getPropertyStates(
1030         const uno::Sequence< OUString >& PropertyNames)
1031 {
1032     SolarMutexGuard aGuard;
1033 
1034     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1035 
1036     const OUString* pNames = PropertyNames.getConstArray();
1037     uno::Sequence< beans::PropertyState > aRet(PropertyNames.getLength());
1038     beans::PropertyState* pStates = aRet.getArray();
1039     const SfxItemPropertyMap &rMap = m_pImpl->m_rPropSet.getPropertyMap();
1040     const SwAttrSet* pSet = nullptr;
1041     bool bAttrSetFetched = false;
1042 
1043     for (sal_Int32 i = 0, nEnd = PropertyNames.getLength(); i < nEnd;
1044             ++i, ++pStates, ++pNames)
1045     {
1046         SfxItemPropertyMapEntry const*const pEntry =
1047             rMap.getByName( *pNames );
1048         if (!pEntry)
1049         {
1050             throw beans::UnknownPropertyException(
1051                 "Unknown property: " + *pNames,
1052                 static_cast<cppu::OWeakObject *>(this));
1053         }
1054 
1055         if (bAttrSetFetched && !pSet && isATR(pEntry->nWID))
1056         {
1057             *pStates = beans::PropertyState_DEFAULT_VALUE;
1058         }
1059         else
1060         {
1061             *pStates = lcl_SwXParagraph_getPropertyState(
1062                 rTextNode, &pSet, *pEntry, bAttrSetFetched );
1063         }
1064     }
1065 
1066     return aRet;
1067 }
1068 
1069 void SAL_CALL
setPropertyToDefault(const OUString & rPropertyName)1070 SwXParagraph::setPropertyToDefault(const OUString& rPropertyName)
1071 {
1072     SolarMutexGuard aGuard;
1073 
1074     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1075 
1076     SwPosition aPos( rTextNode );
1077     SwCursor aCursor( aPos, nullptr );
1078     if (rPropertyName == UNO_NAME_ANCHOR_TYPE  ||
1079         rPropertyName == UNO_NAME_ANCHOR_TYPES ||
1080         rPropertyName == UNO_NAME_TEXT_WRAP)
1081     {
1082         return;
1083     }
1084 
1085     // select paragraph
1086     SwParaSelection aParaSel( aCursor );
1087     SfxItemPropertyMapEntry const*const pEntry =
1088         m_pImpl->m_rPropSet.getPropertyMap().getByName( rPropertyName );
1089     if (!pEntry)
1090     {
1091         throw beans::UnknownPropertyException(
1092             "Unknown property: " + rPropertyName,
1093             static_cast<cppu::OWeakObject *>(this));
1094     }
1095 
1096     if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
1097     {
1098         throw uno::RuntimeException(
1099             "Property is read-only: " + rPropertyName,
1100             static_cast<cppu::OWeakObject *>(this));
1101     }
1102 
1103     const bool bBelowFrameAtrEnd(pEntry->nWID < RES_FRMATR_END);
1104     const bool bDrawingLayerRange(XATTR_FILL_FIRST <= pEntry->nWID && XATTR_FILL_LAST >= pEntry->nWID);
1105 
1106     if(bBelowFrameAtrEnd || bDrawingLayerRange)
1107     {
1108         o3tl::sorted_vector<sal_uInt16> aWhichIds;
1109 
1110         // For FillBitmapMode two IDs have to be reset (!)
1111         if(OWN_ATTR_FILLBMP_MODE == pEntry->nWID)
1112         {
1113             aWhichIds.insert(XATTR_FILLBMP_STRETCH);
1114             aWhichIds.insert(XATTR_FILLBMP_TILE);
1115         }
1116         else
1117         {
1118             aWhichIds.insert(pEntry->nWID);
1119         }
1120 
1121         if (pEntry->nWID < RES_PARATR_BEGIN)
1122         {
1123             aCursor.GetDoc().ResetAttrs(aCursor, true, aWhichIds);
1124         }
1125         else
1126         {
1127             // for paragraph attributes the selection must be extended
1128             // to paragraph boundaries
1129             SwPosition aStart( *aCursor.Start() );
1130             SwPosition aEnd  ( *aCursor.End()   );
1131             auto pTemp( aCursor.GetDoc().CreateUnoCursor(aStart) );
1132             if(!SwUnoCursorHelper::IsStartOfPara(*pTemp))
1133             {
1134                 pTemp->MovePara(GoCurrPara, fnParaStart);
1135             }
1136 
1137             pTemp->SetMark();
1138             *pTemp->GetPoint() = aEnd;
1139 
1140             SwUnoCursorHelper::SelectPam(*pTemp, true);
1141 
1142             if (!SwUnoCursorHelper::IsEndOfPara(*pTemp))
1143             {
1144                 pTemp->MovePara(GoCurrPara, fnParaEnd);
1145             }
1146 
1147 
1148             pTemp->GetDoc().ResetAttrs(*pTemp, true, aWhichIds);
1149         }
1150     }
1151     else
1152     {
1153         SwUnoCursorHelper::resetCursorPropertyValue(*pEntry, aCursor);
1154     }
1155 }
1156 
1157 uno::Any SAL_CALL
getPropertyDefault(const OUString & rPropertyName)1158 SwXParagraph::getPropertyDefault(const OUString& rPropertyName)
1159 {
1160     SolarMutexGuard g;
1161 
1162     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1163 
1164     uno::Any aRet;
1165     if (::sw::GetDefaultTextContentValue(aRet, rPropertyName))
1166     {
1167         return aRet;
1168     }
1169 
1170     SfxItemPropertyMapEntry const*const pEntry =
1171         m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
1172     if (!pEntry)
1173     {
1174         throw beans::UnknownPropertyException(
1175             "Unknown property: " + rPropertyName,
1176             static_cast<cppu::OWeakObject *>(this));
1177     }
1178 
1179     const bool bBelowFrameAtrEnd(pEntry->nWID < RES_FRMATR_END);
1180     const bool bDrawingLayerRange(XATTR_FILL_FIRST <= pEntry->nWID && XATTR_FILL_LAST >= pEntry->nWID);
1181 
1182     if(bBelowFrameAtrEnd || bDrawingLayerRange)
1183     {
1184         const SfxPoolItem& rDefItem = rTextNode.GetDoc().GetAttrPool().GetDefaultItem(pEntry->nWID);
1185 
1186         rDefItem.QueryValue(aRet, pEntry->nMemberId);
1187     }
1188 
1189     return aRet;
1190 }
1191 
1192 void SAL_CALL
attach(const uno::Reference<text::XTextRange> &)1193 SwXParagraph::attach(const uno::Reference< text::XTextRange > & /*xTextRange*/)
1194 {
1195     SolarMutexGuard aGuard;
1196     // SwXParagraph will only created in order to be inserted by
1197     // 'insertTextContentBefore' or 'insertTextContentAfter' therefore
1198     // they cannot be attached
1199     throw uno::RuntimeException();
1200 }
1201 
1202 uno::Reference< text::XTextRange > SAL_CALL
getAnchor()1203 SwXParagraph::getAnchor()
1204 {
1205     SolarMutexGuard aGuard;
1206 
1207     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1208 
1209     SwPosition aPos( rTextNode );
1210     SwCursor aCursor( aPos, nullptr );
1211     // select paragraph
1212     SwParaSelection aParaSel( aCursor );
1213     const uno::Reference< text::XTextRange >  xRet =
1214         new SwXTextRange(aCursor, m_pImpl->m_xParentText);
1215     return xRet;
1216 }
1217 
dispose()1218 void SAL_CALL SwXParagraph::dispose()
1219 {
1220     SolarMutexGuard aGuard;
1221 
1222     SwTextNode *const pTextNode( m_pImpl->GetTextNode() );
1223     if (pTextNode)
1224     {
1225         SwCursor aCursor( SwPosition( *pTextNode ), nullptr );
1226         pTextNode->GetDoc().getIDocumentContentOperations().DelFullPara(aCursor);
1227         lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
1228         m_pImpl->m_EventListeners.disposeAndClear(ev);
1229     }
1230 }
1231 
addEventListener(const uno::Reference<lang::XEventListener> & xListener)1232 void SAL_CALL SwXParagraph::addEventListener(
1233         const uno::Reference< lang::XEventListener > & xListener)
1234 {
1235     // no need to lock here as m_pImpl is const and container threadsafe
1236     m_pImpl->m_EventListeners.addInterface(xListener);
1237 }
1238 
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)1239 void SAL_CALL SwXParagraph::removeEventListener(
1240         const uno::Reference< lang::XEventListener > & xListener)
1241 {
1242     // no need to lock here as m_pImpl is const and container threadsafe
1243     m_pImpl->m_EventListeners.removeInterface(xListener);
1244 }
1245 
1246 uno::Reference< container::XEnumeration >  SAL_CALL
createEnumeration()1247 SwXParagraph::createEnumeration()
1248 {
1249     SolarMutexGuard aGuard;
1250 
1251     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1252 
1253     SwPosition aPos( rTextNode );
1254     SwPaM aPam ( aPos );
1255     const uno::Reference< container::XEnumeration > xRef =
1256         new SwXTextPortionEnumeration(aPam, m_pImpl->m_xParentText,
1257             m_pImpl->m_nSelectionStartPos, m_pImpl->m_nSelectionEndPos);
1258     return xRef;
1259 }
1260 
getElementType()1261 uno::Type SAL_CALL SwXParagraph::getElementType()
1262 {
1263     return cppu::UnoType<text::XTextRange>::get();
1264 }
1265 
hasElements()1266 sal_Bool SAL_CALL SwXParagraph::hasElements()
1267 {
1268     SolarMutexGuard aGuard;
1269     return GetTextNode() != nullptr;
1270 }
1271 
1272 uno::Reference< text::XText > SAL_CALL
getText()1273 SwXParagraph::getText()
1274 {
1275     SolarMutexGuard g;
1276 
1277     return m_pImpl->m_xParentText;
1278 }
1279 
1280 uno::Reference< text::XTextRange > SAL_CALL
getStart()1281 SwXParagraph::getStart()
1282 {
1283     SolarMutexGuard aGuard;
1284 
1285     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1286 
1287     SwPosition aPos( rTextNode );
1288     SwCursor aCursor( aPos, nullptr );
1289     SwParaSelection aParaSel( aCursor );
1290     SwPaM aPam( *aCursor.Start() );
1291     uno::Reference< text::XText >  xParent = getText();
1292     const uno::Reference< text::XTextRange > xRet =
1293         new SwXTextRange(aPam, xParent);
1294     return xRet;
1295 }
1296 
1297 uno::Reference< text::XTextRange > SAL_CALL
getEnd()1298 SwXParagraph::getEnd()
1299 {
1300     SolarMutexGuard aGuard;
1301 
1302     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1303 
1304     SwPosition aPos( rTextNode );
1305     SwCursor aCursor( aPos, nullptr );
1306     SwParaSelection aParaSel( aCursor );
1307     SwPaM aPam( *aCursor.End() );
1308     uno::Reference< text::XText >  xParent = getText();
1309     const uno::Reference< text::XTextRange > xRet =
1310         new SwXTextRange(aPam, xParent);
1311     return xRet;
1312 }
1313 
getString()1314 OUString SAL_CALL SwXParagraph::getString()
1315 {
1316     SolarMutexGuard aGuard;
1317     OUString aRet;
1318     SwTextNode const*const pTextNode( GetTextNode() );
1319     if (pTextNode)
1320     {
1321         SwPosition aPos( *pTextNode );
1322         SwCursor aCursor( aPos, nullptr );
1323         SwParaSelection aParaSel( aCursor );
1324         SwUnoCursorHelper::GetTextFromPam(aCursor, aRet);
1325     }
1326     else if (m_pImpl->IsDescriptor())
1327     {
1328         aRet = m_pImpl->m_sText;
1329     }
1330     else
1331     {
1332         // Seems object is being disposed or some other problem occurs.
1333         // Anyway from user point of view object still exist, so on that level this is not an error
1334         SAL_WARN("sw.uno", "getString() for invalid paragraph called. Returning empty string.");
1335     }
1336     return aRet;
1337 }
1338 
setString(const OUString & aString)1339 void SAL_CALL SwXParagraph::setString(const OUString& aString)
1340 {
1341     SolarMutexGuard aGuard;
1342 
1343     SwTextNode const*const pTextNode( GetTextNode() );
1344     if (pTextNode)
1345     {
1346         SwPosition aPos( *pTextNode );
1347         SwCursor aCursor( aPos, nullptr );
1348         if (!SwUnoCursorHelper::IsStartOfPara(aCursor)) {
1349             aCursor.MovePara(GoCurrPara, fnParaStart);
1350         }
1351         SwUnoCursorHelper::SelectPam(aCursor, true);
1352         if (pTextNode->GetText().getLength()) {
1353             aCursor.MovePara(GoCurrPara, fnParaEnd);
1354         }
1355         SwUnoCursorHelper::SetString(aCursor, aString);
1356         SwUnoCursorHelper::SelectPam(aCursor, false);
1357     }
1358     else if (m_pImpl->IsDescriptor())
1359     {
1360         m_pImpl->m_sText = aString;
1361     }
1362     else
1363     {
1364         throw uno::RuntimeException();
1365     }
1366 }
1367 
1368 uno::Reference< container::XEnumeration > SAL_CALL
createContentEnumeration(const OUString & rServiceName)1369 SwXParagraph::createContentEnumeration(const OUString& rServiceName)
1370 {
1371     SolarMutexGuard g;
1372 
1373     if ( rServiceName != "com.sun.star.text.TextContent" )
1374     {
1375         throw uno::RuntimeException();
1376     }
1377 
1378     SwTextNode & rTextNode(m_pImpl->GetTextNodeOrThrow());
1379 
1380     SwPosition aPos( rTextNode );
1381     SwPaM aPam( aPos );
1382     uno::Reference< container::XEnumeration > xRet =
1383         SwXParaFrameEnumeration::Create(aPam, PARAFRAME_PORTION_PARAGRAPH);
1384     return xRet;
1385 }
1386 
1387 uno::Sequence< OUString > SAL_CALL
getAvailableServiceNames()1388 SwXParagraph::getAvailableServiceNames()
1389 {
1390     uno::Sequence<OUString> aRet { "com.sun.star.text.TextContent" };
1391     return aRet;
1392 }
1393 
1394 // MetadatableMixin
GetCoreObject()1395 ::sfx2::Metadatable* SwXParagraph::GetCoreObject()
1396 {
1397     SwTextNode *const pTextNode( m_pImpl->GetTextNode() );
1398     return pTextNode;
1399 }
1400 
GetModel()1401 uno::Reference<frame::XModel> SwXParagraph::GetModel()
1402 {
1403     SwTextNode *const pTextNode( m_pImpl->GetTextNode() );
1404     if (pTextNode)
1405     {
1406         SwDocShell const*const pShell( pTextNode->GetDoc().GetDocShell() );
1407         return pShell ? pShell->GetModel() : nullptr;
1408     }
1409     return nullptr;
1410 }
1411 
1412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1413