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