fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / xcl97 / xcl97esc.cxx
blob6bd7448a780e176bc158c6f023299a331bc12f99
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 <com/sun/star/awt/XControlModel.hpp>
21 #include <com/sun/star/embed/XClassifiedObject.hpp>
22 #include <com/sun/star/form/XFormsSupplier.hpp>
23 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
24 #include <com/sun/star/script/XEventAttacherManager.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/form/XForm.hpp>
28 #include <svx/svdpage.hxx>
29 #include <editeng/outlobj.hxx>
30 #include <svx/svdotext.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdoole2.hxx>
33 #include <svx/unoapi.hxx>
34 #include <svx/fmglob.hxx>
35 #include <vcl/outdev.hxx>
36 #include <unotools/tempfile.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #include <svx/sdasitm.hxx>
39 #include <sfx2/docfile.hxx>
41 #include <sot/exchange.hxx>
42 #include "xeescher.hxx"
44 #include "global.hxx"
45 #include "document.hxx"
46 #include "drwlayer.hxx"
47 #include "xecontent.hxx"
48 #include <editeng/flditem.hxx>
49 #include "userdat.hxx"
50 #include "xcl97rec.hxx"
51 #include "xehelper.hxx"
52 #include "xechart.hxx"
53 #include "xcl97esc.hxx"
54 #include <unotools/streamwrap.hxx>
55 #include <oox/ole/olehelper.hxx>
56 #include <sfx2/objsh.hxx>
58 using ::com::sun::star::uno::Any;
59 using ::com::sun::star::uno::Exception;
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::uno::Sequence;
62 using ::com::sun::star::uno::UNO_QUERY;
63 using ::com::sun::star::uno::UNO_QUERY_THROW;
64 using ::com::sun::star::container::XIndexAccess;
65 using ::com::sun::star::embed::XClassifiedObject;
66 using ::com::sun::star::drawing::XShape;
67 using ::com::sun::star::awt::XControlModel;
68 using ::com::sun::star::beans::XPropertySet;
69 using ::com::sun::star::uno::Any;
70 using ::com::sun::star::form::XForm;
71 using ::com::sun::star::form::XFormComponent;
72 using ::com::sun::star::form::XFormsSupplier;
73 using ::com::sun::star::io::XOutputStream;
74 using ::com::sun::star::script::ScriptEventDescriptor;
75 using ::com::sun::star::script::XEventAttacherManager;
77 XclEscherExGlobal::XclEscherExGlobal( const XclExpRoot& rRoot ) :
78 XclExpRoot( rRoot )
80 SetBaseURI( GetMedium().GetBaseURL( true ) );
83 SvStream* XclEscherExGlobal::ImplQueryPictureStream()
85 mxPicTempFile.reset( new ::utl::TempFile );
86 if( mxPicTempFile->IsValid() )
88 mxPicTempFile->EnableKillingFile();
89 mxPicStrm.reset( ::utl::UcbStreamHelper::CreateStream( mxPicTempFile->GetURL(), STREAM_STD_READWRITE ) );
90 mxPicStrm->SetEndian( SvStreamEndian::LITTLE );
92 return mxPicStrm.get();
95 XclEscherEx::XclEscherEx( const XclExpRoot& rRoot, XclExpObjectManager& rObjMgr, SvStream& rStrm, const XclEscherEx* pParent ) :
96 EscherEx( pParent ? pParent->mxGlobal : EscherExGlobalRef( new XclEscherExGlobal( rRoot ) ), &rStrm ),
97 XclExpRoot( rRoot ),
98 mrObjMgr( rObjMgr ),
99 pCurrXclObj( NULL ),
100 pCurrAppData( NULL ),
101 pTheClientData( new XclEscherClientData ),
102 pAdditionalText( NULL ),
103 nAdditionalText( 0 ),
104 mnNextKey( 0 ),
105 mbIsRootDff( pParent == 0 )
107 InsertPersistOffset( mnNextKey, 0 );
110 XclEscherEx::~XclEscherEx()
112 OSL_ENSURE( !aStack.empty(), "~XclEscherEx: stack not empty" );
113 DeleteCurrAppData();
114 delete pTheClientData;
117 sal_uInt32 XclEscherEx::InitNextDffFragment()
119 /* Current value of mnNextKey will be used by caller to refer to the
120 starting point of the DFF fragment. The key exists already in the
121 PersistTable (has been inserted by c'tor of previous call of
122 InitNextDffFragment(), has been updated by UpdateDffFragmentEnd(). */
123 sal_uInt32 nPersistKey = mnNextKey;
125 /* Prepare the next key that is used by caller as end point of the DFF
126 fragment. Will be updated by caller when writing to the DFF stream,
127 using the UpdateDffFragmentEnd() function. This is needed to find DFF
128 data written by the SVX base class implementation without interaction,
129 e.g. the solver container that will be written after the last shape. */
130 ++mnNextKey;
131 InsertPersistOffset( mnNextKey, mpOutStrm->Tell() );
133 return nPersistKey;
136 void XclEscherEx::UpdateDffFragmentEnd()
138 // update existing fragment key with new stream position
139 ReplacePersistOffset( mnNextKey, mpOutStrm->Tell() );
142 sal_uInt32 XclEscherEx::GetDffFragmentPos( sal_uInt32 nFragmentKey )
144 /* TODO: this function is non-const because PersistTable::PtGetOffsetByID()
145 is non-const due to tools/List usage. */
146 return GetPersistOffset( nFragmentKey );
149 sal_uInt32 XclEscherEx::GetDffFragmentSize( sal_uInt32 nFragmentKey )
151 /* TODO: this function is non-const because PersistTable::PtGetOffsetByID()
152 is non-const due to tools/List usage. */
153 return GetDffFragmentPos( nFragmentKey + 1 ) - GetDffFragmentPos( nFragmentKey );
156 bool XclEscherEx::HasPendingDffData()
158 /* TODO: this function is non-const because PersistTable::PtGetOffsetByID()
159 is non-const due to tools/List usage. */
160 return GetDffFragmentPos( mnNextKey ) < GetStreamPos();
163 XclExpDffAnchorBase* XclEscherEx::CreateDffAnchor( const SdrObject& rSdrObj ) const
165 // the object manager creates the correct anchor type according to context
166 XclExpDffAnchorBase* pAnchor = mrObjMgr.CreateDffAnchor();
167 // pass the drawing object, that will calculate the anchor position
168 pAnchor->SetSdrObject( rSdrObj );
169 return pAnchor;
172 namespace {
174 bool lcl_IsFontwork( const SdrObject* pObj )
176 bool bIsFontwork = false;
177 if( pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE )
179 const OUString aTextPath = "TextPath";
180 const SdrCustomShapeGeometryItem& rGeometryItem = static_cast<const SdrCustomShapeGeometryItem&>(
181 pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
182 if( const Any* pAny = rGeometryItem.GetPropertyValueByName( aTextPath, aTextPath ) )
183 *pAny >>= bIsFontwork;
185 return bIsFontwork;
188 } // namespace
190 EscherExHostAppData* XclEscherEx::StartShape( const Reference< XShape >& rxShape, const Rectangle* pChildAnchor )
192 if ( nAdditionalText )
193 nAdditionalText++;
194 bool bInGroup = ( pCurrXclObj != NULL );
195 if ( bInGroup )
196 { // stacked recursive group object
197 if ( !pCurrAppData->IsStackedGroup() )
198 { //! UpdateDffFragmentEnd only once
199 pCurrAppData->SetStackedGroup( true );
200 UpdateDffFragmentEnd();
203 aStack.push( std::make_pair( pCurrXclObj, pCurrAppData ) );
204 pCurrAppData = new XclEscherHostAppData;
205 SdrObject* pObj = GetSdrObjectFromXShape( rxShape );
206 //added for exporting OCX control
207 sal_Int16 nMsCtlType = 0;
208 if ( !pObj )
209 pCurrXclObj = new XclObjAny( mrObjMgr, rxShape ); // just what is it?!?
210 else
212 pCurrXclObj = NULL;
213 sal_uInt16 nObjType = pObj->GetObjIdentifier();
215 if( nObjType == OBJ_OLE2 )
217 // no OLE objects in embedded drawings (chart shapes)
218 if( mbIsRootDff )
220 //! not-const because GetObjRef may load the OLE object
221 Reference < XClassifiedObject > xObj( static_cast<SdrOle2Obj*>(pObj)->GetObjRef(), UNO_QUERY );
222 if ( xObj.is() )
224 SvGlobalName aObjClsId( xObj->getClassID() );
225 if ( SotExchange::IsChart( aObjClsId ) )
226 { // yes, it's a chart diagram
227 mrObjMgr.AddObj( new XclExpChartObj( mrObjMgr, rxShape, pChildAnchor ) );
228 pCurrXclObj = NULL; // no metafile or whatsoever
230 else // metafile and OLE object
231 pCurrXclObj = new XclObjOle( mrObjMgr, *pObj );
233 else // just a metafile
234 pCurrXclObj = new XclObjAny( mrObjMgr, rxShape );
236 else
237 pCurrXclObj = new XclObjAny( mrObjMgr, rxShape );
239 else if( nObjType == OBJ_UNO )
241 //added for exporting OCX control
242 Reference< XPropertySet > xPropSet( rxShape, UNO_QUERY );
243 Any aAny;
246 aAny = xPropSet->getPropertyValue("ControlTypeinMSO");
247 aAny >>= nMsCtlType;
249 catch(const Exception&)
251 OSL_TRACE("XclEscherEx::StartShape, this control can't get the property ControlTypeinMSO!");
253 if( nMsCtlType == 2 ) //OCX Form Control
254 pCurrXclObj = CreateOCXCtrlObj( rxShape, pChildAnchor );
255 else //TBX Form Control
256 pCurrXclObj = CreateTBXCtrlObj( rxShape, pChildAnchor );
257 if( !pCurrXclObj )
258 pCurrXclObj = new XclObjAny( mrObjMgr, rxShape ); // just a metafile
260 else if( !ScDrawLayer::IsNoteCaption( pObj ) )
262 // ignore permanent note shapes
263 // #i12190# do not ignore callouts (do not filter by object type ID)
264 pCurrXclObj = ShapeInteractionHelper::CreateShapeObj( mrObjMgr, rxShape );
265 ShapeInteractionHelper::PopulateShapeInteractionInfo( mrObjMgr, rxShape, *pCurrAppData );
268 if ( pCurrXclObj )
270 if ( !mrObjMgr.AddObj( pCurrXclObj ) )
271 { // maximum count reached, object got deleted
272 pCurrXclObj = NULL;
274 else
276 pCurrAppData->SetClientData( pTheClientData );
277 if ( nAdditionalText == 0 )
279 if ( pObj )
281 if ( !bInGroup )
283 /* Create a dummy anchor carrying the flags. Real
284 coordinates are calculated later in virtual call of
285 WriteData(EscherEx&,const Rectangle&). */
286 XclExpDffAnchorBase* pAnchor = mrObjMgr.CreateDffAnchor();
287 pAnchor->SetFlags( *pObj );
288 pCurrAppData->SetClientAnchor( pAnchor );
290 const SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pObj );
291 if( pTextObj && !lcl_IsFontwork( pTextObj ) && (pObj->GetObjIdentifier() != OBJ_CAPTION) )
293 const OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
294 if( pParaObj )
295 pCurrAppData->SetClientTextbox(
296 new XclEscherClientTextbox( GetRoot(), *pTextObj, pCurrXclObj ) );
299 else
301 if ( !bInGroup )
302 pCurrAppData->SetClientAnchor( mrObjMgr.CreateDffAnchor() );
305 else if ( nAdditionalText == 3 )
307 if ( pAdditionalText )
309 pAdditionalText->SetXclObj( pCurrXclObj );
310 pCurrAppData->SetClientTextbox( pAdditionalText );
315 if(pObj)
317 //add for exporting OCX control
318 //for OCX control import from MS office file,we need keep the id value as MS office file.
319 //GetOldRoot().pObjRecs->Add( pCurrXclObj ) statement has generated the id value as obj id rule;
320 //but we trick it here.
321 sal_uInt16 nObjType = pObj->GetObjIdentifier();
322 if( nObjType == OBJ_UNO && pCurrXclObj )
324 Reference< XPropertySet > xPropSet( rxShape, UNO_QUERY );
325 Any aAny;
328 aAny = xPropSet->getPropertyValue("ObjIDinMSO");
330 catch(const Exception&)
332 OSL_TRACE("XclEscherEx::StartShape, this control can't get the property ObjIDinMSO!");
334 sal_uInt16 nObjIDinMSO = 0xFFFF;
335 aAny >>= nObjIDinMSO;
336 if( nObjIDinMSO != 0xFFFF && nMsCtlType == 2) //OCX
338 pCurrXclObj->SetId(nObjIDinMSO);
342 if ( !pCurrXclObj )
343 pCurrAppData->SetDontWriteShape( true );
344 return pCurrAppData;
347 void XclEscherEx::EndShape( sal_uInt16 nShapeType, sal_uInt32 nShapeID )
349 // own escher data created? -> never delete such objects
350 bool bOwnEscher = pCurrXclObj && pCurrXclObj->IsOwnEscher();
352 // post process the current object - not for objects with own escher data
353 if( pCurrXclObj && !bOwnEscher )
355 // escher data of last shape not written? -> delete it from object list
356 if( nShapeID == 0 )
358 XclObj* pLastObj = mrObjMgr.RemoveLastObj();
359 OSL_ENSURE( pLastObj == pCurrXclObj, "XclEscherEx::EndShape - wrong object" );
360 DELETEZ( pLastObj );
361 pCurrXclObj = 0;
364 if( pCurrXclObj )
366 // set shape type
367 if ( pCurrAppData->IsStackedGroup() )
368 pCurrXclObj->SetEscherShapeTypeGroup();
369 else
371 pCurrXclObj->SetEscherShapeType( nShapeType );
372 UpdateDffFragmentEnd();
377 // get next object from stack
378 DeleteCurrAppData();
379 if (aStack.empty())
381 pCurrXclObj = NULL;
382 pCurrAppData = NULL;
384 else
386 pCurrXclObj = aStack.top().first;
387 pCurrAppData = aStack.top().second;
388 aStack.pop();
390 if( nAdditionalText == 3 )
391 nAdditionalText = 0;
394 EscherExHostAppData* XclEscherEx::EnterAdditionalTextGroup()
396 nAdditionalText = 1;
397 pAdditionalText = static_cast<XclEscherClientTextbox*>( pCurrAppData->GetClientTextbox() );
398 pCurrAppData->SetClientTextbox( NULL );
399 return pCurrAppData;
402 void XclEscherEx::EndDocument()
404 if( mbIsRootDff )
405 Flush( static_cast< XclEscherExGlobal& >( *mxGlobal ).GetPictureStream() );
407 // seek back DFF stream to prepare saving the MSODRAWING[GROUP] records
408 mpOutStrm->Seek( 0 );
411 XclExpOcxControlObj* XclEscherEx::CreateOCXCtrlObj( Reference< XShape > xShape, const Rectangle* pChildAnchor )
413 ::std::unique_ptr< XclExpOcxControlObj > xOcxCtrl;
415 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
416 if( xCtrlModel.is() )
418 // output stream
419 if( !mxCtlsStrm.Is() )
420 mxCtlsStrm = OpenStream( EXC_STREAM_CTLS );
421 if( mxCtlsStrm.Is() )
423 OUString aClassName;
424 sal_uInt32 nStrmStart = static_cast< sal_uInt32 >( mxCtlsStrm->Tell() );
426 // writes from xCtrlModel into mxCtlsStrm, raw class name returned in aClassName
427 Reference< XOutputStream > xOut( new utl::OSeekableOutputStreamWrapper( *mxCtlsStrm ) );
428 Reference< com::sun::star::frame::XModel > xModel( GetDocShell() ? GetDocShell()->GetModel() : NULL );
429 if( xModel.is() && xOut.is() && oox::ole::MSConvertOCXControls::WriteOCXExcelKludgeStream( xModel, xOut, xCtrlModel, xShape->getSize(), aClassName ) )
431 sal_uInt32 nStrmSize = static_cast< sal_uInt32 >( mxCtlsStrm->Tell() - nStrmStart );
432 // adjust the class name to "Forms.***.1"
433 aClassName = "Forms." + aClassName + ".1";
434 xOcxCtrl.reset( new XclExpOcxControlObj( mrObjMgr, xShape, pChildAnchor, aClassName, nStrmStart, nStrmSize ) );
438 return xOcxCtrl.release();
441 XclExpTbxControlObj* XclEscherEx::CreateTBXCtrlObj( Reference< XShape > xShape, const Rectangle* pChildAnchor )
443 ::std::unique_ptr< XclExpTbxControlObj > xTbxCtrl( new XclExpTbxControlObj( mrObjMgr, xShape, pChildAnchor ) );
444 if( xTbxCtrl->GetObjType() == EXC_OBJTYPE_UNKNOWN )
445 xTbxCtrl.reset();
447 if( xTbxCtrl.get() )
449 // find attached macro
450 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
451 ConvertTbxMacro( *xTbxCtrl, xCtrlModel );
453 return xTbxCtrl.release();
456 void XclEscherEx::ConvertTbxMacro( XclExpTbxControlObj& rTbxCtrlObj, Reference< XControlModel > xCtrlModel )
458 SdrPage* pSdrPage = GetSdrPage( GetCurrScTab() );
459 if( xCtrlModel.is() && GetDocShell() && pSdrPage ) try
461 Reference< XFormsSupplier > xFormsSupplier( pSdrPage->getUnoPage(), UNO_QUERY_THROW );
462 Reference< XIndexAccess > xFormsIA( xFormsSupplier->getForms(), UNO_QUERY_THROW );
464 // 1) try to find the index of the processed control in the form
466 Reference< XIndexAccess > xFormIA; // needed in step 2) below
467 sal_Int32 nFoundIdx = -1;
469 // search all existing forms in the draw page
470 for( sal_Int32 nFormIdx = 0, nFormCount = xFormsIA->getCount();
471 (nFoundIdx < 0) && (nFormIdx < nFormCount); ++nFormIdx )
473 // get the XIndexAccess interface of the form with index nFormIdx
474 if( xFormIA.set( xFormsIA->getByIndex( nFormIdx ), UNO_QUERY ) )
476 // search all elements (controls) of the current form by index
477 for( sal_Int32 nCtrlIdx = 0, nCtrlCount = xFormIA->getCount();
478 (nFoundIdx < 0) && (nCtrlIdx < nCtrlCount); ++nCtrlIdx )
480 // compare implementation pointers of the control models
481 Reference< XControlModel > xCurrModel( xFormIA->getByIndex( nCtrlIdx ), UNO_QUERY );
482 if( xCtrlModel.get() == xCurrModel.get() )
483 nFoundIdx = nCtrlIdx;
488 // 2) try to find an attached macro
490 if( xFormIA.is() && (nFoundIdx >= 0) )
492 Reference< XEventAttacherManager > xEventMgr( xFormIA, UNO_QUERY_THROW );
493 // loop over all events attached to the found control
494 const Sequence< ScriptEventDescriptor > aEventSeq( xEventMgr->getScriptEvents( nFoundIdx ) );
495 bool bFound = false;
496 for( sal_Int32 nEventIdx = 0, nEventCount = aEventSeq.getLength();
497 !bFound && (nEventIdx < nEventCount); ++nEventIdx )
499 // try to set the event data at the Excel control object, returns true on success
500 bFound = rTbxCtrlObj.SetMacroLink( aEventSeq[ nEventIdx ] );
504 catch( Exception& )
509 void XclEscherEx::DeleteCurrAppData()
511 if ( pCurrAppData )
513 delete pCurrAppData->GetClientAnchor();
514 // delete pCurrAppData->GetClientData();
515 delete pCurrAppData->GetClientTextbox();
516 delete pCurrAppData->GetInteractionInfo();
517 delete pCurrAppData;
521 // --- class XclEscherClientData -------------------------------------
523 void XclEscherClientData::WriteData( EscherEx& rEx ) const
524 { // actual data is in the following OBJ record
525 rEx.AddAtom( 0, ESCHER_ClientData );
528 // --- class XclEscherClientTextbox -------------------------------------
530 XclEscherClientTextbox::XclEscherClientTextbox( const XclExpRoot& rRoot,
531 const SdrTextObj& rObj, XclObj* pObj )
533 XclExpRoot( rRoot ),
534 rTextObj( rObj ),
535 pXclObj( pObj )
539 void XclEscherClientTextbox::WriteData( EscherEx& /*rEx*/ ) const
541 pXclObj->SetText( GetRoot(), rTextObj );
544 XclExpShapeObj*
545 ShapeInteractionHelper::CreateShapeObj( XclExpObjectManager& rObjMgr, const Reference< XShape >& xShape )
547 return new XclExpShapeObj( rObjMgr, xShape );
550 void
551 ShapeInteractionHelper::PopulateShapeInteractionInfo( XclExpObjectManager& rObjMgr, const Reference< XShape >& xShape, EscherExHostAppData& rHostAppData )
555 SvMemoryStream* pMemStrm = NULL;
556 OUString sHyperLink;
557 OUString sMacro;
558 if ( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( ::GetSdrObjectFromXShape( xShape ) ) )
560 sHyperLink = pInfo->GetHlink();
561 sMacro = pInfo->GetMacro();
563 if ( !sHyperLink.isEmpty() )
565 pMemStrm = new SvMemoryStream();
566 XclExpStream tmpStream( *pMemStrm, rObjMgr.GetRoot() );
567 ScAddress dummyAddress;
568 SvxURLField aUrlField;
569 aUrlField.SetURL( sHyperLink );
570 XclExpHyperlink hExpHlink( rObjMgr.GetRoot(), aUrlField, dummyAddress );
571 hExpHlink.WriteEmbeddedData( tmpStream );
573 if ( !sHyperLink.isEmpty() || !sMacro.isEmpty() )
574 rHostAppData.SetInteractionInfo( new InteractionInfo( pMemStrm, true ) );
576 catch( Exception& )
581 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */