/* -*- 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 <comphelper/storagehelper.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/servicehelper.hxx>
#include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
#include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/task/XInteractionHandler.hpp>
#include <o3tl/any.hxx>
#include <osl/diagnose.h>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <comphelper/classids.hxx>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <xmloff/prstylei.hxx>
#include <xmloff/maptype.hxx>
#include <xmloff/xmlprmap.hxx>
#include <xmloff/txtprmap.hxx>
#include <xmloff/i18nmap.hxx>
#include <xmloff/xmlimppr.hxx>
#include <TextCursorHelper.hxx>
#include <unoframe.hxx>
#include <doc.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentContentOperations.hxx>
#include <fmtfsize.hxx>
#include <fmtanchr.hxx>
#include <fmtcntnt.hxx>
#include "xmlimp.hxx"
#include "xmltbli.hxx"
#include "xmltexti.hxx"
#include "XMLRedlineImportHelper.hxx"
#include <xmloff/XMLFilterServiceNames.h>
#include <SwAppletImpl.hxx>
#include <ndole.hxx>
#include <docsh.hxx>
#include <sfx2/docfile.hxx>
#include <vcl/svapp.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <svtools/embedhlp.hxx>
#include <svl/urihelper.hxx>
#include <sfx2/frmdescr.hxx>
#include <tools/globname.hxx>
#include <algorithm>
#include <utility>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::beans;
using namespace xml::sax;
const std::pair<OUString, SvGUID> aServiceMap[] = {
{ XML_IMPORT_FILTER_WRITER, { SO3_SW_CLASSID } },
{ XML_IMPORT_FILTER_CALC, { SO3_SC_CLASSID } },
{ XML_IMPORT_FILTER_DRAW, { SO3_SDRAW_CLASSID } },
{ XML_IMPORT_FILTER_IMPRESS, { SO3_SIMPRESS_CLASSID } },
{ XML_IMPORT_FILTER_CHART, { SO3_SCH_CLASSID } },
{ XML_IMPORT_FILTER_MATH, { SO3_SM_CLASSID } },
};
static void lcl_putHeightAndWidth ( SfxItemSet &rItemSet,
sal_Int32 nHeight, sal_Int32 nWidth,
Size *pTwipSize = nullptr )
{
if( nWidth > 0 && nHeight > 0 )
{
nWidth = o3tl::toTwips(nWidth, o3tl::Length::mm100);
if( nWidth < MINFLY )
nWidth = MINFLY;
nHeight = o3tl::toTwips(nHeight, o3tl::Length::mm100);
if( nHeight < MINFLY )
nHeight = MINFLY;
rItemSet.Put( SwFormatFrameSize( SwFrameSize::Fixed, nWidth, nHeight ) );
}
SwFormatAnchor aAnchor( RndStdIds::FLY_AT_CHAR );
rItemSet.Put( aAnchor );
if( pTwipSize )
{
pTwipSize->setWidth( nWidth );
pTwipSize->setHeight( nHeight);
}
}
static void lcl_setObjectVisualArea( const uno::Reference< embed::XEmbeddedObject >& xObj,
sal_Int64 nAspect,
const Size& aVisSize,
const MapUnit& aUnit )
{
if( !(xObj.is() && nAspect != embed::Aspects::MSOLE_ICON) )
return;
// convert the visual area to the objects units
MapUnit aObjUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
Size aObjVisSize = OutputDevice::LogicToLogic(aVisSize, MapMode(aUnit), MapMode(aObjUnit));
awt::Size aSz;
aSz.Width = aObjVisSize.Width();
aSz.Height = aObjVisSize.Height();
try
{
xObj->setVisualAreaSize( nAspect, aSz );
}
catch( uno::Exception& )
{
OSL_FAIL( "Couldn't set visual area of the object!" );
}
}
SwXMLTextImportHelper::SwXMLTextImportHelper(
const uno::Reference < XModel>& rModel,
SwXMLImport& rImport,
const uno::Reference<XPropertySet> & rInfoSet,
bool bInsertM, bool bStylesOnlyM,
bool bBlockM, bool bOrganizerM ) :
XMLTextImportHelper( rModel, rImport, bInsertM, bStylesOnlyM, true/*bProgress*/,
bBlockM, bOrganizerM ),
m_pRedlineHelper( nullptr )
{
uno::Reference<XPropertySet> xDocPropSet( rModel, UNO_QUERY );
m_pRedlineHelper = new XMLRedlineImportHelper(rImport,
bInsertM || bBlockM, xDocPropSet, rInfoSet );
}
SwXMLTextImportHelper::~SwXMLTextImportHelper()
{
// the redline helper destructor sets properties on the document
// and may throw an exception while doing so... catch this
try
{
delete m_pRedlineHelper;
}
catch ( const RuntimeException& )
{
// ignore
}
}
SvXMLImportContext *SwXMLTextImportHelper::CreateTableChildContext(
SvXMLImport& rImport,
sal_Int32 /*nElement*/,
const uno::Reference< XFastAttributeList > & xAttrList )
{
return new SwXMLTableContext( static_cast<SwXMLImport&>(rImport), xAttrList );
}
bool SwXMLTextImportHelper::IsInHeaderFooter() const
{
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(const_cast<SwXMLTextImportHelper *>(this)->GetCursor().get());
SAL_WARN_IF(!pTextCursor, "sw.uno", "SwXTextCursor missing");
SwDoc *pDoc = pTextCursor ? pTextCursor->GetDoc() : nullptr;
return pDoc && pDoc->IsInHeaderFooter( pTextCursor->GetPaM()->GetPoint()->GetNode() );
}
static SwOLENode *lcl_GetOLENode( const SwFrameFormat *pFrameFormat )
{
SwOLENode *pOLENd = nullptr;
if( pFrameFormat )
{
const SwFormatContent& rContent = pFrameFormat->GetContent();
const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
pOLENd = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetOLENode();
}
OSL_ENSURE( pOLENd, "Where is the OLE node" );
return pOLENd;
}
uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertOLEObject(
SvXMLImport& rImport,
const OUString& rHRef,
const OUString& rStyleName,
const OUString& rTableName,
sal_Int32 nWidth, sal_Int32 nHeight )
{
// this method will modify the document directly -> lock SolarMutex
SolarMutexGuard aGuard;
uno::Reference < XPropertySet > xPropSet;
sal_Int32 nPos = rHRef.indexOf( ':' );
if( -1 == nPos )
return xPropSet;
OUString aObjName( rHRef.copy( nPos+1) );
if( aObjName.isEmpty() )
return xPropSet;
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(GetCursor().get());
SAL_WARN_IF(!pTextCursor, "sw.uno", "SwXTextCursor missing");
SwDoc *pDoc = static_cast<SwXMLImport&>(rImport).getDoc();
SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END> aItemSet( pDoc->GetAttrPool() );
Size aTwipSize( 0, 0 );
tools::Rectangle aVisArea( 0, 0, nWidth, nHeight );
lcl_putHeightAndWidth( aItemSet, nHeight, nWidth,
&aTwipSize );
SwFrameFormat *pFrameFormat = nullptr;
SwOLENode *pOLENd = nullptr;
if( rHRef.startsWith("vnd.sun.star.ServiceName:") )
{
bool bInsert = false;
SvGlobalName aClassName;
for (const auto& [sFilterService, rCLASSID] : aServiceMap)
{
if (aObjName == sFilterService)
{
aClassName = SvGlobalName(rCLASSID);
bInsert = true;
break;
}
}
if( bInsert )
{
uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
try
{
// create object with desired ClassId
uno::Sequence < sal_Int8 > aClass( aClassName.GetByteSequence() );
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence<beans::PropertyValue> aObjArgs( comphelper::InitPropertySequence({
{ "DefaultParentBaseURL", Any(GetXMLImport().GetBaseURL()) }
}));
uno::Reference < embed::XEmbeddedObject > xObj( xFactory->createInstanceInitNew(
aClass, OUString(), xStorage, u"DummyName"_ustr, aObjArgs), uno::UNO_QUERY );
if ( xObj.is() )
{
//TODO/LATER: is it enough to only set the VisAreaSize?
lcl_setObjectVisualArea( xObj, embed::Aspects::MSOLE_CONTENT, aTwipSize, MapUnit::MapTwip );
}
if( pTextCursor )
{
pFrameFormat = pDoc->getIDocumentContentOperations().InsertEmbObject(
*pTextCursor->GetPaM(),
::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
&aItemSet);
pOLENd = lcl_GetOLENode( pFrameFormat );
}
if( pOLENd )
aObjName = pOLENd->GetOLEObj().GetCurrentPersistName();
}
catch ( uno::Exception& )
{
}
}
}
else
{
// check whether an object with this name already exists in the document
OUString aName;
SwIterator<SwContentNode,SwFormatColl> aIter( *pDoc->GetDfltGrfFormatColl() );
for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
{
SwOLENode* pExistingOLENd = pNd->GetOLENode();
if( pExistingOLENd )
{
OUString aExistingName = pExistingOLENd->GetOLEObj().GetCurrentPersistName();
if ( aExistingName == aObjName )
{
OSL_FAIL( "The document contains duplicate object references, means it is partially broken, please let developers know how this document was generated!" );
OUString aTmpName = pDoc->GetPersist()->GetEmbeddedObjectContainer().CreateUniqueObjectName();
try
{
pDoc->GetPersist()->GetStorage()->copyElementTo( aObjName,
pDoc->GetPersist()->GetStorage(),
aTmpName );
aName = aTmpName;
}
catch ( uno::Exception& )
{
OSL_FAIL( "Couldn't create a copy of the object!" );
}
break;
}
}
}
if ( aName.isEmpty() )
aName = aObjName;
// the correct aspect will be set later
// TODO/LATER: Actually it should be set here
if( pTextCursor )
{
pFrameFormat = pDoc->getIDocumentContentOperations().InsertOLE( *pTextCursor->GetPaM(), aName, embed::Aspects::MSOLE_CONTENT, &aItemSet, nullptr );
pOLENd = lcl_GetOLENode( pFrameFormat );
}
aObjName = aName;
}
if( !pFrameFormat )
return xPropSet;
if( IsInsertMode() )
{
if( !pOLENd )
pOLENd = lcl_GetOLENode( pFrameFormat );
if( pOLENd )
pOLENd->SetOLESizeInvalid( true );
}
xPropSet = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
*pDoc, pFrameFormat);
if( pDoc->getIDocumentDrawModelAccess().GetDrawModel() )
{
// req for z-order
SwXFrame::GetOrCreateSdrObject(*static_cast<SwFlyFrameFormat*>(pFrameFormat));
}
if( !rTableName.isEmpty() )
{
const SwFormatContent& rContent = pFrameFormat->GetContent();
const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
SwOLENode *pOLENode = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetOLENode();
OSL_ENSURE( pOLENode, "Where is the OLE node" );
OUStringBuffer aBuffer( rTableName.getLength() );
bool bQuoted = false;
bool bEscape = false;
bool bError = false;
for( sal_Int32 i=0; i < rTableName.getLength(); i++ )
{
bool bEndOfNameFound = false;
sal_Unicode c = rTableName[i];
switch( c )
{
case '\'':
if( bEscape )
{
aBuffer.append( c );
bEscape = false;
}
else if( bQuoted )
{
bEndOfNameFound = true;
}
else if( 0 == i )
{
bQuoted = true;
}
else
{
bError = true;
}
break;
case '\\':
if( bEscape )
{
aBuffer.append( c );
bEscape = false;
}
else
{
bEscape = true;
}
break;
case ' ':
case '.':
if( !bQuoted )
{
bEndOfNameFound = true;
}
else
{
aBuffer.append( c );
bEscape = false;
}
break;
default:
{
aBuffer.append( c );
bEscape = false;
}
break;
}
if( bError || bEndOfNameFound )
break;
}
if( !bError )
{
OUString sTableName( aBuffer.makeStringAndClear() );
pOLENode->SetChartTableName( GetRenameMap().Get( XML_TEXT_RENAME_TYPE_TABLE, sTableName ) );
}
}
sal_Int64 nDrawAspect = 0;
const XMLPropStyleContext *pStyle = nullptr;
bool bHasSizeProps = false;
if( !rStyleName.isEmpty() )
{
pStyle = FindAutoFrameStyle( rStyleName );
if( pStyle )
{
rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
pStyle->GetStyles()
->GetImportPropertyMapper(pStyle->GetFamily());
OSL_ENSURE( xImpPrMap.is(), "Where is the import prop mapper?" );
if( xImpPrMap.is() )
{
rtl::Reference<XMLPropertySetMapper> rPropMapper =
xImpPrMap->getPropertySetMapper();
sal_Int32 nCount = pStyle->GetProperties().size();
for( sal_Int32 i=0; i < nCount; i++ )
{
const XMLPropertyState& rProp = pStyle->GetProperties()[i];
sal_Int32 nIdx = rProp.mnIndex;
if( -1 == nIdx )
continue;
switch( rPropMapper->GetEntryContextId(nIdx) )
{
case CTF_OLE_VIS_AREA_LEFT:
{
sal_Int32 nVal = 0;
rProp.maValue >>= nVal;
aVisArea.SetPosX( nVal );
}
break;
case CTF_OLE_VIS_AREA_TOP:
{
sal_Int32 nVal = 0;
rProp.maValue >>= nVal;
aVisArea.SetPosY( nVal );
}
break;
case CTF_OLE_VIS_AREA_WIDTH:
{
sal_Int32 nVal = 0;
rProp.maValue >>= nVal;
aVisArea.setWidth( nVal );
bHasSizeProps = true;
}
break;
case CTF_OLE_VIS_AREA_HEIGHT:
{
sal_Int32 nVal = 0;
rProp.maValue >>= nVal;
aVisArea.setHeight( nVal );
bHasSizeProps = true;
}
break;
case CTF_OLE_DRAW_ASPECT:
{
rProp.maValue >>= nDrawAspect;
if ( !nDrawAspect )
nDrawAspect = embed::Aspects::MSOLE_CONTENT;
if ( pOLENd )
pOLENd->GetOLEObj().GetObject().SetViewAspect( nDrawAspect );
}
break;
}
}
}
}
}
if ( bHasSizeProps )
{
uno::Reference < embed::XEmbeddedObject > xObj =
pDoc->GetPersist()->GetEmbeddedObjectContainer().GetEmbeddedObject( aObjName );
if( xObj.is() )
lcl_setObjectVisualArea( xObj, ( nDrawAspect ? nDrawAspect : embed::Aspects::MSOLE_CONTENT ),
aVisArea.GetSize(), MapUnit::Map100thMM );
}
return xPropSet;
}
uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertOOoLink(
SvXMLImport& rImport,
const OUString& rHRef,
const OUString& /*rStyleName*/,
const OUString& /*rTableName*/,
sal_Int32 nWidth, sal_Int32 nHeight )
{
// this method will modify the document directly -> lock SolarMutex
SolarMutexGuard aGuard;
uno::Reference < XPropertySet > xPropSet;
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(GetCursor().get());
assert( pTextCursor && "SwXTextCursor missing" );
SwDoc *pDoc = static_cast<SwXMLImport&>(rImport).getDoc();
SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END> aItemSet( pDoc->GetAttrPool() );
Size aTwipSize( 0, 0 );
lcl_putHeightAndWidth( aItemSet, nHeight, nWidth,
&aTwipSize );
// We'll need a (valid) URL. If we don't have do not insert the link and return early.
// Copy URL into URL object on the way.
INetURLObject aURLObj;
bool bValidURL = !rHRef.isEmpty() &&
aURLObj.SetURL( URIHelper::SmartRel2Abs(
INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) );
if( !bValidURL )
return xPropSet;
uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
try
{
// create object with desired ClassId
uno::Reference < embed::XEmbeddedObjectCreator > xFactory =
embed::OOoEmbeddedObjectFactory::create(::comphelper::getProcessComponentContext());
uno::Sequence< beans::PropertyValue > aMediaDescriptor{ comphelper::makePropertyValue(
u"URL"_ustr, aURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE )) };
SwDocShell* pShell = pDoc->GetDocShell();
if (SfxMedium* pMedium = pShell ? pShell->GetMedium() : nullptr)
{
uno::Reference< task::XInteractionHandler > xInteraction = pMedium->GetInteractionHandler();
if ( xInteraction.is() )
{
aMediaDescriptor.realloc( 2 );
auto pMediaDescriptor = aMediaDescriptor.getArray();
pMediaDescriptor[1].Name = "InteractionHandler";
pMediaDescriptor[1].Value <<= xInteraction;
}
const auto nLen = aMediaDescriptor.getLength() + 1;
aMediaDescriptor.realloc(nLen);
auto pMediaDescriptor = aMediaDescriptor.getArray();
pMediaDescriptor[nLen - 1].Name = "Referer";
pMediaDescriptor[nLen - 1].Value <<= pMedium->GetName();
}
uno::Reference < embed::XEmbeddedObject > xObj(
xFactory->createInstanceLink(
xStorage, u"DummyName"_ustr, aMediaDescriptor, uno::Sequence< beans::PropertyValue >() ),
uno::UNO_QUERY_THROW );
{
SwFrameFormat *const pFrameFormat =
pDoc->getIDocumentContentOperations().InsertEmbObject(
*pTextCursor->GetPaM(),
::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
&aItemSet );
// TODO/LATER: in future may need a way to set replacement image url to the link ( may be even to the object ), needs oasis cws???
xPropSet = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
*pDoc, pFrameFormat);
if( pDoc->getIDocumentDrawModelAccess().GetDrawModel() )
{
SwXFrame::GetOrCreateSdrObject(*
static_cast<SwFlyFrameFormat*>(pFrameFormat)); // req for z-order
}
}
}
catch ( uno::Exception& )
{
}
// TODO/LATER: should the rStyleName and rTableName be handled as for usual embedded object?
return xPropSet;
}
uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertApplet(
const OUString &rName,
const OUString &rCode,
bool bMayScript,
const OUString& rHRef,
sal_Int32 nWidth, sal_Int32 nHeight )
{
// this method will modify the document directly -> lock SolarMutex
SolarMutexGuard aGuard;
uno::Reference < XPropertySet > xPropSet;
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(GetCursor().get());
assert( pTextCursor && "SwXTextCursor missing" );
SwDoc *pDoc = pTextCursor->GetDoc();
SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END> aItemSet( pDoc->GetAttrPool() );
lcl_putHeightAndWidth( aItemSet, nHeight, nWidth);
SwApplet_Impl aAppletImpl ( std::move(aItemSet) );
OUString sCodeBase;
if( !rHRef.isEmpty() )
sCodeBase = GetXMLImport().GetAbsoluteReference( rHRef );
aAppletImpl.CreateApplet ( rCode, rName, bMayScript, sCodeBase, GetXMLImport().GetDocumentBase() );
// set the size of the applet
lcl_setObjectVisualArea( aAppletImpl.GetApplet(),
embed::Aspects::MSOLE_CONTENT,
Size( nWidth, nHeight ),
MapUnit::Map100thMM );
SwFrameFormat *const pFrameFormat =
pDoc->getIDocumentContentOperations().InsertEmbObject( *pTextCursor->GetPaM(),
::svt::EmbeddedObjectRef(aAppletImpl.GetApplet(), embed::Aspects::MSOLE_CONTENT),
&aAppletImpl.GetItemSet());
xPropSet = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
*pDoc, pFrameFormat);
if( pDoc->getIDocumentDrawModelAccess().GetDrawModel() )
{
// req for z-order
SwXFrame::GetOrCreateSdrObject(*static_cast<SwFlyFrameFormat*>(pFrameFormat));
}
return xPropSet;
}
uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertPlugin(
const OUString &rMimeType,
const OUString& rHRef,
sal_Int32 nWidth, sal_Int32 nHeight )
{
uno::Reference < XPropertySet > xPropSet;
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(GetCursor().get());
assert( pTextCursor && "SwXTextCursor missing" );
SwDoc *pDoc = pTextCursor->GetDoc();
SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END> aItemSet( pDoc->GetAttrPool() );
lcl_putHeightAndWidth( aItemSet, nHeight, nWidth);
// We'll need a (valid) URL, or we need a MIME type. If we don't have
// either, do not insert plugin and return early. Copy URL into URL object
// on the way.
INetURLObject aURLObj;
bool bValidURL = !rHRef.isEmpty() &&
aURLObj.SetURL( URIHelper::SmartRel2Abs( INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) );
bool bValidMimeType = !rMimeType.isEmpty();
if( !bValidURL && !bValidMimeType )
return xPropSet;
uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
try
{
// create object with desired ClassId
uno::Sequence < sal_Int8 > aClass( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence() );
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Reference < embed::XEmbeddedObject > xObj( xFactory->createInstanceInitNew(
aClass, OUString(), xStorage, u"DummyName"_ustr,
uno::Sequence < beans::PropertyValue >() ), uno::UNO_QUERY );
// set size to the object
lcl_setObjectVisualArea( xObj,
embed::Aspects::MSOLE_CONTENT,
Size( nWidth, nHeight ),
MapUnit::Map100thMM );
if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
{
uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
if ( xSet.is() )
{
if( bValidURL )
xSet->setPropertyValue(u"PluginURL"_ustr,
Any( aURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) );
if( bValidMimeType )
xSet->setPropertyValue(u"PluginMimeType"_ustr,
Any( rMimeType ) );
}
SwFrameFormat *const pFrameFormat =
pDoc->getIDocumentContentOperations().InsertEmbObject(
*pTextCursor->GetPaM(),
::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
&aItemSet);
xPropSet = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
*pDoc, pFrameFormat);
if( pDoc->getIDocumentDrawModelAccess().GetDrawModel() )
{
SwXFrame::GetOrCreateSdrObject(*
static_cast<SwFlyFrameFormat*>(pFrameFormat)); // req for z-order
}
}
}
catch ( uno::Exception& )
{
}
return xPropSet;
}
uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertFloatingFrame(
const OUString& rName,
const OUString& rHRef,
const OUString& rStyleName,
sal_Int32 nWidth, sal_Int32 nHeight )
{
// this method will modify the document directly -> lock SolarMutex
SolarMutexGuard aGuard;
uno::Reference < XPropertySet > xPropSet;
OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(GetCursor().get());
assert( pTextCursor && "SwXTextCursor missing" );
SwDoc *pDoc = pTextCursor->GetDoc();
SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END> aItemSet( pDoc->GetAttrPool() );
lcl_putHeightAndWidth( aItemSet, nHeight, nWidth);
ScrollingMode eScrollMode = ScrollingMode::Auto;
bool bHasBorder = false;
bool bIsBorderSet = false;
Size aMargin( SIZE_NOT_SET, SIZE_NOT_SET );
const XMLPropStyleContext *pStyle = nullptr;
if( !rStyleName.isEmpty() )
{
pStyle = FindAutoFrameStyle( rStyleName );
if( pStyle )
{
rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
pStyle->GetStyles()
->GetImportPropertyMapper(pStyle->GetFamily());
OSL_ENSURE( xImpPrMap.is(), "Where is the import prop mapper?" );
if( xImpPrMap.is() )
{
rtl::Reference<XMLPropertySetMapper> rPropMapper =
xImpPrMap->getPropertySetMapper();
sal_Int32 nCount = pStyle->GetProperties().size();
for( sal_Int32 i=0; i < nCount; i++ )
{
const XMLPropertyState& rProp = pStyle->GetProperties()[i];
sal_Int32 nIdx = rProp.mnIndex;
if( -1 == nIdx )
continue;
switch( rPropMapper->GetEntryContextId(nIdx) )
{
case CTF_FRAME_DISPLAY_SCROLLBAR:
{
bool bYes = *o3tl::doAccess<bool>(rProp.maValue);
eScrollMode = bYes ? ScrollingMode::Yes : ScrollingMode::No;
}
break;
case CTF_FRAME_DISPLAY_BORDER:
{
bHasBorder = *o3tl::doAccess<bool>(rProp.maValue);
bIsBorderSet = true;
}
break;
case CTF_FRAME_MARGIN_HORI:
{
sal_Int32 nVal = SIZE_NOT_SET;
rProp.maValue >>= nVal;
aMargin.setWidth( nVal );
}
break;
case CTF_FRAME_MARGIN_VERT:
{
sal_Int32 nVal = SIZE_NOT_SET;
rProp.maValue >>= nVal;
aMargin.setHeight( nVal );
}
break;
}
}
}
}
}
uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
try
{
// create object with desired ClassId
uno::Sequence < sal_Int8 > aClass( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence() );
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Reference < embed::XEmbeddedObject > xObj( xFactory->createInstanceInitNew(
aClass, OUString(), xStorage, u"DummyName"_ustr,
uno::Sequence < beans::PropertyValue >() ), uno::UNO_QUERY );
// set size to the object
lcl_setObjectVisualArea( xObj,
embed::Aspects::MSOLE_CONTENT,
Size( nWidth, nHeight ),
MapUnit::Map100thMM );
if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
{
uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
if ( xSet.is() )
{
OUString sHRef = URIHelper::SmartRel2Abs(
INetURLObject( GetXMLImport().GetBaseURL() ), rHRef );
if (INetURLObject(sHRef).IsExoticProtocol())
GetXMLImport().NotifyMacroEventRead();
xSet->setPropertyValue(u"FrameURL"_ustr,
Any( sHRef ) );
xSet->setPropertyValue(u"FrameName"_ustr,
Any( rName ) );
if ( eScrollMode == ScrollingMode::Auto )
xSet->setPropertyValue(u"FrameIsAutoScroll"_ustr,
Any( true ) );
else
xSet->setPropertyValue(u"FrameIsScrollingMode"_ustr,
Any( eScrollMode == ScrollingMode::Yes ) );
if ( bIsBorderSet )
xSet->setPropertyValue(u"FrameIsBorder"_ustr,
Any( bHasBorder ) );
else
xSet->setPropertyValue(u"FrameIsAutoBorder"_ustr,
Any( true ) );
xSet->setPropertyValue(u"FrameMarginWidth"_ustr,
Any( sal_Int32( aMargin.Width() ) ) );
xSet->setPropertyValue(u"FrameMarginHeight"_ustr,
Any( sal_Int32( aMargin.Height() ) ) );
}
SwFrameFormat *const pFrameFormat =
pDoc->getIDocumentContentOperations().InsertEmbObject(
*pTextCursor->GetPaM(),
::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
&aItemSet);
xPropSet = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
*pDoc, pFrameFormat);
if( pDoc->getIDocumentDrawModelAccess().GetDrawModel() )
{
// req for z-order
SwXFrame::GetOrCreateSdrObject(*
static_cast<SwFlyFrameFormat*>(pFrameFormat));
}
}
}
catch ( uno::Exception& )
{
}
return xPropSet;
}
void SwXMLTextImportHelper::endAppletOrPlugin(
const uno::Reference < XPropertySet > &rPropSet,
std::map < const OUString, OUString > &rParamMap)
{
// this method will modify the document directly -> lock SolarMutex
SolarMutexGuard aGuard;
SwXFrame* pFrame = dynamic_cast<SwXFrame*>(rPropSet.get());
assert(pFrame && "SwXFrame missing");
SwFrameFormat *pFrameFormat = pFrame->GetFrameFormat();
const SwFormatContent& rContent = pFrameFormat->GetContent();
const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
SwOLENode *pOLENd = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTextNode()->GetOLENode();
SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
uno::Reference < embed::XEmbeddedObject > xEmbObj( rOLEObj.GetOleRef() );
if ( !svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) )
return;
uno::Reference < beans::XPropertySet > xSet( xEmbObj->getComponent(), uno::UNO_QUERY );
if ( !xSet.is() )
return;
const sal_Int32 nCount = rParamMap.size();
uno::Sequence< beans::PropertyValue > aCommandSequence( nCount );
std::transform(rParamMap.begin(), rParamMap.end(), aCommandSequence.getArray(),
[](const auto& rParam)
{
return beans::PropertyValue(/* Name */ rParam.first,
/* Handle */ -1,
/* Value */ uno::Any(rParam.second),
/* State */ beans::PropertyState_DIRECT_VALUE);
});
// unfortunately the names of the properties are depending on the object
OUString aParaName(u"AppletCommands"_ustr);
try
{
xSet->setPropertyValue( aParaName, Any( aCommandSequence ) );
}
catch ( uno::Exception& )
{
aParaName = "PluginCommands";
try
{
xSet->setPropertyValue( aParaName, Any( aCommandSequence ) );
}
catch ( uno::Exception& )
{
}
}
}
// redlining helper methods
// (override to provide the real implementation)
void SwXMLTextImportHelper::RedlineAdd(
const OUString& rType,
const OUString& rId,
const OUString& rAuthor,
const OUString& rComment,
const util::DateTime& rDateTime,
const OUString& rMovedID,
bool bMergeLastPara)
{
// create redline helper on demand
OSL_ENSURE(nullptr != m_pRedlineHelper, "helper should have been created in constructor");
if (nullptr != m_pRedlineHelper)
m_pRedlineHelper->Add(rType, rId, rAuthor, rComment, rDateTime, rMovedID,
bMergeLastPara);
}
uno::Reference<XTextCursor> SwXMLTextImportHelper::RedlineCreateText(
uno::Reference<XTextCursor> & rOldCursor,
const OUString& rId)
{
uno::Reference<XTextCursor> xRet;
if (nullptr != m_pRedlineHelper)
{
xRet = m_pRedlineHelper->CreateRedlineTextSection(rOldCursor, rId);
}
return xRet;
}
void SwXMLTextImportHelper::RedlineSetCursor(
const OUString& rId,
bool bStart,
bool bIsOutsideOfParagraph)
{
if (nullptr != m_pRedlineHelper) {
uno::Reference<XTextRange> xTextRange( GetCursor()->getStart() );
m_pRedlineHelper->SetCursor(rId, bStart, xTextRange,
bIsOutsideOfParagraph);
}
// else: ignore redline (wasn't added before, else we'd have a helper)
}
void SwXMLTextImportHelper::RedlineAdjustStartNodeCursor()
{
OUString rId = GetOpenRedlineId();
if ((nullptr != m_pRedlineHelper) && !rId.isEmpty())
{
m_pRedlineHelper->AdjustStartNodeCursor(rId);
ResetOpenRedlineId();
}
// else: ignore redline (wasn't added before, or no open redline ID
}
void SwXMLTextImportHelper::SetShowChanges( bool bShowChanges )
{
if ( nullptr != m_pRedlineHelper )
m_pRedlineHelper->SetShowChanges( bShowChanges );
}
void SwXMLTextImportHelper::SetRecordChanges( bool bRecordChanges )
{
if ( nullptr != m_pRedlineHelper )
m_pRedlineHelper->SetRecordChanges( bRecordChanges );
}
void SwXMLTextImportHelper::SetChangesProtectionKey(
const Sequence<sal_Int8> & rKey )
{
if ( nullptr != m_pRedlineHelper )
m_pRedlineHelper->SetProtectionKey( rKey );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V522 There might be dereferencing of a potential null pointer 'pTextCursor'.
↑ V522 There might be dereferencing of a potential null pointer 'pTextCursor'.
↑ V522 There might be dereferencing of a potential null pointer 'pTextCursor'.
↑ V522 There might be dereferencing of a potential null pointer 'pTextCursor'.
↑ V522 There might be dereferencing of a potential null pointer 'pTextCursor'.
↑ V522 There might be dereferencing of a potential null pointer 'pFrame'.