xref: /trunk/main/embedserv/source/embed/ed_ioleobject.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "embeddoc.hxx"
29 #include <osl/diagnose.h>
30 #include <com/sun/star/frame/XController.hpp>
31 #include <com/sun/star/beans/PropertyValue.hpp>
32 
33 
34 using namespace ::com::sun::star;
35 
36 
37 extern ::rtl::OUString  getFilterNameFromGUID_Impl( GUID* );
38 
39 //-------------------------------------------------------------------------------
40 // IOleObject
41 
42 
43 STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite )
44 {
45     m_pClientSite = pSite;
46     return S_OK;
47 }
48 
49 STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite )
50 {
51     *pSite = m_pClientSite;
52     return S_OK;
53 }
54 
55 STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj )
56 {
57     // the code should be ignored for links
58     if ( !m_aFileName.getLength() )
59     {
60         m_pDocHolder->setTitle(
61             rtl::OUString(
62                 (sal_Unicode*)szContainerObj));
63         m_pDocHolder->setContainerName(
64             rtl::OUString(
65                 (sal_Unicode*)szContainerApp));
66     }
67 
68     return S_OK;
69 }
70 
71 STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption )
72 {
73     HRESULT hr = S_OK;
74 
75     if ( m_pDocHolder->HasFrame() )
76     {
77         if ( dwSaveOption == 2 && m_aFileName.getLength() )
78         {
79             // ask the user about saving
80             if ( m_pDocHolder->ExecuteSuspendCloseFrame() )
81             {
82                 m_pDocHolder->CloseDocument();
83                 return S_OK;
84             }
85             else
86                 return OLE_E_PROMPTSAVECANCELLED;
87         }
88 
89         if ( dwSaveOption != 1 )
90             hr = SaveObject(); // ADVF_DATAONSTOP);
91 
92         m_pDocHolder->CloseFrame();
93         OLENotifyDeactivation();
94     }
95 
96     m_pDocHolder->FreeOffice();
97     m_pDocHolder->CloseDocument();
98 
99     OLENotifyClosing();
100 
101     return hr;
102 }
103 
104 
105 HRESULT EmbedDocument_Impl::OLENotifyClosing()
106 {
107     HRESULT hr = S_OK;
108 
109     AdviseSinkHashMap aAHM(m_aAdviseHashMap);
110 
111     for ( AdviseSinkHashMapIterator iAdvise = aAHM.begin();
112           iAdvise != aAHM.end(); iAdvise++ )
113     {
114         if ( iAdvise->second )
115             iAdvise->second->OnClose();
116     }
117 
118     return hr;
119 
120 }
121 
122 STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ )
123 {
124     return E_NOTIMPL;
125 }
126 
127 STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ )
128 {
129     return E_NOTIMPL;
130 }
131 
132 STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ )
133 {
134     return E_NOTIMPL;
135 }
136 
137 STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ )
138 {
139     return E_NOTIMPL;
140 }
141 
142 /**
143  *  Well, this is a not so very inefficient way to deliver
144  *
145  */
146 
147 STDMETHODIMP EmbedDocument_Impl::DoVerb(
148     LONG iVerb,
149     LPMSG,
150     IOleClientSite *pActiveSite,
151     LONG,
152     HWND,
153     LPCRECT )
154 {
155     // no locking is used since the OLE must use the same thread always
156     if ( m_bIsInVerbHandling )
157         return OLEOBJ_S_CANNOT_DOVERB_NOW;
158 
159     // an object can not handle any Verbs in Hands off mode
160     if ( m_pMasterStorage == NULL || m_pOwnStream == NULL )
161         return OLE_E_CANT_BINDTOSOURCE;
162 
163 
164     BooleanGuard_Impl aGuard( m_bIsInVerbHandling );
165 
166     if ( iVerb == OLEIVERB_PRIMARY )
167     {
168         if ( m_aFileName.getLength() )
169         {
170             // that should be a link
171             iVerb = OLEIVERB_OPEN;
172         }
173         else
174             iVerb = OLEIVERB_SHOW;
175     }
176 
177     try
178     {
179         switch(iVerb) {
180             case OLEIVERB_DISCARDUNDOSTATE:
181                 // free any undostate?
182                 break;
183             case OLEIVERB_INPLACEACTIVATE:
184                 OSL_ENSURE(m_pDocHolder,"no document for inplace activation");
185 
186                 return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE);
187                 break;
188             case OLEIVERB_UIACTIVATE:
189                 OSL_ENSURE(m_pDocHolder,"no document for     inplace activation");
190 
191                 return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE);
192                 break;
193             case OLEIVERB_PRIMARY:
194             case OLEIVERB_SHOW:
195                 OSL_ENSURE(m_pDocHolder,"no document for inplace activation");
196 
197                 if(m_pDocHolder->isActive())
198                     return NOERROR; //Already active
199 
200                 if(SUCCEEDED(
201                     m_pDocHolder->InPlaceActivate(
202                         pActiveSite,TRUE)))
203                     return NOERROR;
204 
205                 // intended fall trough
206             case OLEIVERB_OPEN:
207                 OSL_ENSURE(m_pDocHolder,"no document to open");
208 
209                 // the commented code could be usefull in case
210                 // outer window would be resized depending from inner one
211                 // RECTL aEmbArea;
212                 // m_pDocHolder->GetVisArea( &aEmbArea );
213                 // m_pDocHolder->show();
214                 // m_pDocHolder->SetVisArea( &aEmbArea );
215 
216                 if(m_pDocHolder->isActive())
217                 {
218                     m_pDocHolder->InPlaceDeactivate();
219                     m_pDocHolder->DisableInplaceActivation(true);
220                 }
221 
222                 SIZEL aEmbSize;
223                 m_pDocHolder->GetExtent( &aEmbSize );
224                 m_pDocHolder->show();
225                 m_pDocHolder->resizeWin( aEmbSize );
226 
227                 if ( m_pClientSite )
228                     m_pClientSite->OnShowWindow( TRUE );
229 
230                 notify();
231                 break;
232             case OLEIVERB_HIDE:
233                 OSL_ENSURE(m_pDocHolder,"no document to hide");
234 
235                 if(m_pDocHolder->isActive())
236                     m_pDocHolder->InPlaceDeactivate();
237                 else {
238                     m_pDocHolder->hide();
239 
240                     if( m_pClientSite )
241                         m_pClientSite->OnShowWindow(FALSE);
242                 }
243                 break;
244             default:
245                 break;
246         }
247     }
248     catch( uno::Exception& )
249     {
250         return OLEOBJ_S_CANNOT_DOVERB_NOW;
251     }
252 
253     return NOERROR;
254 }
255 
256 
257 
258 STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ )
259 {
260     return OLE_S_USEREG;
261 }
262 
263 STDMETHODIMP EmbedDocument_Impl::Update()
264 {
265     return S_OK;
266 //    HRESULT hr = CACHE_E_NOCACHE_UPDATED;
267 //    return hr;
268 }
269 
270 STDMETHODIMP EmbedDocument_Impl::IsUpToDate()
271 {
272     return S_OK;
273 }
274 
275 STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid )
276 {
277     return GetClassID( pClsid );
278 }
279 
280 STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ )
281 {
282     return OLE_S_USEREG;
283 }
284 
285 STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel )
286 {
287     if ( !psizel )
288         return E_FAIL;
289 
290     m_pDocHolder->SetExtent( psizel );
291 
292     return S_OK;
293 }
294 
295 STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel )
296 {
297     if ( !psizel )
298         return E_INVALIDARG;
299 
300     if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) )
301     {
302         // return default values
303         psizel->cx = 500;
304         psizel->cy = 500;
305     }
306 
307     return S_OK;
308 }
309 
310 STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection )
311 {
312     if ( m_nAdviseNum == 0xFFFFFFFF )
313         return E_OUTOFMEMORY;
314 
315     pAdvSink->AddRef();
316     m_aAdviseHashMap.insert( ::std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) );
317     *pdwConnection = m_nAdviseNum++;
318 
319     return S_OK;
320 }
321 
322 STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection )
323 {
324     AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.find( dwConnection );
325     if ( iAdvise != m_aAdviseHashMap.end() )
326     {
327         iAdvise->second->Release();
328         m_aAdviseHashMap.erase( iAdvise );
329     }
330     else
331         return OLE_E_NOCONNECTION;
332 
333     return S_OK;
334 }
335 
336 STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ )
337 {
338     return E_NOTIMPL;
339 }
340 
341 STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ )
342 {
343     return OLE_S_USEREG;
344 }
345 
346 STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ )
347 {
348     return E_NOTIMPL;
349 }
350 
351 //-------------------------------------------------------------------------------
352 // IDispatch
353 
354 STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount( unsigned int FAR*  pctinfo )
355 {
356     if ( m_pDocHolder->GetIDispatch() )
357         return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo );
358 
359     return E_NOTIMPL;
360 }
361 
362 STDMETHODIMP EmbedDocument_Impl::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo )
363 {
364     if ( m_pDocHolder->GetIDispatch() )
365         return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo );
366 
367     return DISP_E_BADINDEX; // the only error that can be returned
368 }
369 
370 STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid,
371                                                 OLECHAR FAR* FAR* rgszNames,
372                                                 unsigned int cNames,
373                                                 LCID lcid,
374                                                 DISPID FAR* rgDispId )
375 {
376     if ( m_pDocHolder->GetIDispatch() )
377         return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );
378 
379     for ( unsigned int ind = 0; ind < cNames; ind++ )
380         rgDispId[ind] = DISPID_UNKNOWN;
381 
382     return DISP_E_UNKNOWNNAME;
383 }
384 
385 STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember,
386                                          REFIID riid,
387                                          LCID lcid,
388                                          WORD wFlags,
389                                          DISPPARAMS FAR* pDispParams,
390                                          VARIANT FAR* pVarResult,
391                                          EXCEPINFO FAR* pExcepInfo,
392                                          unsigned int FAR* puArgErr )
393 {
394     if ( m_pDocHolder->GetIDispatch() )
395         return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember,
396                                                      riid,
397                                                      lcid,
398                                                      wFlags,
399                                                      pDispParams,
400                                                      pVarResult,
401                                                      pExcepInfo,
402                                                      puArgErr );
403 
404     return DISP_E_MEMBERNOTFOUND;
405 }
406 
407 //-------------------------------------------------------------------------------
408 // IExternalConnection
409 
410 DWORD STDMETHODCALLTYPE EmbedDocument_Impl::AddConnection( DWORD , DWORD )
411 {
412     return AddRef();
413 }
414 
415 DWORD STDMETHODCALLTYPE EmbedDocument_Impl::ReleaseConnection( DWORD , DWORD , BOOL )
416 {
417     return Release();
418 }
419 
420 // C++ - methods
421 
422 HRESULT EmbedDocument_Impl::SaveObject()
423 {
424     HRESULT hr = S_OK;
425 
426     if(m_pClientSite) {
427         hr = m_pClientSite->SaveObject();
428 
429         for ( AdviseSinkHashMapIterator iAdvise =
430                   m_aAdviseHashMap.begin();
431               iAdvise != m_aAdviseHashMap.end();
432               iAdvise++ )
433             if ( iAdvise->second )
434                 iAdvise->second->OnSave( );
435     }
436     else if ( m_aFileName.getLength() && IsDirty() == S_OK )
437     {
438         ::rtl::OUString aPreservFileName = m_aFileName;
439 
440         // in case of links the containers does not provide client site sometimes
441         hr = Save( (LPCOLESTR)NULL, FALSE ); // triggers saving to the link location
442         SaveCompleted( (LPCOLESTR)aPreservFileName.getStr() );
443     }
444 
445     notify( false );
446 
447     return hr;
448 }
449 
450 
451 HRESULT EmbedDocument_Impl::ShowObject()
452 {
453     HRESULT hr = S_OK;
454 
455     if(m_pClientSite)
456         hr = m_pClientSite->ShowObject();
457 
458     return hr;
459 }
460 
461 
462 void EmbedDocument_Impl::notify( bool bDataChanged )
463 {
464     for ( AdviseSinkHashMapIterator iAdvise =
465               m_aAdviseHashMap.begin();
466           iAdvise != m_aAdviseHashMap.end();
467           iAdvise++ )
468         if ( iAdvise->second )
469             iAdvise->second->OnViewChange( DVASPECT_CONTENT, -1 );
470 
471     if ( m_pDAdviseHolder && bDataChanged )
472         m_pDAdviseHolder->SendOnDataChange( (IDataObject*)this, 0, 0 );
473 }
474 
475 void EmbedDocument_Impl::Deactivate()
476 {
477     HRESULT hr = S_OK;
478 
479     if ( m_pDocHolder->HasFrame() )
480     {
481         hr = SaveObject();
482         m_pDocHolder->CloseFrame();
483         OLENotifyDeactivation();
484     }
485 }
486 
487 HRESULT EmbedDocument_Impl::OLENotifyDeactivation()
488 {
489     HRESULT hr = S_OK;
490 
491     if ( m_pClientSite )
492         hr = m_pClientSite->OnShowWindow( FALSE );
493 
494     return hr;
495 
496 }
497 
498 // Fix strange warnings about some
499 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
500 // warning C4505: 'xxx' : unreferenced local function has been removed
501 #if defined(_MSC_VER)
502 #pragma warning(disable: 4505)
503 #endif
504 
505