diff options
Diffstat (limited to 'embedserv/source/embed/ed_ioleobject.cxx')
-rw-r--r-- | embedserv/source/embed/ed_ioleobject.cxx | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/embedserv/source/embed/ed_ioleobject.cxx b/embedserv/source/embed/ed_ioleobject.cxx new file mode 100644 index 000000000..839fd8e2d --- /dev/null +++ b/embedserv/source/embed/ed_ioleobject.cxx @@ -0,0 +1,469 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <embeddoc.hxx> +#include <osl/diagnose.h> +#include <o3tl/char16_t2wchar_t.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> + + +using namespace ::com::sun::star; + +// IOleObject + + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite ) +{ + m_pClientSite = pSite; + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite ) +{ + *pSite = m_pClientSite; + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj ) +{ + // the code should be ignored for links + if ( !m_aFileName.getLength() ) + { + m_pDocHolder->setTitle(OUString(o3tl::toU(szContainerObj))); + m_pDocHolder->setContainerName(OUString(o3tl::toU(szContainerApp))); + } + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption ) +{ + HRESULT hr = S_OK; + + if ( m_pDocHolder->HasFrame() ) + { + if ( dwSaveOption == 2 && m_aFileName.getLength() ) + { + // ask the user about saving + if ( m_pDocHolder->ExecuteSuspendCloseFrame() ) + { + m_pDocHolder->CloseDocument(); + return S_OK; + } + else + return OLE_E_PROMPTSAVECANCELLED; + } + + if ( dwSaveOption != 1 ) + hr = SaveObject(); // ADVF_DATAONSTOP); + + m_pDocHolder->CloseFrame(); + OLENotifyDeactivation(); + } + + m_pDocHolder->FreeOffice(); + m_pDocHolder->CloseDocument(); + + OLENotifyClosing(); + + return hr; +} + + +HRESULT EmbedDocument_Impl::OLENotifyClosing() +{ + AdviseSinkHashMap aAHM(m_aAdviseHashMap); + + for (auto const& advise : aAHM) + { + if (advise.second) + advise.second->OnClose(); + } + + return S_OK; + +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ ) +{ + return E_NOTIMPL; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ ) +{ + return E_NOTIMPL; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ ) +{ + return E_NOTIMPL; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ ) +{ + return E_NOTIMPL; +} + +/** + * Well, this is a not so very inefficient way to deliver + * + */ + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::DoVerb( + LONG iVerb, + LPMSG, + IOleClientSite *pActiveSite, + LONG, + HWND, + LPCRECT ) +{ + // no locking is used since the OLE must use the same thread always + if ( m_bIsInVerbHandling ) + return OLEOBJ_S_CANNOT_DOVERB_NOW; + + // an object can not handle any Verbs in Hands off mode + if ( m_pMasterStorage == nullptr || m_pOwnStream == nullptr ) + return OLE_E_CANT_BINDTOSOURCE; + + + BooleanGuard_Impl aGuard( m_bIsInVerbHandling ); + + if ( iVerb == OLEIVERB_PRIMARY ) + { + if ( m_aFileName.getLength() ) + { + // that should be a link + iVerb = OLEIVERB_OPEN; + } + else + iVerb = OLEIVERB_SHOW; + } + + try + { + switch(iVerb) { + case OLEIVERB_DISCARDUNDOSTATE: + // free any undostate? + break; + case OLEIVERB_INPLACEACTIVATE: + OSL_ENSURE(m_pDocHolder,"no document for inplace activation"); + + return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE); + case OLEIVERB_UIACTIVATE: + OSL_ENSURE(m_pDocHolder,"no document for inplace activation"); + + return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE); + case OLEIVERB_PRIMARY: + case OLEIVERB_SHOW: + OSL_ENSURE(m_pDocHolder,"no document for inplace activation"); + + if(m_pDocHolder->isActive()) + return NOERROR; //Already active + + if(SUCCEEDED( + m_pDocHolder->InPlaceActivate( + pActiveSite,TRUE))) + return NOERROR; + + [[fallthrough]]; + case OLEIVERB_OPEN: + OSL_ENSURE(m_pDocHolder,"no document to open"); + + // the commented code could be useful in case + // outer window would be resized depending from inner one + // RECTL aEmbArea; + // m_pDocHolder->GetVisArea( &aEmbArea ); + // m_pDocHolder->show(); + // m_pDocHolder->SetVisArea( &aEmbArea ); + + if(m_pDocHolder->isActive()) + { + m_pDocHolder->InPlaceDeactivate(); + m_pDocHolder->DisableInplaceActivation(true); + } + + SIZEL aEmbSize; + m_pDocHolder->GetExtent( &aEmbSize ); + m_pDocHolder->show(); + m_pDocHolder->resizeWin( aEmbSize ); + + if ( m_pClientSite ) + m_pClientSite->OnShowWindow( TRUE ); + + notify(); + break; + case OLEIVERB_HIDE: + OSL_ENSURE(m_pDocHolder,"no document to hide"); + + if(m_pDocHolder->isActive()) + m_pDocHolder->InPlaceDeactivate(); + else { + m_pDocHolder->hide(); + + if( m_pClientSite ) + m_pClientSite->OnShowWindow(FALSE); + } + break; + default: + break; + } + } + catch( const uno::Exception& ) + { + return OLEOBJ_S_CANNOT_DOVERB_NOW; + } + + return NOERROR; +} + + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ ) +{ + return OLE_S_USEREG; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::Update() +{ + return S_OK; +// HRESULT hr = CACHE_E_NOCACHE_UPDATED; +// return hr; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::IsUpToDate() +{ + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid ) +{ + return GetClassID( pClsid ); +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ ) +{ + return OLE_S_USEREG; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel ) +{ + if ( !psizel ) + return E_FAIL; + + m_pDocHolder->SetExtent( psizel ); + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel ) +{ + if ( !psizel ) + return E_INVALIDARG; + + if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) ) + { + // return default values + psizel->cx = 500; + psizel->cy = 500; + } + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection ) +{ + if ( m_nAdviseNum == 0xFFFFFFFF ) + return E_OUTOFMEMORY; + + pAdvSink->AddRef(); + m_aAdviseHashMap.insert( std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) ); + *pdwConnection = m_nAdviseNum++; + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection ) +{ + auto iAdvise = m_aAdviseHashMap.find( dwConnection ); + if ( iAdvise != m_aAdviseHashMap.end() ) + { + iAdvise->second->Release(); + m_aAdviseHashMap.erase( iAdvise ); + } + else + return OLE_E_NOCONNECTION; + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ ) +{ + return E_NOTIMPL; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ ) +{ + return OLE_S_USEREG; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ ) +{ + return E_NOTIMPL; +} + + +// IDispatch + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount(unsigned int* pctinfo) +{ + if ( m_pDocHolder->GetIDispatch() ) + return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo ); + + return E_NOTIMPL; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetTypeInfo(unsigned int iTInfo, LCID lcid, + ITypeInfo** ppTInfo) +{ + if ( m_pDocHolder->GetIDispatch() ) + return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo ); + + return DISP_E_BADINDEX; // the only error that can be returned +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid, + OLECHAR** rgszNames, + unsigned int cNames, + LCID lcid, + DISPID* rgDispId ) +{ + if ( m_pDocHolder->GetIDispatch() ) + return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId ); + + for ( unsigned int ind = 0; ind < cNames; ind++ ) + rgDispId[ind] = DISPID_UNKNOWN; + + return DISP_E_UNKNOWNNAME; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + unsigned int* puArgErr ) +{ + if ( m_pDocHolder->GetIDispatch() ) + return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember, + riid, + lcid, + wFlags, + pDispParams, + pVarResult, + pExcepInfo, + puArgErr ); + + return DISP_E_MEMBERNOTFOUND; +} + + +// IExternalConnection + +DWORD STDMETHODCALLTYPE EmbedDocument_Impl::AddConnection( DWORD , DWORD ) +{ + return AddRef(); +} + +DWORD STDMETHODCALLTYPE EmbedDocument_Impl::ReleaseConnection( DWORD , DWORD , BOOL ) +{ + return Release(); +} + +// C++ - methods + +HRESULT EmbedDocument_Impl::SaveObject() +{ + HRESULT hr = S_OK; + + if(m_pClientSite) { + hr = m_pClientSite->SaveObject(); + + for (auto const& advise : m_aAdviseHashMap) + if (advise.second) + advise.second->OnSave(); + } + else if ( m_aFileName.getLength() && IsDirty() == S_OK ) + { + OUString aPreservFileName = m_aFileName; + + // in case of links the containers does not provide client site sometimes + hr = Save( static_cast<LPCOLESTR>(nullptr), FALSE ); // triggers saving to the link location + SaveCompleted(o3tl::toW(aPreservFileName.getStr())); + } + + notify( false ); + + return hr; +} + + +HRESULT EmbedDocument_Impl::ShowObject() +{ + HRESULT hr = S_OK; + + if(m_pClientSite) + hr = m_pClientSite->ShowObject(); + + return hr; +} + + +void EmbedDocument_Impl::notify( bool bDataChanged ) +{ + for (auto const& advise : m_aAdviseHashMap) + if (advise.second) + advise.second->OnViewChange( DVASPECT_CONTENT, -1 ); + + if ( m_pDAdviseHolder && bDataChanged ) + m_pDAdviseHolder->SendOnDataChange( static_cast<IDataObject*>(this), 0, 0 ); +} + +void EmbedDocument_Impl::Deactivate() +{ + if ( m_pDocHolder->HasFrame() ) + { + SaveObject(); + m_pDocHolder->CloseFrame(); + OLENotifyDeactivation(); + } +} + +HRESULT EmbedDocument_Impl::OLENotifyDeactivation() +{ + HRESULT hr = S_OK; + + if ( m_pClientSite ) + hr = m_pClientSite->OnShowWindow( FALSE ); + + return hr; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |