1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <unoparagraph.hxx>
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>
30 #include <unoparaframeenum.hxx>
31 #include <unotext.hxx>
32 #include <unotextrange.hxx>
33 #include <unoport.hxx>
35 #include <unocrsr.hxx>
36 #include <unoprnms.hxx>
37 #include <unocrsrhelper.hxx>
40 #include <osl/mutex.hxx>
41 #include <vcl/svapp.hxx>
43 #include <swunohelper.hxx>
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>
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>
61 using namespace ::com::sun::star
;
69 explicit SwParaSelection(SwCursor
& rCursor
);
75 SwParaSelection::SwParaSelection(SwCursor
& rCursor
)
78 if (m_rCursor
.HasMark())
80 m_rCursor
.DeleteMark();
82 // is it at the start?
83 if (m_rCursor
.GetPoint()->nContent
!= 0)
85 m_rCursor
.MovePara(GoCurrPara
, fnParaStart
);
87 // or at the end already?
88 if (m_rCursor
.GetPoint()->nContent
!= m_rCursor
.GetContentNode()->Len())
91 m_rCursor
.MovePara(GoCurrPara
, fnParaEnd
);
95 SwParaSelection::~SwParaSelection()
97 if (m_rCursor
.GetPoint()->nContent
!= 0)
99 m_rCursor
.DeleteMark();
100 m_rCursor
.MovePara(GoCurrPara
, fnParaStart
);
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
);
112 class SwXParagraph::Impl
116 ::osl::Mutex m_Mutex
; // just for OInterfaceContainerHelper2
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
;
127 uno::Reference
<text::XText
> m_xParentText
;
128 SwTextNode
* m_pTextNode
;
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)
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
)
142 m_pTextNode
&& StartListening(m_pTextNode
->GetNotifier());
145 SwTextNode
* GetTextNode() {
149 SwTextNode
& GetTextNodeOrThrow() {
151 throw uno::RuntimeException("SwXParagraph: disposed or invalid", nullptr);
156 bool IsDescriptor() const { return m_bIsDescriptor
; }
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
);
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
);
174 /// @throws uno::RuntimeException
175 void GetSinglePropertyValue_Impl(
176 const SfxItemPropertyMapEntry
& rEntry
,
177 const SfxItemSet
& rSet
,
178 uno::Any
& rAny
) const;
180 /// @throws uno::RuntimeException
181 uno::Sequence
< beans::GetDirectPropertyTolerantResult
>
182 GetPropertyValuesTolerant_Impl(
183 const uno::Sequence
< OUString
>& rPropertyNames
,
184 bool bDirectValuesOnly
);
186 virtual void Notify(const SfxHint
& rHint
) override
;
190 void SwXParagraph::Impl::Notify(const SfxHint
& rHint
)
192 if(rHint
.GetId() == SfxHintId::Dying
)
194 m_pTextNode
= nullptr;
195 uno::Reference
<uno::XInterface
> const xThis(m_wThis
);
197 { // fdo#72695: if UNO object is already dead, don't revive it with event
200 lang::EventObject
const ev(xThis
);
201 m_EventListeners
.disposeAndClear(ev
);
205 SwXParagraph::SwXParagraph()
206 : m_pImpl( new SwXParagraph::Impl(*this) )
210 SwXParagraph::SwXParagraph(
211 uno::Reference
< text::XText
> const & xParent
,
212 SwTextNode
& rTextNode
,
213 const sal_Int32 nSelStart
, const sal_Int32 nSelEnd
)
215 new SwXParagraph::Impl(*this, &rTextNode
, xParent
, nSelStart
, nSelEnd
))
219 SwXParagraph::~SwXParagraph()
223 const SwTextNode
* SwXParagraph::GetTextNode() const
225 return m_pImpl
->GetTextNode();
228 bool SwXParagraph::IsDescriptor() const
230 return m_pImpl
->IsDescriptor();
233 uno::Reference
<text::XTextContent
>
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
)
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());
250 // create new SwXParagraph
251 uno::Reference
<text::XText
> xParentText(i_xParent
);
252 if (!xParentText
.is() && pTextNode
)
254 SwPosition
Pos(*pTextNode
);
255 xParentText
.set(::sw::CreateParentXText( rDoc
, Pos
));
257 SwXParagraph
*const pXPara( pTextNode
258 ? new SwXParagraph(xParentText
, *pTextNode
, nSelStart
, nSelEnd
)
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
))
265 pTextNode
->SetXParagraph(xParagraph
);
267 // need a permanent Reference to initialize m_wThis
268 pXPara
->m_pImpl
->m_wThis
= xParagraph
;
272 bool SwXParagraph::SelectPaM(SwPaM
& rPaM
)
274 SwTextNode
const*const pTextNode( GetTextNode() );
281 *rPaM
.GetPoint() = SwPosition( *pTextNode
);
282 // set selection to the whole paragraph
284 rPaM
.GetMark()->nContent
= pTextNode
->GetText().getLength();
288 const uno::Sequence
< sal_Int8
> & SwXParagraph::getUnoTunnelId()
290 static const comphelper::UnoIdInit theSwXParagraphUnoTunnelId
;
291 return theSwXParagraphUnoTunnelId
.getSeq();
295 SwXParagraph::getSomething(const uno::Sequence
< sal_Int8
>& rId
)
297 return comphelper::getSomethingImpl
<SwXParagraph
>(rId
, this);
301 SwXParagraph::getImplementationName()
303 return "SwXParagraph";
307 SwXParagraph::supportsService(const OUString
& rServiceName
)
309 return cppu::supportsService(this, rServiceName
);
312 uno::Sequence
< OUString
> SAL_CALL
313 SwXParagraph::getSupportedServiceNames()
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"
328 SwXParagraph::attachToText(SwXText
& rParent
, SwTextNode
& rTextNode
)
330 OSL_ENSURE(m_pImpl
->m_bIsDescriptor
, "Paragraph is not a descriptor");
331 if (!m_pImpl
->m_bIsDescriptor
)
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())
341 try { setString(m_pImpl
->m_sText
); }
343 m_pImpl
->m_sText
.clear();
347 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
348 SwXParagraph::getPropertySetInfo()
352 static uno::Reference
< beans::XPropertySetInfo
> xRef
=
353 m_pImpl
->m_rPropSet
.getPropertySetInfo();
358 SwXParagraph::setPropertyValue(const OUString
& rPropertyName
,
359 const uno::Any
& rValue
)
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
);
369 SwXParagraph::getPropertyValue(const OUString
& rPropertyName
)
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];
378 void SwXParagraph::Impl::SetPropertyValues_Impl(
379 const uno::Sequence
< OUString
>& rPropertyNames
,
380 const uno::Sequence
< uno::Any
>& rValues
)
382 SwTextNode
& rTextNode(GetTextNodeOrThrow());
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
);
391 uno::Sequence
< beans::PropertyValue
> aValues( rPropertyNames
.getLength() );
392 for (sal_Int32 nProp
= 0; nProp
< rPropertyNames
.getLength(); nProp
++)
394 SfxItemPropertyMapEntry
const*const pEntry
=
395 rMap
.getByName( pPropertyNames
[nProp
] );
398 throw beans::UnknownPropertyException(
399 "Unknown property: " + pPropertyNames
[nProp
],
400 static_cast< cppu::OWeakObject
* >(&m_rThis
));
402 if (pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
404 throw beans::PropertyVetoException(
405 "Property is read-only: " + pPropertyNames
[nProp
],
406 static_cast< cppu::OWeakObject
* >(&m_rThis
));
408 aValues
[nProp
].Name
= pPropertyNames
[nProp
];
409 aValues
[nProp
].Value
= pValues
[nProp
];
411 SwUnoCursorHelper::SetPropertyValues(aCursor
, m_rPropSet
, aValues
);
414 void SAL_CALL
SwXParagraph::setPropertyValues(
415 const uno::Sequence
< OUString
>& rPropertyNames
,
416 const uno::Sequence
< uno::Any
>& rValues
)
418 SolarMutexGuard aGuard
;
420 // workaround for bad designed API
423 m_pImpl
->SetPropertyValues_Impl( rPropertyNames
, rValues
);
425 catch (const beans::UnknownPropertyException
&rException
)
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
;
435 // Support for DrawingLayer FillStyles for GetPropertyValue() usages
436 void SwXParagraph::Impl::GetSinglePropertyValue_Impl(
437 const SfxItemPropertyMapEntry
& rEntry
,
438 const SfxItemSet
& rSet
,
439 uno::Any
& rAny
) const
447 const std::unique_ptr
<SvxBrushItem
> aOriginalBrushItem(getSvxBrushItemFromSourceSet(rSet
, RES_BACKGROUND
));
449 if(!aOriginalBrushItem
->QueryValue(rAny
, rEntry
.nMemberId
))
451 OSL_ENSURE(false, "Error getting attribute from RES_BACKGROUND (!)");
457 case OWN_ATTR_FILLBMP_MODE
:
459 if (rSet
.Get(XATTR_FILLBMP_TILE
).GetValue())
461 rAny
<<= drawing::BitmapMode_REPEAT
;
463 else if (rSet
.Get(XATTR_FILLBMP_STRETCH
).GetValue())
465 rAny
<<= drawing::BitmapMode_STRETCH
;
469 rAny
<<= drawing::BitmapMode_NO_REPEAT
;
481 // fallback to standard get value implementation used before this helper was created
482 m_rPropSet
.getPropertyValue(rEntry
, rSet
, rAny
);
484 if(rEntry
.aType
== cppu::UnoType
<sal_Int16
>::get() && rEntry
.aType
!= rAny
.getValueType())
486 // since the sfx uInt16 item now exports a sal_Int32, we may have to fix this here
491 rAny
<<= static_cast<sal_Int16
>(nValue
);
495 // check for needed metric translation
496 if(!(rEntry
.nMoreFlags
& PropertyMoreFlags::METRIC_ITEM
))
501 if(XATTR_FILLBMP_SIZEX
== rEntry
.nWID
|| XATTR_FILLBMP_SIZEY
== rEntry
.nWID
)
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;
515 const MapUnit
eMapUnit(rSet
.GetPool()->GetMetric(rEntry
.nWID
));
517 if(eMapUnit
!= MapUnit::Map100thMM
)
519 SvxUnoConvertToMM(eMapUnit
, rAny
);
524 uno::Sequence
< uno::Any
> SwXParagraph::Impl::GetPropertyValues_Impl(
525 const uno::Sequence
< OUString
> & rPropertyNames
)
527 SwTextNode
& rTextNode(GetTextNodeOrThrow());
529 uno::Sequence
< uno::Any
> aValues(rPropertyNames
.getLength());
530 SwPosition
aPos( rTextNode
);
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
++)
538 SfxItemPropertyMapEntry
const*const pEntry
=
539 rMap
.getByName( pPropertyNames
[nProp
] );
542 throw beans::UnknownPropertyException(
543 "Unknown property: " + pPropertyNames
[nProp
],
544 static_cast< cppu::OWeakObject
* >(&m_rThis
));
546 if (! ::sw::GetDefaultTextContentValue(
547 pValues
[nProp
], pPropertyNames
[nProp
], pEntry
->nWID
))
549 beans::PropertyState eTemp
;
550 const bool bDone
= SwUnoCursorHelper::getCursorPropertyValue(
551 *pEntry
, aPam
, &(pValues
[nProp
]), eTemp
, &rTextNode
);
554 GetSinglePropertyValue_Impl(*pEntry
, rAttrSet
, pValues
[nProp
]);
561 uno::Sequence
< uno::Any
> SAL_CALL
562 SwXParagraph::getPropertyValues(const uno::Sequence
< OUString
>& rPropertyNames
)
564 SolarMutexGuard aGuard
;
565 uno::Sequence
< uno::Any
> aValues
;
567 // workaround for bad designed API
570 aValues
= m_pImpl
->GetPropertyValues_Impl( rPropertyNames
);
572 catch (beans::UnknownPropertyException
&)
574 css::uno::Any anyEx
= cppu::getCaughtException();
575 throw css::lang::WrappedTargetRuntimeException("Unknown property exception caught",
576 static_cast < cppu::OWeakObject
* > ( this ), anyEx
);
578 catch (lang::WrappedTargetException
&)
580 css::uno::Any anyEx
= cppu::getCaughtException();
581 throw css::lang::WrappedTargetRuntimeException("WrappedTargetException caught",
582 static_cast < cppu::OWeakObject
* > ( this ), anyEx
);
588 void SAL_CALL
SwXParagraph::addPropertiesChangeListener(
589 const uno::Sequence
< OUString
>& /*aPropertyNames*/,
590 const uno::Reference
< beans::XPropertiesChangeListener
>& /*xListener*/ )
592 OSL_FAIL("SwXParagraph::addPropertiesChangeListener(): not implemented");
595 void SAL_CALL
SwXParagraph::removePropertiesChangeListener(
596 const uno::Reference
< beans::XPropertiesChangeListener
>& /*xListener*/ )
598 OSL_FAIL("SwXParagraph::removePropertiesChangeListener(): not implemented");
601 void SAL_CALL
SwXParagraph::firePropertiesChangeEvent(
602 const uno::Sequence
< OUString
>& /*aPropertyNames*/,
603 const uno::Reference
< beans::XPropertiesChangeListener
>& /*xListener*/ )
605 OSL_FAIL("SwXParagraph::firePropertiesChangeEvent(): not implemented");
608 /* disabled for #i46921# */
610 uno::Sequence
< beans::SetPropertyTolerantFailed
> SAL_CALL
611 SwXParagraph::setPropertyValuesTolerant(
612 const uno::Sequence
< OUString
>& rPropertyNames
,
613 const uno::Sequence
< uno::Any
>& rValues
)
615 SolarMutexGuard aGuard
;
617 if (rPropertyNames
.getLength() != rValues
.getLength())
619 throw lang::IllegalArgumentException();
622 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
624 //SwNode& rTextNode = pUnoCursor->GetPoint()->nNode.GetNode();
625 //const SwAttrSet& rAttrSet = static_cast<SwTextNode&>(rTextNode).GetSwAttrSet();
626 //sal_uInt16 nAttrCount = rAttrSet.Count();
628 const sal_Int32 nProps
= rPropertyNames
.getLength();
629 const OUString
*pProp
= rPropertyNames
.getConstArray();
631 //sal_Int32 nVals = rValues.getLength();
632 const uno::Any
*pValue
= rValues
.getConstArray();
634 sal_Int32 nFailed
= 0;
635 uno::Sequence
< beans::SetPropertyTolerantFailed
> aFailed( nProps
);
636 beans::SetPropertyTolerantFailed
*pFailed
= aFailed
.getArray();
638 // get entry to start with
639 const SfxItemPropertyMap
&rPropMap
=
640 m_pImpl
->m_rPropSet
.getPropertyMap();
642 SwPosition
aPos( rTextNode
);
643 SwCursor
aCursor( aPos
, nullptr );
644 SwParaSelection
aParaSel( aCursor
);
645 for (sal_Int32 i
= 0; i
< nProps
; ++i
)
649 pFailed
[ nFailed
].Name
= pProp
[i
];
651 SfxItemPropertyMapEntry
const*const pEntry
=
652 rPropMap
.getByName( pProp
[i
] );
655 pFailed
[ nFailed
++ ].Result
=
656 beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY
;
660 // set property value
661 // (compare to SwXParagraph::setPropertyValues)
662 if (pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
664 pFailed
[ nFailed
++ ].Result
=
665 beans::TolerantPropertySetResultType::PROPERTY_VETO
;
669 SwUnoCursorHelper::SetPropertyValue(
670 aCursor
, m_pImpl
->m_rPropSet
, pProp
[i
], pValue
[i
]);
674 catch (beans::UnknownPropertyException
&)
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
;
681 catch (lang::IllegalArgumentException
&)
683 pFailed
[ nFailed
++ ].Result
=
684 beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT
;
686 catch (beans::PropertyVetoException
&)
688 pFailed
[ nFailed
++ ].Result
=
689 beans::TolerantPropertySetResultType::PROPERTY_VETO
;
691 catch (lang::WrappedTargetException
&)
693 pFailed
[ nFailed
++ ].Result
=
694 beans::TolerantPropertySetResultType::WRAPPED_TARGET
;
698 aFailed
.realloc( nFailed
);
702 uno::Sequence
< beans::GetPropertyTolerantResult
> SAL_CALL
703 SwXParagraph::getPropertyValuesTolerant(
704 const uno::Sequence
< OUString
>& rPropertyNames
)
706 SolarMutexGuard aGuard
;
708 const uno::Sequence
< beans::GetDirectPropertyTolerantResult
> aTmpRes(
709 m_pImpl
->GetPropertyValuesTolerant_Impl( rPropertyNames
, false ) );
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
.getArray());
718 uno::Sequence
< beans::GetDirectPropertyTolerantResult
> SAL_CALL
719 SwXParagraph::getDirectPropertyValuesTolerant(
720 const uno::Sequence
< OUString
>& rPropertyNames
)
722 SolarMutexGuard aGuard
;
724 return m_pImpl
->GetPropertyValuesTolerant_Impl( rPropertyNames
, true );
727 uno::Sequence
< beans::GetDirectPropertyTolerantResult
>
728 SwXParagraph::Impl::GetPropertyValuesTolerant_Impl(
729 const uno::Sequence
< OUString
>& rPropertyNames
,
730 bool bDirectValuesOnly
)
732 SolarMutexGuard aGuard
;
734 SwTextNode
& rTextNode(GetTextNodeOrThrow());
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();
742 sal_Int32 nProps
= rPropertyNames
.getLength();
744 uno::Sequence
< beans::GetDirectPropertyTolerantResult
> aResult( nProps
);
745 beans::GetDirectPropertyTolerantResult
*pResult
= aResult
.getArray();
748 // get entry to start with
749 const SfxItemPropertyMap
&rPropMap
= m_rPropSet
.getPropertyMap();
751 for (const OUString
& rProp
: rPropertyNames
)
753 OSL_ENSURE( nIdx
< nProps
, "index out of bounds" );
754 beans::GetDirectPropertyTolerantResult
&rResult
= pResult
[nIdx
];
758 rResult
.Name
= rProp
;
760 SfxItemPropertyMapEntry
const*const pEntry
=
761 rPropMap
.getByName( rProp
);
762 if (!pEntry
) // property available?
765 beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY
;
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
;
776 rResult
.Result
= beans::TolerantPropertySetResultType::UNKNOWN_FAILURE
;
777 if (!bDirectValuesOnly
||
778 (beans::PropertyState_DIRECT_VALUE
== eState
))
780 // get property value
781 // (compare to SwXParagraph::getPropertyValue(s))
783 if (! ::sw::GetDefaultTextContentValue(
784 aValue
, rProp
, pEntry
->nWID
) )
786 SwPosition
aPos( rTextNode
);
788 // handle properties that are not part of the attribute
789 // and thus only pretended to be paragraph attributes
790 beans::PropertyState eTemp
;
792 SwUnoCursorHelper::getCursorPropertyValue(
793 *pEntry
, aPam
, &aValue
, eTemp
, &rTextNode
);
795 // if not found try the real paragraph attributes...
798 GetSinglePropertyValue_Impl(*pEntry
, rValueAttrSet
, aValue
);
802 rResult
.Value
= aValue
;
803 rResult
.Result
= beans::TolerantPropertySetResultType::SUCCESS
;
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" );
813 catch (beans::UnknownPropertyException
&)
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
;
819 catch (lang::IllegalArgumentException
&)
821 rResult
.Result
= beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT
;
823 catch (beans::PropertyVetoException
&)
825 rResult
.Result
= beans::TolerantPropertySetResultType::PROPERTY_VETO
;
827 catch (lang::WrappedTargetException
&)
829 rResult
.Result
= beans::TolerantPropertySetResultType::WRAPPED_TARGET
;
833 // resize to actually used size
834 aResult
.realloc( nIdx
);
839 bool ::sw::GetDefaultTextContentValue(
840 uno::Any
& rAny
, std::u16string_view rPropertyName
, sal_uInt16 nWID
)
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
;
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
};
870 SwXParagraph::addPropertyChangeListener(
871 const OUString
& /*rPropertyName*/,
872 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
874 OSL_FAIL("SwXParagraph::addPropertyChangeListener(): not implemented");
878 SwXParagraph::removePropertyChangeListener(
879 const OUString
& /*rPropertyName*/,
880 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
882 OSL_FAIL("SwXParagraph::removePropertyChangeListener(): not implemented");
886 SwXParagraph::addVetoableChangeListener(
887 const OUString
& /*rPropertyName*/,
888 const uno::Reference
< beans::XVetoableChangeListener
>& /*xListener*/)
890 OSL_FAIL("SwXParagraph::addVetoableChangeListener(): not implemented");
894 SwXParagraph::removeVetoableChangeListener(
895 const OUString
& /*rPropertyName*/,
896 const uno::Reference
< beans::XVetoableChangeListener
>& /*xListener*/)
898 OSL_FAIL("SwXParagraph::removeVetoableChangeListener(): not implemented");
901 static beans::PropertyState
lcl_SwXParagraph_getPropertyState(
902 const SwTextNode
& rTextNode
,
903 const SwAttrSet
** ppSet
,
904 const SfxItemPropertyMapEntry
& rEntry
,
905 bool &rAttrSetFetched
)
907 beans::PropertyState
eRet(beans::PropertyState_DEFAULT_VALUE
);
909 if(!(*ppSet
) && !rAttrSetFetched
)
911 (*ppSet
) = rTextNode
.GetpSwAttrSet();
912 rAttrSetFetched
= true;
915 SwPosition
aPos(rTextNode
);
921 case FN_UNO_NUM_RULES
:
923 // if numbering is set, return it; else do nothing
924 SwUnoCursorHelper::getNumberingProperty(aPam
,eRet
,nullptr);
928 case FN_UNO_ANCHOR_TYPES
:
935 bDone
= (MID_SURROUND_SURROUNDTYPE
== rEntry
.nMemberId
);
940 bDone
= (MID_ANCHOR_ANCHORTYPE
== rEntry
.nMemberId
);
943 case FN_UNO_PARA_STYLE
:
944 case FN_UNO_PARA_CONDITIONAL_STYLE_NAME
:
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
;
951 case FN_UNO_PAGE_STYLE
:
954 SwUnoCursorHelper::GetCurPageStyle( aPam
, sVal
);
955 eRet
= !sVal
.isEmpty() ? beans::PropertyState_DIRECT_VALUE
956 : beans::PropertyState_AMBIGUOUS_VALUE
;
961 // DrawingLayer PropertyStyle support
962 case OWN_ATTR_FILLBMP_MODE
:
966 if(SfxItemState::SET
== (*ppSet
)->GetItemState(XATTR_FILLBMP_STRETCH
, false)
967 || SfxItemState::SET
== (*ppSet
)->GetItemState(XATTR_FILLBMP_TILE
, false))
969 eRet
= beans::PropertyState_DIRECT_VALUE
;
973 eRet
= beans::PropertyState_AMBIGUOUS_VALUE
;
984 if (SWUnoHelper::needToMapFillItemsToSvxBrushItemTypes(**ppSet
,
987 eRet
= beans::PropertyState_DIRECT_VALUE
;
997 if((*ppSet
) && SfxItemState::SET
== (*ppSet
)->GetItemState(rEntry
.nWID
, false))
999 eRet
= beans::PropertyState_DIRECT_VALUE
;
1006 beans::PropertyState SAL_CALL
1007 SwXParagraph::getPropertyState(const OUString
& rPropertyName
)
1009 SolarMutexGuard aGuard
;
1011 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
1013 const SwAttrSet
* pSet
= nullptr;
1014 SfxItemPropertyMapEntry
const*const pEntry
=
1015 m_pImpl
->m_rPropSet
.getPropertyMap().getByName(rPropertyName
);
1018 throw beans::UnknownPropertyException(
1019 "Unknown property: " + rPropertyName
,
1020 static_cast<cppu::OWeakObject
*>(this));
1022 bool bDummy
= false;
1023 const beans::PropertyState eRet
=
1024 lcl_SwXParagraph_getPropertyState(rTextNode
, &pSet
, *pEntry
, bDummy
);
1028 uno::Sequence
< beans::PropertyState
> SAL_CALL
1029 SwXParagraph::getPropertyStates(
1030 const uno::Sequence
< OUString
>& PropertyNames
)
1032 SolarMutexGuard aGuard
;
1034 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
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;
1043 for (sal_Int32 i
= 0, nEnd
= PropertyNames
.getLength(); i
< nEnd
;
1044 ++i
, ++pStates
, ++pNames
)
1046 SfxItemPropertyMapEntry
const*const pEntry
=
1047 rMap
.getByName( *pNames
);
1050 throw beans::UnknownPropertyException(
1051 "Unknown property: " + *pNames
,
1052 static_cast<cppu::OWeakObject
*>(this));
1055 if (bAttrSetFetched
&& !pSet
&& isATR(pEntry
->nWID
))
1057 *pStates
= beans::PropertyState_DEFAULT_VALUE
;
1061 *pStates
= lcl_SwXParagraph_getPropertyState(
1062 rTextNode
, &pSet
, *pEntry
, bAttrSetFetched
);
1070 SwXParagraph::setPropertyToDefault(const OUString
& rPropertyName
)
1072 SolarMutexGuard aGuard
;
1074 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
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
)
1086 SwParaSelection
aParaSel( aCursor
);
1087 SfxItemPropertyMapEntry
const*const pEntry
=
1088 m_pImpl
->m_rPropSet
.getPropertyMap().getByName( rPropertyName
);
1091 throw beans::UnknownPropertyException(
1092 "Unknown property: " + rPropertyName
,
1093 static_cast<cppu::OWeakObject
*>(this));
1096 if (pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1098 throw uno::RuntimeException(
1099 "Property is read-only: " + rPropertyName
,
1100 static_cast<cppu::OWeakObject
*>(this));
1103 const bool bBelowFrameAtrEnd(pEntry
->nWID
< RES_FRMATR_END
);
1104 const bool bDrawingLayerRange(XATTR_FILL_FIRST
<= pEntry
->nWID
&& XATTR_FILL_LAST
>= pEntry
->nWID
);
1106 if(bBelowFrameAtrEnd
|| bDrawingLayerRange
)
1108 o3tl::sorted_vector
<sal_uInt16
> aWhichIds
;
1110 // For FillBitmapMode two IDs have to be reset (!)
1111 if(OWN_ATTR_FILLBMP_MODE
== pEntry
->nWID
)
1113 aWhichIds
.insert(XATTR_FILLBMP_STRETCH
);
1114 aWhichIds
.insert(XATTR_FILLBMP_TILE
);
1118 aWhichIds
.insert(pEntry
->nWID
);
1121 if (pEntry
->nWID
< RES_PARATR_BEGIN
)
1123 aCursor
.GetDoc().ResetAttrs(aCursor
, true, aWhichIds
);
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
))
1134 pTemp
->MovePara(GoCurrPara
, fnParaStart
);
1138 *pTemp
->GetPoint() = aEnd
;
1140 SwUnoCursorHelper::SelectPam(*pTemp
, true);
1142 if (!SwUnoCursorHelper::IsEndOfPara(*pTemp
))
1144 pTemp
->MovePara(GoCurrPara
, fnParaEnd
);
1148 pTemp
->GetDoc().ResetAttrs(*pTemp
, true, aWhichIds
);
1153 SwUnoCursorHelper::resetCursorPropertyValue(*pEntry
, aCursor
);
1158 SwXParagraph::getPropertyDefault(const OUString
& rPropertyName
)
1162 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
1165 if (::sw::GetDefaultTextContentValue(aRet
, rPropertyName
))
1170 SfxItemPropertyMapEntry
const*const pEntry
=
1171 m_pImpl
->m_rPropSet
.getPropertyMap().getByName(rPropertyName
);
1174 throw beans::UnknownPropertyException(
1175 "Unknown property: " + rPropertyName
,
1176 static_cast<cppu::OWeakObject
*>(this));
1179 const bool bBelowFrameAtrEnd(pEntry
->nWID
< RES_FRMATR_END
);
1180 const bool bDrawingLayerRange(XATTR_FILL_FIRST
<= pEntry
->nWID
&& XATTR_FILL_LAST
>= pEntry
->nWID
);
1182 if(bBelowFrameAtrEnd
|| bDrawingLayerRange
)
1184 const SfxPoolItem
& rDefItem
= rTextNode
.GetDoc().GetAttrPool().GetDefaultItem(pEntry
->nWID
);
1186 rDefItem
.QueryValue(aRet
, pEntry
->nMemberId
);
1193 SwXParagraph::attach(const uno::Reference
< text::XTextRange
> & /*xTextRange*/)
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();
1202 uno::Reference
< text::XTextRange
> SAL_CALL
1203 SwXParagraph::getAnchor()
1205 SolarMutexGuard aGuard
;
1207 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
1209 SwPosition
aPos( rTextNode
);
1210 SwCursor
aCursor( aPos
, nullptr );
1212 SwParaSelection
aParaSel( aCursor
);
1213 const uno::Reference
< text::XTextRange
> xRet
=
1214 new SwXTextRange(aCursor
, m_pImpl
->m_xParentText
);
1218 void SAL_CALL
SwXParagraph::dispose()
1220 SolarMutexGuard aGuard
;
1222 SwTextNode
*const pTextNode( m_pImpl
->GetTextNode() );
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
);
1232 void SAL_CALL
SwXParagraph::addEventListener(
1233 const uno::Reference
< lang::XEventListener
> & xListener
)
1235 // no need to lock here as m_pImpl is const and container threadsafe
1236 m_pImpl
->m_EventListeners
.addInterface(xListener
);
1239 void SAL_CALL
SwXParagraph::removeEventListener(
1240 const uno::Reference
< lang::XEventListener
> & xListener
)
1242 // no need to lock here as m_pImpl is const and container threadsafe
1243 m_pImpl
->m_EventListeners
.removeInterface(xListener
);
1246 uno::Reference
< container::XEnumeration
> SAL_CALL
1247 SwXParagraph::createEnumeration()
1249 SolarMutexGuard aGuard
;
1251 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
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
);
1261 uno::Type SAL_CALL
SwXParagraph::getElementType()
1263 return cppu::UnoType
<text::XTextRange
>::get();
1266 sal_Bool SAL_CALL
SwXParagraph::hasElements()
1268 SolarMutexGuard aGuard
;
1269 return GetTextNode() != nullptr;
1272 uno::Reference
< text::XText
> SAL_CALL
1273 SwXParagraph::getText()
1277 return m_pImpl
->m_xParentText
;
1280 uno::Reference
< text::XTextRange
> SAL_CALL
1281 SwXParagraph::getStart()
1283 SolarMutexGuard aGuard
;
1285 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
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
);
1297 uno::Reference
< text::XTextRange
> SAL_CALL
1298 SwXParagraph::getEnd()
1300 SolarMutexGuard aGuard
;
1302 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
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
);
1314 OUString SAL_CALL
SwXParagraph::getString()
1316 SolarMutexGuard aGuard
;
1318 SwTextNode
const*const pTextNode( GetTextNode() );
1321 SwPosition
aPos( *pTextNode
);
1322 SwCursor
aCursor( aPos
, nullptr );
1323 SwParaSelection
aParaSel( aCursor
);
1324 SwUnoCursorHelper::GetTextFromPam(aCursor
, aRet
);
1326 else if (m_pImpl
->IsDescriptor())
1328 aRet
= m_pImpl
->m_sText
;
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.");
1339 void SAL_CALL
SwXParagraph::setString(const OUString
& aString
)
1341 SolarMutexGuard aGuard
;
1343 SwTextNode
const*const pTextNode( GetTextNode() );
1346 SwPosition
aPos( *pTextNode
);
1347 SwCursor
aCursor( aPos
, nullptr );
1348 if (!SwUnoCursorHelper::IsStartOfPara(aCursor
)) {
1349 aCursor
.MovePara(GoCurrPara
, fnParaStart
);
1351 SwUnoCursorHelper::SelectPam(aCursor
, true);
1352 if (pTextNode
->GetText().getLength()) {
1353 aCursor
.MovePara(GoCurrPara
, fnParaEnd
);
1355 SwUnoCursorHelper::SetString(aCursor
, aString
);
1356 SwUnoCursorHelper::SelectPam(aCursor
, false);
1358 else if (m_pImpl
->IsDescriptor())
1360 m_pImpl
->m_sText
= aString
;
1364 throw uno::RuntimeException();
1368 uno::Reference
< container::XEnumeration
> SAL_CALL
1369 SwXParagraph::createContentEnumeration(const OUString
& rServiceName
)
1373 if ( rServiceName
!= "com.sun.star.text.TextContent" )
1375 throw uno::RuntimeException();
1378 SwTextNode
& rTextNode(m_pImpl
->GetTextNodeOrThrow());
1380 SwPosition
aPos( rTextNode
);
1382 uno::Reference
< container::XEnumeration
> xRet
=
1383 SwXParaFrameEnumeration::Create(aPam
, PARAFRAME_PORTION_PARAGRAPH
);
1387 uno::Sequence
< OUString
> SAL_CALL
1388 SwXParagraph::getAvailableServiceNames()
1390 uno::Sequence
<OUString
> aRet
{ "com.sun.star.text.TextContent" };
1395 ::sfx2::Metadatable
* SwXParagraph::GetCoreObject()
1397 SwTextNode
*const pTextNode( m_pImpl
->GetTextNode() );
1401 uno::Reference
<frame::XModel
> SwXParagraph::GetModel()
1403 SwTextNode
*const pTextNode( m_pImpl
->GetTextNode() );
1406 SwDocShell
const*const pShell( pTextNode
->GetDoc().GetDocShell() );
1407 return pShell
? pShell
->GetModel() : nullptr;
1412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */