tdf#35361 Add a Quick Look plugins for .od* files on macOS
[LibreOffice.git] / sw / source / filter / xml / xmltexte.cxx
blobd0edfa03512e8dcf0e9729564e04fd1849d79eb2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <comphelper/classids.hxx>
23 #include <com/sun/star/embed/XEmbeddedObject.hpp>
24 #include <com/sun/star/embed/XLinkageSupport.hpp>
25 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
26 #include <xmloff/families.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/xmltoken.hxx>
29 #include <xmloff/txtprmap.hxx>
30 #include <xmloff/maptype.hxx>
31 #include <xmloff/xmlexppr.hxx>
33 #include <ndole.hxx>
34 #include <fmtcntnt.hxx>
35 #include <unoframe.hxx>
36 #include "xmlexp.hxx"
37 #include "xmltexte.hxx"
38 #include <SwAppletImpl.hxx>
39 #include <ndindex.hxx>
41 #include <osl/diagnose.h>
42 #include <sot/exchange.hxx>
43 #include <svl/urihelper.hxx>
44 #include <sfx2/frmdescr.hxx>
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::document;
51 using namespace ::xmloff::token;
53 namespace {
55 enum SvEmbeddedObjectTypes
57 SV_EMBEDDED_OWN,
58 SV_EMBEDDED_OUTPLACE,
59 SV_EMBEDDED_APPLET,
60 SV_EMBEDDED_PLUGIN,
61 SV_EMBEDDED_FRAME
66 SwNoTextNode *SwXMLTextParagraphExport::GetNoTextNode(
67 const Reference < XPropertySet >& rPropSet )
69 SwXFrame* pFrame = dynamic_cast<SwXFrame*>(rPropSet.get());
70 assert(pFrame && "SwXFrame missing");
71 SwFrameFormat *pFrameFormat = pFrame->GetFrameFormat();
72 const SwFormatContent& rContent = pFrameFormat->GetContent();
73 const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
74 return pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTextNode();
77 constexpr OUString gsEmbeddedObjectProtocol( u"vnd.sun.star.EmbeddedObject:"_ustr );
79 SwXMLTextParagraphExport::SwXMLTextParagraphExport(
80 SwXMLExport& rExp,
81 SvXMLAutoStylePoolP& _rAutoStylePool ) :
82 XMLTextParagraphExport( rExp, _rAutoStylePool ),
83 m_aAppletClassId( SO3_APPLET_CLASSID ),
84 m_aPluginClassId( SO3_PLUGIN_CLASSID ),
85 m_aIFrameClassId( SO3_IFRAME_CLASSID )
89 SwXMLTextParagraphExport::~SwXMLTextParagraphExport()
93 static void lcl_addURL ( SvXMLExport &rExport, const OUString &rURL,
94 bool bToRel = true )
96 const OUString sRelURL = ( bToRel && !rURL.isEmpty() )
97 ? URIHelper::simpleNormalizedMakeRelative(rExport.GetOrigFileName(), rURL)
98 : rURL;
100 if (!sRelURL.isEmpty())
102 rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, sRelURL );
103 rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
104 rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
105 rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
109 static void lcl_addAspect(
110 const svt::EmbeddedObjectRef& rObj,
111 std::vector<XMLPropertyState>& rStates,
112 const rtl::Reference < XMLPropertySetMapper >& rMapper )
114 sal_Int64 nAspect = rObj.GetViewAspect();
115 if ( nAspect )
116 rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_DRAW_ASPECT ), uno::Any( nAspect ) );
119 static void lcl_addOutplaceProperties(
120 const svt::EmbeddedObjectRef& rObj,
121 std::vector<XMLPropertyState>& rStates,
122 const rtl::Reference < XMLPropertySetMapper >& rMapper )
124 MapMode aMode( MapUnit::Map100thMM ); // the API expects this map mode for the embedded objects
125 Size aSize = rObj.GetSize( &aMode ); // get the size in the requested map mode
127 if( !(aSize.Width() && aSize.Height()) )
128 return;
130 rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_LEFT ), Any(sal_Int32(0)) );
131 rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_TOP ), Any(sal_Int32(0)) );
132 rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_WIDTH ), Any(static_cast<sal_Int32>(aSize.Width())) );
133 rStates.emplace_back( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_HEIGHT ), Any(static_cast<sal_Int32>(aSize.Height())) );
136 static void lcl_addFrameProperties(
137 const uno::Reference < embed::XEmbeddedObject >& xObj,
138 std::vector<XMLPropertyState>& rStates,
139 const rtl::Reference < XMLPropertySetMapper >& rMapper )
141 if ( !::svt::EmbeddedObjectRef::TryRunningState( xObj ) )
142 return;
144 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
145 if ( !xSet.is() )
146 return;
148 bool bIsAutoScroll = false, bIsScrollingMode = false;
149 Any aAny = xSet->getPropertyValue(u"FrameIsAutoScroll"_ustr);
150 aAny >>= bIsAutoScroll;
151 if ( !bIsAutoScroll )
153 aAny = xSet->getPropertyValue(u"FrameIsScrollingMode"_ustr);
154 aAny >>= bIsScrollingMode;
157 bool bIsBorderSet = false, bIsAutoBorder = false;
158 aAny = xSet->getPropertyValue(u"FrameIsAutoBorder"_ustr);
159 aAny >>= bIsAutoBorder;
160 if ( !bIsAutoBorder )
162 aAny = xSet->getPropertyValue(u"FrameIsBorder"_ustr);
163 aAny >>= bIsBorderSet;
166 sal_Int32 nWidth, nHeight;
167 aAny = xSet->getPropertyValue(u"FrameMarginWidth"_ustr);
168 aAny >>= nWidth;
169 aAny = xSet->getPropertyValue(u"FrameMarginHeight"_ustr);
170 aAny >>= nHeight;
172 if( !bIsAutoScroll )
173 rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_SCROLLBAR ), Any(bIsScrollingMode) );
174 if( !bIsAutoBorder )
175 rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_BORDER ), Any(bIsBorderSet) );
176 if( SIZE_NOT_SET != nWidth )
177 rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_HORI ), Any(nWidth) );
178 if( SIZE_NOT_SET != nHeight )
179 rStates.emplace_back( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_VERT ), Any(nHeight) );
182 void SwXMLTextParagraphExport::_collectTextEmbeddedAutoStyles(
183 const Reference < XPropertySet > & rPropSet )
185 SwOLENode *pOLENd = GetNoTextNode( rPropSet )->GetOLENode();
186 svt::EmbeddedObjectRef& rObjRef = pOLENd->GetOLEObj().GetObject();
187 if( !rObjRef.is() )
188 return;
190 std::vector<XMLPropertyState> aStates;
191 aStates.reserve(8);
192 SvGlobalName aClassId( rObjRef->getClassID() );
194 if( m_aIFrameClassId == aClassId )
196 lcl_addFrameProperties( rObjRef.GetObject(), aStates,
197 GetAutoFramePropMapper()->getPropertySetMapper() );
199 else if ( !SotExchange::IsInternal( aClassId ) )
201 lcl_addOutplaceProperties( rObjRef, aStates,
202 GetAutoFramePropMapper()->getPropertySetMapper() );
205 lcl_addAspect( rObjRef, aStates,
206 GetAutoFramePropMapper()->getPropertySetMapper() );
208 Add( XmlStyleFamily::TEXT_FRAME, rPropSet, aStates );
211 void SwXMLTextParagraphExport::_exportTextEmbedded(
212 const Reference < XPropertySet > & rPropSet,
213 const Reference < XPropertySetInfo > & rPropSetInfo )
215 SwOLENode *pOLENd = GetNoTextNode( rPropSet )->GetOLENode();
216 SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
217 svt::EmbeddedObjectRef& rObjRef = rOLEObj.GetObject();
218 if( !rObjRef.is() )
219 return;
221 SvGlobalName aClassId( rObjRef->getClassID() );
223 SvEmbeddedObjectTypes nType = SV_EMBEDDED_OWN;
224 if( m_aPluginClassId == aClassId )
226 nType = SV_EMBEDDED_PLUGIN;
228 else if( m_aAppletClassId == aClassId )
230 nType = SV_EMBEDDED_APPLET;
232 else if( m_aIFrameClassId == aClassId )
234 nType = SV_EMBEDDED_FRAME;
236 else if ( !SotExchange::IsInternal( aClassId ) )
238 nType = SV_EMBEDDED_OUTPLACE;
241 enum XMLTokenEnum eElementName = XML__UNKNOWN_;
242 SvXMLExport &rXMLExport = GetExport();
244 // First the stuff common to each of Applet/Plugin/Floating Frame
245 OUString sStyle;
246 Any aAny;
247 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
249 aAny = rPropSet->getPropertyValue( gsFrameStyleName );
250 aAny >>= sStyle;
253 std::vector<XMLPropertyState> aStates;
254 aStates.reserve(8);
255 switch( nType )
257 case SV_EMBEDDED_FRAME:
258 lcl_addFrameProperties( rObjRef.GetObject(), aStates,
259 GetAutoFramePropMapper()->getPropertySetMapper() );
260 break;
261 case SV_EMBEDDED_OUTPLACE:
262 lcl_addOutplaceProperties( rObjRef, aStates,
263 GetAutoFramePropMapper()->getPropertySetMapper() );
264 break;
265 default:
269 lcl_addAspect( rObjRef, aStates,
270 GetAutoFramePropMapper()->getPropertySetMapper() );
272 const OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME,
273 rPropSet, sStyle, aStates );
274 aStates.clear();
276 if( !sAutoStyle.isEmpty() )
277 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, sAutoStyle );
278 addTextFrameAttributes( rPropSet, false );
280 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
281 XML_FRAME, false, true );
283 switch (nType)
285 case SV_EMBEDDED_OUTPLACE:
286 case SV_EMBEDDED_OWN:
287 if( !(rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED) )
289 OUString sURL;
291 bool bIsOwnLink = false;
292 if( SV_EMBEDDED_OWN == nType )
296 uno::Reference< embed::XLinkageSupport > xLinkage( rObjRef.GetObject(), uno::UNO_QUERY );
297 bIsOwnLink = xLinkage.is() && xLinkage->isLink();
298 if ( bIsOwnLink )
299 sURL = xLinkage->getLinkURL();
301 catch(const uno::Exception&)
303 // TODO/LATER: error handling
304 OSL_FAIL( "Link detection or retrieving of the URL of OOo link is failed!" );
308 if ( !bIsOwnLink )
310 sURL = gsEmbeddedObjectProtocol + rOLEObj.GetCurrentPersistName();
313 sURL = GetExport().AddEmbeddedObject( sURL );
314 lcl_addURL( rXMLExport, sURL, false );
316 if( SV_EMBEDDED_OWN == nType && !pOLENd->GetChartTableName().isEmpty() )
318 OUString sRange( pOLENd->GetChartTableName() );
319 OUStringBuffer aBuffer( sRange.getLength() + 2 );
320 for( sal_Int32 i=0; i < sRange.getLength(); i++ )
322 sal_Unicode c = sRange[i];
323 switch( c )
325 case ' ':
326 case '.':
327 case '\'':
328 case '\\':
329 if( aBuffer.isEmpty() )
331 aBuffer.append( OUString::Concat("\'") + sRange.subView(0, i) );
333 if( '\'' == c || '\\' == c )
334 aBuffer.append( '\\' );
335 [[fallthrough]];
336 default:
337 if( !aBuffer.isEmpty() )
338 aBuffer.append( c );
341 if( !aBuffer.isEmpty() )
343 aBuffer.append( '\'' );
344 sRange = aBuffer.makeStringAndClear();
347 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES,
348 sRange );
350 eElementName = SV_EMBEDDED_OUTPLACE==nType ? XML_OBJECT_OLE
351 : XML_OBJECT;
352 break;
353 case SV_EMBEDDED_APPLET:
355 // It's an applet!
356 if( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
358 uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
359 OUString aStr;
360 Any aAny2 = xSet->getPropertyValue(u"AppletCodeBase"_ustr);
361 aAny2 >>= aStr;
362 if (!aStr.isEmpty() )
363 lcl_addURL(rXMLExport, aStr);
365 aAny2 = xSet->getPropertyValue(u"AppletName"_ustr);
366 aAny2 >>= aStr;
367 if (!aStr.isEmpty())
368 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_APPLET_NAME, aStr );
370 aAny2 = xSet->getPropertyValue(u"AppletCode"_ustr);
371 aAny2 >>= aStr;
372 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CODE, aStr );
374 bool bScript = false;
375 aAny2 = xSet->getPropertyValue(u"AppletIsScript"_ustr);
376 aAny2 >>= bScript;
377 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MAY_SCRIPT, bScript ? XML_TRUE : XML_FALSE );
379 uno::Sequence < beans::PropertyValue > aProps;
380 aAny2 = xSet->getPropertyValue(u"AppletCommands"_ustr);
381 aAny2 >>= aProps;
383 sal_Int32 i = aProps.getLength();
384 while ( i > 0 )
386 const beans::PropertyValue& aProp = aProps[--i];
387 const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, true );
388 if ( nType2 == SwHtmlOptType::TAG)
390 OUString aStr2;
391 aProp.Value >>= aStr2;
392 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, aProp.Name, aStr2);
396 eElementName = XML_APPLET;
399 break;
400 case SV_EMBEDDED_PLUGIN:
402 // It's a plugin!
403 if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
405 uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
406 OUString aStr;
407 Any aAny2 = xSet->getPropertyValue(u"PluginURL"_ustr);
408 aAny2 >>= aStr;
409 lcl_addURL( rXMLExport, aStr );
411 aAny2 = xSet->getPropertyValue(u"PluginMimeType"_ustr);
412 aAny2 >>= aStr;
413 if (!aStr.isEmpty())
414 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, aStr );
415 eElementName = XML_PLUGIN;
418 break;
419 case SV_EMBEDDED_FRAME:
421 // It's a floating frame!
422 if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
424 uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
425 OUString aStr;
426 Any aAny2 = xSet->getPropertyValue(u"FrameURL"_ustr);
427 aAny2 >>= aStr;
429 lcl_addURL( rXMLExport, aStr );
431 aAny2 = xSet->getPropertyValue(u"FrameName"_ustr);
432 aAny2 >>= aStr;
434 if (!aStr.isEmpty())
435 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FRAME_NAME, aStr );
436 eElementName = XML_FLOATING_FRAME;
439 break;
440 default:
441 OSL_ENSURE( false, "unknown object type! Base class should have been called!" );
445 SvXMLElementExport aElementExport( rXMLExport, XML_NAMESPACE_DRAW, eElementName,
446 false, true );
447 switch( nType )
449 case SV_EMBEDDED_OWN:
450 if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
452 Reference < XEmbeddedObjectSupplier > xEOS( rPropSet, UNO_QUERY );
453 OSL_ENSURE( xEOS.is(), "no embedded object supplier for own object" );
454 Reference < XComponent > xComp = xEOS->getEmbeddedObject();
455 rXMLExport.ExportEmbeddedOwnObject( xComp );
457 break;
458 case SV_EMBEDDED_OUTPLACE:
459 if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
461 OUString sURL( gsEmbeddedObjectProtocol + rOLEObj.GetCurrentPersistName() );
463 if ( !( rXMLExport.getExportFlags() & SvXMLExportFlags::OASIS ) )
464 sURL += "?oasis=false";
466 rXMLExport.AddEmbeddedObjectAsBase64( sURL );
468 break;
469 case SV_EMBEDDED_APPLET:
471 if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
473 uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
474 uno::Sequence < beans::PropertyValue > aProps;
475 aAny = xSet->getPropertyValue(u"AppletCommands"_ustr);
476 aAny >>= aProps;
478 sal_Int32 i = aProps.getLength();
479 while ( i > 0 )
481 const beans::PropertyValue& aProp = aProps[--i];
482 const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, true );
483 if (SwHtmlOptType::PARAM == nType2 || SwHtmlOptType::SIZE == nType2 )
485 OUString aStr;
486 aProp.Value >>= aStr;
487 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name );
488 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
489 SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
494 break;
495 case SV_EMBEDDED_PLUGIN:
497 if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) )
499 uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY );
500 uno::Sequence < beans::PropertyValue > aProps;
501 aAny = xSet->getPropertyValue(u"PluginCommands"_ustr);
502 aAny >>= aProps;
504 sal_Int32 i = aProps.getLength();
505 while ( i > 0 )
507 const beans::PropertyValue& aProp = aProps[--i];
508 const SwHtmlOptType nType2 = SwApplet_Impl::GetOptionType( aProp.Name, false );
509 if ( nType2 == SwHtmlOptType::TAG)
511 OUString aStr;
512 aProp.Value >>= aStr;
513 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name );
514 rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
515 SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
520 break;
521 default:
522 break;
525 if( SV_EMBEDDED_OUTPLACE==nType || SV_EMBEDDED_OWN==nType )
527 OUString sURL = XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE + rOLEObj.GetCurrentPersistName();
528 if( !(rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED) )
530 sURL = GetExport().AddEmbeddedObject( sURL );
531 lcl_addURL( rXMLExport, sURL, false );
534 SvXMLElementExport aElementExport( GetExport(), XML_NAMESPACE_DRAW,
535 XML_IMAGE, false, true );
537 if( rXMLExport.getExportFlags() & SvXMLExportFlags::EMBEDDED )
538 GetExport().AddEmbeddedObjectAsBase64( sURL );
541 // Lastly the stuff common to each of Applet/Plugin/Floating Frame
542 exportEvents( rPropSet );
543 exportTitleAndDescription( rPropSet, rPropSetInfo ); // #i73249#
544 exportContour( rPropSet, rPropSetInfo );
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */