/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
SwParaSelection::SwParaSelection(SwCursor & rCursor)
: m_rCursor(rCursor)
{ if (m_rCursor.HasMark())
{
m_rCursor.DeleteMark();
} // is it at the start? if (m_rCursor.GetPoint()->GetContentIndex() != 0)
{
m_rCursor.MovePara(GoCurrPara, fnParaStart);
} // or at the end already? if (m_rCursor.GetPoint()->GetContentIndex() != m_rCursor.GetPointContentNode()->Len())
{
m_rCursor.SetMark();
m_rCursor.MovePara(GoCurrPara, fnParaEnd);
}
}
SwTextNode& SwXParagraph::GetTextNodeOrThrow()
{ if (!m_pTextNode) { throw uno::RuntimeException(u"SwXParagraph: disposed or invalid"_ustr, nullptr);
} return *m_pTextNode;
}
void SwXParagraph::MySvtListener::Notify(const SfxHint& rHint)
{ if(rHint.GetId() == SfxHintId::Dying)
{
m_rThis.m_pTextNode = nullptr;
std::unique_lock aGuard(m_rThis.m_Mutex); if (m_rThis.m_EventListeners.getLength(aGuard) != 0)
{ // fdo#72695: if UNO object is already dead, don't revive it with event // The specific pattern we are guarding against is this: // [1] Thread1 takes the SolarMutex // [2] Thread2 decrements the SwXParagraph reference count, and calls the // SwXParagraph destructor, which tries to take the SolarMutex, and blocks // [3] Thread1 destroys a SwTextNode, which calls this Notify event, which results // in a double-free if we construct the xThis object. if (m_rThis.m_refCount == 0)
{ // fdo#72695: if UNO object is already dead, don't revive it with event return;
}
lang::EventObject const ev(static_cast<cppu::OWeakObject*>(&m_rThis));
m_rThis.m_EventListeners.disposeAndClear(aGuard, ev);
}
}
}
SwXParagraph::~SwXParagraph()
{ // need to hold solar mutex while destructing SvtListener
SolarMutexGuard aGuard;
moSvtListener.reset();
}
rtl::Reference<SwXParagraph>
SwXParagraph::CreateXParagraph(SwDoc & rDoc, SwTextNode *const pTextNode,
css::uno::Reference< SwXText> const& i_xParent, const sal_Int32 nSelStart, const sal_Int32 nSelEnd)
{ // re-use existing SwXParagraph // #i105557#: do not iterate over the registered clients: race condition
rtl::Reference<SwXParagraph> xParagraph; if (pTextNode && (-1 == nSelStart) && (-1 == nSelEnd))
{ // only use cache if no selection!
xParagraph = pTextNode->GetXParagraph();
} if (xParagraph.is())
{ return xParagraph;
}
// create new SwXParagraph
css::uno::Reference<SwXText> xParentText(i_xParent); if (!xParentText.is() && pTextNode)
{
SwPosition Pos(*pTextNode);
xParentText = ::sw::CreateParentXText( rDoc, Pos );
}
SwXParagraph *const pXPara( pTextNode
? new SwXParagraph(xParentText, *pTextNode, nSelStart, nSelEnd)
: new SwXParagraph); // this is why the constructor is private: need to acquire pXPara here
xParagraph.set(pXPara); // in order to initialize the weak pointer cache in the core object if (pTextNode && (-1 == nSelStart) && (-1 == nSelEnd))
{
pTextNode->SetXParagraph(xParagraph);
} return xParagraph;
}
void
SwXParagraph::attachToText(SwXText & rParent, SwTextNode & rTextNode)
{
OSL_ENSURE(m_bIsDescriptor, "Paragraph is not a descriptor"); if (!m_bIsDescriptor) return;
void SAL_CALL SwXParagraph::setPropertyValues( const uno::Sequence< OUString >& rPropertyNames, const uno::Sequence< uno::Any >& rValues )
{ if (rPropertyNames.getLength() != rValues.getLength()) throw lang::IllegalArgumentException(u"lengths do not match"_ustr,
getXWeak(), -1);
SolarMutexGuard aGuard;
// workaround for bad designed API try
{
SetPropertyValues_Impl( rPropertyNames, rValues );
} catch (const beans::UnknownPropertyException &rException)
{ // wrap the original (here not allowed) exception in // a lang::WrappedTargetException that gets thrown instead.
lang::WrappedTargetException aWExc;
aWExc.TargetException <<= rException; throw aWExc;
}
}
// Support for DrawingLayer FillStyles for GetPropertyValue() usages // static void SwXParagraph::GetSinglePropertyValue_Impl( const SfxItemPropertyMapEntry& rEntry, const SfxItemSet& rSet,
uno::Any& rAny )
{ bool bDone(false);
switch(rEntry.nWID)
{ case RES_BACKGROUND:
{ const std::unique_ptr<SvxBrushItem> aOriginalBrushItem(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND));
// fallback to standard get value implementation used before this helper was created
SfxItemPropertySet::getPropertyValue(rEntry, rSet, rAny);
if(rEntry.aType == cppu::UnoType<sal_Int16>::get() && rEntry.aType != rAny.getValueType())
{ // since the sfx uInt16 item now exports a sal_Int32, we may have to fix this here
sal_Int32 nValue(0);
if (rAny >>= nValue)
{
rAny <<= static_cast<sal_Int16>(nValue);
}
}
// check for needed metric translation if(!(rEntry.nMoreFlags & PropertyMoreFlags::METRIC_ITEM)) return;
bool bDoIt(true);
if(XATTR_FILLBMP_SIZEX == rEntry.nWID || XATTR_FILLBMP_SIZEY == rEntry.nWID)
{ // exception: If these ItemTypes are used, do not convert when these are negative // since this means they are intended as percent values
sal_Int32 nValue = 0;
uno::Sequence< uno::Any > aValues(rPropertyNames.getLength());
SwPaM aPam( rTextNode );
uno::Any* pValues = aValues.getArray(); const OUString* pPropertyNames = rPropertyNames.getConstArray(); const SfxItemPropertyMap &rMap = m_rPropSet.getPropertyMap(); const SwAttrSet& rAttrSet( rTextNode.GetSwAttrSet() ); for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
{ if (pPropertyNames[nProp] == "ParaMarkerAutoStyleSpan")
{ // A hack to tunnel the fake text span to ODF export // see XMLTextParagraphExport::exportParagraph if (rTextNode.GetAttr(RES_PARATR_LIST_AUTOFMT).GetStyleHandle())
{
SwUnoCursor aEndCursor(*aPam.GetMark());
css::uno::Reference<css::beans::XPropertySet> xFakeSpan( new SwXTextPortion(&aEndCursor, {}, PORTION_LIST_AUTOFMT));
pValues[nProp] <<= xFakeSpan;
} continue;
}
if (pPropertyNames[nProp] == "ODFExport_NodeIndex")
{ // A hack to avoid writing random list ids to ODF when they are not referred later // see XMLTextParagraphExport::DocumentListNodes::ShouldSkipListId
pValues[nProp] <<= rTextNode.GetIndex().get(); continue;
}
if (pPropertyNames[nProp] == "OOXMLImport_AnchoredShapes")
{ // A hack to provide list of anchored objects fast // See reanchorObjects in writerfilter/source/dmapper/DomainMapper_Impl.cxx
FrameClientSortList_t aFrames;
CollectFrameAtNode(rTextNode, aFrames, false); // Frames anchored to paragraph
CollectFrameAtNode(rTextNode, aFrames, true); // Frames anchored to character
std::vector<uno::Reference<text::XTextContent>> aRet;
aRet.reserve(aFrames.size()); for (constauto& rFrame : aFrames) if (auto xContent = FrameClientToXTextContent(rFrame.pFrameClient.get()))
aRet.push_back(xContent);
// copy temporary result to final result type const sal_Int32 nLen = aTmpRes.getLength();
uno::Sequence< beans::GetPropertyTolerantResult > aRes( nLen );
std::copy(aTmpRes.begin(), aTmpRes.end(), aRes.getArray()); return aRes;
}
// #i46786# Use SwAttrSet pointer for determining the state. // Use the value SwAttrSet (from the paragraph OR the style) // for determining the actual value(s). const SwAttrSet* pAttrSet = rTextNode.GetpSwAttrSet(); const SwAttrSet& rValueAttrSet = rTextNode.GetSwAttrSet();
rResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_FAILURE; if (!bDirectValuesOnly ||
(beans::PropertyState_DIRECT_VALUE == eState))
{ // get property value // (compare to SwXParagraph::getPropertyValue(s))
uno::Any aValue; if (! ::sw::GetDefaultTextContentValue(
aValue, rProp, pEntry->nWID ) )
{
SwPaM aPam( rTextNode ); // handle properties that are not part of the attribute // and thus only pretending to be paragraph attributes
beans::PropertyState eTemp; constbool bDone =
SwUnoCursorHelper::getCursorPropertyValue(
*pEntry, aPam, &aValue, eTemp, &rTextNode );
// if not found try the real paragraph attributes... if (!bDone)
{
GetSinglePropertyValue_Impl(*pEntry, rValueAttrSet, aValue);
}
}
// For FillBitmapMode two IDs have to be reset (!) if(OWN_ATTR_FILLBMP_MODE == pEntry->nWID)
{
aWhichIds.insert(XATTR_FILLBMP_STRETCH);
aWhichIds.insert(XATTR_FILLBMP_TILE);
} else
{
aWhichIds.insert(pEntry->nWID);
}
if (pEntry->nWID < RES_PARATR_BEGIN)
{
aCursor.GetDoc().ResetAttrs(aCursor, true, aWhichIds);
} else
{ // for paragraph attributes the selection must be extended // to paragraph boundaries
SwPosition aStart( *aCursor.Start() );
SwPosition aEnd ( *aCursor.End() ); auto pTemp( aCursor.GetDoc().CreateUnoCursor(aStart) ); if(!SwUnoCursorHelper::IsStartOfPara(*pTemp))
{
pTemp->MovePara(GoCurrPara, fnParaStart);
}
void SAL_CALL
SwXParagraph::attach(const uno::Reference< text::XTextRange > & /*xTextRange*/)
{ // SwXParagraph will only created in order to be inserted by // 'insertTextContentBefore' or 'insertTextContentAfter' therefore // they cannot be attached throw uno::RuntimeException();
}
void SAL_CALL SwXParagraph::addEventListener( const uno::Reference< lang::XEventListener > & xListener)
{ // no need to lock here as m_pImpl is const and container threadsafe
std::unique_lock aGuard(m_Mutex);
m_EventListeners.addInterface(aGuard, xListener);
}
void SAL_CALL SwXParagraph::removeEventListener( const uno::Reference< lang::XEventListener > & xListener)
{ // no need to lock here as m_pImpl is const and container threadsafe
std::unique_lock aGuard(m_Mutex);
m_EventListeners.removeInterface(aGuard, xListener);
}
/// tries to return less data, but may return more than just text fields
rtl::Reference< SwXTextPortionEnumeration >
SwXParagraph::createTextFieldsEnumeration()
{
SolarMutexGuard aGuard;
OUString SAL_CALL SwXParagraph::getString()
{
SolarMutexGuard aGuard;
OUString aRet;
SwTextNode const*const pTextNode( GetTextNode() ); if (pTextNode)
{
SwPosition aPos( *pTextNode );
SwCursor aCursor( aPos, nullptr );
SwParaSelection aParaSel( aCursor );
SwUnoCursorHelper::GetTextFromPam(aCursor, aRet);
} elseif (IsDescriptor())
{
aRet = m_sText;
} else
{ // Seems object is being disposed or some other problem occurs. // Anyway from user point of view object still exist, so on that level this is not an error
SAL_WARN("sw.uno", "getString() for invalid paragraph called. Returning empty string.");
} return aRet;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.