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