1440 lines
51 KiB
C++
1440 lines
51 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 <unocrsrhelper.hxx>
|
|
|
|
#include <map>
|
|
#include <algorithm>
|
|
|
|
#include <com/sun/star/beans/PropertyState.hpp>
|
|
#include <com/sun/star/embed/ElementModes.hpp>
|
|
#include <com/sun/star/embed/XStorage.hpp>
|
|
#include <com/sun/star/text/XTextSection.hpp>
|
|
|
|
#include <svx/svxids.hrc>
|
|
#include <svx/unoshape.hxx>
|
|
|
|
#include <cmdid.h>
|
|
#include <unotextrange.hxx>
|
|
#include <unodraw.hxx>
|
|
#include <unofootnote.hxx>
|
|
#include <unobookmark.hxx>
|
|
#include <unorefmark.hxx>
|
|
#include <unostyle.hxx>
|
|
#include <unoidx.hxx>
|
|
#include <unofield.hxx>
|
|
#include <unotbl.hxx>
|
|
#include <unosett.hxx>
|
|
#include <unoframe.hxx>
|
|
#include <unocrsr.hxx>
|
|
#include <doc.hxx>
|
|
#include <IDocumentUndoRedo.hxx>
|
|
#include <IDocumentRedlineAccess.hxx>
|
|
#include <IDocumentLayoutAccess.hxx>
|
|
#include <fmtftn.hxx>
|
|
#include <fmtpdsc.hxx>
|
|
#include <charfmt.hxx>
|
|
#include <pagedesc.hxx>
|
|
#include <docstyle.hxx>
|
|
#include <ndtxt.hxx>
|
|
#include <txtrfmrk.hxx>
|
|
#include <fmtfld.hxx>
|
|
#include <docsh.hxx>
|
|
#include <section.hxx>
|
|
#include <shellio.hxx>
|
|
#include <edimp.hxx>
|
|
#include <swundo.hxx>
|
|
#include <cntfrm.hxx>
|
|
#include <pagefrm.hxx>
|
|
#include <svl/eitem.hxx>
|
|
#include <docary.hxx>
|
|
#include <swtable.hxx>
|
|
#include <tox.hxx>
|
|
#include <doctxm.hxx>
|
|
#include <fchrfmt.hxx>
|
|
#include <editeng/flstitem.hxx>
|
|
#include <vcl/metric.hxx>
|
|
#include <svtools/ctrltool.hxx>
|
|
#include <sfx2/docfilt.hxx>
|
|
#include <sfx2/docfile.hxx>
|
|
#include <sfx2/fcontnr.hxx>
|
|
#include <svl/stritem.hxx>
|
|
#include <SwStyleNameMapper.hxx>
|
|
#include <redline.hxx>
|
|
#include <numrule.hxx>
|
|
#include <comphelper/storagehelper.hxx>
|
|
#include <unotools/mediadescriptor.hxx>
|
|
#include <comphelper/sequenceashashmap.hxx>
|
|
#include <SwNodeNum.hxx>
|
|
#include <fmtmeta.hxx>
|
|
#include <txtfld.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::text;
|
|
using namespace ::com::sun::star::table;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::lang;
|
|
|
|
namespace SwUnoCursorHelper
|
|
{
|
|
|
|
static SwPaM* lcl_createPamCopy(const SwPaM& rPam)
|
|
{
|
|
SwPaM *const pRet = new SwPaM(*rPam.GetPoint());
|
|
::sw::DeepCopyPaM(rPam, *pRet);
|
|
return pRet;
|
|
}
|
|
|
|
void GetSelectableFromAny(uno::Reference<uno::XInterface> const& xIfc,
|
|
SwDoc & rTargetDoc,
|
|
SwPaM *& o_rpPaM, std::pair<OUString, FlyCntType> & o_rFrame,
|
|
OUString & o_rTableName, SwUnoTableCrsr const*& o_rpTableCursor,
|
|
::sw::mark::IMark const*& o_rpMark,
|
|
std::vector<SdrObject *> & o_rSdrObjects)
|
|
{
|
|
uno::Reference<drawing::XShapes> const xShapes(xIfc, UNO_QUERY);
|
|
if (xShapes.is())
|
|
{
|
|
sal_Int32 nShapes(xShapes->getCount());
|
|
for (sal_Int32 i = 0; i < nShapes; ++i)
|
|
{
|
|
uno::Reference<lang::XUnoTunnel> xShape;
|
|
xShapes->getByIndex(i) >>= xShape;
|
|
if (xShape.is())
|
|
{
|
|
SvxShape *const pSvxShape(
|
|
::sw::UnoTunnelGetImplementation<SvxShape>(xShape));
|
|
if (pSvxShape)
|
|
{
|
|
SdrObject *const pSdrObject = pSvxShape->GetSdrObject();
|
|
if (pSdrObject)
|
|
{ // hmm... needs view to verify it's in right doc...
|
|
o_rSdrObjects.push_back(pSdrObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
uno::Reference<lang::XUnoTunnel> const xTunnel(xIfc, UNO_QUERY);
|
|
if (!xTunnel.is()) // everything below needs tunnel
|
|
{
|
|
return;
|
|
}
|
|
|
|
SwXShape *const pShape(::sw::UnoTunnelGetImplementation<SwXShape>(xTunnel));
|
|
if (pShape)
|
|
{
|
|
uno::Reference<uno::XAggregation> const xAgg(
|
|
pShape->GetAggregationInterface());
|
|
if (xAgg.is())
|
|
{
|
|
SvxShape *const pSvxShape(
|
|
::sw::UnoTunnelGetImplementation<SvxShape>(xTunnel));
|
|
if (pSvxShape)
|
|
{
|
|
SdrObject *const pSdrObject = pSvxShape->GetSdrObject();
|
|
if (pSdrObject)
|
|
{ // hmm... needs view to verify it's in right doc...
|
|
o_rSdrObjects.push_back(pSdrObject);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
OTextCursorHelper *const pCursor(
|
|
::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel));
|
|
if (pCursor)
|
|
{
|
|
if (pCursor->GetDoc() == &rTargetDoc)
|
|
{
|
|
o_rpPaM = lcl_createPamCopy(*pCursor->GetPaM());
|
|
}
|
|
return;
|
|
}
|
|
|
|
SwXTextRanges *const pRanges(
|
|
::sw::UnoTunnelGetImplementation<SwXTextRanges>(xTunnel));
|
|
if (pRanges)
|
|
{
|
|
SwUnoCrsr const* pUnoCrsr = pRanges->GetCursor();
|
|
if (pUnoCrsr && pUnoCrsr->GetDoc() == &rTargetDoc)
|
|
{
|
|
o_rpPaM = lcl_createPamCopy(*pUnoCrsr);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// check these before Range to prevent misinterpretation of text frames
|
|
// and cells also implement XTextRange
|
|
SwXFrame *const pFrame(
|
|
::sw::UnoTunnelGetImplementation<SwXFrame>(xTunnel));
|
|
if (pFrame)
|
|
{
|
|
const SwFrmFmt *const pFrmFmt(pFrame->GetFrmFmt());
|
|
if (pFrmFmt && pFrmFmt->GetDoc() == &rTargetDoc)
|
|
{
|
|
o_rFrame = std::make_pair(pFrmFmt->GetName(), pFrame->GetFlyCntType());
|
|
}
|
|
return;
|
|
}
|
|
|
|
SwXTextTable *const pTextTable(
|
|
::sw::UnoTunnelGetImplementation<SwXTextTable>(xTunnel));
|
|
if (pTextTable)
|
|
{
|
|
SwFrmFmt *const pFrmFmt(pTextTable->GetFrmFmt());
|
|
if (pFrmFmt && pFrmFmt->GetDoc() == &rTargetDoc)
|
|
{
|
|
o_rTableName = pFrmFmt->GetName();
|
|
}
|
|
return;
|
|
}
|
|
|
|
SwXCell *const pCell(
|
|
::sw::UnoTunnelGetImplementation<SwXCell>(xTunnel));
|
|
if (pCell)
|
|
{
|
|
SwFrmFmt *const pFrmFmt(pCell->GetFrmFmt());
|
|
if (pFrmFmt && pFrmFmt->GetDoc() == &rTargetDoc)
|
|
{
|
|
SwTableBox * pBox = pCell->GetTblBox();
|
|
SwTable *const pTable = SwTable::FindTable(pFrmFmt);
|
|
// ??? what's the benefit of setting pBox in this convoluted way?
|
|
pBox = pCell->FindBox(pTable, pBox);
|
|
if (pBox)
|
|
{
|
|
SwPosition const aPos(*pBox->GetSttNd());
|
|
SwPaM aPam(aPos);
|
|
aPam.Move(fnMoveForward, fnGoNode);
|
|
o_rpPaM = lcl_createPamCopy(aPam);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
uno::Reference<text::XTextRange> const xTextRange(xTunnel, UNO_QUERY);
|
|
if (xTextRange.is())
|
|
{
|
|
SwUnoInternalPaM aPam(rTargetDoc);
|
|
if (::sw::XTextRangeToSwPaM(aPam, xTextRange))
|
|
{
|
|
o_rpPaM = lcl_createPamCopy(aPam);
|
|
}
|
|
return;
|
|
}
|
|
|
|
SwXCellRange *const pCellRange(
|
|
::sw::UnoTunnelGetImplementation<SwXCellRange>(xTunnel));
|
|
if (pCellRange)
|
|
{
|
|
SwUnoCrsr const*const pUnoCrsr(pCellRange->GetTblCrsr());
|
|
if (pUnoCrsr && pUnoCrsr->GetDoc() == &rTargetDoc)
|
|
{
|
|
// probably can't copy it to o_rpPaM for this since it's
|
|
// a SwTableCursor
|
|
o_rpTableCursor = dynamic_cast<SwUnoTableCrsr const*>(pUnoCrsr);
|
|
}
|
|
return;
|
|
}
|
|
|
|
::sw::mark::IMark const*const pMark(
|
|
SwXBookmark::GetBookmarkInDoc(& rTargetDoc, xTunnel));
|
|
if (pMark)
|
|
{
|
|
o_rpMark = pMark;
|
|
return;
|
|
}
|
|
}
|
|
|
|
uno::Reference<text::XTextContent>
|
|
GetNestedTextContent(SwTxtNode & rTextNode, sal_Int32 const nIndex,
|
|
bool const bParent)
|
|
{
|
|
// these should be unambiguous because of the dummy character
|
|
SwTxtNode::GetTxtAttrMode const eMode( (bParent)
|
|
? SwTxtNode::PARENT : SwTxtNode::EXPAND );
|
|
SwTxtAttr *const pMetaTxtAttr =
|
|
rTextNode.GetTxtAttrAt(nIndex, RES_TXTATR_META, eMode);
|
|
SwTxtAttr *const pMetaFieldTxtAttr =
|
|
rTextNode.GetTxtAttrAt(nIndex, RES_TXTATR_METAFIELD, eMode);
|
|
// which is innermost?
|
|
SwTxtAttr *const pTxtAttr = (pMetaTxtAttr)
|
|
? ((pMetaFieldTxtAttr)
|
|
? ((pMetaFieldTxtAttr->GetStart() >
|
|
pMetaTxtAttr->GetStart())
|
|
? pMetaFieldTxtAttr : pMetaTxtAttr)
|
|
: pMetaTxtAttr)
|
|
: pMetaFieldTxtAttr;
|
|
uno::Reference<XTextContent> xRet;
|
|
if (pTxtAttr)
|
|
{
|
|
::sw::Meta *const pMeta(
|
|
static_cast<SwFmtMeta &>(pTxtAttr->GetAttr()).GetMeta());
|
|
OSL_ASSERT(pMeta);
|
|
xRet.set(pMeta->MakeUnoObject(), uno::UNO_QUERY);
|
|
}
|
|
return xRet;
|
|
}
|
|
|
|
// Read the special properties of the cursor
|
|
bool getCrsrPropertyValue(const SfxItemPropertySimpleEntry& rEntry
|
|
, SwPaM& rPam
|
|
, Any *pAny
|
|
, PropertyState& eState
|
|
, const SwTxtNode* pNode )
|
|
{
|
|
PropertyState eNewState = PropertyState_DIRECT_VALUE;
|
|
bool bDone = true;
|
|
switch(rEntry.nWID)
|
|
{
|
|
case FN_UNO_PARA_CONT_PREV_SUBTREE:
|
|
if (pAny)
|
|
{
|
|
const SwTxtNode * pTmpNode = pNode;
|
|
|
|
if (!pTmpNode)
|
|
pTmpNode = rPam.GetNode().GetTxtNode();
|
|
|
|
bool bRet = false;
|
|
|
|
if ( pTmpNode &&
|
|
pTmpNode->GetNum() &&
|
|
pTmpNode->GetNum()->IsContinueingPreviousSubTree() )
|
|
{
|
|
bRet = true;
|
|
}
|
|
|
|
*pAny <<= bRet;
|
|
}
|
|
break;
|
|
case FN_UNO_PARA_NUM_STRING:
|
|
if (pAny)
|
|
{
|
|
const SwTxtNode * pTmpNode = pNode;
|
|
|
|
if (!pTmpNode)
|
|
pTmpNode = rPam.GetNode().GetTxtNode();
|
|
|
|
OUString sRet;
|
|
if ( pTmpNode && pTmpNode->GetNum() )
|
|
{
|
|
sRet = pTmpNode->GetNumString();
|
|
}
|
|
|
|
*pAny <<= sRet;
|
|
}
|
|
break;
|
|
case RES_PARATR_OUTLINELEVEL:
|
|
if (pAny)
|
|
{
|
|
const SwTxtNode * pTmpNode = pNode;
|
|
|
|
if (!pTmpNode)
|
|
pTmpNode = rPam.GetNode().GetTxtNode();
|
|
|
|
sal_Int16 nRet = -1;
|
|
if ( pTmpNode )
|
|
nRet = sal::static_int_cast< sal_Int16 >( pTmpNode->GetAttrOutlineLevel() );
|
|
|
|
*pAny <<= nRet;
|
|
}
|
|
break;
|
|
case FN_UNO_PARA_CONDITIONAL_STYLE_NAME:
|
|
case FN_UNO_PARA_STYLE :
|
|
{
|
|
SwFmtColl* pFmt = 0;
|
|
if(pNode)
|
|
pFmt = FN_UNO_PARA_CONDITIONAL_STYLE_NAME == rEntry.nWID
|
|
? pNode->GetFmtColl() : &pNode->GetAnyFmtColl();
|
|
else
|
|
{
|
|
pFmt = SwUnoCursorHelper::GetCurTxtFmtColl(rPam,
|
|
FN_UNO_PARA_CONDITIONAL_STYLE_NAME == rEntry.nWID);
|
|
}
|
|
if(pFmt)
|
|
{
|
|
if( pAny )
|
|
{
|
|
OUString sVal;
|
|
SwStyleNameMapper::FillProgName(pFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
|
|
*pAny <<= sVal;
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_AMBIGUOUS_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_PAGE_STYLE :
|
|
{
|
|
OUString sVal;
|
|
GetCurPageStyle(rPam, sVal);
|
|
if( pAny )
|
|
*pAny <<= sVal;
|
|
if(sVal.isEmpty())
|
|
eNewState = PropertyState_AMBIGUOUS_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_NUM_START_VALUE :
|
|
if( pAny )
|
|
{
|
|
sal_Int16 nValue = IsNodeNumStart(rPam, eNewState);
|
|
*pAny <<= nValue;
|
|
}
|
|
break;
|
|
case FN_UNO_NUM_LEVEL :
|
|
case FN_UNO_IS_NUMBER :
|
|
// #i91601#
|
|
case FN_UNO_LIST_ID:
|
|
case FN_NUMBER_NEWSTART:
|
|
{
|
|
// a multi selection is not considered
|
|
const SwTxtNode* pTxtNd = rPam.GetNode().GetTxtNode();
|
|
if ( pTxtNd && pTxtNd->IsInList() )
|
|
{
|
|
if( pAny )
|
|
{
|
|
if(rEntry.nWID == FN_UNO_NUM_LEVEL)
|
|
*pAny <<= (sal_Int16)(pTxtNd->GetActualListLevel());
|
|
else if(rEntry.nWID == FN_UNO_IS_NUMBER)
|
|
{
|
|
sal_Bool bIsNumber = pTxtNd->IsCountedInList();
|
|
pAny->setValue(&bIsNumber, ::getBooleanCppuType());
|
|
}
|
|
// #i91601#
|
|
else if ( rEntry.nWID == FN_UNO_LIST_ID )
|
|
{
|
|
*pAny <<= pTxtNd->GetListId();
|
|
}
|
|
else
|
|
{
|
|
sal_Bool bIsRestart = pTxtNd->IsListRestart();
|
|
pAny->setValue(&bIsRestart, ::getBooleanCppuType());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
|
|
if( pAny )
|
|
{
|
|
// #i30838# set default values for default properties
|
|
if(rEntry.nWID == FN_UNO_NUM_LEVEL)
|
|
*pAny <<= static_cast<sal_Int16>( 0 );
|
|
else if(rEntry.nWID == FN_UNO_IS_NUMBER)
|
|
*pAny <<= false;
|
|
// #i91601#
|
|
else if ( rEntry.nWID == FN_UNO_LIST_ID )
|
|
{
|
|
*pAny <<= OUString();
|
|
}
|
|
else
|
|
*pAny <<= false;
|
|
}
|
|
}
|
|
//PROPERTY_MAYBEVOID!
|
|
}
|
|
break;
|
|
case FN_UNO_NUM_RULES :
|
|
if( pAny )
|
|
getNumberingProperty(rPam, eNewState, pAny);
|
|
else
|
|
{
|
|
if( !rPam.GetDoc()->GetNumRuleAtPos( *rPam.GetPoint() ) )
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_DOCUMENT_INDEX_MARK:
|
|
{
|
|
::std::vector<SwTxtAttr *> marks;
|
|
if (rPam.GetNode().IsTxtNode())
|
|
{
|
|
marks = rPam.GetNode().GetTxtNode()->GetTxtAttrsAt(
|
|
rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_TOXMARK);
|
|
}
|
|
if (marks.size())
|
|
{
|
|
if( pAny )
|
|
{ // hmm... can only return 1 here
|
|
SwTOXMark & rMark =
|
|
static_cast<SwTOXMark &>((*marks.begin())->GetAttr());
|
|
const uno::Reference< text::XDocumentIndexMark > xRef =
|
|
SwXDocumentIndexMark::CreateXDocumentIndexMark(
|
|
*rPam.GetDoc(), &rMark);
|
|
(*pAny) <<= xRef;
|
|
}
|
|
}
|
|
else
|
|
//also here - indistinguishable
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_DOCUMENT_INDEX:
|
|
{
|
|
const SwTOXBase* pBase = rPam.GetDoc()->GetCurTOX(
|
|
*rPam.Start() );
|
|
if( pBase )
|
|
{
|
|
if( pAny )
|
|
{
|
|
const uno::Reference< text::XDocumentIndex > xRef =
|
|
SwXDocumentIndex::CreateXDocumentIndex(*rPam.GetDoc(),
|
|
static_cast<SwTOXBaseSection const*>(pBase));
|
|
(*pAny) <<= xRef;
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_TEXT_FIELD:
|
|
{
|
|
const SwPosition *pPos = rPam.Start();
|
|
const SwTxtNode *pTxtNd =
|
|
rPam.GetDoc()->GetNodes()[pPos->nNode.GetIndex()]->GetTxtNode();
|
|
const SwTxtAttr* pTxtAttr = (pTxtNd)
|
|
? pTxtNd->GetFldTxtAttrAt( pPos->nContent.GetIndex(), true )
|
|
: 0;
|
|
if ( pTxtAttr != NULL )
|
|
{
|
|
if( pAny )
|
|
{
|
|
uno::Reference<text::XTextField> const xField(
|
|
SwXTextField::CreateXTextField(rPam.GetDoc(),
|
|
&pTxtAttr->GetFmtFld()));
|
|
*pAny <<= xField;
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_TEXT_TABLE:
|
|
case FN_UNO_CELL:
|
|
{
|
|
SwStartNode* pSttNode = rPam.GetNode().StartOfSectionNode();
|
|
SwStartNodeType eType = pSttNode->GetStartNodeType();
|
|
if(SwTableBoxStartNode == eType)
|
|
{
|
|
if( pAny )
|
|
{
|
|
const SwTableNode* pTblNode = pSttNode->FindTableNode();
|
|
SwFrmFmt* pTableFmt = (SwFrmFmt*)pTblNode->GetTable().GetFrmFmt();
|
|
//SwTable& rTable = ((SwTableNode*)pSttNode)->GetTable();
|
|
if(FN_UNO_TEXT_TABLE == rEntry.nWID)
|
|
{
|
|
uno::Reference< XTextTable > xTable = SwXTextTables::GetObject(*pTableFmt);
|
|
pAny->setValue(&xTable, cppu::UnoType<XTextTable>::get());
|
|
}
|
|
else
|
|
{
|
|
SwTableBox* pBox = pSttNode->GetTblBox();
|
|
uno::Reference< XCell > xCell = SwXCell::CreateXCell(pTableFmt, pBox);
|
|
pAny->setValue(&xCell, cppu::UnoType<XCell>::get());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_TEXT_FRAME:
|
|
{
|
|
SwStartNode* pSttNode = rPam.GetNode().StartOfSectionNode();
|
|
SwStartNodeType eType = pSttNode->GetStartNodeType();
|
|
|
|
SwFrmFmt* pFmt;
|
|
if(eType == SwFlyStartNode && 0 != (pFmt = pSttNode->GetFlyFmt()))
|
|
{
|
|
if( pAny )
|
|
{
|
|
uno::Reference<XTextFrame> const xFrame(
|
|
SwXTextFrame::CreateXTextFrame(*pFmt->GetDoc(), pFmt));
|
|
(*pAny) <<= xFrame;
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_TEXT_SECTION:
|
|
{
|
|
SwSection* pSect = rPam.GetDoc()->GetCurrSection(*rPam.GetPoint());
|
|
if(pSect)
|
|
{
|
|
if( pAny )
|
|
{
|
|
uno::Reference< XTextSection > xSect = SwXTextSections::GetObject( *pSect->GetFmt() );
|
|
pAny->setValue(&xSect, cppu::UnoType<XTextSection>::get());
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_ENDNOTE:
|
|
case FN_UNO_FOOTNOTE:
|
|
{
|
|
SwTxtAttr *const pTxtAttr = rPam.GetNode().IsTxtNode() ?
|
|
rPam.GetNode().GetTxtNode()->GetTxtAttrForCharAt(
|
|
rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN) : 0;
|
|
if(pTxtAttr)
|
|
{
|
|
const SwFmtFtn& rFtn = pTxtAttr->GetFtn();
|
|
if(rFtn.IsEndNote() == (FN_UNO_ENDNOTE == rEntry.nWID))
|
|
{
|
|
if( pAny )
|
|
{
|
|
const uno::Reference< text::XFootnote > xFootnote =
|
|
SwXFootnote::CreateXFootnote(*rPam.GetDoc(),
|
|
&const_cast<SwFmtFtn&>(rFtn));
|
|
*pAny <<= xFootnote;
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_REFERENCE_MARK:
|
|
{
|
|
::std::vector<SwTxtAttr *> marks;
|
|
if (rPam.GetNode().IsTxtNode())
|
|
{
|
|
marks = (
|
|
rPam.GetNode().GetTxtNode()->GetTxtAttrsAt(
|
|
rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
|
|
}
|
|
if (marks.size())
|
|
{
|
|
if( pAny )
|
|
{ // hmm... can only return 1 here
|
|
const SwFmtRefMark& rRef = (*marks.begin())->GetRefMark();
|
|
uno::Reference<XTextContent> const xRef =
|
|
SwXReferenceMark::CreateXReferenceMark(*rPam.GetDoc(),
|
|
const_cast<SwFmtRefMark*>(&rRef));
|
|
pAny->setValue(&xRef, cppu::UnoType<XTextContent>::get());
|
|
}
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case FN_UNO_NESTED_TEXT_CONTENT:
|
|
{
|
|
uno::Reference<XTextContent> const xRet(rPam.GetNode().IsTxtNode()
|
|
? GetNestedTextContent(*rPam.GetNode().GetTxtNode(),
|
|
rPam.GetPoint()->nContent.GetIndex(), false)
|
|
: 0);
|
|
if (xRet.is())
|
|
{
|
|
if (pAny)
|
|
{
|
|
(*pAny) <<= xRet;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
}
|
|
break;
|
|
case FN_UNO_CHARFMT_SEQUENCE:
|
|
{
|
|
|
|
SwTxtNode *const pTxtNode = rPam.GetNode().GetTxtNode();
|
|
if (&rPam.GetNode(true) == &rPam.GetNode(false)
|
|
&& pTxtNode && pTxtNode->GetpSwpHints())
|
|
{
|
|
sal_Int32 nPaMStart = rPam.GetPoint()->nContent.GetIndex();
|
|
sal_Int32 nPaMEnd = rPam.GetMark() ? rPam.GetMark()->nContent.GetIndex() : nPaMStart;
|
|
if(nPaMStart > nPaMEnd)
|
|
{
|
|
std::swap(nPaMStart, nPaMEnd);
|
|
}
|
|
Sequence< OUString> aCharStyles;
|
|
SwpHints* pHints = pTxtNode->GetpSwpHints();
|
|
for( size_t nAttr = 0; nAttr < pHints->GetStartCount(); ++nAttr )
|
|
{
|
|
SwTxtAttr* pAttr = pHints->GetStart( nAttr );
|
|
if(pAttr->Which() != RES_TXTATR_CHARFMT)
|
|
continue;
|
|
const sal_Int32 nAttrStart = pAttr->GetStart();
|
|
const sal_Int32 nAttrEnd = *pAttr->GetEnd();
|
|
//check if the attribute touches the selection
|
|
if( ( nAttrEnd > nPaMStart && nAttrStart < nPaMEnd ) ||
|
|
( !nAttrStart && !nAttrEnd && !nPaMStart && !nPaMEnd ) )
|
|
{
|
|
//check for overlapping
|
|
if(nAttrStart > nPaMStart ||
|
|
nAttrEnd < nPaMEnd)
|
|
{
|
|
aCharStyles.realloc(0);
|
|
eNewState = PropertyState_AMBIGUOUS_VALUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//now the attribute should start before or at the selection
|
|
//and it should end at the end of the selection or behind
|
|
OSL_ENSURE(nAttrStart <= nPaMStart && nAttrEnd >=nPaMEnd,
|
|
"attribute overlaps or is outside");
|
|
//now the name of the style has to be added to the sequence
|
|
aCharStyles.realloc(aCharStyles.getLength() + 1);
|
|
OSL_ENSURE(pAttr->GetCharFmt().GetCharFmt(), "no character format set");
|
|
aCharStyles.getArray()[aCharStyles.getLength() - 1] =
|
|
SwStyleNameMapper::GetProgName(
|
|
pAttr->GetCharFmt().GetCharFmt()->GetName(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
|
|
}
|
|
}
|
|
|
|
}
|
|
eNewState =
|
|
aCharStyles.getLength() ?
|
|
PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
if(pAny)
|
|
(*pAny) <<= aCharStyles;
|
|
}
|
|
else
|
|
eNewState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
break;
|
|
case RES_TXTATR_CHARFMT:
|
|
// no break here!
|
|
default: bDone = false;
|
|
}
|
|
if( bDone )
|
|
eState = eNewState;
|
|
return bDone;
|
|
};
|
|
|
|
sal_Int16 IsNodeNumStart(SwPaM& rPam, PropertyState& eState)
|
|
{
|
|
const SwTxtNode* pTxtNd = rPam.GetNode().GetTxtNode();
|
|
// correction: check, if restart value is set at the text node and use
|
|
// new method <SwTxtNode::GetAttrListRestartValue()> to retrieve the value
|
|
if ( pTxtNd && pTxtNd->GetNumRule() && pTxtNd->IsListRestart() &&
|
|
pTxtNd->HasAttrListRestartValue() )
|
|
{
|
|
eState = PropertyState_DIRECT_VALUE;
|
|
sal_Int16 nTmp = sal::static_int_cast< sal_Int16 >(pTxtNd->GetAttrListRestartValue());
|
|
return nTmp;
|
|
}
|
|
eState = PropertyState_DEFAULT_VALUE;
|
|
return -1;
|
|
}
|
|
|
|
void setNumberingProperty(const Any& rValue, SwPaM& rPam)
|
|
{
|
|
uno::Reference<XIndexReplace> xIndexReplace;
|
|
if(rValue >>= xIndexReplace)
|
|
{
|
|
SwXNumberingRules* pSwNum = 0;
|
|
|
|
uno::Reference<XUnoTunnel> xNumTunnel(xIndexReplace, UNO_QUERY);
|
|
if(xNumTunnel.is())
|
|
{
|
|
pSwNum = reinterpret_cast< SwXNumberingRules * >(
|
|
sal::static_int_cast< sal_IntPtr >( xNumTunnel->getSomething( SwXNumberingRules::getUnoTunnelId() )));
|
|
}
|
|
|
|
if(pSwNum)
|
|
{
|
|
SwDoc* pDoc = rPam.GetDoc();
|
|
if(pSwNum->GetNumRule())
|
|
{
|
|
SwNumRule aRule(*pSwNum->GetNumRule());
|
|
const OUString* pNewCharStyles = pSwNum->GetNewCharStyleNames();
|
|
const OUString* pBulletFontNames = pSwNum->GetBulletFontNames();
|
|
for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
|
|
{
|
|
SwNumFmt aFmt(aRule.Get( i ));
|
|
if (!pNewCharStyles[i].isEmpty() &&
|
|
!SwXNumberingRules::isInvalidStyle(pNewCharStyles[i]) &&
|
|
(!aFmt.GetCharFmt() || pNewCharStyles[i] != aFmt.GetCharFmt()->GetName()))
|
|
{
|
|
if (pNewCharStyles[i].isEmpty())
|
|
{
|
|
// FIXME
|
|
// Is something missing/wrong here?
|
|
// if condition is always false due to outer check!
|
|
aFmt.SetCharFmt(0);
|
|
}
|
|
else
|
|
{
|
|
|
|
// get CharStyle and set the rule
|
|
const size_t nChCount = pDoc->GetCharFmts()->size();
|
|
SwCharFmt* pCharFmt = 0;
|
|
for(size_t nCharFmt = 0; nCharFmt < nChCount; ++nCharFmt)
|
|
{
|
|
SwCharFmt& rChFmt = *((*(pDoc->GetCharFmts()))[nCharFmt]);
|
|
if(rChFmt.GetName() == pNewCharStyles[i])
|
|
{
|
|
pCharFmt = &rChFmt;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!pCharFmt)
|
|
{
|
|
SfxStyleSheetBasePool* pPool = pDoc->GetDocShell()->GetStyleSheetPool();
|
|
SfxStyleSheetBase* pBase;
|
|
pBase = pPool->Find(pNewCharStyles[i], SFX_STYLE_FAMILY_CHAR);
|
|
// shall it really be created?
|
|
if(!pBase)
|
|
pBase = &pPool->Make(pNewCharStyles[i], SFX_STYLE_FAMILY_PAGE);
|
|
pCharFmt = ((SwDocStyleSheet*)pBase)->GetCharFmt();
|
|
}
|
|
if(pCharFmt)
|
|
aFmt.SetCharFmt(pCharFmt);
|
|
}
|
|
}
|
|
//Now again for fonts
|
|
if(
|
|
!pBulletFontNames[i].isEmpty() &&
|
|
!SwXNumberingRules::isInvalidStyle(pBulletFontNames[i]) &&
|
|
(!aFmt.GetBulletFont() || aFmt.GetBulletFont()->GetName() != pBulletFontNames[i])
|
|
)
|
|
{
|
|
const SvxFontListItem* pFontListItem =
|
|
(const SvxFontListItem* )pDoc->GetDocShell()
|
|
->GetItem( SID_ATTR_CHAR_FONTLIST );
|
|
const FontList* pList = pFontListItem->GetFontList();
|
|
|
|
vcl::FontInfo aInfo = pList->Get(
|
|
pBulletFontNames[i],WEIGHT_NORMAL, ITALIC_NONE);
|
|
vcl::Font aFont(aInfo);
|
|
aFmt.SetBulletFont(&aFont);
|
|
}
|
|
aRule.Set( i, aFmt );
|
|
}
|
|
UnoActionContext aAction(pDoc);
|
|
|
|
if( rPam.GetNext() != &rPam ) // Multiple selection?
|
|
{
|
|
pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
|
|
SwPamRanges aRangeArr( rPam );
|
|
SwPaM aPam( *rPam.GetPoint() );
|
|
for ( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
|
|
{
|
|
// no start of a new list
|
|
pDoc->SetNumRule( aRangeArr.SetPam( n, aPam ), aRule, false );
|
|
}
|
|
pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
|
|
}
|
|
else
|
|
{
|
|
// no start of a new list
|
|
pDoc->SetNumRule( rPam, aRule, false );
|
|
}
|
|
|
|
}
|
|
else if(!pSwNum->GetCreatedNumRuleName().isEmpty())
|
|
{
|
|
UnoActionContext aAction( pDoc );
|
|
SwNumRule* pRule = pDoc->FindNumRulePtr( pSwNum->GetCreatedNumRuleName() );
|
|
if ( !pRule )
|
|
throw RuntimeException();
|
|
// no start of a new list
|
|
pDoc->SetNumRule( rPam, *pRule, false );
|
|
}
|
|
else
|
|
{
|
|
// #i103817#
|
|
// outline numbering
|
|
UnoActionContext aAction(pDoc);
|
|
SwNumRule* pRule = pDoc->GetOutlineNumRule();
|
|
if(!pRule)
|
|
throw RuntimeException();
|
|
pDoc->SetNumRule( rPam, *pRule, false );
|
|
}
|
|
}
|
|
}
|
|
else if ( rValue.getValueType() == ::getVoidCppuType() )
|
|
{
|
|
rPam.GetDoc()->DelNumRules(rPam);
|
|
}
|
|
}
|
|
|
|
void getNumberingProperty(SwPaM& rPam, PropertyState& eState, Any * pAny )
|
|
{
|
|
const SwNumRule* pNumRule = rPam.GetDoc()->GetNumRuleAtPos( *rPam.GetPoint() );
|
|
if(pNumRule)
|
|
{
|
|
uno::Reference< XIndexReplace > xNum = new SwXNumberingRules(*pNumRule);
|
|
if ( pAny )
|
|
pAny->setValue(&xNum, cppu::UnoType<XIndexReplace>::get());
|
|
eState = PropertyState_DIRECT_VALUE;
|
|
}
|
|
else
|
|
eState = PropertyState_DEFAULT_VALUE;
|
|
}
|
|
|
|
void GetCurPageStyle(SwPaM& rPaM, OUString &rString)
|
|
{
|
|
if (!rPaM.GetCntntNode())
|
|
return; // TODO: is there an easy way to get it for tables/sections?
|
|
SwCntntFrm* pFrame = rPaM.GetCntntNode()->getLayoutFrm(rPaM.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
|
|
if(pFrame)
|
|
{
|
|
const SwPageFrm* pPage = pFrame->FindPageFrm();
|
|
if(pPage)
|
|
{
|
|
SwStyleNameMapper::FillProgName(pPage->GetPageDesc()->GetName(),
|
|
rString, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// reset special properties of the cursor
|
|
void resetCrsrPropertyValue(const SfxItemPropertySimpleEntry& rEntry, SwPaM& rPam)
|
|
{
|
|
SwDoc* pDoc = rPam.GetDoc();
|
|
switch(rEntry.nWID)
|
|
{
|
|
case FN_UNO_PARA_STYLE :
|
|
break;
|
|
case FN_UNO_PAGE_STYLE :
|
|
break;
|
|
case FN_UNO_NUM_START_VALUE :
|
|
{
|
|
UnoActionContext aAction(pDoc);
|
|
|
|
if( rPam.GetNext() != &rPam ) // Multiple selection?
|
|
{
|
|
pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
|
|
SwPamRanges aRangeArr( rPam );
|
|
SwPaM aPam( *rPam.GetPoint() );
|
|
for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
|
|
pDoc->SetNodeNumStart( *aRangeArr.SetPam( n, aPam ).GetPoint(), 1 );
|
|
pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
|
|
}
|
|
else
|
|
pDoc->SetNodeNumStart( *rPam.GetPoint(), 0 );
|
|
}
|
|
|
|
break;
|
|
case FN_UNO_NUM_LEVEL :
|
|
break;
|
|
case FN_UNO_NUM_RULES:
|
|
break;
|
|
case FN_UNO_CHARFMT_SEQUENCE:
|
|
{
|
|
std::set<sal_uInt16> aWhichIds;
|
|
aWhichIds.insert( RES_TXTATR_CHARFMT);
|
|
pDoc->ResetAttrs(rPam, true, aWhichIds);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void InsertFile(SwUnoCrsr* pUnoCrsr, const OUString& rURL,
|
|
const uno::Sequence< beans::PropertyValue >& rOptions)
|
|
throw (lang::IllegalArgumentException, io::IOException,
|
|
uno::RuntimeException, std::exception)
|
|
{
|
|
SfxMedium* pMed = 0;
|
|
SwDoc* pDoc = pUnoCrsr->GetDoc();
|
|
SwDocShell* pDocSh = pDoc->GetDocShell();
|
|
utl::MediaDescriptor aMediaDescriptor( rOptions );
|
|
OUString sFileName = rURL;
|
|
OUString sFilterName, sFilterOptions, sPassword, sBaseURL;
|
|
uno::Reference < io::XStream > xStream;
|
|
uno::Reference < io::XInputStream > xInputStream;
|
|
|
|
if( sFileName.isEmpty() )
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_URL()] >>= sFileName;
|
|
if( sFileName.isEmpty() )
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_FILENAME()] >>= sFileName;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_STREAM()] >>= xStream;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] >>= sFilterName;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_FILTEROPTIONS()] >>= sFilterOptions;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_PASSWORD()] >>= sPassword;
|
|
aMediaDescriptor[utl::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= sBaseURL;
|
|
if ( !xInputStream.is() && xStream.is() )
|
|
xInputStream = xStream->getInputStream();
|
|
|
|
if(!pDocSh || (sFileName.isEmpty() && !xInputStream.is()))
|
|
return;
|
|
|
|
SfxObjectFactory& rFact = pDocSh->GetFactory();
|
|
const SfxFilter* pFilter = rFact.GetFilterContainer()->GetFilter4FilterName( sFilterName );
|
|
uno::Reference < embed::XStorage > xReadStorage;
|
|
if( xInputStream.is() )
|
|
{
|
|
uno::Sequence< uno::Any > aArgs( 2 );
|
|
aArgs[0] <<= xInputStream;
|
|
aArgs[1] <<= embed::ElementModes::READ;
|
|
try
|
|
{
|
|
xReadStorage = uno::Reference< embed::XStorage >(
|
|
::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
|
|
uno::UNO_QUERY );
|
|
}
|
|
catch( const io::IOException& rEx)
|
|
{
|
|
(void)rEx;
|
|
}
|
|
}
|
|
if ( !pFilter )
|
|
{
|
|
if( xInputStream.is() && !xReadStorage.is())
|
|
{
|
|
pMed = new SfxMedium;
|
|
pMed->setStreamToLoadFrom(xInputStream, true );
|
|
}
|
|
else
|
|
pMed = xReadStorage.is() ?
|
|
new SfxMedium(xReadStorage, sBaseURL, 0 ) :
|
|
new SfxMedium(sFileName, STREAM_READ, 0, 0 );
|
|
if( !sBaseURL.isEmpty() )
|
|
pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, sBaseURL ) );
|
|
|
|
SfxFilterMatcher aMatcher( rFact.GetFilterContainer()->GetName() );
|
|
ErrCode nErr = aMatcher.GuessFilter(*pMed, &pFilter, SFX_FILTER_VERSION_NONE);
|
|
if ( nErr || !pFilter)
|
|
DELETEZ(pMed);
|
|
else
|
|
pMed->SetFilter( pFilter );
|
|
}
|
|
else
|
|
{
|
|
if(!pMed)
|
|
{
|
|
if( xInputStream.is() && !xReadStorage.is())
|
|
{
|
|
pMed = new SfxMedium;
|
|
pMed->setStreamToLoadFrom(xInputStream, true );
|
|
pMed->SetFilter( pFilter );
|
|
}
|
|
else
|
|
{
|
|
if( xReadStorage.is() )
|
|
{
|
|
pMed = new SfxMedium(xReadStorage, sBaseURL, 0 );
|
|
pMed->SetFilter( pFilter );
|
|
}
|
|
else
|
|
pMed = new SfxMedium(sFileName, STREAM_READ, pFilter, 0);
|
|
}
|
|
}
|
|
if(!sFilterOptions.isEmpty())
|
|
pMed->GetItemSet()->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, sFilterOptions ) );
|
|
if(!sBaseURL.isEmpty())
|
|
pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, sBaseURL ) );
|
|
}
|
|
|
|
if( !pMed )
|
|
return;
|
|
|
|
// this sourcecode is not responsible for the lifetime of the shell, SfxObjectShellLock should not be used
|
|
SfxObjectShellRef aRef( pDocSh );
|
|
|
|
pMed->Download(); // if necessary: start the download
|
|
if( aRef.Is() && 1 < aRef->GetRefCount() ) // Ref still valid?
|
|
{
|
|
SwReader* pRdr;
|
|
SfxItemSet* pSet = pMed->GetItemSet();
|
|
pSet->Put(SfxBoolItem(FN_API_CALL, true));
|
|
if(!sPassword.isEmpty())
|
|
pSet->Put(SfxStringItem(SID_PASSWORD, sPassword));
|
|
Reader *pRead = pDocSh->StartConvertFrom( *pMed, &pRdr, 0, pUnoCrsr);
|
|
if( pRead )
|
|
{
|
|
|
|
UnoActionContext aContext(pDoc);
|
|
|
|
if(pUnoCrsr->HasMark())
|
|
pDoc->getIDocumentContentOperations().DeleteAndJoin(*pUnoCrsr);
|
|
|
|
SwNodeIndex aSave( pUnoCrsr->GetPoint()->nNode, -1 );
|
|
sal_Int32 nCntnt = pUnoCrsr->GetPoint()->nContent.GetIndex();
|
|
|
|
sal_uInt32 nErrno = pRdr->Read( *pRead ); // and paste the document
|
|
|
|
if(!nErrno)
|
|
{
|
|
++aSave;
|
|
pUnoCrsr->SetMark();
|
|
pUnoCrsr->GetMark()->nNode = aSave;
|
|
|
|
SwCntntNode* pCntNode = aSave.GetNode().GetCntntNode();
|
|
if( !pCntNode )
|
|
nCntnt = 0;
|
|
pUnoCrsr->GetMark()->nContent.Assign( pCntNode, nCntnt );
|
|
}
|
|
|
|
delete pRdr;
|
|
|
|
}
|
|
}
|
|
delete pMed;
|
|
}
|
|
|
|
// insert text and scan for CR characters in order to insert
|
|
// paragraph breaks at those positions by calling SplitNode
|
|
bool DocInsertStringSplitCR(
|
|
SwDoc &rDoc,
|
|
const SwPaM &rNewCursor,
|
|
const OUString &rText,
|
|
const bool bForceExpandHints )
|
|
{
|
|
bool bOK = true;
|
|
|
|
const enum IDocumentContentOperations::InsertFlags nInsertFlags =
|
|
(bForceExpandHints)
|
|
? static_cast<IDocumentContentOperations::InsertFlags>(
|
|
IDocumentContentOperations::INS_FORCEHINTEXPAND |
|
|
IDocumentContentOperations::INS_EMPTYEXPAND)
|
|
: IDocumentContentOperations::INS_EMPTYEXPAND;
|
|
|
|
// grouping done in InsertString is intended for typing, not API calls
|
|
::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
|
|
SwTxtNode* const pTxtNd =
|
|
rNewCursor.GetPoint()->nNode.GetNode().GetTxtNode();
|
|
if (!pTxtNd)
|
|
{
|
|
SAL_INFO("sw.uno", "DocInsertStringSplitCR: need a text node");
|
|
return false;
|
|
}
|
|
OUString aTxt;
|
|
sal_Int32 nStartIdx = 0;
|
|
const sal_Int32 nMaxLength = COMPLETE_STRING - pTxtNd->GetTxt().getLength();
|
|
|
|
sal_Int32 nIdx = rText.indexOf( '\r', nStartIdx );
|
|
if( ( nIdx == -1 && nMaxLength < rText.getLength() ) ||
|
|
( nIdx != -1 && nMaxLength < nIdx ) )
|
|
{
|
|
nIdx = nMaxLength;
|
|
}
|
|
while (nIdx != -1 )
|
|
{
|
|
OSL_ENSURE( nIdx - nStartIdx >= 0, "index negative!" );
|
|
aTxt = rText.copy( nStartIdx, nIdx - nStartIdx );
|
|
if (!aTxt.isEmpty() &&
|
|
!rDoc.getIDocumentContentOperations().InsertString( rNewCursor, aTxt, nInsertFlags ))
|
|
{
|
|
OSL_FAIL( "Doc->Insert(Str) failed." );
|
|
bOK = false;
|
|
}
|
|
if (!rDoc.getIDocumentContentOperations().SplitNode( *rNewCursor.GetPoint(), false ) )
|
|
{
|
|
OSL_FAIL( "SplitNode failed" );
|
|
bOK = false;
|
|
}
|
|
nStartIdx = nIdx + 1;
|
|
nIdx = rText.indexOf( '\r', nStartIdx );
|
|
}
|
|
aTxt = rText.copy( nStartIdx );
|
|
if (!aTxt.isEmpty() &&
|
|
!rDoc.getIDocumentContentOperations().InsertString( rNewCursor, aTxt, nInsertFlags ))
|
|
{
|
|
OSL_FAIL( "Doc->Insert(Str) failed." );
|
|
bOK = false;
|
|
}
|
|
|
|
return bOK;
|
|
}
|
|
|
|
void makeRedline( SwPaM& rPaM,
|
|
const OUString& rRedlineType,
|
|
const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
|
|
throw (lang::IllegalArgumentException, uno::RuntimeException)
|
|
{
|
|
IDocumentRedlineAccess* pRedlineAccess = &rPaM.GetDoc()->getIDocumentRedlineAccess();
|
|
|
|
RedlineType_t eType;
|
|
if ( rRedlineType == "Insert" )
|
|
eType = nsRedlineType_t::REDLINE_INSERT;
|
|
else if ( rRedlineType == "Delete" )
|
|
eType = nsRedlineType_t::REDLINE_DELETE;
|
|
else if ( rRedlineType == "Format" )
|
|
eType = nsRedlineType_t::REDLINE_FORMAT;
|
|
else if ( rRedlineType == "TextTable" )
|
|
eType = nsRedlineType_t::REDLINE_TABLE;
|
|
else if ( rRedlineType == "ParagraphFormat" )
|
|
eType = nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT;
|
|
else
|
|
throw lang::IllegalArgumentException();
|
|
|
|
//todo: what about REDLINE_FMTCOLL?
|
|
comphelper::SequenceAsHashMap aPropMap( rRedlineProperties );
|
|
uno::Any aAuthorValue;
|
|
aAuthorValue = aPropMap.getUnpackedValueOrDefault("RedlineAuthor", aAuthorValue);
|
|
sal_uInt16 nAuthor = 0;
|
|
OUString sAuthor;
|
|
if( aAuthorValue >>= sAuthor )
|
|
nAuthor = pRedlineAccess->InsertRedlineAuthor(sAuthor);
|
|
|
|
OUString sComment;
|
|
uno::Any aCommentValue;
|
|
aCommentValue = aPropMap.getUnpackedValueOrDefault("RedlineComment", aCommentValue);
|
|
|
|
SwRedlineData aRedlineData( eType, nAuthor );
|
|
if( aCommentValue >>= sComment )
|
|
aRedlineData.SetComment( sComment );
|
|
|
|
::util::DateTime aStamp;
|
|
uno::Any aDateTimeValue;
|
|
aDateTimeValue = aPropMap.getUnpackedValueOrDefault("RedlineDateTime", aDateTimeValue);
|
|
if( aDateTimeValue >>= aStamp )
|
|
{
|
|
aRedlineData.SetTimeStamp(
|
|
DateTime( Date( aStamp.Day, aStamp.Month, aStamp.Year ), tools::Time( aStamp.Hours, aStamp.Minutes, aStamp.Seconds ) ) );
|
|
}
|
|
|
|
SwRedlineExtraData_FormattingChanges* pRedlineExtraData = NULL;
|
|
|
|
// Read the 'Redline Revert Properties' from the parameters
|
|
uno::Sequence< beans::PropertyValue > aRevertProperties;
|
|
uno::Any aRevertPropertiesValue;
|
|
aRevertPropertiesValue = aPropMap.getUnpackedValueOrDefault("RedlineRevertProperties", aRevertPropertiesValue);
|
|
|
|
// Check if the value exists
|
|
if ( aRevertPropertiesValue >>= aRevertProperties )
|
|
{
|
|
// sw/source/core/unocore/unoport.cxx#83 is where it's decided what map gets used for a text portion
|
|
// so it's PROPERTY_MAP_TEXTPORTION_EXTENSIONS, unless it's a redline portion
|
|
SfxItemPropertySet const& rPropSet = (*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXTPORTION_EXTENSIONS));
|
|
|
|
// Check if there are any properties
|
|
if (aRevertProperties.getLength())
|
|
{
|
|
SwDoc *const pDoc = rPaM.GetDoc();
|
|
OUString aUnknownExMsg, aPropertyVetoExMsg;
|
|
|
|
// Build set of attributes we want to fetch
|
|
std::vector<sal_uInt16> aWhichPairs;
|
|
std::vector<SfxItemPropertySimpleEntry const*> aEntries;
|
|
aEntries.reserve(aRevertProperties.getLength());
|
|
for (sal_Int32 i = 0; i < aRevertProperties.getLength(); ++i)
|
|
{
|
|
const OUString &rPropertyName = aRevertProperties[i].Name;
|
|
SfxItemPropertySimpleEntry const* pEntry = rPropSet.getPropertyMap().getByName(rPropertyName);
|
|
|
|
// Queue up any exceptions until the end ...
|
|
if (!pEntry)
|
|
{
|
|
aUnknownExMsg += "Unknown property: '" + rPropertyName + "' ";
|
|
break;
|
|
}
|
|
else if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
|
|
{
|
|
aPropertyVetoExMsg += "Property is read-only: '" + rPropertyName + "' ";
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// FIXME: we should have some nice way of merging ranges surely ?
|
|
aWhichPairs.push_back(pEntry->nWID);
|
|
aWhichPairs.push_back(pEntry->nWID);
|
|
}
|
|
aEntries.push_back(pEntry);
|
|
}
|
|
|
|
if (!aWhichPairs.empty())
|
|
{
|
|
aWhichPairs.push_back(0); // terminate
|
|
SfxItemSet aItemSet(pDoc->GetAttrPool(), &aWhichPairs[0]);
|
|
|
|
for (size_t i = 0; i < aEntries.size(); ++i)
|
|
{
|
|
SfxItemPropertySimpleEntry const*const pEntry = aEntries[i];
|
|
const uno::Any &rValue = aRevertProperties[i].Value;
|
|
rPropSet.setPropertyValue(*pEntry, rValue, aItemSet);
|
|
}
|
|
pRedlineExtraData = new SwRedlineExtraData_FormattingChanges( &aItemSet );
|
|
}
|
|
}
|
|
}
|
|
|
|
SwRangeRedline* pRedline = new SwRangeRedline( aRedlineData, rPaM );
|
|
RedlineMode_t nPrevMode = pRedlineAccess->GetRedlineMode( );
|
|
pRedline->SetExtraData( pRedlineExtraData );
|
|
|
|
pRedlineAccess->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON);
|
|
bool bRet = pRedlineAccess->AppendRedline( pRedline, false );
|
|
pRedlineAccess->SetRedlineMode_intern( nPrevMode );
|
|
if( !bRet )
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
|
|
void makeTableRowRedline( SwTableLine& rTableLine,
|
|
const OUString& rRedlineType,
|
|
const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
|
|
throw (lang::IllegalArgumentException, uno::RuntimeException)
|
|
{
|
|
IDocumentRedlineAccess* pRedlineAccess = &rTableLine.GetFrmFmt()->GetDoc()->getIDocumentRedlineAccess();
|
|
|
|
RedlineType_t eType;
|
|
if ( rRedlineType == "TableRowInsert" )
|
|
{
|
|
eType = nsRedlineType_t::REDLINE_TABLE_ROW_INSERT;
|
|
}
|
|
else if ( rRedlineType == "TableRowDelete" )
|
|
{
|
|
eType = nsRedlineType_t::REDLINE_TABLE_ROW_DELETE;
|
|
}
|
|
else
|
|
{
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
|
|
comphelper::SequenceAsHashMap aPropMap( rRedlineProperties );
|
|
uno::Any aAuthorValue;
|
|
aAuthorValue = aPropMap.getUnpackedValueOrDefault("RedlineAuthor", aAuthorValue);
|
|
sal_uInt16 nAuthor = 0;
|
|
OUString sAuthor;
|
|
if( aAuthorValue >>= sAuthor )
|
|
nAuthor = pRedlineAccess->InsertRedlineAuthor(sAuthor);
|
|
|
|
OUString sComment;
|
|
uno::Any aCommentValue;
|
|
aCommentValue = aPropMap.getUnpackedValueOrDefault("RedlineComment", aCommentValue);
|
|
|
|
SwRedlineData aRedlineData( eType, nAuthor );
|
|
if( aCommentValue >>= sComment )
|
|
aRedlineData.SetComment( sComment );
|
|
|
|
::util::DateTime aStamp;
|
|
uno::Any aDateTimeValue;
|
|
aDateTimeValue = aPropMap.getUnpackedValueOrDefault("RedlineDateTime", aDateTimeValue);
|
|
if( aDateTimeValue >>= aStamp )
|
|
{
|
|
aRedlineData.SetTimeStamp(
|
|
DateTime( Date( aStamp.Day, aStamp.Month, aStamp.Year ), tools::Time( aStamp.Hours, aStamp.Minutes, aStamp.Seconds ) ) );
|
|
}
|
|
|
|
SwTableRowRedline* pRedline = new SwTableRowRedline( aRedlineData, rTableLine );
|
|
RedlineMode_t nPrevMode = pRedlineAccess->GetRedlineMode( );
|
|
pRedline->SetExtraData( NULL );
|
|
|
|
pRedlineAccess->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON);
|
|
bool bRet = pRedlineAccess->AppendTableRowRedline( pRedline, false );
|
|
pRedlineAccess->SetRedlineMode_intern( nPrevMode );
|
|
if( !bRet )
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
|
|
void makeTableCellRedline( SwTableBox& rTableBox,
|
|
const OUString& rRedlineType,
|
|
const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
|
|
throw (lang::IllegalArgumentException, uno::RuntimeException)
|
|
{
|
|
IDocumentRedlineAccess* pRedlineAccess = &rTableBox.GetFrmFmt()->GetDoc()->getIDocumentRedlineAccess();
|
|
|
|
RedlineType_t eType;
|
|
if ( rRedlineType == "TableCellInsert" )
|
|
{
|
|
eType = nsRedlineType_t::REDLINE_TABLE_CELL_INSERT;
|
|
}
|
|
else if ( rRedlineType == "TableCellDelete" )
|
|
{
|
|
eType = nsRedlineType_t::REDLINE_TABLE_CELL_DELETE;
|
|
}
|
|
else
|
|
{
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
|
|
comphelper::SequenceAsHashMap aPropMap( rRedlineProperties );
|
|
uno::Any aAuthorValue;
|
|
aAuthorValue = aPropMap.getUnpackedValueOrDefault("RedlineAuthor", aAuthorValue);
|
|
sal_uInt16 nAuthor = 0;
|
|
OUString sAuthor;
|
|
if( aAuthorValue >>= sAuthor )
|
|
nAuthor = pRedlineAccess->InsertRedlineAuthor(sAuthor);
|
|
|
|
OUString sComment;
|
|
uno::Any aCommentValue;
|
|
aCommentValue = aPropMap.getUnpackedValueOrDefault("RedlineComment", aCommentValue);
|
|
|
|
SwRedlineData aRedlineData( eType, nAuthor );
|
|
if( aCommentValue >>= sComment )
|
|
aRedlineData.SetComment( sComment );
|
|
|
|
::util::DateTime aStamp;
|
|
uno::Any aDateTimeValue;
|
|
aDateTimeValue = aPropMap.getUnpackedValueOrDefault("RedlineDateTime", aDateTimeValue);
|
|
if( aDateTimeValue >>= aStamp )
|
|
{
|
|
aRedlineData.SetTimeStamp(
|
|
DateTime( Date( aStamp.Day, aStamp.Month, aStamp.Year ), tools::Time( aStamp.Hours, aStamp.Minutes, aStamp.Seconds ) ) );
|
|
}
|
|
|
|
SwTableCellRedline* pRedline = new SwTableCellRedline( aRedlineData, rTableBox );
|
|
RedlineMode_t nPrevMode = pRedlineAccess->GetRedlineMode( );
|
|
pRedline->SetExtraData( NULL );
|
|
|
|
pRedlineAccess->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON);
|
|
bool bRet = pRedlineAccess->AppendTableCellRedline( pRedline, false );
|
|
pRedlineAccess->SetRedlineMode_intern( nPrevMode );
|
|
if( !bRet )
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
|
|
SwAnyMapHelper::~SwAnyMapHelper()
|
|
{
|
|
AnyMapHelper_t::iterator aIt = begin();
|
|
while( aIt != end() )
|
|
{
|
|
delete ( aIt->second );
|
|
++aIt;
|
|
}
|
|
}
|
|
|
|
void SwAnyMapHelper::SetValue( sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any& rAny )
|
|
{
|
|
sal_uInt32 nKey = (nWhichId << 16) + nMemberId;
|
|
AnyMapHelper_t::iterator aIt = find( nKey );
|
|
if( aIt != end() )
|
|
{
|
|
*(aIt->second) = rAny;
|
|
}
|
|
else
|
|
insert( value_type(nKey, new uno::Any( rAny )) );
|
|
}
|
|
|
|
bool SwAnyMapHelper::FillValue( sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any*& pAny )
|
|
{
|
|
bool bRet = false;
|
|
sal_uInt32 nKey = (nWhichId << 16) + nMemberId;
|
|
AnyMapHelper_t::iterator aIt = find( nKey );
|
|
if( aIt != end() )
|
|
{
|
|
pAny = aIt->second;
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
}//namespace SwUnoCursorHelper
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|