merge the formfield patch from ooo-build
[ooovba.git] / svx / source / msfilter / msoleexp.cxx
blob04495b5e3e3cdcb51dffb32af97e460600d4e0af
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: msoleexp.cxx,v $
10 * $Revision: 1.22 $
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_svx.hxx"
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #ifndef _COM_SUN_STAR_EMBED_XEmbedPersist_HPP_
39 #include <com/sun/star/embed/XEmbedPersist.hpp>
40 #endif
41 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
42 #include <com/sun/star/embed/EmbedStates.hpp>
43 #include <com/sun/star/frame/XStorable.hpp>
44 #include <com/sun/star/awt/Size.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
47 #ifndef _SO_CLSIDS_HXX
48 #include <sot/clsids.hxx>
49 #endif
50 #include <sfx2/objsh.hxx>
51 //#ifndef _SFX_INTERNO_HXX
52 //#include <sfx2/interno.hxx>
53 //#endif
54 #include <sfx2/docfac.hxx>
55 #include <sfx2/docfilt.hxx>
56 #include <sfx2/docfile.hxx>
57 #include <sfx2/fcontnr.hxx>
58 #include <sot/formats.hxx>
59 #include <comphelper/processfactory.hxx>
61 #include <unotools/streamwrap.hxx>
62 #include <comphelper/storagehelper.hxx>
63 #include <svtools/embedhlp.hxx>
64 #include <svx/msdffimp.hxx> // extern sichtbare Header-Datei
66 #include "msoleexp.hxx"
68 #define CREATE_CONST_ASC(s) String::CreateFromAscii( \
69 RTL_CONSTASCII_STRINGPARAM(s))
71 using namespace ::com::sun::star;
73 SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
75 if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
76 return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
77 else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
78 return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
79 else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
80 return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
81 else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
82 return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
83 else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
84 return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
85 else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
86 return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );
88 return SvGlobalName();
91 String GetStorageType( const SvGlobalName& aEmbName )
93 if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
94 return String::CreateFromAscii( "opendocument.MathDocument.1" );
95 else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
96 return String::CreateFromAscii( "opendocument.WriterDocument.1" );
97 else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
98 return String::CreateFromAscii( "opendocument.CalcDocument.1" );
99 else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
100 return String::CreateFromAscii( "opendocument.DrawDocument.1" );
101 else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
102 return String::CreateFromAscii( "opendocument.ImpressDocument.1" );
103 else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
104 return String::CreateFromAscii( "opendocument.ChartDocument.1" );
106 return String();
109 sal_Bool UseOldMSExport()
111 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
113 if ( xFactory.is() )
115 uno::Reference< lang::XMultiServiceFactory > xProvider( xFactory->createInstance(
116 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider"))),
117 uno::UNO_QUERY);
118 if ( xProvider.is() )
120 try {
121 uno::Sequence< uno::Any > aArg( 1 );
122 aArg[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") );
123 uno::Reference< container::XNameAccess > xNameAccess(
124 xProvider->createInstanceWithArguments(
125 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
126 aArg ),
127 uno::UNO_QUERY );
128 if ( xNameAccess.is() )
130 uno::Any aResult = xNameAccess->getByName(
131 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) );
133 sal_Bool bResult = sal_Bool();
134 if ( aResult >>= bResult )
135 return bResult;
138 catch( uno::Exception& )
144 OSL_ENSURE( sal_False, "Could not get access to configuration entry!\n" );
145 return sal_False;
148 void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
150 svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
151 ExportOLEObject( aObj, rDestStg );
154 void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg )
156 SvGlobalName aOwnGlobalName;
157 SvGlobalName aObjName( rObj->getClassID() );
158 const SfxFilter* pExpFilter = NULL;
160 static struct _ObjExpType {
161 UINT32 nFlag;
162 const char* pFilterNm;
163 // GlobalNameId
164 struct _GlobalNameIds {
165 UINT32 n1;
166 USHORT n2, n3;
167 BYTE b8, b9, b10, b11, b12, b13, b14, b15;
169 aGlNmIds[4];
170 } aArr[] = {
171 { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
172 {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
173 {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
174 { OLE_STARWRITER_2_WINWORD, "MS Word 97",
175 {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
176 {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
177 { OLE_STARCALC_2_EXCEL, "MS Excel 97",
178 {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
179 {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
180 { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
181 {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
182 {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
183 { 0, "",
184 {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
185 {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
186 { 0, "",
187 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
188 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here.
190 { 0xffff,0,
191 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
192 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
195 for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
197 for ( int n = 0; n < 4; ++n )
199 const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
200 SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
201 rId.b8, rId.b9, rId.b10, rId.b11,
202 rId.b12, rId.b13, rId.b14, rId.b15 );
203 if( aObjName == aGlbNm )
205 aOwnGlobalName = aGlbNm;
207 // flags for checking if conversion is wanted at all (SaveOptions?!)
208 if( GetFlags() & pArr->nFlag )
210 pExpFilter = SfxFilterMatcher().GetFilter4FilterName(String::CreateFromAscii(pArr->pFilterNm));
211 break;
218 if( pExpFilter ) // use this filter for the export
222 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
223 rObj->changeState( embed::EmbedStates::RUNNING );
224 //TODO/LATER: is stream instead of outputstream a better choice?!
225 //TODO/LATER: a "StoreTo" method at embedded object would be nice
226 uno::Sequence < beans::PropertyValue > aSeq(2);
227 SvStream* pStream = new SvMemoryStream;
228 aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
229 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
230 aSeq[0].Value <<= xOut;
231 aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
232 aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() );
233 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
236 xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq );
238 catch( uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
240 SotStorageRef xOLEStor = new SotStorage( pStream, TRUE );
241 xOLEStor->CopyTo( &rDestStg );
242 rDestStg.Commit();
244 catch( uno::Exception& )
246 // TODO/LATER: Error handling
247 DBG_ERROR( "The object could not be exported!" );
250 else if( aOwnGlobalName != SvGlobalName() )
252 // own format, maybe SO6 format or lower
253 SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
254 if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
256 // this is a SO6 embedded object, save in old binary format
257 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
258 rDestStg.SetClass( aEmbName,
259 SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE,
260 GetStorageType( aEmbName ) );
261 SotStorageStreamRef xExtStm = rDestStg.OpenSotStream(
262 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "properties_stream" ) ),
263 STREAM_STD_READWRITE );
265 sal_Bool bExtentSuccess = sal_False;
266 if( !xExtStm->GetError() )
268 // write extent
269 //TODO/MBA: check if writing a size is enough
270 if( rObj.GetObject().is() )
272 // MSOLE objects don't need to be in running state for VisualArea access
273 awt::Size aSize;
276 // this is an own object, the content size must be stored in the
277 // extension stream
278 aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
280 catch( embed::NoVisualAreaSizeException& )
282 OSL_ENSURE( sal_False, "Could not get visual area size!\n" );
283 aSize.Width = 5000;
284 aSize.Height = 5000;
286 catch( uno::Exception& )
288 OSL_ENSURE( sal_False, "Unexpected exception while getting visual area size!\n" );
289 aSize.Width = 5000;
290 aSize.Height = 5000;
293 //Rectangle aVisArea = xSfxIPObj->GetVisArea( ASPECT_CONTENT );
294 sal_Int32 pRect[4];
295 //pRect[0] = aVisArea.Left();
296 //pRect[1] = aVisArea.Right();
297 //pRect[2] = aVisArea.Top();
298 //pRect[3] = aVisArea.Bottom();
299 pRect[0] = 0;
300 pRect[1] = aSize.Width;
301 pRect[2] = 0;
302 pRect[3] = aSize.Height;
304 sal_Int8 aWriteSet[16];
305 for ( int ind = 0; ind < 4; ind++ )
307 sal_Int32 nVal = pRect[ind];
308 for ( int nByte = 0; nByte < 4; nByte++ )
310 aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100;
311 nVal /= 0x100;
315 bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 );
319 if ( bExtentSuccess )
321 SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream(
322 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "package_stream" ) ),
323 STREAM_STD_READWRITE );
324 if( !xEmbStm->GetError() )
328 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
329 rObj->changeState( embed::EmbedStates::RUNNING );
330 //TODO/LATER: is stream instead of outputstream a better choice?!
331 //TODO/LATER: a "StoreTo" method at embedded object would be nice
332 uno::Sequence < beans::PropertyValue > aSeq(1);
333 aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
334 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
335 aSeq[0].Value <<= xOut;
336 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
337 xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq );
339 catch( uno::Exception& )
341 // TODO/LATER: Error handling
342 DBG_ERROR( "The object could not be exported!" );
347 else
349 DBG_ERROR("Own binary format inside own container document!");
352 else
354 // alien objects
355 //TODO/LATER: a "StoreTo" method at embedded object would be nice
356 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
357 uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
358 uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
359 if ( xPers.is() )
361 uno::Sequence < beans::PropertyValue > aEmptySeq;
362 ::rtl::OUString aTempName(::rtl::OUString::createFromAscii("bla"));
365 xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
367 catch ( uno::Exception& )
370 SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ );
371 xOLEStor->CopyTo( &rDestStg );
372 rDestStg.Commit();
376 //We never need this stream: See #99809# and #i2179#
377 rDestStg.Remove(CREATE_CONST_ASC(SVEXT_PERSIST_STREAM));