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