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