update dev300-m58
[ooovba.git] / sc / source / filter / xcl97 / xcl97esc.cxx
blobb2c0e7d589d916f42dea97156af303ebf842b283
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xcl97esc.cxx,v $
10 * $Revision: 1.26.128.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include <com/sun/star/awt/XControlModel.hpp>
35 #include <com/sun/star/embed/XClassifiedObject.hpp>
36 #include <com/sun/star/form/XFormsSupplier.hpp>
37 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
38 #include <com/sun/star/script/XEventAttacherManager.hpp>
40 #include <svx/svdpage.hxx>
41 #include <svx/outlobj.hxx>
42 #include <svx/svdotext.hxx>
43 #include <svx/svdobj.hxx>
44 #include <svx/svdoole2.hxx>
45 #include <svx/unoapi.hxx>
46 #include <svx/fmglob.hxx>
47 #include <svx/msocximex.hxx>
48 #include <vcl/outdev.hxx>
49 #include <unotools/tempfile.hxx>
50 #include <unotools/ucbstreamhelper.hxx>
51 #include <tools/debug.hxx>
52 #include <svx/sdasitm.hxx>
54 #include <sot/exchange.hxx>
55 #include "xeescher.hxx"
57 #include "global.hxx"
58 #include "document.hxx"
59 #include "drwlayer.hxx"
60 #include "xecontent.hxx"
61 #include <svx/flditem.hxx>
62 #include "userdat.hxx"
63 #include "xcl97rec.hxx"
64 #include "xehelper.hxx"
65 #include "xechart.hxx"
66 #include "xcl97esc.hxx"
68 using ::com::sun::star::uno::Reference;
69 using ::com::sun::star::uno::Sequence;
70 using ::com::sun::star::uno::Exception;
71 using ::com::sun::star::uno::UNO_QUERY;
72 using ::com::sun::star::uno::UNO_QUERY_THROW;
73 using ::com::sun::star::container::XIndexAccess;
74 using ::com::sun::star::embed::XClassifiedObject;
75 using ::com::sun::star::drawing::XShape;
76 using ::com::sun::star::awt::XControlModel;
77 using ::com::sun::star::form::XFormsSupplier;
78 using ::com::sun::star::script::ScriptEventDescriptor;
79 using ::com::sun::star::script::XEventAttacherManager;
81 // --- class XclEscherEx ---------------------------------------------
83 XclEscherEx::XclEscherEx( const XclExpRoot& rRoot, SvStream& rStrm, UINT32 nDrawings )
85 EscherEx( rStrm, nDrawings ),
86 XclExpRoot( rRoot ),
87 pPicTempFile( NULL ),
88 pPicStrm( NULL ),
89 pCurrXclObj( NULL ),
90 pCurrAppData( NULL ),
91 pTheClientData( new XclEscherClientData ),
92 pAdditionalText( NULL ),
93 nAdditionalText( 0 )
95 aOffsetMap.Insert( (void*) 0, LIST_APPEND ); // start of stream
96 // Xcl forgets OLE objects completely if the Escher object is not EMF and
97 // the corresponding OLE application is opened and nothing is changed.
98 SetOleEmf( TRUE );
102 XclEscherEx::~XclEscherEx()
104 DBG_ASSERT( !aStack.Count(), "~XclEscherEx: stack not empty" );
105 DeleteCurrAppData();
106 delete pTheClientData;
107 if ( pPicStrm )
109 delete pPicStrm;
111 if ( pPicTempFile )
112 delete pPicTempFile;
116 SvStream* XclEscherEx::QueryPicStream()
118 if ( !pPicStrm )
120 if ( !pPicTempFile )
122 pPicTempFile = new utl::TempFile;
123 if ( pPicTempFile->IsValid() )
124 pPicTempFile->EnableKillingFile();
125 else
127 delete pPicTempFile;
128 pPicTempFile = NULL;
131 if ( pPicTempFile )
133 pPicStrm = utl::UcbStreamHelper::CreateStream( pPicTempFile->GetURL(), STREAM_STD_READWRITE );
134 pPicStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
137 return pPicStrm;
141 void XclEscherEx::InsertAtCurrentPos( UINT32 nBytes, BOOL bCont )
143 ULONG nPos = GetStreamPos();
144 ULONG nCnt = aOffsetMap.Count();
145 ULONG j, nOff;
146 for ( j=0, nOff = (ULONG) aOffsetMap.First(); j<nCnt;
147 j++, nOff = (ULONG) aOffsetMap.Next() )
149 if ( nOff >= nPos )
150 aOffsetMap.Replace( (void*) (nOff + nBytes) );
152 EscherEx::InsertAtCurrentPos( nBytes, bCont );
156 ULONG XclEscherEx::AddCurrentOffsetToMap()
158 aOffsetMap.Insert( (void*) GetStreamPos(), LIST_APPEND );
159 return aOffsetMap.Count() - 1;
163 void XclEscherEx::ReplaceCurrentOffsetInMap( ULONG nPos )
165 aOffsetMap.Replace( (void*) GetStreamPos(), nPos );
168 sal_Bool ImplXclEscherExIsFontwork( const SdrObject* pObj )
170 const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) );
172 sal_Bool bIsFontwork = sal_False;
173 if ( pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE )
175 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)
176 pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
178 com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
179 if ( pAny )
180 *pAny >>= bIsFontwork;
182 return bIsFontwork;
185 EscherExHostAppData* XclEscherEx::StartShape( const com::sun::star::uno::Reference<
186 com::sun::star::drawing::XShape >& rShape )
188 if ( nAdditionalText )
189 nAdditionalText++;
190 BOOL bInGroup = ( pCurrXclObj != NULL );
191 if ( bInGroup )
192 { // stacked recursive group object
193 if ( !pCurrAppData->IsStackedGroup() )
194 { //! UpdateStopPos only once
195 pCurrAppData->SetStackedGroup( TRUE );
196 pCurrXclObj->UpdateStopPos();
199 aStack.Push( pCurrXclObj );
200 aStack.Push( pCurrAppData );
201 pCurrAppData = new XclEscherHostAppData;
202 SdrObject* pObj = GetSdrObjectFromXShape( rShape );
203 if ( !pObj )
204 pCurrXclObj = new XclObjAny( GetRoot() ); // just what is it?!?
205 else
207 pCurrXclObj = NULL;
208 sal_uInt16 nObjType = pObj->GetObjIdentifier();
210 if( nObjType == OBJ_OLE2 )
212 //! not-const because GetObjRef may load the OLE object
213 Reference < XClassifiedObject > xObj( ((SdrOle2Obj*)pObj)->GetObjRef(), UNO_QUERY );
214 if ( xObj.is() )
216 SvGlobalName aObjClsId( xObj->getClassID() );
217 if ( SotExchange::IsChart( aObjClsId ) )
218 { // yes, it's a chart diagram
219 GetOldRoot().pObjRecs->Add( new XclExpChartObj( GetRoot(), rShape ) );
220 pCurrXclObj = NULL; // no metafile or whatsoever
222 else // metafile and OLE object
223 pCurrXclObj = new XclObjOle( GetRoot(), *pObj );
225 else // just a metafile
226 pCurrXclObj = new XclObjAny( GetRoot() );
228 else if( nObjType == OBJ_UNO )
230 pCurrXclObj = CreateCtrlObj( rShape );
231 if( !pCurrXclObj )
232 pCurrXclObj = new XclObjAny( GetRoot() ); // just a metafile
234 else if( !ScDrawLayer::IsNoteCaption( pObj ) )
236 // #107540# ignore permanent note shapes
237 // #i12190# do not ignore callouts (do not filter by object type ID)
238 pCurrXclObj = ShapeInteractionHelper::CreateShapeObj( GetRoot(), rShape );
239 ShapeInteractionHelper::PopulateShapeInteractionInfo( GetRoot(), rShape, *pCurrAppData );
242 if ( pCurrXclObj )
244 if ( !GetOldRoot().pObjRecs->Add( pCurrXclObj ) )
245 { // maximum count reached, object got deleted
246 pCurrXclObj = NULL;
248 else
250 pCurrAppData->SetClientData( pTheClientData );
251 if ( nAdditionalText == 0 )
253 if ( pObj )
255 if ( !bInGroup )
257 /* Create a dummy anchor carrying the flags. Real coordinates are
258 calculated later in WriteData(EscherEx&,const Rectangle&). */
259 XclExpDffAnchor* pAnchor = new XclExpDffAnchor( GetRoot() );
260 pAnchor->SetFlags( *pObj );
261 pCurrAppData->SetClientAnchor( pAnchor );
263 const SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pObj );
264 if ( pTextObj && !ImplXclEscherExIsFontwork( pTextObj ) && ( pObj->GetObjIdentifier() != OBJ_CAPTION ) )
266 const OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
267 if( pParaObj )
268 pCurrAppData->SetClientTextbox(
269 new XclEscherClientTextbox( GetRoot(), *pTextObj, pCurrXclObj ) );
272 else
274 if ( !bInGroup )
275 pCurrAppData->SetClientAnchor( new XclExpDffAnchor( GetRoot() ) );
278 else if ( nAdditionalText == 3 )
280 if ( pAdditionalText )
282 pAdditionalText->SetXclObj( pCurrXclObj );
283 pCurrAppData->SetClientTextbox( pAdditionalText );
288 if ( !pCurrXclObj )
289 pCurrAppData->SetDontWriteShape( TRUE );
290 return pCurrAppData;
294 void XclEscherEx::EndShape( UINT16 nShapeType, UINT32 nShapeID )
296 // own escher data created? -> never delete such objects
297 bool bOwnEscher = pCurrXclObj && pCurrXclObj->IsOwnEscher();
299 // post process the current object - not for objects with own escher data
300 if( pCurrXclObj && !bOwnEscher )
302 // escher data of last shape not written? -> delete it from object list
303 if( nShapeID == 0 )
305 XclObj* pLastObj = static_cast< XclObj* >( GetOldRoot().pObjRecs->Last() );
306 DBG_ASSERT( pLastObj == pCurrXclObj, "XclEscherEx::EndShape - wrong object" );
307 if ( pLastObj == pCurrXclObj )
309 GetOldRoot().pObjRecs->Remove();
310 DELETEZ( pCurrXclObj );
314 if( pCurrXclObj )
316 // set shape type
317 if ( pCurrAppData->IsStackedGroup() )
318 pCurrXclObj->SetEscherShapeTypeGroup();
319 else
321 pCurrXclObj->SetEscherShapeType( nShapeType );
322 pCurrXclObj->UpdateStopPos();
327 // get next object from stack
328 DeleteCurrAppData();
329 pCurrAppData = static_cast< XclEscherHostAppData* >( aStack.Pop() );
330 pCurrXclObj = static_cast< XclObj* >( aStack.Pop() );
331 if( nAdditionalText == 3 )
332 nAdditionalText = 0;
336 EscherExHostAppData* XclEscherEx::EnterAdditionalTextGroup()
338 nAdditionalText = 1;
339 pAdditionalText = (XclEscherClientTextbox*) pCurrAppData->GetClientTextbox();
340 pCurrAppData->SetClientTextbox( NULL );
341 return pCurrAppData;
345 void XclEscherEx::DeleteCurrAppData()
347 if ( pCurrAppData )
349 delete pCurrAppData->GetClientAnchor();
350 // delete pCurrAppData->GetClientData();
351 delete pCurrAppData->GetClientTextbox();
352 delete pCurrAppData->GetInteractionInfo();
353 delete pCurrAppData;
358 void XclEscherEx::EndDocument()
360 Flush( pPicStrm );
363 #if EXC_EXP_OCX_CTRL
365 XclExpOcxControlObj* XclEscherEx::CreateCtrlObj( Reference< XShape > xShape )
367 ::std::auto_ptr< XclExpOcxControlObj > xOcxCtrl;
369 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
370 if( xCtrlModel.is() )
372 // output stream
373 if( !mxCtlsStrm.Is() )
374 mxCtlsStrm = OpenStream( EXC_STREAM_CTLS );
375 if( mxCtlsStrm.Is() )
377 String aClassName;
378 sal_uInt32 nStrmStart = static_cast< sal_uInt32 >( mxCtlsStrm->Tell() );
380 // writes from xCtrlModel into mxCtlsStrm, raw class name returned in aClassName
381 if( SvxMSConvertOCXControls::WriteOCXExcelKludgeStream( mxCtlsStrm, xCtrlModel, xShape->getSize(), aClassName ) )
383 sal_uInt32 nStrmSize = static_cast< sal_uInt32 >( mxCtlsStrm->Tell() - nStrmStart );
384 // adjust the class name to "Forms.***.1"
385 aClassName.InsertAscii( "Forms.", 0 ).AppendAscii( ".1" );
386 xOcxCtrl.reset( new XclExpOcxControlObj( GetRoot(), xShape, aClassName, nStrmStart, nStrmSize ) );
390 return xOcxCtrl.release();
393 #else
395 XclExpTbxControlObj* XclEscherEx::CreateCtrlObj( Reference< XShape > xShape )
397 ::std::auto_ptr< XclExpTbxControlObj > xTbxCtrl( new XclExpTbxControlObj( GetRoot(), xShape ) );
398 if( xTbxCtrl->GetObjType() == EXC_OBJTYPE_UNKNOWN )
399 xTbxCtrl.reset();
401 if( xTbxCtrl.get() )
403 // find attached macro
404 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
405 ConvertTbxMacro( *xTbxCtrl, xCtrlModel );
407 return xTbxCtrl.release();
410 void XclEscherEx::ConvertTbxMacro( XclExpTbxControlObj& rTbxCtrlObj, Reference< XControlModel > xCtrlModel )
412 SdrPage* pSdrPage = GetSdrPage( GetCurrScTab() );
413 if( xCtrlModel.is() && GetDocShell() && pSdrPage ) try
415 Reference< XFormsSupplier > xFormsSupplier( pSdrPage->getUnoPage(), UNO_QUERY_THROW );
416 Reference< XIndexAccess > xFormsIA( xFormsSupplier->getForms(), UNO_QUERY_THROW );
418 // 1) try to find the index of the processed control in the form
420 Reference< XIndexAccess > xFormIA; // needed in step 2) below
421 sal_Int32 nFoundIdx = -1;
423 // search all existing forms in the draw page
424 for( sal_Int32 nFormIdx = 0, nFormCount = xFormsIA->getCount();
425 (nFoundIdx < 0) && (nFormIdx < nFormCount); ++nFormIdx )
427 // get the XIndexAccess interface of the form with index nFormIdx
428 if( xFormIA.set( xFormsIA->getByIndex( nFormIdx ), UNO_QUERY ) )
430 // search all elements (controls) of the current form by index
431 for( sal_Int32 nCtrlIdx = 0, nCtrlCount = xFormIA->getCount();
432 (nFoundIdx < 0) && (nCtrlIdx < nCtrlCount); ++nCtrlIdx )
434 // compare implementation pointers of the control models
435 Reference< XControlModel > xCurrModel( xFormIA->getByIndex( nCtrlIdx ), UNO_QUERY );
436 if( xCtrlModel.get() == xCurrModel.get() )
437 nFoundIdx = nCtrlIdx;
442 // 2) try to find an attached macro
444 if( xFormIA.is() && (nFoundIdx >= 0) )
446 Reference< XEventAttacherManager > xEventMgr( xFormIA, UNO_QUERY_THROW );
447 // loop over all events attached to the found control
448 const Sequence< ScriptEventDescriptor > aEventSeq( xEventMgr->getScriptEvents( nFoundIdx ) );
449 bool bFound = false;
450 for( sal_Int32 nEventIdx = 0, nEventCount = aEventSeq.getLength();
451 !bFound && (nEventIdx < nEventCount); ++nEventIdx )
453 // try to set the event data at the Excel control object, returns true on success
454 bFound = rTbxCtrlObj.SetMacroLink( aEventSeq[ nEventIdx ] );
458 catch( Exception& )
463 #endif
465 // --- class XclEscher -----------------------------------------------
467 XclEscher::XclEscher( const XclExpRoot& rRoot, UINT32 nDrawings ) :
468 XclExpRoot( rRoot )
470 pTempFile = new utl::TempFile;
471 pTempFile->EnableKillingFile();
472 pStrm = utl::UcbStreamHelper::CreateStream( pTempFile->GetURL(), STREAM_STD_READWRITE );
473 pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
474 pEx = new XclEscherEx( rRoot, *pStrm, nDrawings );
478 XclEscher::~XclEscher()
480 delete pEx;
481 delete pStrm;
482 delete pTempFile;
486 void XclEscher::AddSdrPage()
488 if( SdrPage* pPage = GetSdrPage( GetCurrScTab() ) )
489 pEx->AddSdrPage( *pPage );
490 // #106213# the first dummy object may still be open
491 DBG_ASSERT( pEx->GetGroupLevel() <= 1, "XclEscher::AddSdrPage - still groups open?" );
492 while( pEx->GetGroupLevel() )
493 pEx->LeaveGroup();
497 // Escher client anchor =======================================================
499 XclExpDffAnchor::XclExpDffAnchor( const XclExpRoot& rRoot, sal_uInt16 nFlags ) :
500 XclExpRoot( rRoot ),
501 maAnchor( rRoot.GetCurrScTab() ),
502 mnFlags( nFlags )
506 XclExpDffAnchor::XclExpDffAnchor( const XclExpRoot& rRoot, const SdrObject& rSdrObj ) :
507 XclExpRoot( rRoot ),
508 maAnchor( rRoot.GetCurrScTab() )
510 SetFlags( rSdrObj );
511 maAnchor.SetRect( GetDoc(), rSdrObj.GetCurrentBoundRect(), MAP_100TH_MM );
514 void XclExpDffAnchor::SetFlags( const SdrObject& rSdrObj )
516 // Special case "page anchor" (X==0,Y==1) -> lock pos and size.
517 const Point& rPos = rSdrObj.GetAnchorPos();
518 mnFlags = ((rPos.X() == 0) && (rPos.Y() == 1)) ? EXC_ESC_ANCHOR_LOCKED : 0;
521 void XclExpDffAnchor::WriteData( EscherEx& rEx, const Rectangle& rRect )
523 // the rectangle is already in twips
524 maAnchor.SetRect( GetDoc(), rRect, MAP_TWIP );
525 WriteData( rEx );
529 void XclExpDffAnchor::WriteData( EscherEx& rEx ) const
531 rEx.AddAtom( 18, ESCHER_ClientAnchor );
532 rEx.GetStream() << mnFlags << maAnchor;
536 // ----------------------------------------------------------------------------
538 XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const Rectangle& rRect ) :
539 XclExpDffAnchor( rRoot, EXC_ESC_ANCHOR_SIZELOCKED )
541 maAnchor.SetRect( GetDoc(), rRect, MAP_100TH_MM );
545 // ----------------------------------------------------------------------------
547 XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
548 XclExpDffAnchor( rRoot, EXC_ESC_ANCHOR_POSLOCKED )
550 GetAddressConverter().ConvertAddress( maAnchor.maFirst, rScPos, true );
551 maAnchor.maLast.mnCol = maAnchor.maFirst.mnCol + 1;
552 maAnchor.maLast.mnRow = maAnchor.maFirst.mnRow + 1;
553 maAnchor.mnLX = maAnchor.mnTY = maAnchor.mnRX = maAnchor.mnBY = 0;
557 // ============================================================================
559 // --- class XclEscherClientData -------------------------------------
561 void XclEscherClientData::WriteData( EscherEx& rEx ) const
562 { // actual data is in the following OBJ record
563 rEx.AddAtom( 0, ESCHER_ClientData );
567 // --- class XclEscherClientTextbox -------------------------------------
569 XclEscherClientTextbox::XclEscherClientTextbox( const XclExpRoot& rRoot,
570 const SdrTextObj& rObj, XclObj* pObj )
572 XclExpRoot( rRoot ),
573 rTextObj( rObj ),
574 pXclObj( pObj )
579 void XclEscherClientTextbox::WriteData( EscherEx& /*rEx*/ ) const
581 pXclObj->SetText( GetRoot(), rTextObj );
584 XclExpShapeObj*
585 ShapeInteractionHelper::CreateShapeObj(const XclExpRoot& rRoot, const Reference< XShape >& xShape )
587 return new XclExpShapeObj( rRoot, xShape );
590 void
591 ShapeInteractionHelper::PopulateShapeInteractionInfo(const XclExpRoot& rRoot, const Reference< XShape >& xShape, EscherExHostAppData& rHostAppData )
595 SvMemoryStream* pMemStrm = NULL;
596 rtl::OUString sHyperLink;
597 rtl::OUString sMacro;
598 if ( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( ::GetSdrObjectFromXShape( xShape ) ) )
600 sHyperLink = pInfo->GetHlink();
601 sMacro = pInfo->GetMacro();
603 if ( sHyperLink.getLength() > 0 )
605 pMemStrm = new SvMemoryStream();
606 XclExpStream tmpStream( *pMemStrm, rRoot );
607 ScAddress dummyAddress;
608 SvxURLField aUrlField;
609 aUrlField.SetURL( sHyperLink );
610 XclExpHyperlink hExpHlink( rRoot, aUrlField, dummyAddress );
611 hExpHlink.WriteEmbeddedData( tmpStream );
613 if ( ( sHyperLink.getLength() > 0 ) || ( sMacro.getLength() > 0 ) )
614 rHostAppData.SetInteractionInfo( new InteractionInfo( pMemStrm, true ) );
616 catch( Exception& )