fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / embeddedobj / source / msole / ownview.cxx
blob758e0811e0b584cd9bef0d1907c4b2338a9701db
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/frame/Desktop.hpp>
21 #include <com/sun/star/frame/XFrame.hpp>
22 #include <com/sun/star/frame/XController.hpp>
23 #include <com/sun/star/frame/XComponentLoader.hpp>
24 #include <com/sun/star/awt/XTopWindow.hpp>
25 #include <com/sun/star/embed/XClassifiedObject.hpp>
26 #include <com/sun/star/io/TempFile.hpp>
27 #include <com/sun/star/io/XStream.hpp>
28 #include <com/sun/star/io/XInputStream.hpp>
29 #include <com/sun/star/io/XOutputStream.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <com/sun/star/task/XInteractionHandler.hpp>
32 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
33 #include <com/sun/star/util/XCloseable.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/document/XEventBroadcaster.hpp>
37 #include <com/sun/star/document/XEventListener.hpp>
38 #include <com/sun/star/document/XTypeDetection.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40 #include <cppuhelper/implbase1.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/storagehelper.hxx>
43 #include <comphelper/mimeconfighelper.hxx>
45 #include "olepersist.hxx"
46 #include "ownview.hxx"
49 using namespace ::com::sun::star;
50 using namespace ::comphelper;
52 class DummyHandler_Impl : public ::cppu::WeakImplHelper1< task::XInteractionHandler >
54 public:
55 DummyHandler_Impl() {}
56 virtual ~DummyHandler_Impl();
58 virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& xRequest )
59 throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
63 DummyHandler_Impl::~DummyHandler_Impl()
68 void SAL_CALL DummyHandler_Impl::handle( const uno::Reference< task::XInteractionRequest >& )
69 throw( uno::RuntimeException, std::exception )
71 return;
75 // Object viewer
78 OwnView_Impl::OwnView_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
79 const uno::Reference< io::XInputStream >& xInputStream )
80 : m_xFactory( xFactory )
81 , m_bBusy( false )
82 , m_bUseNative( false )
84 if ( !xFactory.is() || !xInputStream.is() )
85 throw uno::RuntimeException();
87 m_aTempFileURL = GetNewFilledTempFile_Impl( xInputStream, m_xFactory );
91 OwnView_Impl::~OwnView_Impl()
93 try {
94 KillFile_Impl( m_aTempFileURL, m_xFactory );
95 } catch( uno::Exception& ) {}
97 try {
98 if ( !m_aNativeTempURL.isEmpty() )
99 KillFile_Impl( m_aNativeTempURL, m_xFactory );
100 } catch( uno::Exception& ) {}
104 bool OwnView_Impl::CreateModelFromURL( const OUString& aFileURL )
106 bool bResult = false;
108 if ( !aFileURL.isEmpty() )
110 try {
111 uno::Reference < frame::XDesktop2 > xDocumentLoader = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
113 uno::Sequence< beans::PropertyValue > aArgs( m_aFilterName.isEmpty() ? 4 : 5 );
115 aArgs[0].Name = "URL";
116 aArgs[0].Value <<= aFileURL;
118 aArgs[1].Name = "ReadOnly";
119 aArgs[1].Value <<= sal_True;
121 aArgs[2].Name = "InteractionHandler";
122 aArgs[2].Value <<= uno::Reference< task::XInteractionHandler >(
123 static_cast< ::cppu::OWeakObject* >( new DummyHandler_Impl() ), uno::UNO_QUERY );
125 aArgs[3].Name = "DontEdit";
126 aArgs[3].Value <<= sal_True;
128 if ( !m_aFilterName.isEmpty() )
130 aArgs[4].Name = "FilterName";
131 aArgs[4].Value <<= m_aFilterName;
134 uno::Reference< frame::XModel > xModel( xDocumentLoader->loadComponentFromURL(
135 aFileURL,
136 OUString( "_blank" ),
138 aArgs ),
139 uno::UNO_QUERY );
141 if ( xModel.is() )
143 uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
144 if ( xBroadCaster.is() )
145 xBroadCaster->addEventListener( uno::Reference< document::XEventListener >(
146 static_cast< ::cppu::OWeakObject* >( this ),
147 uno::UNO_QUERY ) );
149 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
150 if ( xCloseable.is() )
152 xCloseable->addCloseListener( uno::Reference< util::XCloseListener >(
153 static_cast< ::cppu::OWeakObject* >( this ),
154 uno::UNO_QUERY ) );
156 ::osl::MutexGuard aGuard( m_aMutex );
157 m_xModel = xModel;
158 bResult = true;
162 catch (uno::Exception const& e)
164 SAL_WARN("embeddedobj.ole", "OwnView_Impl::CreateModelFromURL:"
165 " exception caught: " << e.Message);
169 return bResult;
173 bool OwnView_Impl::CreateModel( bool bUseNative )
175 bool bResult = false;
177 try {
178 bResult = CreateModelFromURL( bUseNative ? m_aNativeTempURL : m_aTempFileURL );
180 catch( uno::Exception& )
184 return bResult;
188 OUString OwnView_Impl::GetFilterNameFromExtentionAndInStream(
189 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory,
190 const OUString& aNameWithExtention,
191 const uno::Reference< io::XInputStream >& xInputStream )
193 if ( !xInputStream.is() )
194 throw uno::RuntimeException();
196 uno::Reference< document::XTypeDetection > xTypeDetection(
197 xFactory->createInstance("com.sun.star.document.TypeDetection"),
198 uno::UNO_QUERY_THROW );
200 OUString aTypeName;
202 if ( !aNameWithExtention.isEmpty() )
204 OUString aURLToAnalyze = "file:///" + aNameWithExtention;
205 aTypeName = xTypeDetection->queryTypeByURL( aURLToAnalyze );
208 uno::Sequence< beans::PropertyValue > aArgs( aTypeName.isEmpty() ? 2 : 3 );
209 aArgs[0].Name = "URL";
210 aArgs[0].Value <<= OUString( "private:stream" );
211 aArgs[1].Name = "InputStream";
212 aArgs[1].Value <<= xInputStream;
213 if ( !aTypeName.isEmpty() )
215 aArgs[2].Name = "TypeName";
216 aArgs[2].Value <<= aTypeName;
219 aTypeName = xTypeDetection->queryTypeByDescriptor( aArgs, sal_True );
221 OUString aFilterName;
222 for ( sal_Int32 nInd = 0; nInd < aArgs.getLength(); nInd++ )
223 if ( aArgs[nInd].Name == "FilterName" )
224 aArgs[nInd].Value >>= aFilterName;
226 if ( aFilterName.isEmpty() && !aTypeName.isEmpty() )
228 // get the default filter name for the type
229 uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY_THROW );
230 uno::Sequence< beans::PropertyValue > aTypes;
232 if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
234 for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ )
236 if ( aTypes[nInd].Name == "PreferredFilter" && ( aTypes[nInd].Value >>= aFilterName ) )
238 aTypes[nInd].Value >>= aFilterName;
239 break;
245 return aFilterName;
249 bool OwnView_Impl::ReadContentsAndGenerateTempFile( const uno::Reference< io::XInputStream >& xInStream,
250 bool bParseHeader )
252 uno::Reference< io::XSeekable > xSeekable( xInStream, uno::UNO_QUERY_THROW );
253 xSeekable->seek( 0 );
255 // create m_aNativeTempURL
256 OUString aNativeTempURL;
257 uno::Reference < beans::XPropertySet > xNativeTempFile(
258 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
259 uno::UNO_QUERY_THROW );
260 uno::Reference < io::XStream > xNativeTempStream( xNativeTempFile, uno::UNO_QUERY_THROW );
261 uno::Reference < io::XOutputStream > xNativeOutTemp = xNativeTempStream->getOutputStream();
262 uno::Reference < io::XInputStream > xNativeInTemp = xNativeTempStream->getInputStream();
263 if ( !xNativeOutTemp.is() || !xNativeInTemp.is() )
264 throw uno::RuntimeException();
266 try {
267 xNativeTempFile->setPropertyValue("RemoveFile", uno::makeAny( sal_False ) );
268 uno::Any aUrl = xNativeTempFile->getPropertyValue("Uri");
269 aUrl >>= aNativeTempURL;
271 catch ( uno::Exception& )
275 bool bFailed = false;
276 OUString aFileSuffix;
278 if ( bParseHeader )
280 uno::Sequence< sal_Int8 > aReadSeq( 4 );
281 // read the complete size of the Object Package
282 if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
283 return false;
284 // read the first header ( have no idea what does this header mean )
285 if ( xInStream->readBytes( aReadSeq, 2 ) != 2 || aReadSeq[0] != 2 || aReadSeq[1] != 0 )
286 return false;
288 // read file name
289 // only extension is interesting so only subset of symbols is accepted
292 if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
293 return false;
295 if (
296 (aReadSeq[0] >= '0' && aReadSeq[0] <= '9') ||
297 (aReadSeq[0] >= 'a' && aReadSeq[0] <= 'z') ||
298 (aReadSeq[0] >= 'A' && aReadSeq[0] <= 'Z') ||
299 aReadSeq[0] == '.'
302 aFileSuffix += OUString( (sal_Unicode) aReadSeq[0] );
305 } while( aReadSeq[0] );
307 // skip url
310 if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
311 return false;
312 } while( aReadSeq[0] );
314 // check the next header
315 if ( xInStream->readBytes( aReadSeq, 4 ) != 4
316 || aReadSeq[0] || aReadSeq[1] || aReadSeq[2] != 3 || aReadSeq[3] )
317 return false;
319 // get the size of the next entry
320 if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
321 return false;
323 sal_uInt32 nUrlSize = (sal_uInt8)aReadSeq[0]
324 + (sal_uInt8)aReadSeq[1] * 0x100
325 + (sal_uInt8)aReadSeq[2] * 0x10000
326 + (sal_uInt8)aReadSeq[3] * 0x1000000;
327 sal_Int64 nTargetPos = xSeekable->getPosition() + nUrlSize;
329 xSeekable->seek( nTargetPos );
331 // get the size of stored data
332 if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
333 return false;
335 sal_uInt32 nDataSize = (sal_uInt8)aReadSeq[0]
336 + (sal_uInt8)aReadSeq[1] * 0x100
337 + (sal_uInt8)aReadSeq[2] * 0x10000
338 + (sal_uInt8)aReadSeq[3] * 0x1000000;
340 aReadSeq.realloc( 32000 );
341 sal_uInt32 nRead = 0;
342 while ( nRead < nDataSize )
344 sal_uInt32 nToRead = ( nDataSize - nRead > 32000 ) ? 32000 : nDataSize - nRead;
345 sal_uInt32 nLocalRead = xInStream->readBytes( aReadSeq, nToRead );
348 if ( !nLocalRead )
350 bFailed = true;
351 break;
353 else if ( nLocalRead == 32000 )
354 xNativeOutTemp->writeBytes( aReadSeq );
355 else
357 uno::Sequence< sal_Int8 > aToWrite( aReadSeq );
358 aToWrite.realloc( nLocalRead );
359 xNativeOutTemp->writeBytes( aToWrite );
362 nRead += nLocalRead;
365 else
367 uno::Sequence< sal_Int8 > aData( 8 );
368 if ( xInStream->readBytes( aData, 8 ) == 8
369 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1
370 && ( aData[4] == 2 || aData[4] == 3 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
372 // the header has to be removed
373 xSeekable->seek( 40 );
375 else
377 // the usual Ole10Native format
378 xSeekable->seek( 4 );
381 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xNativeOutTemp );
384 xNativeOutTemp->closeOutput();
386 // The temporary native file is created, now the filter must be detected
387 if ( !bFailed )
389 m_aFilterName = GetFilterNameFromExtentionAndInStream( m_xFactory, aFileSuffix, xNativeInTemp );
390 m_aNativeTempURL = aNativeTempURL;
393 return !bFailed;
397 void OwnView_Impl::CreateNative()
399 if ( !m_aNativeTempURL.isEmpty() )
400 return;
404 uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
405 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
407 uno::Reference< io::XInputStream > xInStream = xAccess->openFileRead( m_aTempFileURL );
408 if ( !xInStream.is() )
409 throw uno::RuntimeException();
411 uno::Sequence< uno::Any > aArgs( 1 );
412 aArgs[0] <<= xInStream;
413 uno::Reference< container::XNameAccess > xNameAccess(
414 m_xFactory->createInstanceWithArguments(
415 OUString( "com.sun.star.embed.OLESimpleStorage" ),
416 aArgs ),
417 uno::UNO_QUERY_THROW );
419 OUString aSubStreamName = "\1Ole10Native";
420 uno::Reference< embed::XClassifiedObject > xStor( xNameAccess, uno::UNO_QUERY_THROW );
421 uno::Sequence< sal_Int8 > aStorClassID = xStor->getClassID();
423 if ( xNameAccess->hasByName( aSubStreamName ) )
425 sal_uInt8 aClassID[] =
426 { 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
427 uno::Sequence< sal_Int8 > aPackageClassID( reinterpret_cast<sal_Int8*>(aClassID), 16 );
429 uno::Reference< io::XStream > xSubStream;
430 xNameAccess->getByName( aSubStreamName ) >>= xSubStream;
431 if ( xSubStream.is() )
433 bool bOk = false;
435 if ( MimeConfigurationHelper::ClassIDsEqual( aPackageClassID, aStorClassID ) )
437 // the storage represents Object Package
439 bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), true );
441 if ( !bOk && !m_aNativeTempURL.isEmpty() )
443 KillFile_Impl( m_aNativeTempURL, m_xFactory );
444 m_aNativeTempURL.clear();
448 if ( !bOk )
450 bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), false );
452 if ( !bOk && !m_aNativeTempURL.isEmpty() )
454 KillFile_Impl( m_aNativeTempURL, m_xFactory );
455 m_aNativeTempURL.clear();
460 else
462 // TODO/LATER: No native stream, needs a new solution
465 catch( uno::Exception& )
470 bool OwnView_Impl::Open()
472 bool bResult = false;
474 uno::Reference< frame::XModel > xExistingModel;
477 ::osl::MutexGuard aGuard( m_aMutex );
478 xExistingModel = m_xModel;
479 if ( m_bBusy )
480 return false;
482 m_bBusy = true;
485 if ( xExistingModel.is() )
487 try {
488 uno::Reference< frame::XController > xController = xExistingModel->getCurrentController();
489 if ( xController.is() )
491 uno::Reference< frame::XFrame > xFrame = xController->getFrame();
492 if ( xFrame.is() )
494 xFrame->activate();
495 uno::Reference<awt::XTopWindow> xTopWindow( xFrame->getContainerWindow(), uno::UNO_QUERY );
496 if(xTopWindow.is())
497 xTopWindow->toFront();
499 bResult = true;
503 catch( uno::Exception& )
507 else
509 bResult = CreateModel( m_bUseNative );
511 if ( !bResult && !m_bUseNative )
513 // the original storage can not be recognized
514 if ( m_aNativeTempURL.isEmpty() )
516 // create a temporary file for the native representation if there is no
517 CreateNative();
520 if ( !m_aNativeTempURL.isEmpty() )
522 bResult = CreateModel( true );
523 if ( bResult )
524 m_bUseNative = true;
529 m_bBusy = false;
531 return bResult;
535 void OwnView_Impl::Close()
537 uno::Reference< frame::XModel > xModel;
540 ::osl::MutexGuard aGuard( m_aMutex );
541 if ( !m_xModel.is() )
542 return;
543 xModel = m_xModel;
544 m_xModel = uno::Reference< frame::XModel >();
546 if ( m_bBusy )
547 return;
549 m_bBusy = true;
552 try {
553 uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
554 if ( xBroadCaster.is() )
555 xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
556 static_cast< ::cppu::OWeakObject* >( this ),
557 uno::UNO_QUERY ) );
559 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
560 if ( xCloseable.is() )
562 xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
563 static_cast< ::cppu::OWeakObject* >( this ),
564 uno::UNO_QUERY ) );
565 xCloseable->close( sal_True );
568 catch( uno::Exception& )
571 m_bBusy = false;
575 void SAL_CALL OwnView_Impl::notifyEvent( const document::EventObject& aEvent )
576 throw ( uno::RuntimeException, std::exception )
579 uno::Reference< frame::XModel > xModel;
582 ::osl::MutexGuard aGuard( m_aMutex );
583 if ( aEvent.Source == m_xModel && aEvent.EventName == "OnSaveAsDone" )
585 // SaveAs operation took place, so just forget the model and deregister listeners
586 xModel = m_xModel;
587 m_xModel = uno::Reference< frame::XModel >();
591 if ( xModel.is() )
593 try {
594 uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
595 if ( xBroadCaster.is() )
596 xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
597 static_cast< ::cppu::OWeakObject* >( this ),
598 uno::UNO_QUERY ) );
600 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
601 if ( xCloseable.is() )
602 xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
603 static_cast< ::cppu::OWeakObject* >( this ),
604 uno::UNO_QUERY ) );
606 catch( uno::Exception& )
612 void SAL_CALL OwnView_Impl::queryClosing( const lang::EventObject&, sal_Bool )
613 throw ( util::CloseVetoException,
614 uno::RuntimeException, std::exception )
619 void SAL_CALL OwnView_Impl::notifyClosing( const lang::EventObject& Source )
620 throw ( uno::RuntimeException, std::exception )
622 ::osl::MutexGuard aGuard( m_aMutex );
623 if ( Source.Source == m_xModel )
624 m_xModel = uno::Reference< frame::XModel >();
628 void SAL_CALL OwnView_Impl::disposing( const lang::EventObject& Source )
629 throw (uno::RuntimeException, std::exception)
631 ::osl::MutexGuard aGuard( m_aMutex );
632 if ( Source.Source == m_xModel )
633 m_xModel = uno::Reference< frame::XModel >();
636 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */