Aha, now we know that the reason for the defensive programming in lcl_AssureFieldMarksSet() was that there are actually 2 different use-cases for it: usually a new mark is inserted, so there are no dummy characters and they must be inserted. However when copying text, the dummy characters are copied too, so they must not be inserted, or we get duplicate fieldmarks. This also reverts commitd4036d3a89
which fixed the problem only for CHECKBOX_FIELDMARK in a different way. (regression frombb069fe7b8
) Change-Id: I3c99b8c6d720951655198e682018794337859373
1737 lines
54 KiB
C++
1737 lines
54 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <utility>
|
|
|
|
#include <rtl/ustrbuf.hxx>
|
|
#include <swtypes.hxx>
|
|
#include <hintids.hxx>
|
|
#include <cmdid.h>
|
|
#include <hints.hxx>
|
|
#include <IMark.hxx>
|
|
#include <bookmrk.hxx>
|
|
#include <frmfmt.hxx>
|
|
#include <doc.hxx>
|
|
#include <IDocumentUndoRedo.hxx>
|
|
#include <IDocumentLayoutAccess.hxx>
|
|
#include <textboxhelper.hxx>
|
|
#include <ndtxt.hxx>
|
|
#include <ndnotxt.hxx>
|
|
#include <unocrsr.hxx>
|
|
#include <swundo.hxx>
|
|
#include <rootfrm.hxx>
|
|
#include <flyfrm.hxx>
|
|
#include <ftnidx.hxx>
|
|
#include <sfx2/linkmgr.hxx>
|
|
#include <docary.hxx>
|
|
#include <paratr.hxx>
|
|
#include <pam.hxx>
|
|
#include <shellio.hxx>
|
|
#include <swerror.h>
|
|
#include <swtblfmt.hxx>
|
|
#include <docsh.hxx>
|
|
#include <docstyle.hxx>
|
|
#include <charfmt.hxx>
|
|
#include <txtfld.hxx>
|
|
#include <fmtfld.hxx>
|
|
#include <fmtpdsc.hxx>
|
|
#include <pagedesc.hxx>
|
|
#include <strings.hrc>
|
|
#include <poolfmt.hxx>
|
|
#include <edimp.hxx>
|
|
#include <fchrfmt.hxx>
|
|
#include <cntfrm.hxx>
|
|
#include <pagefrm.hxx>
|
|
#include <doctxm.hxx>
|
|
#include <sfx2/docfilt.hxx>
|
|
#include <sfx2/docfile.hxx>
|
|
#include <sfx2/fcontnr.hxx>
|
|
#include <fmtrfmrk.hxx>
|
|
#include <txtrfmrk.hxx>
|
|
#include <unoparaframeenum.hxx>
|
|
#include <unofootnote.hxx>
|
|
#include <unotextbodyhf.hxx>
|
|
#include <unotextrange.hxx>
|
|
#include <unoparagraph.hxx>
|
|
#include <unomap.hxx>
|
|
#include <unoport.hxx>
|
|
#include <unocrsrhelper.hxx>
|
|
#include <unosett.hxx>
|
|
#include <unoprnms.hxx>
|
|
#include <unotbl.hxx>
|
|
#include <unodraw.hxx>
|
|
#include <unocoll.hxx>
|
|
#include <unostyle.hxx>
|
|
#include <fmtanchr.hxx>
|
|
#include <editeng/flstitem.hxx>
|
|
#include <editeng/unolingu.hxx>
|
|
#include <svtools/ctrltool.hxx>
|
|
#include <flypos.hxx>
|
|
#include <txtftn.hxx>
|
|
#include <fmtftn.hxx>
|
|
#include <fmtcntnt.hxx>
|
|
#include <com/sun/star/text/WrapTextMode.hpp>
|
|
#include <com/sun/star/text/TextContentAnchorType.hpp>
|
|
#include <com/sun/star/style/PageStyleLayout.hpp>
|
|
#include <com/sun/star/text/XTextDocument.hpp>
|
|
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
|
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
|
|
#include <unoframe.hxx>
|
|
#include <fmthdft.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <fmtflcnt.hxx>
|
|
#include <editeng/brushitem.hxx>
|
|
#include <fmtclds.hxx>
|
|
#include <dcontact.hxx>
|
|
#include <dflyobj.hxx>
|
|
#include <vector>
|
|
#include <sortedobjs.hxx>
|
|
#include <sortopt.hxx>
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <calbck.hxx>
|
|
#include <comphelper/servicehelper.hxx>
|
|
#include <cppuhelper/supportsservice.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
namespace sw {
|
|
|
|
uno::Sequence< OUString >
|
|
GetSupportedServiceNamesImpl(
|
|
size_t const nServices, char const*const pServices[])
|
|
{
|
|
uno::Sequence< OUString > ret(nServices);
|
|
for (size_t i = 0; i < nServices; ++i)
|
|
{
|
|
ret[i] = OUString::createFromAscii(pServices[i]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace sw
|
|
|
|
namespace sw {
|
|
|
|
void DeepCopyPaM(SwPaM const & rSource, SwPaM & rTarget)
|
|
{
|
|
rTarget = rSource;
|
|
|
|
if (rSource.GetNext() != &rSource)
|
|
{
|
|
SwPaM *pPam = const_cast<SwPaM*>(rSource.GetNext());
|
|
do
|
|
{
|
|
// create new PaM
|
|
SwPaM *const pNew = new SwPaM(*pPam, nullptr);
|
|
// insert into ring
|
|
pNew->MoveTo(&rTarget);
|
|
pPam = pPam->GetNext();
|
|
}
|
|
while (pPam != &rSource);
|
|
}
|
|
}
|
|
|
|
} // namespace sw
|
|
|
|
struct FrameClientSortListLess
|
|
{
|
|
bool operator() (FrameClientSortListEntry const& r1,
|
|
FrameClientSortListEntry const& r2) const
|
|
{
|
|
return (r1.nIndex < r2.nIndex)
|
|
|| ((r1.nIndex == r2.nIndex) && (r1.nOrder < r2.nOrder));
|
|
}
|
|
};
|
|
|
|
namespace
|
|
{
|
|
void lcl_CollectFrameAtNodeWithLayout(const SwContentFrame* pCFrame,
|
|
FrameClientSortList_t& rFrames,
|
|
const RndStdIds nAnchorType)
|
|
{
|
|
auto pObjs = pCFrame->GetDrawObjs();
|
|
if(!pObjs)
|
|
return;
|
|
for(const auto pAnchoredObj : *pObjs)
|
|
{
|
|
SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
|
|
// Filter out textboxes, which are not interesting at an UNO level.
|
|
if(SwTextBoxHelper::isTextBox(&rFormat, RES_FLYFRMFMT))
|
|
continue;
|
|
if(rFormat.GetAnchor().GetAnchorId() == nAnchorType)
|
|
{
|
|
const auto nIdx =
|
|
rFormat.GetAnchor().GetContentAnchor()->nContent.GetIndex();
|
|
const auto nOrder = rFormat.GetAnchor().GetOrder();
|
|
FrameClientSortListEntry entry(nIdx, nOrder, new sw::FrameClient(&rFormat));
|
|
rFrames.push_back(entry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CollectFrameAtNode( const SwNodeIndex& rIdx,
|
|
FrameClientSortList_t& rFrames,
|
|
const bool bAtCharAnchoredObjs )
|
|
{
|
|
// _bAtCharAnchoredObjs:
|
|
// <true>: at-character anchored objects are collected
|
|
// <false>: at-paragraph anchored objects are collected
|
|
|
|
// search all borders, images, and OLEs that are connected to the paragraph
|
|
SwDoc* pDoc = rIdx.GetNode().GetDoc();
|
|
|
|
const auto nChkType = bAtCharAnchoredObjs ? RndStdIds::FLY_AT_CHAR : RndStdIds::FLY_AT_PARA;
|
|
const SwContentFrame* pCFrame;
|
|
const SwContentNode* pCNd;
|
|
if( pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() &&
|
|
nullptr != (pCNd = rIdx.GetNode().GetContentNode()) &&
|
|
nullptr != (pCFrame = pCNd->getLayoutFrame( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())) )
|
|
{
|
|
lcl_CollectFrameAtNodeWithLayout(pCFrame, rFrames, nChkType);
|
|
}
|
|
else
|
|
{
|
|
const SwFrameFormats& rFormats = *pDoc->GetSpzFrameFormats();
|
|
const size_t nSize = rFormats.size();
|
|
for ( size_t i = 0; i < nSize; i++)
|
|
{
|
|
const SwFrameFormat* pFormat = rFormats[ i ];
|
|
const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
|
|
const SwPosition* pAnchorPos;
|
|
if( rAnchor.GetAnchorId() == nChkType &&
|
|
nullptr != (pAnchorPos = rAnchor.GetContentAnchor()) &&
|
|
pAnchorPos->nNode == rIdx )
|
|
{
|
|
|
|
// OD 2004-05-07 #i28701# - determine insert position for
|
|
// sorted <rFrameArr>
|
|
const sal_Int32 nIndex = pAnchorPos->nContent.GetIndex();
|
|
sal_uInt32 nOrder = rAnchor.GetOrder();
|
|
|
|
FrameClientSortListEntry entry(nIndex, nOrder, new sw::FrameClient(const_cast<SwFrameFormat*>(pFormat)));
|
|
rFrames.push_back(entry);
|
|
}
|
|
}
|
|
std::sort(rFrames.begin(), rFrames.end(), FrameClientSortListLess());
|
|
}
|
|
}
|
|
|
|
UnoActionContext::UnoActionContext(SwDoc *const pDoc)
|
|
: m_pDoc(pDoc)
|
|
{
|
|
SwRootFrame *const pRootFrame = m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
|
if (pRootFrame)
|
|
{
|
|
pRootFrame->StartAllAction();
|
|
}
|
|
}
|
|
|
|
UnoActionContext::~UnoActionContext() COVERITY_NOEXCEPT_FALSE
|
|
{
|
|
// Doc may already have been removed here
|
|
if (m_pDoc)
|
|
{
|
|
SwRootFrame *const pRootFrame = m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
|
if (pRootFrame)
|
|
{
|
|
pRootFrame->EndAllAction();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void lcl_RemoveImpl(SwDoc *const pDoc)
|
|
{
|
|
assert(pDoc);
|
|
SwRootFrame *const pRootFrame = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
|
if (pRootFrame)
|
|
{
|
|
pRootFrame->UnoRemoveAllActions();
|
|
}
|
|
}
|
|
|
|
UnoActionRemoveContext::UnoActionRemoveContext(SwDoc *const pDoc)
|
|
: m_pDoc(pDoc)
|
|
{
|
|
lcl_RemoveImpl(m_pDoc);
|
|
}
|
|
|
|
static SwDoc * lcl_IsNewStyleTable(SwUnoTableCursor const& rCursor)
|
|
{
|
|
SwTableNode *const pTableNode = rCursor.GetNode().FindTableNode();
|
|
return (pTableNode && !pTableNode->GetTable().IsNewModel())
|
|
? rCursor.GetDoc()
|
|
: nullptr;
|
|
}
|
|
|
|
UnoActionRemoveContext::UnoActionRemoveContext(SwUnoTableCursor const& rCursor)
|
|
: m_pDoc(lcl_IsNewStyleTable(rCursor))
|
|
{
|
|
// this insanity is only necessary for old-style tables
|
|
// because SwRootFrame::MakeTableCursors() creates the table cursor for these
|
|
if (m_pDoc)
|
|
{
|
|
lcl_RemoveImpl(m_pDoc);
|
|
}
|
|
}
|
|
|
|
UnoActionRemoveContext::~UnoActionRemoveContext()
|
|
{
|
|
if (m_pDoc)
|
|
{
|
|
SwRootFrame *const pRootFrame = m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
|
if (pRootFrame)
|
|
{
|
|
pRootFrame->UnoRestoreAllActions();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClientModify(SwClient* pClient, const SfxPoolItem *pOld, const SfxPoolItem *pNew)
|
|
{
|
|
switch( pOld ? pOld->Which() : 0 )
|
|
{
|
|
case RES_REMOVE_UNO_OBJECT:
|
|
case RES_OBJECTDYING:
|
|
if( static_cast<void*>(pClient->GetRegisteredIn()) == static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject )
|
|
pClient->GetRegisteredIn()->Remove(pClient);
|
|
break;
|
|
|
|
case RES_FMT_CHG:
|
|
// Is the move to the new one finished and will the old one be deleted?
|
|
if( static_cast<const SwFormatChg*>(pNew)->pChangedFormat == pClient->GetRegisteredIn() &&
|
|
static_cast<const SwFormatChg*>(pOld)->pChangedFormat->IsFormatInDTOR() )
|
|
pClient->GetRegisteredIn()->Remove(pClient);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SwUnoCursorHelper::SetCursorAttr(SwPaM & rPam,
|
|
const SfxItemSet& rSet,
|
|
const SetAttrMode nAttrMode, const bool bTableMode)
|
|
{
|
|
const SetAttrMode nFlags = nAttrMode | SetAttrMode::APICALL;
|
|
SwDoc* pDoc = rPam.GetDoc();
|
|
//StartEndAction
|
|
UnoActionContext aAction(pDoc);
|
|
if (rPam.GetNext() != &rPam) // Ring of Cursors
|
|
{
|
|
pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSATTR, nullptr);
|
|
|
|
for(SwPaM& rCurrent : rPam.GetRingContainer())
|
|
{
|
|
if (rCurrent.HasMark() &&
|
|
( bTableMode ||
|
|
(*rCurrent.GetPoint() != *rCurrent.GetMark()) ))
|
|
{
|
|
pDoc->getIDocumentContentOperations().InsertItemSet(rCurrent, rSet, nFlags);
|
|
}
|
|
}
|
|
|
|
pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSATTR, nullptr);
|
|
}
|
|
else
|
|
{
|
|
pDoc->getIDocumentContentOperations().InsertItemSet( rPam, rSet, nFlags );
|
|
}
|
|
|
|
if( rSet.GetItemState( RES_PARATR_OUTLINELEVEL, false ) >= SfxItemState::DEFAULT )
|
|
{
|
|
SwTextNode * pTmpNode = rPam.GetNode().GetTextNode();
|
|
if ( pTmpNode )
|
|
{
|
|
rPam.GetDoc()->GetNodes().UpdateOutlineNode( *pTmpNode );
|
|
}
|
|
}
|
|
}
|
|
|
|
// #i63870#
|
|
// split third parameter <bCurrentAttrOnly> into new parameters <bOnlyTextAttr>
|
|
// and <bGetFromChrFormat> to get better control about resulting <SfxItemSet>
|
|
void SwUnoCursorHelper::GetCursorAttr(SwPaM & rPam,
|
|
SfxItemSet & rSet, const bool bOnlyTextAttr, const bool bGetFromChrFormat)
|
|
{
|
|
static const sal_uLong nMaxLookup = 1000;
|
|
SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
|
|
SfxItemSet *pSet = &rSet;
|
|
for(SwPaM& rCurrent : rPam.GetRingContainer())
|
|
{
|
|
SwPosition const & rStart( *rCurrent.Start() );
|
|
SwPosition const & rEnd( *rCurrent.End() );
|
|
const sal_uLong nSttNd = rStart.nNode.GetIndex();
|
|
const sal_uLong nEndNd = rEnd .nNode.GetIndex();
|
|
|
|
if (nEndNd - nSttNd >= nMaxLookup)
|
|
{
|
|
rSet.ClearItem();
|
|
rSet.InvalidateAllItems();
|
|
return;// uno::Any();
|
|
}
|
|
|
|
// the first node inserts the values into the get set
|
|
// all other nodes merge their values into the get set
|
|
for (sal_uLong n = nSttNd; n <= nEndNd; ++n)
|
|
{
|
|
SwNode *const pNd = rPam.GetDoc()->GetNodes()[ n ];
|
|
switch (pNd->GetNodeType())
|
|
{
|
|
case SwNodeType::Text:
|
|
{
|
|
const sal_Int32 nStart = (n == nSttNd)
|
|
? rStart.nContent.GetIndex() : 0;
|
|
const sal_Int32 nEnd = (n == nEndNd)
|
|
? rEnd.nContent.GetIndex()
|
|
: pNd->GetTextNode()->GetText().getLength();
|
|
pNd->GetTextNode()->GetAttr(*pSet, nStart, nEnd, bOnlyTextAttr, bGetFromChrFormat);
|
|
}
|
|
break;
|
|
|
|
case SwNodeType::Grf:
|
|
case SwNodeType::Ole:
|
|
static_cast<SwContentNode*>(pNd)->GetAttr( *pSet );
|
|
break;
|
|
|
|
default:
|
|
continue; // skip this node
|
|
}
|
|
|
|
if (pSet != &rSet)
|
|
{
|
|
rSet.MergeValues( aSet );
|
|
}
|
|
else
|
|
{
|
|
pSet = &aSet;
|
|
}
|
|
|
|
if (aSet.Count())
|
|
{
|
|
aSet.ClearItem();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct SwXParagraphEnumerationImpl final : public SwXParagraphEnumeration
|
|
{
|
|
uno::Reference< text::XText > const m_xParentText;
|
|
const CursorType m_eCursorType;
|
|
/// Start node of the cell _or_ table the enumeration belongs to.
|
|
/// Used to restrict the movement of the UNO cursor to the cell and its
|
|
/// embedded tables.
|
|
SwStartNode const*const m_pOwnStartNode;
|
|
SwTable const*const m_pOwnTable;
|
|
const sal_uLong m_nEndIndex;
|
|
sal_Int32 m_nFirstParaStart;
|
|
sal_Int32 m_nLastParaEnd;
|
|
bool m_bFirstParagraph;
|
|
uno::Reference< text::XTextContent > m_xNextPara;
|
|
sw::UnoCursorPointer m_pCursor;
|
|
|
|
SwXParagraphEnumerationImpl(
|
|
uno::Reference< text::XText > const& xParent,
|
|
const std::shared_ptr<SwUnoCursor>& pCursor,
|
|
const CursorType eType,
|
|
SwStartNode const*const pStartNode, SwTable const*const pTable)
|
|
: m_xParentText( xParent )
|
|
, m_eCursorType( eType )
|
|
// remember table and start node for later travelling
|
|
// (used in export of tables in tables)
|
|
, m_pOwnStartNode( pStartNode )
|
|
// for import of tables in tables we have to remember the actual
|
|
// table and start node of the current position in the enumeration.
|
|
, m_pOwnTable( pTable )
|
|
, m_nEndIndex( pCursor->End()->nNode.GetIndex() )
|
|
, m_nFirstParaStart( -1 )
|
|
, m_nLastParaEnd( -1 )
|
|
, m_bFirstParagraph( true )
|
|
, m_pCursor(pCursor)
|
|
{
|
|
OSL_ENSURE(m_xParentText.is(), "SwXParagraphEnumeration: no parent?");
|
|
OSL_ENSURE( !((CursorType::SelectionInTable == eType) ||
|
|
(CursorType::TableText == eType))
|
|
|| (m_pOwnTable && m_pOwnStartNode),
|
|
"SwXParagraphEnumeration: table type but no start node or table?");
|
|
|
|
if ((CursorType::Selection == m_eCursorType) ||
|
|
(CursorType::SelectionInTable == m_eCursorType))
|
|
{
|
|
SwUnoCursor & rCursor = GetCursor();
|
|
rCursor.Normalize();
|
|
m_nFirstParaStart = rCursor.GetPoint()->nContent.GetIndex();
|
|
m_nLastParaEnd = rCursor.GetMark()->nContent.GetIndex();
|
|
rCursor.DeleteMark();
|
|
}
|
|
}
|
|
|
|
virtual ~SwXParagraphEnumerationImpl() override
|
|
{ m_pCursor.reset(nullptr); }
|
|
virtual void SAL_CALL release() throw () override
|
|
{
|
|
SolarMutexGuard g;
|
|
OWeakObject::release();
|
|
}
|
|
|
|
// XServiceInfo
|
|
virtual OUString SAL_CALL getImplementationName() override
|
|
{ return OUString("SwXParagraphEnumeration"); }
|
|
virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName) override
|
|
{ return cppu::supportsService(this, rServiceName); };
|
|
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
|
|
{ return {"com.sun.star.text.ParagraphEnumeration"}; };
|
|
|
|
// XEnumeration
|
|
virtual sal_Bool SAL_CALL hasMoreElements() override;
|
|
virtual css::uno::Any SAL_CALL nextElement() override;
|
|
|
|
SwUnoCursor& GetCursor()
|
|
{ return *m_pCursor; }
|
|
/// @throws container::NoSuchElementException
|
|
/// @throws lang::WrappedTargetException
|
|
/// @throws uno::RuntimeException
|
|
uno::Reference< text::XTextContent > NextElement_Impl();
|
|
};
|
|
|
|
SwXParagraphEnumeration* SwXParagraphEnumeration::Create(
|
|
uno::Reference< text::XText > const& xParent,
|
|
const std::shared_ptr<SwUnoCursor>& pCursor,
|
|
const CursorType eType,
|
|
SwStartNode const*const pStartNode,
|
|
SwTable const*const pTable)
|
|
{
|
|
return new SwXParagraphEnumerationImpl(xParent, pCursor, eType, pStartNode, pTable);
|
|
}
|
|
|
|
sal_Bool SAL_CALL
|
|
SwXParagraphEnumerationImpl::hasMoreElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return m_bFirstParagraph || m_xNextPara.is();
|
|
}
|
|
|
|
//!! compare to SwShellTableCursor::FillRects() in viscrs.cxx
|
|
static SwTableNode *
|
|
lcl_FindTopLevelTable(
|
|
SwTableNode *const pTableNode, SwTable const*const pOwnTable)
|
|
{
|
|
// find top-most table in current context (section) level
|
|
|
|
SwTableNode * pLast = pTableNode;
|
|
for (SwTableNode* pTmp = pLast;
|
|
pTmp != nullptr && &pTmp->GetTable() != pOwnTable; /* we must not go up higher than the own table! */
|
|
pTmp = pTmp->StartOfSectionNode()->FindTableNode() )
|
|
{
|
|
pLast = pTmp;
|
|
}
|
|
return pLast;
|
|
}
|
|
|
|
static bool
|
|
lcl_CursorIsInSection(
|
|
SwUnoCursor const*const pUnoCursor, SwStartNode const*const pOwnStartNode)
|
|
{
|
|
// returns true if the cursor is in the section (or in a sub section!)
|
|
// represented by pOwnStartNode
|
|
|
|
bool bRes = true;
|
|
if (pUnoCursor && pOwnStartNode)
|
|
{
|
|
const SwEndNode * pOwnEndNode = pOwnStartNode->EndOfSectionNode();
|
|
bRes = pOwnStartNode->GetIndex() <= pUnoCursor->Start()->nNode.GetIndex() &&
|
|
pUnoCursor->End()->nNode.GetIndex() <= pOwnEndNode->GetIndex();
|
|
}
|
|
return bRes;
|
|
}
|
|
|
|
uno::Reference< text::XTextContent >
|
|
SwXParagraphEnumerationImpl::NextElement_Impl()
|
|
{
|
|
SwUnoCursor& rUnoCursor = GetCursor();
|
|
|
|
// check for exceeding selections
|
|
if (!m_bFirstParagraph &&
|
|
((CursorType::Selection == m_eCursorType) ||
|
|
(CursorType::SelectionInTable == m_eCursorType)))
|
|
{
|
|
SwPosition* pStart = rUnoCursor.Start();
|
|
auto aNewCursor(rUnoCursor.GetDoc()->CreateUnoCursor(*pStart));
|
|
// one may also go into tables here
|
|
if ((CursorType::TableText != m_eCursorType) &&
|
|
(CursorType::SelectionInTable != m_eCursorType))
|
|
{
|
|
aNewCursor->SetRemainInSection( false );
|
|
}
|
|
|
|
// os 2005-01-14: This part is only necessary to detect movements out
|
|
// of a selection; if there is no selection we don't have to care
|
|
SwTableNode *const pTableNode = aNewCursor->GetNode().FindTableNode();
|
|
if (((CursorType::TableText != m_eCursorType) &&
|
|
(CursorType::SelectionInTable != m_eCursorType)) && pTableNode)
|
|
{
|
|
aNewCursor->GetPoint()->nNode = pTableNode->EndOfSectionIndex();
|
|
aNewCursor->Move(fnMoveForward, GoInNode);
|
|
}
|
|
else
|
|
{
|
|
aNewCursor->MovePara(GoNextPara, fnParaStart);
|
|
}
|
|
if (m_nEndIndex < aNewCursor->Start()->nNode.GetIndex())
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
bool bInTable = false;
|
|
if (!m_bFirstParagraph)
|
|
{
|
|
rUnoCursor.SetRemainInSection( false );
|
|
// what to do if already in a table?
|
|
SwTableNode * pTableNode = rUnoCursor.GetNode().FindTableNode();
|
|
pTableNode = lcl_FindTopLevelTable( pTableNode, m_pOwnTable );
|
|
if (pTableNode && (&pTableNode->GetTable() != m_pOwnTable))
|
|
{
|
|
// this is a foreign table: go to end
|
|
rUnoCursor.GetPoint()->nNode = pTableNode->EndOfSectionIndex();
|
|
if (!rUnoCursor.Move(fnMoveForward, GoInNode))
|
|
{
|
|
return nullptr;
|
|
}
|
|
bInTable = true;
|
|
}
|
|
}
|
|
|
|
uno::Reference< text::XTextContent > xRef;
|
|
// the cursor must remain in the current section or a subsection
|
|
// before AND after the movement...
|
|
if (lcl_CursorIsInSection( &rUnoCursor, m_pOwnStartNode ) &&
|
|
(m_bFirstParagraph || bInTable ||
|
|
(rUnoCursor.MovePara(GoNextPara, fnParaStart) &&
|
|
lcl_CursorIsInSection( &rUnoCursor, m_pOwnStartNode ))))
|
|
{
|
|
SwPosition* pStart = rUnoCursor.Start();
|
|
const sal_Int32 nFirstContent =
|
|
(m_bFirstParagraph) ? m_nFirstParaStart : -1;
|
|
const sal_Int32 nLastContent =
|
|
(m_nEndIndex == pStart->nNode.GetIndex()) ? m_nLastParaEnd : -1;
|
|
|
|
// position in a table, or in a simple paragraph?
|
|
SwTableNode * pTableNode = rUnoCursor.GetNode().FindTableNode();
|
|
pTableNode = lcl_FindTopLevelTable( pTableNode, m_pOwnTable );
|
|
if (/*CursorType::TableText != eCursorType && CursorType::SelectionInTable != eCursorType && */
|
|
pTableNode && (&pTableNode->GetTable() != m_pOwnTable))
|
|
{
|
|
// this is a foreign table
|
|
SwFrameFormat* pTableFormat =
|
|
static_cast<SwFrameFormat*>(pTableNode->GetTable().GetFrameFormat());
|
|
xRef = SwXTextTable::CreateXTextTable(pTableFormat);
|
|
}
|
|
else
|
|
{
|
|
text::XText *const pText = m_xParentText.get();
|
|
xRef = SwXParagraph::CreateXParagraph(*rUnoCursor.GetDoc(),
|
|
pStart->nNode.GetNode().GetTextNode(),
|
|
static_cast<SwXText*>(pText), nFirstContent, nLastContent);
|
|
}
|
|
}
|
|
|
|
return xRef;
|
|
}
|
|
|
|
uno::Any SAL_CALL SwXParagraphEnumerationImpl::nextElement()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (m_bFirstParagraph)
|
|
{
|
|
m_xNextPara = NextElement_Impl();
|
|
m_bFirstParagraph = false;
|
|
}
|
|
const uno::Reference< text::XTextContent > xRef = m_xNextPara;
|
|
if (!xRef.is())
|
|
{
|
|
throw container::NoSuchElementException();
|
|
}
|
|
m_xNextPara = NextElement_Impl();
|
|
|
|
uno::Any aRet;
|
|
aRet <<= xRef;
|
|
return aRet;
|
|
}
|
|
|
|
class SwXTextRange::Impl
|
|
: public SwClient
|
|
{
|
|
public:
|
|
const SfxItemPropertySet & m_rPropSet;
|
|
const enum RangePosition m_eRangePosition;
|
|
SwDoc & m_rDoc;
|
|
uno::Reference<text::XText> m_xParentText;
|
|
SwDepend m_ObjectDepend; // register at format of table or frame
|
|
::sw::mark::IMark * m_pMark;
|
|
|
|
Impl( SwDoc & rDoc, const enum RangePosition eRange,
|
|
SwFrameFormat *const pTableFormat,
|
|
const uno::Reference< text::XText > & xParent = nullptr)
|
|
: SwClient()
|
|
, m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
|
|
, m_eRangePosition(eRange)
|
|
, m_rDoc(rDoc)
|
|
, m_xParentText(xParent)
|
|
, m_ObjectDepend(this, pTableFormat)
|
|
, m_pMark(nullptr)
|
|
{
|
|
}
|
|
|
|
virtual ~Impl() override
|
|
{
|
|
// Impl owns the bookmark; delete it here: SolarMutex is locked
|
|
Invalidate();
|
|
}
|
|
|
|
void Invalidate()
|
|
{
|
|
if (m_pMark)
|
|
{
|
|
m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
|
|
m_pMark = nullptr;
|
|
}
|
|
}
|
|
|
|
const ::sw::mark::IMark * GetBookmark() const { return m_pMark; }
|
|
|
|
protected:
|
|
// SwClient
|
|
virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew) override;
|
|
};
|
|
|
|
void SwXTextRange::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
|
|
{
|
|
const bool bAlreadyRegistered = nullptr != GetRegisteredIn();
|
|
ClientModify(this, pOld, pNew);
|
|
if (m_ObjectDepend.GetRegisteredIn())
|
|
{
|
|
ClientModify(&m_ObjectDepend, pOld, pNew);
|
|
// if the depend was removed then the range must be removed too
|
|
if (!m_ObjectDepend.GetRegisteredIn() && GetRegisteredIn())
|
|
{
|
|
GetRegisteredIn()->Remove(this);
|
|
}
|
|
// or if the range has been removed but the depend is still
|
|
// connected then the depend must be removed
|
|
else if (bAlreadyRegistered && !GetRegisteredIn() &&
|
|
m_ObjectDepend.GetRegisteredIn())
|
|
{
|
|
m_ObjectDepend.GetRegisteredIn()
|
|
->Remove(& m_ObjectDepend);
|
|
}
|
|
}
|
|
if (!GetRegisteredIn())
|
|
{
|
|
m_pMark = nullptr;
|
|
}
|
|
}
|
|
|
|
SwXTextRange::SwXTextRange(SwPaM const & rPam,
|
|
const uno::Reference< text::XText > & xParent,
|
|
const enum RangePosition eRange)
|
|
: m_pImpl( new SwXTextRange::Impl(*rPam.GetDoc(), eRange, nullptr, xParent) )
|
|
{
|
|
SetPositions(rPam);
|
|
}
|
|
|
|
SwXTextRange::SwXTextRange(SwFrameFormat& rTableFormat)
|
|
: m_pImpl(
|
|
new SwXTextRange::Impl(*rTableFormat.GetDoc(), RANGE_IS_TABLE, &rTableFormat) )
|
|
{
|
|
SwTable *const pTable = SwTable::FindTable( &rTableFormat );
|
|
SwTableNode *const pTableNode = pTable->GetTableNode();
|
|
SwPosition aPosition( *pTableNode );
|
|
SwPaM aPam( aPosition );
|
|
|
|
SetPositions( aPam );
|
|
}
|
|
|
|
SwXTextRange::~SwXTextRange()
|
|
{
|
|
}
|
|
|
|
const SwDoc& SwXTextRange::GetDoc() const
|
|
{
|
|
return m_pImpl->m_rDoc;
|
|
}
|
|
|
|
SwDoc& SwXTextRange::GetDoc()
|
|
{
|
|
return m_pImpl->m_rDoc;
|
|
}
|
|
|
|
void SwXTextRange::Invalidate()
|
|
{
|
|
m_pImpl->Invalidate();
|
|
}
|
|
|
|
void SwXTextRange::SetPositions(const SwPaM& rPam)
|
|
{
|
|
m_pImpl->Invalidate();
|
|
IDocumentMarkAccess* const pMA = m_pImpl->m_rDoc.getIDocumentMarkAccess();
|
|
m_pImpl->m_pMark = pMA->makeMark(rPam, OUString(),
|
|
IDocumentMarkAccess::MarkType::UNO_BOOKMARK, sw::mark::InsertMode::New);
|
|
m_pImpl->m_pMark->Add(m_pImpl.get());
|
|
}
|
|
|
|
void SwXTextRange::DeleteAndInsert(
|
|
const OUString& rText, const bool bForceExpandHints)
|
|
{
|
|
if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
|
|
{
|
|
// setString on table not allowed
|
|
throw uno::RuntimeException();
|
|
}
|
|
|
|
const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
|
|
SwCursor aCursor(aPos, nullptr);
|
|
if (GetPositions(aCursor))
|
|
{
|
|
UnoActionContext aAction(& m_pImpl->m_rDoc);
|
|
m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
|
|
if (aCursor.HasMark())
|
|
{
|
|
m_pImpl->m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor);
|
|
}
|
|
|
|
if (!rText.isEmpty())
|
|
{
|
|
SwUnoCursorHelper::DocInsertStringSplitCR(
|
|
m_pImpl->m_rDoc, aCursor, rText, bForceExpandHints);
|
|
|
|
SwUnoCursorHelper::SelectPam(aCursor, true);
|
|
aCursor.Left(rText.getLength());
|
|
}
|
|
SetPositions(aCursor);
|
|
m_pImpl->m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
class theSwXTextRangeUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextRangeUnoTunnelId > {};
|
|
}
|
|
|
|
const uno::Sequence< sal_Int8 > & SwXTextRange::getUnoTunnelId()
|
|
{
|
|
return theSwXTextRangeUnoTunnelId::get().getSeq();
|
|
}
|
|
|
|
// XUnoTunnel
|
|
sal_Int64 SAL_CALL
|
|
SwXTextRange::getSomething(const uno::Sequence< sal_Int8 >& rId)
|
|
{
|
|
return ::sw::UnoTunnelImpl<SwXTextRange>(rId, this);
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
SwXTextRange::getImplementationName()
|
|
{
|
|
return OUString("SwXTextRange");
|
|
}
|
|
|
|
static char const*const g_ServicesTextRange[] =
|
|
{
|
|
"com.sun.star.text.TextRange",
|
|
"com.sun.star.style.CharacterProperties",
|
|
"com.sun.star.style.CharacterPropertiesAsian",
|
|
"com.sun.star.style.CharacterPropertiesComplex",
|
|
"com.sun.star.style.ParagraphProperties",
|
|
"com.sun.star.style.ParagraphPropertiesAsian",
|
|
"com.sun.star.style.ParagraphPropertiesComplex",
|
|
};
|
|
|
|
static const size_t g_nServicesTextRange(SAL_N_ELEMENTS(g_ServicesTextRange));
|
|
|
|
sal_Bool SAL_CALL SwXTextRange::supportsService(const OUString& rServiceName)
|
|
{
|
|
return cppu::supportsService(this, rServiceName);
|
|
}
|
|
|
|
uno::Sequence< OUString > SAL_CALL
|
|
SwXTextRange::getSupportedServiceNames()
|
|
{
|
|
return ::sw::GetSupportedServiceNamesImpl(
|
|
g_nServicesTextRange, g_ServicesTextRange);
|
|
}
|
|
|
|
uno::Reference< text::XText > SAL_CALL
|
|
SwXTextRange::getText()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->m_xParentText.is())
|
|
{
|
|
if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE &&
|
|
m_pImpl->m_ObjectDepend.GetRegisteredIn())
|
|
{
|
|
SwFrameFormat const*const pTableFormat = static_cast<SwFrameFormat const*>(
|
|
m_pImpl->m_ObjectDepend.GetRegisteredIn());
|
|
SwTable const*const pTable = SwTable::FindTable( pTableFormat );
|
|
SwTableNode const*const pTableNode = pTable->GetTableNode();
|
|
const SwPosition aPosition( *pTableNode );
|
|
m_pImpl->m_xParentText =
|
|
::sw::CreateParentXText(m_pImpl->m_rDoc, aPosition);
|
|
}
|
|
}
|
|
OSL_ENSURE(m_pImpl->m_xParentText.is(), "SwXTextRange::getText: no text");
|
|
return m_pImpl->m_xParentText;
|
|
}
|
|
|
|
uno::Reference< text::XTextRange > SAL_CALL
|
|
SwXTextRange::getStart()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
uno::Reference< text::XTextRange > xRet;
|
|
::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
|
|
if (!m_pImpl->m_xParentText.is())
|
|
{
|
|
getText();
|
|
}
|
|
if(pBkmk)
|
|
{
|
|
SwPaM aPam(pBkmk->GetMarkStart());
|
|
xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
|
|
}
|
|
else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
|
|
{
|
|
// start and end are this, if it's a table
|
|
xRet = this;
|
|
}
|
|
else
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
uno::Reference< text::XTextRange > SAL_CALL
|
|
SwXTextRange::getEnd()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
uno::Reference< text::XTextRange > xRet;
|
|
::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
|
|
if (!m_pImpl->m_xParentText.is())
|
|
{
|
|
getText();
|
|
}
|
|
if(pBkmk)
|
|
{
|
|
SwPaM aPam(pBkmk->GetMarkEnd());
|
|
xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
|
|
}
|
|
else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
|
|
{
|
|
// start and end are this, if it's a table
|
|
xRet = this;
|
|
}
|
|
else
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
OUString SAL_CALL SwXTextRange::getString()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
OUString sRet;
|
|
// for tables there is no bookmark, thus also no text
|
|
// one could export the table as ASCII here maybe?
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
if (GetPositions(aPaM) && aPaM.HasMark())
|
|
{
|
|
SwUnoCursorHelper::GetTextFromPam(aPaM, sRet);
|
|
}
|
|
return sRet;
|
|
}
|
|
|
|
void SAL_CALL SwXTextRange::setString(const OUString& rString)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
DeleteAndInsert(rString, false);
|
|
}
|
|
|
|
bool SwXTextRange::GetPositions(SwPaM& rToFill) const
|
|
{
|
|
::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
|
|
if(pBkmk)
|
|
{
|
|
*rToFill.GetPoint() = pBkmk->GetMarkPos();
|
|
if(pBkmk->IsExpanded())
|
|
{
|
|
rToFill.SetMark();
|
|
*rToFill.GetMark() = pBkmk->GetOtherMarkPos();
|
|
}
|
|
else
|
|
{
|
|
rToFill.DeleteMark();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
namespace sw {
|
|
|
|
bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
|
|
const uno::Reference< text::XTextRange > & xTextRange)
|
|
{
|
|
bool bRet = false;
|
|
|
|
uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
|
|
SwXTextRange* pRange = nullptr;
|
|
OTextCursorHelper* pCursor = nullptr;
|
|
SwXTextPortion* pPortion = nullptr;
|
|
SwXText* pText = nullptr;
|
|
SwXParagraph* pPara = nullptr;
|
|
if(xRangeTunnel.is())
|
|
{
|
|
pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
|
|
pCursor =
|
|
::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
|
|
pPortion=
|
|
::sw::UnoTunnelGetImplementation<SwXTextPortion>(xRangeTunnel);
|
|
pText = ::sw::UnoTunnelGetImplementation<SwXText>(xRangeTunnel);
|
|
pPara = ::sw::UnoTunnelGetImplementation<SwXParagraph>(xRangeTunnel);
|
|
}
|
|
|
|
// if it's a text then create a temporary cursor there and re-use
|
|
// the pCursor variable
|
|
// #i108489#: Reference in outside scope to keep cursor alive
|
|
uno::Reference< text::XTextCursor > xTextCursor;
|
|
if (pText)
|
|
{
|
|
xTextCursor.set( pText->CreateCursor() );
|
|
xTextCursor->gotoEnd(true);
|
|
const uno::Reference<lang::XUnoTunnel> xCursorTunnel(
|
|
xTextCursor, uno::UNO_QUERY);
|
|
pCursor =
|
|
::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCursorTunnel);
|
|
}
|
|
if(pRange && &pRange->GetDoc() == rToFill.GetDoc())
|
|
{
|
|
bRet = pRange->GetPositions(rToFill);
|
|
}
|
|
else
|
|
{
|
|
if (pPara)
|
|
{
|
|
bRet = pPara->SelectPaM(rToFill);
|
|
}
|
|
else
|
|
{
|
|
SwDoc* const pDoc = (pCursor) ? pCursor->GetDoc()
|
|
: ((pPortion) ? pPortion->GetCursor().GetDoc() : nullptr);
|
|
const SwPaM* const pUnoCursor = (pCursor) ? pCursor->GetPaM()
|
|
: ((pPortion) ? &pPortion->GetCursor() : nullptr);
|
|
if (pUnoCursor && pDoc == rToFill.GetDoc())
|
|
{
|
|
OSL_ENSURE(!pUnoCursor->IsMultiSelection(),
|
|
"what to do about rings?");
|
|
bRet = true;
|
|
*rToFill.GetPoint() = *pUnoCursor->GetPoint();
|
|
if (pUnoCursor->HasMark())
|
|
{
|
|
rToFill.SetMark();
|
|
*rToFill.GetMark() = *pUnoCursor->GetMark();
|
|
}
|
|
else
|
|
rToFill.DeleteMark();
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
static bool
|
|
lcl_IsStartNodeInFormat(const bool bHeader, SwStartNode const *const pSttNode,
|
|
SwFrameFormat const*const pFrameFormat, SwFrameFormat*& rpFormat)
|
|
{
|
|
bool bRet = false;
|
|
const SfxItemSet& rSet = pFrameFormat->GetAttrSet();
|
|
const SfxPoolItem* pItem;
|
|
if (SfxItemState::SET == rSet.GetItemState(
|
|
static_cast<sal_uInt16>(bHeader ? RES_HEADER : RES_FOOTER),
|
|
true, &pItem))
|
|
{
|
|
SfxPoolItem *const pItemNonConst(const_cast<SfxPoolItem *>(pItem));
|
|
SwFrameFormat *const pHeadFootFormat = (bHeader) ?
|
|
static_cast<SwFormatHeader*>(pItemNonConst)->GetHeaderFormat() :
|
|
static_cast<SwFormatFooter*>(pItemNonConst)->GetFooterFormat();
|
|
if (pHeadFootFormat)
|
|
{
|
|
const SwFormatContent& rFlyContent = pHeadFootFormat->GetContent();
|
|
const SwNode& rNode = rFlyContent.GetContentIdx()->GetNode();
|
|
SwStartNode const*const pCurSttNode = rNode.FindSttNodeByType(
|
|
(bHeader) ? SwHeaderStartNode : SwFooterStartNode);
|
|
if (pCurSttNode && (pCurSttNode == pSttNode))
|
|
{
|
|
rpFormat = pHeadFootFormat;
|
|
bRet = true;
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
} // namespace sw
|
|
|
|
uno::Reference< text::XTextRange >
|
|
SwXTextRange::CreateXTextRange(
|
|
SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark)
|
|
{
|
|
const uno::Reference<text::XText> xParentText(
|
|
::sw::CreateParentXText(rDoc, rPos));
|
|
const auto pNewCursor(rDoc.CreateUnoCursor(rPos));
|
|
if(pMark)
|
|
{
|
|
pNewCursor->SetMark();
|
|
*pNewCursor->GetMark() = *pMark;
|
|
}
|
|
const bool isCell( dynamic_cast<SwXCell*>(xParentText.get()) );
|
|
const uno::Reference< text::XTextRange > xRet(
|
|
new SwXTextRange(*pNewCursor, xParentText,
|
|
isCell ? RANGE_IN_CELL : RANGE_IN_TEXT) );
|
|
return xRet;
|
|
}
|
|
|
|
namespace sw {
|
|
|
|
uno::Reference< text::XText >
|
|
CreateParentXText(SwDoc & rDoc, const SwPosition& rPos)
|
|
{
|
|
uno::Reference< text::XText > xParentText;
|
|
SwStartNode* pSttNode = rPos.nNode.GetNode().StartOfSectionNode();
|
|
while(pSttNode && pSttNode->IsSectionNode())
|
|
{
|
|
pSttNode = pSttNode->StartOfSectionNode();
|
|
}
|
|
SwStartNodeType eType = pSttNode ? pSttNode->GetStartNodeType() : SwNormalStartNode;
|
|
switch(eType)
|
|
{
|
|
case SwTableBoxStartNode:
|
|
{
|
|
SwTableNode const*const pTableNode = pSttNode->FindTableNode();
|
|
SwFrameFormat *const pTableFormat =
|
|
static_cast<SwFrameFormat*>(pTableNode->GetTable().GetFrameFormat());
|
|
SwTableBox *const pBox = pSttNode->GetTableBox();
|
|
|
|
xParentText = (pBox)
|
|
? SwXCell::CreateXCell( pTableFormat, pBox )
|
|
: new SwXCell( pTableFormat, *pSttNode );
|
|
}
|
|
break;
|
|
case SwFlyStartNode:
|
|
{
|
|
SwFrameFormat *const pFormat = pSttNode->GetFlyFormat();
|
|
if (nullptr != pFormat)
|
|
{
|
|
xParentText.set(SwXTextFrame::CreateXTextFrame(rDoc, pFormat),
|
|
uno::UNO_QUERY);
|
|
}
|
|
}
|
|
break;
|
|
case SwHeaderStartNode:
|
|
case SwFooterStartNode:
|
|
{
|
|
const bool bHeader = (SwHeaderStartNode == eType);
|
|
const size_t nPDescCount = rDoc.GetPageDescCnt();
|
|
for(size_t i = 0; i < nPDescCount; i++)
|
|
{
|
|
const SwPageDesc& rDesc = rDoc.GetPageDesc( i );
|
|
const SwFrameFormat* pFrameFormatMaster = &rDesc.GetMaster();
|
|
const SwFrameFormat* pFrameFormatLeft = &rDesc.GetLeft();
|
|
|
|
SwFrameFormat* pHeadFootFormat = nullptr;
|
|
if (!lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrameFormatMaster,
|
|
pHeadFootFormat))
|
|
{
|
|
lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrameFormatLeft,
|
|
pHeadFootFormat);
|
|
}
|
|
|
|
if (pHeadFootFormat)
|
|
{
|
|
xParentText = SwXHeadFootText::CreateXHeadFootText(
|
|
*pHeadFootFormat, bHeader);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SwFootnoteStartNode:
|
|
{
|
|
const size_t nFootnoteCnt = rDoc.GetFootnoteIdxs().size();
|
|
for (size_t n = 0; n < nFootnoteCnt; ++n )
|
|
{
|
|
const SwTextFootnote* pTextFootnote = rDoc.GetFootnoteIdxs()[ n ];
|
|
const SwFormatFootnote& rFootnote = pTextFootnote->GetFootnote();
|
|
pTextFootnote = rFootnote.GetTextFootnote();
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
const SwStartNode* pTmpSttNode =
|
|
pTextFootnote->GetStartNode()->GetNode().
|
|
FindSttNodeByType(SwFootnoteStartNode);
|
|
(void)pTmpSttNode;
|
|
#endif
|
|
|
|
if (pSttNode == pTextFootnote->GetStartNode()->GetNode().
|
|
FindSttNodeByType(SwFootnoteStartNode))
|
|
{
|
|
xParentText.set(SwXFootnote::CreateXFootnote(rDoc,
|
|
&const_cast<SwFormatFootnote&>(rFootnote)), uno::UNO_QUERY);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
// then it is the body text
|
|
const uno::Reference<frame::XModel> xModel =
|
|
rDoc.GetDocShell()->GetBaseModel();
|
|
const uno::Reference< text::XTextDocument > xDoc(
|
|
xModel, uno::UNO_QUERY);
|
|
xParentText = xDoc->getText();
|
|
}
|
|
}
|
|
OSL_ENSURE(xParentText.is(), "no parent text?");
|
|
return xParentText;
|
|
}
|
|
|
|
} // namespace sw
|
|
|
|
uno::Reference< container::XEnumeration > SAL_CALL
|
|
SwXTextRange::createContentEnumeration(const OUString& rServiceName)
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if ( rServiceName != "com.sun.star.text.TextContent" )
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
|
|
const auto pNewCursor(m_pImpl->m_rDoc.CreateUnoCursor(aPos));
|
|
if (!GetPositions(*pNewCursor))
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
|
|
return SwXParaFrameEnumeration::Create(*pNewCursor, PARAFRAME_PORTION_TEXTRANGE);
|
|
}
|
|
|
|
uno::Reference< container::XEnumeration > SAL_CALL
|
|
SwXTextRange::createEnumeration()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
const SwPosition aPos(GetDoc().GetNodes().GetEndOfContent());
|
|
auto pNewCursor(m_pImpl->m_rDoc.CreateUnoCursor(aPos));
|
|
if (!GetPositions(*pNewCursor))
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
if (!m_pImpl->m_xParentText.is())
|
|
{
|
|
getText();
|
|
}
|
|
|
|
const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
|
|
? CursorType::SelectionInTable : CursorType::Selection;
|
|
return SwXParagraphEnumeration::Create(m_pImpl->m_xParentText, pNewCursor, eSetType);
|
|
}
|
|
|
|
uno::Type SAL_CALL SwXTextRange::getElementType()
|
|
{
|
|
return cppu::UnoType<text::XTextRange>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL SwXTextRange::hasElements()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
uno::Sequence< OUString > SAL_CALL
|
|
SwXTextRange::getAvailableServiceNames()
|
|
{
|
|
uno::Sequence<OUString> aRet { "com.sun.star.text.TextContent" };
|
|
return aRet;
|
|
}
|
|
|
|
uno::Reference< beans::XPropertySetInfo > SAL_CALL
|
|
SwXTextRange::getPropertySetInfo()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
static uno::Reference< beans::XPropertySetInfo > xRef =
|
|
m_pImpl->m_rPropSet.getPropertySetInfo();
|
|
return xRef;
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::setPropertyValue(
|
|
const OUString& rPropertyName, const uno::Any& rValue)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
SwUnoCursorHelper::SetPropertyValue(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName, rValue);
|
|
}
|
|
|
|
uno::Any SAL_CALL
|
|
SwXTextRange::getPropertyValue(const OUString& rPropertyName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
return SwUnoCursorHelper::GetPropertyValue(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName);
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::addPropertyChangeListener(
|
|
const OUString& /*rPropertyName*/,
|
|
const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
|
|
{
|
|
OSL_FAIL("SwXTextRange::addPropertyChangeListener(): not implemented");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::removePropertyChangeListener(
|
|
const OUString& /*rPropertyName*/,
|
|
const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
|
|
{
|
|
OSL_FAIL("SwXTextRange::removePropertyChangeListener(): not implemented");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::addVetoableChangeListener(
|
|
const OUString& /*rPropertyName*/,
|
|
const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
|
|
{
|
|
OSL_FAIL("SwXTextRange::addVetoableChangeListener(): not implemented");
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::removeVetoableChangeListener(
|
|
const OUString& /*rPropertyName*/,
|
|
const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
|
|
{
|
|
OSL_FAIL("SwXTextRange::removeVetoableChangeListener(): not implemented");
|
|
}
|
|
|
|
beans::PropertyState SAL_CALL
|
|
SwXTextRange::getPropertyState(const OUString& rPropertyName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
return SwUnoCursorHelper::GetPropertyState(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName);
|
|
}
|
|
|
|
uno::Sequence< beans::PropertyState > SAL_CALL
|
|
SwXTextRange::getPropertyStates(const uno::Sequence< OUString >& rPropertyName)
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
return SwUnoCursorHelper::GetPropertyStates(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName);
|
|
}
|
|
|
|
void SAL_CALL SwXTextRange::setPropertyToDefault(const OUString& rPropertyName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName);
|
|
}
|
|
|
|
uno::Any SAL_CALL
|
|
SwXTextRange::getPropertyDefault(const OUString& rPropertyName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
GetPositions(aPaM);
|
|
return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_pImpl->m_rPropSet,
|
|
rPropertyName);
|
|
}
|
|
|
|
void SAL_CALL
|
|
SwXTextRange::makeRedline(
|
|
const OUString& rRedlineType,
|
|
const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
if (!m_pImpl->GetBookmark())
|
|
{
|
|
throw uno::RuntimeException();
|
|
}
|
|
SwPaM aPaM(GetDoc().GetNodes());
|
|
SwXTextRange::GetPositions(aPaM);
|
|
SwUnoCursorHelper::makeRedline( aPaM, rRedlineType, rRedlineProperties );
|
|
}
|
|
|
|
struct SwXTextRangesImpl final : public SwXTextRanges
|
|
{
|
|
|
|
// XUnoTunnel
|
|
virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier) override;
|
|
|
|
// XServiceInfo
|
|
virtual OUString SAL_CALL getImplementationName() override
|
|
{ return OUString("SwXTextRanges"); };
|
|
virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName) override
|
|
{ return cppu::supportsService(this, rServiceName); };
|
|
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
|
|
{ return { "com.sun.star.text.TextRanges" }; };
|
|
|
|
// XElementAccess
|
|
virtual css::uno::Type SAL_CALL getElementType() override
|
|
{ return cppu::UnoType<text::XTextRange>::get(); };
|
|
virtual sal_Bool SAL_CALL hasElements() override
|
|
{ return getCount() > 0; };
|
|
// XIndexAccess
|
|
virtual sal_Int32 SAL_CALL getCount() override;
|
|
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
|
|
|
|
explicit SwXTextRangesImpl(SwPaM *const pPaM)
|
|
{
|
|
if (pPaM)
|
|
{
|
|
m_pUnoCursor.reset(pPaM->GetDoc()->CreateUnoCursor(*pPaM->GetPoint()));
|
|
::sw::DeepCopyPaM(*pPaM, *GetCursor());
|
|
}
|
|
MakeRanges();
|
|
}
|
|
virtual void SAL_CALL release() throw () override
|
|
{
|
|
SolarMutexGuard g;
|
|
OWeakObject::release();
|
|
}
|
|
virtual SwUnoCursor* GetCursor() override
|
|
{ return &(*m_pUnoCursor); };
|
|
void MakeRanges();
|
|
std::vector< uno::Reference< text::XTextRange > > m_Ranges;
|
|
sw::UnoCursorPointer m_pUnoCursor;
|
|
};
|
|
|
|
void SwXTextRangesImpl::MakeRanges()
|
|
{
|
|
if (GetCursor())
|
|
{
|
|
for(SwPaM& rTmpCursor : GetCursor()->GetRingContainer())
|
|
{
|
|
const uno::Reference< text::XTextRange > xRange(
|
|
SwXTextRange::CreateXTextRange(
|
|
*rTmpCursor.GetDoc(),
|
|
*rTmpCursor.GetPoint(), rTmpCursor.GetMark()));
|
|
if (xRange.is())
|
|
{
|
|
m_Ranges.push_back(xRange);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SwXTextRanges* SwXTextRanges::Create(SwPaM *const pPaM)
|
|
{ return new SwXTextRangesImpl(pPaM); }
|
|
|
|
namespace
|
|
{
|
|
class theSwXTextRangesUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextRangesUnoTunnelId > {};
|
|
}
|
|
|
|
const uno::Sequence< sal_Int8 > & SwXTextRanges::getUnoTunnelId()
|
|
{ return theSwXTextRangesUnoTunnelId::get().getSeq(); }
|
|
|
|
sal_Int64 SAL_CALL
|
|
SwXTextRangesImpl::getSomething(const uno::Sequence< sal_Int8 >& rId)
|
|
{
|
|
return ::sw::UnoTunnelImpl<SwXTextRanges>(rId, this);
|
|
}
|
|
|
|
/*
|
|
* Text positions
|
|
* Up to the first access to a text position, only a SwCursor is stored.
|
|
* Afterwards, an array with uno::Reference<XTextPosition> will be created.
|
|
*/
|
|
|
|
sal_Int32 SAL_CALL SwXTextRangesImpl::getCount()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return static_cast<sal_Int32>(m_Ranges.size());
|
|
}
|
|
|
|
uno::Any SAL_CALL SwXTextRangesImpl::getByIndex(sal_Int32 nIndex)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ((nIndex < 0) || (static_cast<size_t>(nIndex) >= m_Ranges.size()))
|
|
throw lang::IndexOutOfBoundsException();
|
|
uno::Any ret;
|
|
ret <<= (m_Ranges.at(nIndex));
|
|
return ret;
|
|
}
|
|
|
|
void SwUnoCursorHelper::SetString(SwCursor & rCursor, const OUString& rString)
|
|
{
|
|
// Start/EndAction
|
|
SwDoc *const pDoc = rCursor.GetDoc();
|
|
UnoActionContext aAction(pDoc);
|
|
pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
|
|
if (rCursor.HasMark())
|
|
{
|
|
pDoc->getIDocumentContentOperations().DeleteAndJoin(rCursor);
|
|
}
|
|
if (!rString.isEmpty())
|
|
{
|
|
const bool bSuccess( SwUnoCursorHelper::DocInsertStringSplitCR(
|
|
*pDoc, rCursor, rString, false ) );
|
|
OSL_ENSURE( bSuccess, "DocInsertStringSplitCR" );
|
|
SwUnoCursorHelper::SelectPam(rCursor, true);
|
|
rCursor.Left(rString.getLength());
|
|
}
|
|
pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
|
|
}
|
|
|
|
struct SwXParaFrameEnumerationImpl final : public SwXParaFrameEnumeration
|
|
{
|
|
// XServiceInfo
|
|
virtual OUString SAL_CALL getImplementationName() override
|
|
{ return OUString("SwXParaFrameEnumeration"); };
|
|
virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override
|
|
{ return cppu::supportsService(this, rServiceName); };
|
|
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
|
|
{ return {"com.sun.star.util.ContentEnumeration"}; };
|
|
|
|
// XEnumeration
|
|
virtual sal_Bool SAL_CALL hasMoreElements() override;
|
|
virtual css::uno::Any SAL_CALL nextElement() override;
|
|
|
|
SwXParaFrameEnumerationImpl(const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode, SwFrameFormat* const pFormat);
|
|
virtual void SAL_CALL release() throw () override
|
|
{
|
|
SolarMutexGuard g;
|
|
OWeakObject::release();
|
|
}
|
|
SwUnoCursor& GetCursor()
|
|
{ return *m_pUnoCursor; }
|
|
void PurgeFrameClients()
|
|
{
|
|
if(!m_pUnoCursor)
|
|
{
|
|
m_vFrames.clear();
|
|
m_xNextObject = nullptr;
|
|
}
|
|
else
|
|
{
|
|
// removing orphaned SwDepends
|
|
const auto iter = std::remove_if(m_vFrames.begin(), m_vFrames.end(),
|
|
[] (std::shared_ptr<sw::FrameClient>& rEntry) -> bool { return !rEntry->GetRegisteredIn(); });
|
|
m_vFrames.erase(iter, m_vFrames.end());
|
|
}
|
|
}
|
|
void FillFrame();
|
|
bool CreateNextObject();
|
|
uno::Reference< text::XTextContent > m_xNextObject;
|
|
FrameClientList_t m_vFrames;
|
|
::sw::UnoCursorPointer m_pUnoCursor;
|
|
};
|
|
|
|
|
|
SwXParaFrameEnumeration* SwXParaFrameEnumeration::Create(const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode, SwFrameFormat* const pFormat)
|
|
{ return new SwXParaFrameEnumerationImpl(rPaM, eParaFrameMode, pFormat); }
|
|
|
|
SwXParaFrameEnumerationImpl::SwXParaFrameEnumerationImpl(
|
|
const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode,
|
|
SwFrameFormat* const pFormat)
|
|
: m_pUnoCursor(rPaM.GetDoc()->CreateUnoCursor(*rPaM.GetPoint()))
|
|
{
|
|
if (rPaM.HasMark())
|
|
{
|
|
GetCursor().SetMark();
|
|
*GetCursor().GetMark() = *rPaM.GetMark();
|
|
}
|
|
if (PARAFRAME_PORTION_PARAGRAPH == eParaFrameMode)
|
|
{
|
|
FrameClientSortList_t vFrames;
|
|
::CollectFrameAtNode(rPaM.GetPoint()->nNode, vFrames, false);
|
|
std::transform(vFrames.begin(), vFrames.end(),
|
|
std::back_inserter(m_vFrames),
|
|
[] (const FrameClientSortListEntry& rEntry) { return rEntry.pFrameClient; });
|
|
}
|
|
else if (pFormat)
|
|
{
|
|
m_vFrames.push_back(std::make_shared<sw::FrameClient>(pFormat));
|
|
}
|
|
else if ((PARAFRAME_PORTION_CHAR == eParaFrameMode) ||
|
|
(PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode))
|
|
{
|
|
if (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode)
|
|
{
|
|
//get all frames that are bound at paragraph or at character
|
|
for(const auto& pFlyFrame : rPaM.GetDoc()->GetAllFlyFormats(&GetCursor(), false, true))
|
|
{
|
|
const auto pFrameFormat = const_cast<SwFrameFormat*>(&pFlyFrame->GetFormat());
|
|
m_vFrames.push_back(std::make_shared<sw::FrameClient>(pFrameFormat));
|
|
}
|
|
}
|
|
FillFrame();
|
|
}
|
|
}
|
|
|
|
// Search for a FLYCNT text attribute at the cursor point and fill the frame
|
|
// into the array
|
|
void SwXParaFrameEnumerationImpl::FillFrame()
|
|
{
|
|
if(!m_pUnoCursor->GetNode().IsTextNode())
|
|
return;
|
|
// search for objects at the cursor - anchored at/as char
|
|
const auto pTextAttr = m_pUnoCursor->GetNode().GetTextNode()->GetTextAttrForCharAt(
|
|
m_pUnoCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FLYCNT);
|
|
if(!pTextAttr)
|
|
return;
|
|
const SwFormatFlyCnt& rFlyCnt = pTextAttr->GetFlyCnt();
|
|
SwFrameFormat* const pFrameFormat = rFlyCnt.GetFrameFormat();
|
|
m_vFrames.push_back(std::make_shared<sw::FrameClient>(pFrameFormat));
|
|
}
|
|
|
|
bool SwXParaFrameEnumerationImpl::CreateNextObject()
|
|
{
|
|
if (m_vFrames.empty())
|
|
return false;
|
|
|
|
SwFrameFormat* const pFormat = static_cast<SwFrameFormat*>(
|
|
m_vFrames.front()->GetRegisteredIn());
|
|
m_vFrames.pop_front();
|
|
// the format should be valid here, otherwise the client
|
|
// would have been removed by PurgeFrameClients
|
|
// check for a shape first
|
|
if(pFormat->Which() == RES_DRAWFRMFMT)
|
|
{
|
|
SdrObject* pObject(nullptr);
|
|
pFormat->CallSwClientNotify(sw::FindSdrObjectHint(pObject));
|
|
if(pObject)
|
|
m_xNextObject.set(pObject->getUnoShape(), uno::UNO_QUERY);
|
|
}
|
|
else
|
|
{
|
|
const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx();
|
|
OSL_ENSURE(pIdx, "where is the index?");
|
|
SwNode const*const pNd =
|
|
m_pUnoCursor->GetDoc()->GetNodes()[ pIdx->GetIndex() + 1 ];
|
|
|
|
if (!pNd->IsNoTextNode())
|
|
{
|
|
m_xNextObject.set(SwXTextFrame::CreateXTextFrame(
|
|
*pFormat->GetDoc(), pFormat));
|
|
}
|
|
else if (pNd->IsGrfNode())
|
|
{
|
|
m_xNextObject.set(SwXTextGraphicObject::CreateXTextGraphicObject(
|
|
*pFormat->GetDoc(), pFormat));
|
|
}
|
|
else
|
|
{
|
|
assert(pNd->IsOLENode());
|
|
m_xNextObject.set(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
|
|
*pFormat->GetDoc(), pFormat));
|
|
}
|
|
}
|
|
return m_xNextObject.is();
|
|
}
|
|
|
|
sal_Bool SAL_CALL
|
|
SwXParaFrameEnumerationImpl::hasMoreElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
PurgeFrameClients();
|
|
return m_xNextObject.is() || CreateNextObject();
|
|
}
|
|
|
|
uno::Any SAL_CALL SwXParaFrameEnumerationImpl::nextElement()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
PurgeFrameClients();
|
|
if (!m_xNextObject.is() && !m_vFrames.empty())
|
|
CreateNextObject();
|
|
if (!m_xNextObject.is())
|
|
throw container::NoSuchElementException();
|
|
uno::Any aRet;
|
|
aRet <<= m_xNextObject;
|
|
m_xNextObject = nullptr;
|
|
return aRet;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|