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