1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <com/sun/star/embed/XComponentSupplier.hpp>
27 #include <com/sun/star/embed/EmbedStates.hpp>
28 #include <com/sun/star/embed/XVisualObject.hpp>
29 #include <com/sun/star/embed/XEmbedPersist.hpp>
30 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
31 #include <com/sun/star/datatransfer/XTransferable.hpp>
32 #include <com/sun/star/embed/Aspects.hpp>
33 
34 #include <svtools/embedtransfer.hxx>
35 #include <tools/mapunit.hxx>
36 #include <vcl/outdev.hxx>
37 #include <comphelper/storagehelper.hxx>
38 #include <unotools/ucbstreamhelper.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <unotools/tempfile.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
42 
43 #include <svtools/embedhlp.hxx>
44 
45 using namespace ::com::sun::star;
46 
SvEmbedTransferHelper(const uno::Reference<embed::XEmbeddedObject> & xObj,Graphic * pGraphic,sal_Int64 nAspect)47 SvEmbedTransferHelper::SvEmbedTransferHelper( const uno::Reference< embed::XEmbeddedObject >& xObj,
48 												Graphic* pGraphic,
49 												sal_Int64 nAspect )
50 : m_xObj( xObj )
51 , m_pGraphic( pGraphic ? new Graphic( *pGraphic ) : NULL )
52 , m_nAspect( nAspect )
53 {
54     if( xObj.is() )
55     {
56         TransferableObjectDescriptor aObjDesc;
57 
58         FillTransferableObjectDescriptor( aObjDesc, m_xObj, NULL, m_nAspect );
59         PrepareOLE( aObjDesc );
60     }
61 }
62 
63 // -----------------------------------------------------------------------------
64 
~SvEmbedTransferHelper()65 SvEmbedTransferHelper::~SvEmbedTransferHelper()
66 {
67 	if ( m_pGraphic )
68 	{
69 		delete m_pGraphic;
70 		m_pGraphic = NULL;
71 	}
72 }
73 
74 // -----------------------------------------------------------------------------
75 
AddSupportedFormats()76 void SvEmbedTransferHelper::AddSupportedFormats()
77 {
78 	AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
79 	AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
80 	AddFormat( FORMAT_GDIMETAFILE );
81 }
82 
83 // -----------------------------------------------------------------------------
84 
GetData(const::com::sun::star::datatransfer::DataFlavor & rFlavor)85 sal_Bool SvEmbedTransferHelper::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
86 {
87 	sal_Bool bRet = sal_False;
88 
89 	if( m_xObj.is() )
90 	{
91         try
92         {
93             sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
94             if( HasFormat( nFormat ) )
95             {
96                 if( nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
97                 {
98                     TransferableObjectDescriptor aDesc;
99                     FillTransferableObjectDescriptor( aDesc, m_xObj, m_pGraphic, m_nAspect );
100                     bRet = SetTransferableObjectDescriptor( aDesc, rFlavor );
101                 }
102                 else if( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
103                 {
104                     try
105                     {
106 						// TODO/LATER: Propbably the graphic should be copied here as well
107 						// currently it is handled by the applications
108                         utl::TempFile aTmp;
109                         aTmp.EnableKillingFile( sal_True );
110                         uno::Reference < embed::XEmbedPersist > xPers( m_xObj, uno::UNO_QUERY );
111                         if ( xPers.is() )
112                         {
113                             uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetTemporaryStorage();
114                             ::rtl::OUString aName = ::rtl::OUString::createFromAscii("Dummy");
115                             SvStream* pStream = NULL;
116                             sal_Bool bDeleteStream = sal_False;
117                             uno::Sequence < beans::PropertyValue > aEmpty;
118                             xPers->storeToEntry( xStg, aName, aEmpty, aEmpty );
119                             if ( xStg->isStreamElement( aName ) )
120                             {
121                                 uno::Reference < io::XStream > xStm = xStg->cloneStreamElement( aName );
122                                 pStream = utl::UcbStreamHelper::CreateStream( xStm );
123                                 bDeleteStream = sal_True;
124                             }
125                             else
126                             {
127                                 pStream = aTmp.GetStream( STREAM_STD_READWRITE );
128                                 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper( *pStream ) );
129                                 xStg->openStorageElement( aName, embed::ElementModes::READ )->copyToStorage( xStor );
130                             }
131 
132                             ::com::sun::star::uno::Any                  aAny;
133                             const sal_uInt32                            nLen = pStream->Seek( STREAM_SEEK_TO_END );
134                             ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( nLen );
135 
136                             pStream->Seek( STREAM_SEEK_TO_BEGIN );
137                             pStream->Read( aSeq.getArray(),  nLen );
138                             if ( bDeleteStream )
139                                 delete pStream;
140 
141                             if( ( bRet = ( aSeq.getLength() > 0 ) ) == sal_True )
142                             {
143                                 aAny <<= aSeq;
144                                 SetAny( aAny, rFlavor );
145                             }
146                         }
147                         else
148                         {
149                             //TODO/LATER: how to handle objects without persistance?!
150                         }
151                     }
152                     catch ( uno::Exception& )
153                     {
154                     }
155                 }
156                 else if ( nFormat == FORMAT_GDIMETAFILE && m_pGraphic )
157 				{
158 					SvMemoryStream aMemStm( 65535, 65535 );
159                     aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
160 
161 					const GDIMetaFile& aMetaFile = m_pGraphic->GetGDIMetaFile();
162 					((GDIMetaFile*)(&aMetaFile))->Write( aMemStm );
163 					uno::Any aAny;
164 					aAny <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ),
165 													aMemStm.Seek( STREAM_SEEK_TO_END ) );
166 					SetAny( aAny, rFlavor );
167 					bRet = sal_True;
168 				}
169 				else if ( m_xObj.is() && :: svt::EmbeddedObjectRef::TryRunningState( m_xObj ) )
170                 {
171                     uno::Reference< datatransfer::XTransferable > xTransferable( m_xObj->getComponent(), uno::UNO_QUERY );
172                     if ( xTransferable.is() )
173                     {
174                         uno::Any aAny = xTransferable->getTransferData( rFlavor );
175                         SetAny( aAny, rFlavor );
176                         bRet = sal_True;
177                     }
178                 }
179             }
180 		}
181 		catch( uno::Exception& )
182 		{
183 			// Error handling?
184 		}
185 	}
186 
187 	return bRet;
188 }
189 
190 // -----------------------------------------------------------------------------
191 
ObjectReleased()192 void SvEmbedTransferHelper::ObjectReleased()
193 {
194 	m_xObj = uno::Reference< embed::XEmbeddedObject >();
195 }
196 
FillTransferableObjectDescriptor(TransferableObjectDescriptor & rDesc,const::com::sun::star::uno::Reference<::com::sun::star::embed::XEmbeddedObject> & xObj,Graphic * pGraphic,sal_Int64 nAspect)197 void SvEmbedTransferHelper::FillTransferableObjectDescriptor( TransferableObjectDescriptor& rDesc,
198     const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject >& xObj,
199 	Graphic* pGraphic,
200 	sal_Int64 nAspect )
201 {
202     //TODO/LATER: need TypeName to fill it into the Descriptor (will be shown in listbox)
203     ::com::sun::star::datatransfer::DataFlavor aFlavor;
204     SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aFlavor );
205 
206     rDesc.maClassName = SvGlobalName( xObj->getClassID() );
207     rDesc.maTypeName = aFlavor.HumanPresentableName;
208 
209     //TODO/LATER: the aspect size in the descriptor is wrong, unfortunately the stream
210 	// representation of the descriptor allows only 4 bytes for the aspect
211 	// so for internal transport something different should be found
212     rDesc.mnViewAspect = sal::static_int_cast<sal_uInt16>( nAspect );
213 
214     //TODO/LATER: status needs to become sal_Int64
215     rDesc.mnOle2Misc = sal::static_int_cast<sal_Int32>(xObj->getStatus( rDesc.mnViewAspect ));
216 
217 	Size aSize;
218 	MapMode aMapMode( MAP_100TH_MM );
219 	if ( nAspect == embed::Aspects::MSOLE_ICON )
220 	{
221 		if ( pGraphic )
222 		{
223 			aMapMode = pGraphic->GetPrefMapMode();
224 			aSize = pGraphic->GetPrefSize();
225 		}
226 		else
227 			aSize = Size( 2500, 2500 );
228 	}
229 	else
230 	{
231 		try
232 		{
233     		awt::Size aSz;
234 			aSz = xObj->getVisualAreaSize( rDesc.mnViewAspect );
235 			aSize = Size( aSz.Width, aSz.Height );
236 		}
237 		catch( embed::NoVisualAreaSizeException& )
238 		{
239 			OSL_ENSURE( sal_False, "Can not get visual area size!\n" );
240 			aSize = Size( 5000, 5000 );
241 		}
242 
243     	// TODO/LEAN: getMapUnit can switch object to running state
244     	aMapMode = MapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rDesc.mnViewAspect ) ) );
245 	}
246 
247     rDesc.maSize = OutputDevice::LogicToLogic( aSize, aMapMode, MapMode( MAP_100TH_MM ) );
248 	rDesc.maDragStartPos = Point();
249 	rDesc.maDisplayName = String();
250 	rDesc.mbCanLink = sal_False;
251 }
252 
253