/* -*- 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 <comphelper/classids.hxx>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/embed/XLinkageSupport.hpp>
#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
#include <xmloff/families.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/txtprmap.hxx>
#include <xmloff/maptype.hxx>
#include <xmloff/xmlexppr.hxx>
#include <ndole.hxx>
#include <fmtcntnt.hxx>
#include <unoframe.hxx>
#include "xmlexp.hxx"
#include "xmltexte.hxx"
#include <SwAppletImpl.hxx>
#include <ndindex.hxx>
#include <osl/diagnose.h>
#include <sot/exchange.hxx>
#include <svl/urihelper.hxx>
#include <sfx2/frmdescr.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::document;
using namespace ::xmloff::token;
namespace {
enum SvEmbeddedObjectTypes
{
SV_EMBEDDED_OWN,
SV_EMBEDDED_OUTPLACE,
SV_EMBEDDED_APPLET,
SV_EMBEDDED_PLUGIN,
SV_EMBEDDED_FRAME
};
}
SwNoTextNode *SwXMLTextParagraphExport::GetNoTextNode(
const Reference < XPropertySet >& rPropSet )
{
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();
return pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTextNode();
}
constexpr OUString gsEmbeddedObjectProtocol( u"vnd.sun.star.EmbeddedObject:"_ustr );
SwXMLTextParagraphExport::SwXMLTextParagraphExport(
SwXMLExport& rExp,
SvXMLAutoStylePoolP& _rAutoStylePool ) :
XMLTextParagraphExport( rExp, _rAutoStylePool ),
m_aAppletClassId( SO3_APPLET_CLASSID ),
m_aPluginClassId( SO3_PLUGIN_CLASSID ),
m_aIFrameClassId( SO3_IFRAME_CLASSID )
{
}
SwXMLTextParagraphExport::~SwXMLTextParagraphExport()
{
}
static void lcl_addURL ( SvXMLExport &rExport, const OUString &rURL,
bool bToRel = true )
{
const OUString sRelURL = ( bToRel && !rURL.isEmpty() )
? URIHelper::simpleNormalizedMakeRelative(rExport.GetOrigFileName(), rURL)
: rURL;
if (!sRelURL.isEmpty())
{
rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, sRelURL );
rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
}
}
static void lcl_addAspect(
const svt::EmbeddedObjectRef& rObj,
std::vector<XMLPropertyState>& rStates,
const rtl::Reference < XMLPropertySetMapper >& rMapper )
{
sal_Int64 nAspect = rObj.GetViewAspect();
if ( nAspect )
rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_DRAW_ASPECT ), uno::Any( nAspect ) );
}
static void lcl_addOutplaceProperties(
const svt::EmbeddedObjectRef& rObj,
std::vector<XMLPropertyState>& rStates,
const rtl::Reference < XMLPropertySetMapper >& rMapper )
{
MapMode aMode( MapUnit::Map100thMM ); // the API expects this map mode for the embedded objects
Size aSize = rObj.GetSize( &aMode ); // get the size in the requested map mode
if( !(aSize.Width() && aSize.Height()) )
return;
rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_LEFT ), Any(sal_Int32(0)) );
rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_TOP ), Any(sal_Int32(0)) );
rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_WIDTH ), Any(static_cast<sal_Int32>(aSize.Width())) );
rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_HEIGHT ), Any(static_cast<sal_Int32>(aSize.Height())) );
}
static void lcl_addFrameProperties(
const uno::Reference < embed::XEmbeddedObject >& xObj,
std::vector<XMLPropertyState>& rStates,
const rtl::Reference < XMLPropertySetMapper >& rMapper )
{
if ( !::svt::EmbeddedObjectRef::TryRunningState( xObj ) )
return;
uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
if ( !xSet.is() )
return;
bool bIsAutoScroll = false, bIsScrollingMode = false;
Any aAny = xSet->getPropertyValue(u"FrameIsAutoScroll"_ustr);
aAny >>= bIsAutoScroll;
if ( !bIsAutoScroll )
{
aAny = xSet->getPropertyValue(u"FrameIsScrollingMode"_ustr);
aAny >>= bIsScrollingMode;
}
bool bIsBorderSet = false, bIsAutoBorder = false;
aAny = xSet->getPropertyValue(u"FrameIsAutoBorder"_ustr);
aAny >>= bIsAutoBorder;
if ( !bIsAutoBorder )
{
aAny = xSet->getPropertyValue(u"FrameIsBorder"_ustr);
aAny >>= bIsBorderSet;
}
sal_Int32 nWidth, nHeight;
aAny = xSet->getPropertyValue(u"FrameMarginWidth"_ustr);
aAny >>= nWidth;
aAny = xSet->getPropertyValue(u"FrameMarginHeight"_ustr);
aAny >>= nHeight;
if( !bIsAutoScroll )
rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_SCROLLBAR ), Any(bIsScrollingMode) );
if( !bIsAutoBorder )
rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_BORDER ), Any(bIsBorderSet) );
if( SIZE_NOT_SET != nWidth )
rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_HORI ), Any(nWidth) );
if( SIZE_NOT_SET != nHeight )
rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_VERT ), Any(nHeight) );
}
void SwXMLTextParagraphExport::_collectTextEmbeddedAutoStyles(
const Reference < XPropertySet > & rPropSet )
{
SwOLENode *pOLENd = GetNoTextNode( rPropSet )->GetOLENode();
svt::EmbeddedObjectRef& rObjRef = pOLENd->GetOLEObj().GetObject();
if( !rObjRef.is() )
return;
std::vector<XMLPropertyState> aStates;
aStates.reserve(8);
SvGlobalName aClassId( rObjRef->getClassID() );
if( m_aIFrameClassId == aClassId )
{
lcl_addFrameProperties( rObjRef.GetObject(), aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
}
else if ( !SotExchange::IsInternal( aClassId ) )
{
lcl_addOutplaceProperties( rObjRef, aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
}
lcl_addAspect( rObjRef, aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
Add( XmlStyleFamily::TEXT_FRAME, rPropSet, aStates );
}
void SwXMLTextParagraphExport::_exportTextEmbedded(
const Reference < XPropertySet > & rPropSet,
const Reference < XPropertySetInfo > & rPropSetInfo )
{
SwOLENode *pOLENd = GetNoTextNode( rPropSet )->GetOLENode();
SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
svt::EmbeddedObjectRef& rObjRef = rOLEObj.GetObject();
if( !rObjRef.is() )
return;
SvGlobalName aClassId( rObjRef->getClassID() );
SvEmbeddedObjectTypes nType = SV_EMBEDDED_OWN;
if( m_aPluginClassId == aClassId )
{
nType = SV_EMBEDDED_PLUGIN;
}
else if( m_aAppletClassId == aClassId )
{
nType = SV_EMBEDDED_APPLET;
}
else if( m_aIFrameClassId == aClassId )
{
nType = SV_EMBEDDED_FRAME;
}
else if ( !SotExchange::IsInternal( aClassId ) )
{
nType = SV_EMBEDDED_OUTPLACE;
}
enum XMLTokenEnum eElementName = XML__UNKNOWN_;
SvXMLExport &rXMLExport = GetExport();
// First the stuff common to each of Applet/Plugin/Floating Frame
OUString sStyle;
Any aAny;
if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
{
aAny = rPropSet->getPropertyValue( gsFrameStyleName );
aAny >>= sStyle;
}
std::vector<XMLPropertyState> aStates;
aStates.reserve(8);
switch( nType )
{
case SV_EMBEDDED_FRAME:
lcl_addFrameProperties( rObjRef.GetObject(), aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
break;
case SV_EMBEDDED_OUTPLACE:
lcl_addOutplaceProperties( rObjRef, aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
break;
default:
;
}
lcl_addAspect( rObjRef, aStates,
GetAutoFramePropMapper()->getPropertySetMapper() );
const OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME,
rPropSet, sStyle, aStates );
aStates.clear();
if( !sAutoStyle.isEmpty() )
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, sAutoStyle );
addTextFrameAttributes( rPropSet, false );
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
XML_FRAME, false, true );
switch (nType)
{
case SV_EMBEDDED_OUTPLACE:
case SV_EMBEDDED_OWN:
if( !(rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED) )
{
OUString sURL;
bool bIsOwnLink = false;
if( SV_EMBEDDED_OWN == nType )
{
try
{
uno::Reference< embed::XLinkageSupport > xLinkage( rObjRef.GetObject(), uno::UNO_QUERY );
bIsOwnLink = xLinkage.is() && xLinkage->isLink();
if ( bIsOwnLink )
sURL = xLinkage->getLinkURL();
}
catch(const uno::Exception&)
{
// TODO/LATER: error handling
OSL_FAIL( "Link detection or retrieving of the URL of OOo link is failed!" );
}
}
if ( !bIsOwnLink )
{
sURL = gsEmbeddedObjectProtocol + rOLEObj.GetCurrentPersistName();
}
sURL = GetExport().AddEmbeddedObject( sURL );
lcl_addURL( rXMLExport, sURL, false );
}
if( SV_EMBEDDED_OWN == nType && !pOLENd->GetChartTableName().isEmpty() )
{
OUString sRange( pOLENd->GetChartTableName() );
OUStringBuffer aBuffer( sRange.getLength() + 2 );
for( sal_Int32 i=0; i < sRange.getLength(); i++ )
{
sal_Unicode c = sRange[i];
switch( c )
{
case ' ':
case '.':
case '\'':
case '\\':
if( aBuffer.isEmpty() )
{
aBuffer.append( OUString::Concat("\'") + sRange.subView(0, i) );
}
if( '\'' == c || '\\' == c )
aBuffer.append( '\\' );
[[fallthrough]];
default:
if( !aBuffer.isEmpty() )
aBuffer.append( c );
}
}
if( !aBuffer.isEmpty() )
{
aBuffer.append( '\'' );
sRange = aBuffer.makeStringAndClear();
}
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES,
sRange );
}
eElementName = SV_EMBEDDED_OUTPLACE==nType ? XML_OBJECT_OLE
: XML_OBJECT;
break;
case SV_EMBEDDED_APPLET:
{
// It's an applet!
if( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
{
uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
OUString aStr;
Any aAny2 = xSet->getPropertyValue(u"AppletCodeBase"_ustr);
aAny2 >>= aStr;
if (!aStr.isEmpty() )
lcl_addURL(rXMLExport, aStr);
aAny2 = xSet->getPropertyValue(u"AppletName"_ustr);
aAny2 >>= aStr;
if (!aStr.isEmpty())
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_APPLET_NAME, aStr );
aAny2 = xSet->getPropertyValue(u"AppletCode"_ustr);
aAny2 >>= aStr;
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CODE, aStr );
bool bScript = false;
aAny2 = xSet->getPropertyValue(u"AppletIsScript"_ustr);
aAny2 >>= bScript;
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MAY_SCRIPT, bScript ? XML_TRUE : XML_FALSE );
uno::Sequence < beans::PropertyValue > aProps;
aAny2 = xSet->getPropertyValue(u"AppletCommands"_ustr);
aAny2 >>= aProps;
sal_Int32 i = aProps.getLength();
while ( i > 0 )
{
const beans::PropertyValue& aProp = aProps[--i];
const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, true );
if ( nType2 == SwHtmlOptType::TAG)
{
OUString aStr2;
aProp.Value >>= aStr2;
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, aProp.Name, aStr2);
}
}
eElementName = XML_APPLET;
}
}
break;
case SV_EMBEDDED_PLUGIN:
{
// It's a plugin!
if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
{
uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
OUString aStr;
Any aAny2 = xSet->getPropertyValue(u"PluginURL"_ustr);
aAny2 >>= aStr;
lcl_addURL( rXMLExport, aStr );
aAny2 = xSet->getPropertyValue(u"PluginMimeType"_ustr);
aAny2 >>= aStr;
if (!aStr.isEmpty())
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, aStr );
eElementName = XML_PLUGIN;
}
}
break;
case SV_EMBEDDED_FRAME:
{
// It's a floating frame!
if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
{
uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
OUString aStr;
Any aAny2 = xSet->getPropertyValue(u"FrameURL"_ustr);
aAny2 >>= aStr;
lcl_addURL( rXMLExport, aStr );
aAny2 = xSet->getPropertyValue(u"FrameName"_ustr);
aAny2 >>= aStr;
if (!aStr.isEmpty())
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FRAME_NAME, aStr );
eElementName = XML_FLOATING_FRAME;
}
}
break;
default:
OSL_ENSURE( false, "unknown object type! Base class should have been called!" );
}
{
SvXMLElementExport aElementExport( rXMLExport, XML_NAMESPACE_DRAW, eElementName,
false, true );
switch( nType )
{
case SV_EMBEDDED_OWN:
if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
{
Reference < XEmbeddedObjectSupplier > xEOS( rPropSet, UNO_QUERY );
OSL_ENSURE( xEOS.is(), "no embedded object supplier for own object" );
Reference < XComponent > xComp = xEOS->getEmbeddedObject();
rXMLExport.ExportEmbeddedOwnObject( xComp );
}
break;
case SV_EMBEDDED_OUTPLACE:
if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
{
OUString sURL( gsEmbeddedObjectProtocol + rOLEObj.GetCurrentPersistName() );
if ( !( rXMLExport.getExportFlags() & SvXMLExportFlags::OASIS ) )
sURL += "?oasis=false";
rXMLExport.AddEmbeddedObjectAsBase64( sURL );
}
break;
case SV_EMBEDDED_APPLET:
{
if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
{
uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
uno::Sequence < beans::PropertyValue > aProps;
aAny = xSet->getPropertyValue(u"AppletCommands"_ustr);
aAny >>= aProps;
sal_Int32 i = aProps.getLength();
while ( i > 0 )
{
const beans::PropertyValue& aProp = aProps[--i];
const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, true );
if (SwHtmlOptType::PARAM == nType2 || SwHtmlOptType::SIZE == nType2 )
{
OUString aStr;
aProp.Value >>= aStr;
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name );
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
}
}
}
}
break;
case SV_EMBEDDED_PLUGIN:
{
if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
{
uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
uno::Sequence < beans::PropertyValue > aProps;
aAny = xSet->getPropertyValue(u"PluginCommands"_ustr);
aAny >>= aProps;
sal_Int32 i = aProps.getLength();
while ( i > 0 )
{
const beans::PropertyValue& aProp = aProps[--i];
const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, false );
if ( nType2 == SwHtmlOptType::TAG)
{
OUString aStr;
aProp.Value >>= aStr;
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name );
rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
}
}
}
}
break;
default:
break;
}
}
if( SV_EMBEDDED_OUTPLACE==nType || SV_EMBEDDED_OWN==nType )
{
OUString sURL = XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE + rOLEObj.GetCurrentPersistName();
if( !(rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED) )
{
sURL = GetExport().AddEmbeddedObject( sURL );
lcl_addURL( rXMLExport, sURL, false );
}
SvXMLElementExport aElementExport( GetExport(), XML_NAMESPACE_DRAW,
XML_IMAGE, false, true );
if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
GetExport().AddEmbeddedObjectAsBase64( sURL );
}
// Lastly the stuff common to each of Applet/Plugin/Floating Frame
exportEvents( rPropSet );
exportTitleAndDescription( rPropSet, rPropSetInfo ); // #i73249#
exportContour( rPropSet, rPropSetInfo );
}
/* 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.
↑ V519 The 'aAny' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 168, 169.
↑ V522 There might be dereferencing of a potential null pointer 'pFrame'.