1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <docholder.hxx>
21 #include <embeddoc.hxx>
22 #include <intercept.hxx>
23 #include <syswinwrapper.hxx>
24 #include <iipaobj.hxx>
25 #include <common.h>
26
27 #if !defined WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
29 #endif
30 #include <windows.h>
31
32 #include <com/sun/star/awt/XTopWindow.hpp>
33 #include <com/sun/star/awt/PosSize.hpp>
34 #include <com/sun/star/awt/XView.hpp>
35 #include <com/sun/star/awt/Toolkit.hpp>
36 #include <com/sun/star/awt/XSystemChildFactory.hpp>
37 #include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
38 #include <com/sun/star/awt/XSystemDependentMenuPeer.hpp>
39 #include <com/sun/star/awt/WindowAttribute.hpp>
40 #include <com/sun/star/awt/XWindow.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/bridge/XBridgeSupplier2.hpp>
43 #include <com/sun/star/bridge/ModelDependent.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/document/MacroExecMode.hpp>
46 #include <com/sun/star/embed/EmbedMapUnits.hpp>
47 #include <com/sun/star/embed/XVisualObject.hpp>
48 #include <com/sun/star/frame/TerminationVetoException.hpp>
49 #include <com/sun/star/frame/XComponentLoader.hpp>
50 #include <com/sun/star/frame/Frame.hpp>
51 #include <com/sun/star/frame/XModel.hpp>
52 #include <com/sun/star/frame/Desktop.hpp>
53 #include <com/sun/star/frame/XStatusListener.hpp>
54 #include <com/sun/star/lang/SystemDependent.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/task/InteractionHandler.hpp>
57 #include <com/sun/star/ui/XUIElement.hpp>
58 #include <com/sun/star/util/CloseVetoException.hpp>
59 #include <com/sun/star/util/XCloseBroadcaster.hpp>
60 #include <com/sun/star/util/XCloseable.hpp>
61 #include <com/sun/star/util/XModifyBroadcaster.hpp>
62 #include <comphelper/processfactory.hxx>
63 #include <o3tl/any.hxx>
64 #include <osl/diagnose.h>
65 #include <rtl/process.h>
66
67 using namespace ::com::sun::star;
68
69 // add mutex locking ???
70
DocumentHolder(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const::rtl::Reference<EmbeddedDocumentInstanceAccess_Impl> & xOleAccess)71 DocumentHolder::DocumentHolder(
72 const uno::Reference<lang::XMultiServiceFactory >& xFactory,
73 const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess )
74 :
75 m_bAllowInPlace(true),
76 m_pIOleIPSite(nullptr),
77 m_pIOleIPFrame(nullptr),
78 m_pIOleIPUIWindow(nullptr),
79 m_pCHatchWin(nullptr),
80 m_xOleAccess( xOleAccess ),
81 m_pInterceptor(nullptr),
82 m_xFactory( xFactory ),
83 m_bOnDeactivate(false),
84 m_hWndxWinParent(nullptr),
85 m_hWndxWinCont(nullptr),
86 m_nMenuHandle(nullptr),
87 m_nMenuShared(nullptr),
88 m_nOLEMenu(nullptr),
89 m_nMacroExecMode( document::MacroExecMode::USE_CONFIG ),
90 m_bLink( false )
91 {
92 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
93 xDesktop->addTerminateListener( static_cast<frame::XTerminateListener*>(this) );
94 }
95
96
~DocumentHolder()97 DocumentHolder::~DocumentHolder()
98 {
99 delete m_pCHatchWin;
100
101 ClearInterceptorInternally();
102 }
103
104
LoadDocInFrame(bool bPluginMode)105 void DocumentHolder::LoadDocInFrame( bool bPluginMode )
106 {
107 uno::Reference<frame::XComponentLoader> xComponentLoader(
108 m_xFrame,uno::UNO_QUERY);
109 if( xComponentLoader.is() && m_xDocument.is() )
110 {
111 uno::Reference< task::XInteractionHandler2 > xHandler(
112 task::InteractionHandler::createWithParent(comphelper::getComponentContext(m_xFactory), nullptr) );
113
114 sal_Int32 nLen = 3;
115 uno::Sequence<beans::PropertyValue> aSeq( nLen );
116
117 aSeq[0] = beans::PropertyValue(
118 "Model",
119 -1,
120 uno::Any(uno::Reference<uno::XInterface>(m_xDocument, uno::UNO_QUERY)),
121 beans::PropertyState_DIRECT_VALUE);
122
123 aSeq[1] = beans::PropertyValue(
124 "ReadOnly",
125 -1,
126 uno::Any(false),
127 beans::PropertyState_DIRECT_VALUE);
128
129 aSeq[2] = beans::PropertyValue(
130 "NoAutoSave",
131 -1,
132 uno::Any(true),
133 beans::PropertyState_DIRECT_VALUE);
134
135 if ( bPluginMode )
136 {
137 aSeq.realloc( ++nLen );
138 aSeq[nLen-1] = beans::PropertyValue(
139 "PluginMode",
140 -1,
141 uno::Any(sal_Int16(3)),
142 beans::PropertyState_DIRECT_VALUE);
143 }
144
145 aSeq.realloc( nLen+=2 );
146 aSeq[nLen-2] = beans::PropertyValue(
147 "InteractionHandler",
148 -1,
149 uno::Any(xHandler),
150 beans::PropertyState_DIRECT_VALUE);
151
152 aSeq[nLen-1] = beans::PropertyValue(
153 "MacroExecutionMode",
154 -1,
155 uno::Any(m_nMacroExecMode),
156 beans::PropertyState_DIRECT_VALUE);
157
158 xComponentLoader->loadComponentFromURL(
159 "private:object",
160 "_self",
161 0,
162 aSeq);
163
164 uno::Sequence< beans::PropertyValue > aResArgs = m_xDocument->getArgs();
165 for ( int nInd = 0; nInd < aResArgs.getLength(); nInd++ )
166 if ( aResArgs[nInd].Name == "MacroExecutionMode" )
167 {
168 aResArgs[nInd].Value >>= m_nMacroExecMode;
169 break;
170 }
171 }
172 }
173
OnPosRectChanged(LPRECT lpRect) const174 void DocumentHolder::OnPosRectChanged(LPRECT lpRect) const
175 {
176 lpRect->left += m_aBorder.left;
177 lpRect->right -= m_aBorder.right;
178 lpRect->top += m_aBorder.top;
179 lpRect->bottom -= m_aBorder.bottom;
180 if(m_pIOleIPSite)
181 m_pIOleIPSite->OnPosRectChange(lpRect);
182 }
183
184
DisableInplaceActivation(BOOL b)185 void DocumentHolder::DisableInplaceActivation(BOOL b)
186 {
187 m_bAllowInPlace = ! b;
188 }
189
isActive() const190 BOOL DocumentHolder::isActive() const
191 {
192 return m_pIOleIPSite != nullptr;
193 }
194
InPlaceActivate(LPOLECLIENTSITE pActiveSite,BOOL fIncludeUI)195 HRESULT DocumentHolder::InPlaceActivate(
196 LPOLECLIENTSITE pActiveSite,
197 BOOL fIncludeUI)
198 {
199 m_bOnDeactivate = false;
200
201 if(!m_bAllowInPlace)
202 return ERROR;
203
204 HRESULT hr;
205 HWND hWndSite;
206 RECT rcPos;
207 RECT rcClip;
208 OLEINPLACEFRAMEINFO frameInfo;
209
210 if (nullptr==pActiveSite)
211 return ResultFromScode(E_INVALIDARG);
212
213 if (nullptr!=m_pIOleIPSite)
214 {
215 if (fIncludeUI)
216 UIActivate();
217
218 return NOERROR;
219 }
220
221 if ( !m_xDocument.is() )
222 return ERROR;
223
224 //1. Initialization, obtaining interfaces, OnInPlaceActivate.
225 hr=pActiveSite->QueryInterface(
226 IID_IOleInPlaceSite,
227 reinterpret_cast<void**>(&m_pIOleIPSite));
228
229 if (FAILED(hr))
230 return hr;
231
232 hr=m_pIOleIPSite->CanInPlaceActivate();
233
234 if (NOERROR!=hr)
235 {
236 m_pIOleIPSite->Release();
237 m_pIOleIPSite=nullptr;
238 return ResultFromScode(E_FAIL);
239 }
240
241 m_pIOleIPSite->OnInPlaceActivate();
242
243 //2. Get the site window
244 //3. and determine container frame and
245 // document window for tools and menus, as well
246 // as frameInfo for accelerators
247 m_pIOleIPSite->GetWindow(&hWndSite);
248
249 frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
250 m_pIOleIPSite->GetWindowContext(
251 &m_pIOleIPFrame,&m_pIOleIPUIWindow,&rcPos,&rcClip,&frameInfo);
252
253 // initialize the office as, with hwnd as parentwindow
254 uno::Any aAny;
255 uno::Sequence<sal_Int8> aProcessIdent(16);
256 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
257
258 try
259 {
260 if(!m_xEditWindow.is())
261 { // determine XWindow and window handle of parent
262 HWND hWndxWinParent(nullptr);
263 uno::Reference<awt::XWindow> xWin;
264
265 uno::Reference<awt::XToolkit2> xToolkit =
266 awt::Toolkit::create(comphelper::getComponentContext(m_xFactory));
267
268 // create system window wrapper for hwnd
269 if( !m_pCHatchWin )
270 m_pCHatchWin = new winwrap::CHatchWin(
271 m_hInstance,this);
272
273 if(m_pCHatchWin->Init(hWndSite,/*ID_HATCHWINDOW*/2000, nullptr)) {
274 m_pCHatchWin->RectsSet(&rcPos,&rcClip); //set visible area
275 hWndxWinParent = m_pCHatchWin->Window();
276 ShowWindow(hWndxWinParent,SW_SHOW); //Make visible.
277 }
278 else {
279 // no success initializing hatch window
280 delete m_pCHatchWin;
281 m_pCHatchWin = nullptr;
282 hWndxWinParent = hWndSite;
283 }
284
285 xWin.set(
286 xToolkit->createSystemChild(
287 uno::Any(sal_Int32(hWndxWinParent)),
288 aProcessIdent,
289 lang::SystemDependent::SYSTEM_WIN32),
290 uno::UNO_QUERY);
291
292 if(xWin.is()) {
293 xWin->setPosSize(
294 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
295 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
296 rcPos.right-rcPos.left,
297 rcPos.bottom - rcPos.top,
298 awt::PosSize::POSSIZE);
299 xWin->setVisible(true);
300
301 m_xEditWindow = xWin;
302 m_hWndxWinParent = hWndxWinParent;
303 }
304 else
305 return ERROR;
306 }
307 else {
308 if(m_hWndxWinParent) {
309 SetParent(m_hWndxWinParent,hWndSite);
310 ShowWindow(m_hWndxWinParent,SW_SHOW); //Make visible.
311 }
312
313 if ( !m_xFrame.is() )
314 // initially set size to "empty", this guarantees that the final resize
315 // is always executed (will be done by "SetObjectRects" after getting internal border)
316 m_xEditWindow->setPosSize(
317 0,
318 0,
319 0,
320 0,
321 awt::PosSize::POSSIZE);
322 m_xEditWindow->setVisible(true);
323 }
324
325 if(m_xContainerWindow.is()) {
326 if(m_hWndxWinCont) {
327 if(m_pIOleIPFrame) {
328 HWND hWndCont;
329 m_pIOleIPFrame->GetWindow(&hWndCont);
330 SetParent(m_hWndxWinCont,hWndCont);
331 ShowWindow(m_hWndxWinCont,SW_SHOW);
332 }
333 }
334 m_xContainerWindow->setVisible(true);
335 }
336
337 if(m_xFrame.is())
338 m_xFrame->activate();
339 else {
340 // create frame and initialize it with the created window
341 m_xFrame = frame::Frame::create( comphelper::getComponentContext(m_xFactory) );
342 m_xFrame->initialize(m_xEditWindow);
343
344 m_xFrame->registerDispatchProviderInterceptor( CreateNewInterceptor() );
345
346 m_xLayoutManager.set( m_xFrame->getLayoutManager(), uno::UNO_QUERY );
347
348 if(m_xLayoutManager.is())
349 m_xLayoutManager->setDockingAreaAcceptor(this);
350
351 // load the model into the frame
352 LoadDocInFrame( true );
353
354 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
355 xDesktop->getFrames()->append(m_xFrame);
356
357 // determine the menuhandle to get menuitems.
358 if(m_xLayoutManager.is()) {
359 uno::Reference< css::ui::XUIElement > xUIEl(
360 m_xLayoutManager->getElement(
361 "private:resource/menubar/menubar"));
362 OSL_ENSURE(xUIEl.is(),"no menubar");
363 uno::Reference<awt::XSystemDependentMenuPeer> xSDMP(
364 xUIEl->getRealInterface(),
365 uno::UNO_QUERY);
366 aAny = xSDMP->getMenuHandle(
367 aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
368 sal_Int64 tmp;
369 if( aAny >>= tmp )
370 m_nMenuHandle = HMENU(tmp);
371 m_xLayoutManager->hideElement(
372 "private:resource/menubar/menubar" );
373 }
374 }
375
376 // TODO/cd: Workaround for status indicator bug. It always makes the
377 // document window visible, when someone tries to use the status
378 // indicator. As we save our document when we get the deactivation
379 // from OLE this conflict to hide floating windows.
380 if(m_xLayoutManager.is())
381 m_xLayoutManager->setVisible(true);
382
383 // get document border and resize rects according to border
384 GetDocumentBorder( &m_aBorder );
385 SetObjectRects( &rcPos, &rcClip );
386
387 if ( m_xOleAccess.is() )
388 {
389 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
390 if ( aDocLock.GetEmbedDocument() )
391 aDocLock.GetEmbedDocument()->ShowObject();
392 }
393
394 // setTitle(m_aDocumentNamePart);
395 if (fIncludeUI)
396 hr=UIActivate();
397
398 m_pIOleIPSite->DiscardUndoState();
399 }
400 catch( const uno::Exception& )
401 {
402 hr = ERROR;
403 }
404
405 return hr;
406 }
407
408
InPlaceDeactivate()409 void DocumentHolder::InPlaceDeactivate()
410 {
411 m_bOnDeactivate = true;
412
413 UIDeactivate();
414 if(m_xFrame.is()) m_xFrame->deactivate();
415
416 if(m_xEditWindow.is()) {
417 m_xEditWindow->setVisible(false);
418 ShowWindow(m_hWndxWinParent,SW_HIDE);
419 SetParent(m_hWndxWinParent,nullptr);
420 }
421
422 if(m_xContainerWindow.is()) {
423 m_xContainerWindow->setVisible(false);
424 ShowWindow(m_hWndxWinCont,SW_HIDE);
425 SetParent(m_hWndxWinCont,nullptr);
426 }
427
428 // TODO/cd: Workaround for status indicator bug. It always makes the
429 // document window visible, when someone tries to use the status
430 // indicator. As we save our document when we get the deactivation
431 // from OLE this conflict to hide floating windows.
432 if (m_xLayoutManager.is())
433 m_xLayoutManager->setVisible(false);
434
435 if (nullptr!=m_pIOleIPSite)
436 m_pIOleIPSite->OnInPlaceDeactivate();
437
438 if(m_pIOleIPFrame) m_pIOleIPFrame->Release(); m_pIOleIPFrame = nullptr;
439 if(m_pIOleIPUIWindow) m_pIOleIPUIWindow->Release(); m_pIOleIPUIWindow = nullptr;
440 if(m_pIOleIPSite) m_pIOleIPSite->Release(); m_pIOleIPSite = nullptr;
441
442 if ( m_xOleAccess.is() )
443 {
444 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
445 if ( aDocLock.GetEmbedDocument() )
446 {
447 aDocLock.GetEmbedDocument()->SaveObject();
448 }
449 }
450
451 return;
452 }
453
454
UIActivate()455 HRESULT DocumentHolder::UIActivate()
456 {
457 // 1. Call IOleInPlaceSite::UIActivate
458 if (nullptr!=m_pIOleIPSite)
459 m_pIOleIPSite->OnUIActivate();
460
461 //2. Critical for accelerators to work initially.
462 SetFocus(m_pCHatchWin->Window());
463 // if(m_xEditWindow.is()) m_xEditWindow->setFocus();
464
465 //3. Set the active object
466
467 OLECHAR starOffice[] = {'S','t','a','r','O','f','f','i','c','e',0};
468 CComPtr< IOleInPlaceActiveObject > pObj = new CIIAObj( this );
469
470 if (nullptr!=m_pIOleIPFrame)
471 m_pIOleIPFrame->SetActiveObject(
472 pObj, starOffice );
473
474 if (nullptr!=m_pIOleIPUIWindow)
475 m_pIOleIPUIWindow->SetActiveObject(
476 pObj, starOffice );
477
478 //4. Create the shared menu.
479 InPlaceMenuCreate();
480
481 return NOERROR;
482 }
483
UIDeactivate()484 void DocumentHolder::UIDeactivate()
485 {
486 //1. Remove the shared menu.
487 InPlaceMenuDestroy();
488
489 if (nullptr!=m_pIOleIPFrame)
490 m_pIOleIPFrame->SetActiveObject(nullptr, nullptr);
491
492 if (nullptr!=m_pIOleIPUIWindow)
493 m_pIOleIPUIWindow->SetActiveObject(nullptr, nullptr);
494
495 //3. Call IOleInPlaceSite::OnUIDeactivate
496 if (nullptr!=m_pIOleIPSite)
497 m_pIOleIPSite->OnUIDeactivate(FALSE);
498
499 return;
500 }
501
CopyToOLEMenu(HMENU hOrig,WORD origPos,HMENU hDest,WORD destPos)502 static void CopyToOLEMenu(HMENU hOrig,WORD origPos,HMENU hDest,WORD destPos)
503 {
504 HMENU subMenu(nullptr);
505 wchar_t buffer[256];
506
507 subMenu = GetSubMenu(hOrig,origPos);
508 GetMenuStringW(hOrig,origPos,buffer,256,MF_BYPOSITION);
509 InsertMenuW(hDest,destPos,MF_BYPOSITION | MF_POPUP,
510 reinterpret_cast<UINT_PTR>(subMenu),buffer);
511
512 MENUITEMINFOW mi = {};
513 mi.cbSize = sizeof(mi);
514 mi.fMask = MIIM_DATA;
515 if(GetMenuItemInfoW(hOrig,origPos,TRUE,&mi))
516 SetMenuItemInfoW(hDest,destPos,TRUE,&mi);
517 }
518
InPlaceMenuCreate()519 BOOL DocumentHolder::InPlaceMenuCreate()
520 {
521 HMENU hMenu;
522 OLEMENUGROUPWIDTHS mgw;
523
524 for (UINT i=0; i<6; i++)
525 mgw.width[i]=0;
526
527 //We already have popup menu handles in m_pFR->m_phMenu[]
528
529 //Create the new shared menu and let container do its thing
530 hMenu=CreateMenu();
531 m_pIOleIPFrame->InsertMenus(hMenu,&mgw);
532
533 int count = GetMenuItemCount(m_nMenuHandle);
534 int help = count-1;
535
536 // start with 1, because we don't include "File"
537 WORD pos = static_cast<WORD>(mgw.width[0]);
538 CopyToOLEMenu(m_nMenuHandle,1,hMenu,pos);
539 mgw.width[1] = 1;
540
541 // insert object menu here
542 pos = static_cast<WORD>(mgw.width[0] + mgw.width[1] + mgw.width[2]);
543 for(WORD i = 2; i < help-1; ++i,++pos)
544 CopyToOLEMenu(m_nMenuHandle,i,hMenu,pos);
545 mgw.width[3] = help - 3;
546
547 // insert help menu
548 pos = static_cast<WORD>(mgw.width[0] + mgw.width[1] + mgw.width[2] +
549 mgw.width[3] + mgw.width[4]);
550 CopyToOLEMenu(m_nMenuHandle,WORD(help),hMenu,pos);
551 mgw.width[5] = 1;
552
553 m_nMenuShared = hMenu;
554 m_nOLEMenu = OleCreateMenuDescriptor(m_nMenuShared,&mgw);
555
556 uno::Reference<awt::XSystemDependentWindowPeer> xSysDepWin(m_xContainerWindow,uno::UNO_QUERY);
557 if(xSysDepWin.is()) {
558 uno::Sequence<sal_Int8> aProcessIdent(16);
559 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
560 uno::Any aAny = xSysDepWin->getWindowHandle(aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
561 sal_Int64 tmp;
562 aAny >>= tmp;
563 HWND aHwnd = reinterpret_cast<HWND>(tmp);
564 m_pIOleIPFrame->SetMenu(
565 m_nMenuShared,m_nOLEMenu,aHwnd);
566 }
567 else
568 m_pIOleIPFrame->SetMenu(
569 m_nMenuShared,m_nOLEMenu,::GetWindow(m_hWndxWinParent,GW_CHILD));
570 return TRUE;
571 }
572
InPlaceMenuDestroy()573 BOOL DocumentHolder::InPlaceMenuDestroy()
574 {
575 if( nullptr == m_nMenuShared )
576 return TRUE;
577
578 m_pIOleIPFrame->SetMenu(nullptr,nullptr,nullptr);
579
580 OleDestroyMenuDescriptor(m_nOLEMenu);
581 m_nOLEMenu = nullptr;
582 return TRUE;
583 }
584
OpenIntoWindow()585 void DocumentHolder::OpenIntoWindow()
586 {
587 // not implemented
588 }
589
Undo()590 BOOL DocumentHolder::Undo()
591 {
592 // not implemented
593 return false;
594 }
595
596
FreeOffice()597 void DocumentHolder::FreeOffice()
598 {
599 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
600 xDesktop->removeTerminateListener(
601 static_cast<frame::XTerminateListener*>(this) );
602 }
603
DisconnectFrameDocument(bool bComplete)604 void DocumentHolder::DisconnectFrameDocument( bool bComplete )
605 {
606 try
607 {
608 uno::Reference< util::XModifyBroadcaster > xModifiable( m_xDocument, uno::UNO_QUERY_THROW );
609 xModifiable->removeModifyListener( static_cast<util::XModifyListener*>(this) );
610 }
611 catch( const uno::Exception& )
612 {}
613
614 try
615 {
616 uno::Reference< util::XCloseBroadcaster > xBroadcaster(
617 m_xDocument, uno::UNO_QUERY_THROW );
618 xBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
619 }
620 catch( const uno::Exception& )
621 {}
622
623 try
624 {
625 uno::Reference< util::XCloseBroadcaster > xBroadcaster(
626 m_xFrame, uno::UNO_QUERY_THROW );
627 xBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
628 }
629 catch( const uno::Exception& )
630 {}
631
632 if ( bComplete )
633 {
634 m_xFrame.clear();
635 m_pIDispatch = nullptr;
636 m_xDocument.clear();
637 }
638 }
639
CloseDocument()640 void DocumentHolder::CloseDocument()
641 {
642 DisconnectFrameDocument();
643
644 uno::Reference< util::XCloseable > xCloseable(
645 m_xDocument, uno::UNO_QUERY );
646
647 if ( xCloseable.is() )
648 {
649 try
650 {
651 xCloseable->close( true );
652 }
653 catch( const uno::Exception& )
654 {}
655 }
656
657 m_pIDispatch = nullptr;
658 m_xDocument.clear();
659 }
660
661
CloseFrame()662 void DocumentHolder::CloseFrame()
663 {
664 try
665 {
666 uno::Reference< util::XCloseBroadcaster > xBroadcaster(
667 m_xFrame, uno::UNO_QUERY_THROW );
668 xBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
669 }
670 catch( const uno::Exception& )
671 {}
672
673 uno::Reference<util::XCloseable> xCloseable(
674 m_xFrame,uno::UNO_QUERY);
675 if(xCloseable.is())
676 try {
677 xCloseable->close(true);
678 }
679 catch( const uno::Exception& ) {
680 }
681 else if (m_xFrame.is())
682 m_xFrame->dispose();
683
684 m_xFrame.clear();
685 }
686
SetDocument(const uno::Reference<frame::XModel> & xDoc,bool bLink)687 void DocumentHolder::SetDocument( const uno::Reference< frame::XModel >& xDoc, bool bLink )
688 {
689 if ( m_xDocument.is() )
690 CloseDocument();
691
692 m_xDocument = xDoc;
693 m_bLink = bLink;
694
695 uno::Reference< util::XCloseBroadcaster > xBroadcaster(
696 m_xDocument, uno::UNO_QUERY );
697
698 if ( xBroadcaster.is() )
699 xBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
700
701 if ( m_xDocument.is() && !m_bLink )
702 {
703 // set the document mode to embedded
704 uno::Sequence< beans::PropertyValue > aSeq(1);
705 aSeq[0].Name = "SetEmbedded";
706 aSeq[0].Value <<= true;
707 m_xDocument->attachResource(OUString(),aSeq);
708 }
709 }
710
ExecuteSuspendCloseFrame()711 bool DocumentHolder::ExecuteSuspendCloseFrame()
712 {
713 if ( m_xFrame.is() && m_xFactory.is() )
714 {
715 try
716 {
717 uno::Reference< frame::XController > xController = m_xFrame->getController();
718 if ( xController.is() )
719 {
720 if ( !xController->suspend( true ) )
721 return false;
722
723 FreeOffice();
724 try
725 {
726 uno::Reference<util::XCloseable> xCloseable( m_xFrame, uno::UNO_QUERY );
727 if ( xCloseable.is() )
728 xCloseable->close(true);
729 else
730 {
731 m_xFrame->dispose();
732 }
733 }
734 catch( const util::CloseVetoException& )
735 {
736 // should be called if the frame could not be closed
737 xController->suspend( false );
738 }
739 }
740 }
741 catch( uno::Exception& )
742 {
743 }
744
745 m_xFrame.clear();
746 }
747
748 return true;
749 }
750
DocumentFrame()751 uno::Reference< frame::XFrame2 > DocumentHolder::DocumentFrame()
752 {
753 if(! m_xFrame.is() )
754 {
755 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
756
757 // the frame will be registered on desktop here, later when the document
758 // is loaded into the frame in ::show() method the terminate listener will be removed
759 // this is so only for outplace activation
760 m_xFrame.set( xDesktop->findFrame( "_blank", 0 ), uno::UNO_QUERY );
761
762 uno::Reference< util::XCloseBroadcaster > xBroadcaster(
763 m_xFrame, uno::UNO_QUERY );
764
765 if ( xBroadcaster.is() )
766 {
767 xBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
768 FreeOffice(); // the frame is part of the desktop
769 }
770 }
771
772 if( m_xFrame.is() )
773 {
774 // intercept
775 m_xFrame->registerDispatchProviderInterceptor( CreateNewInterceptor() );
776 }
777
778 return m_xFrame;
779 }
780
781
CreateNewInterceptor()782 uno::Reference< frame::XDispatchProviderInterceptor > DocumentHolder::CreateNewInterceptor()
783 {
784 ::osl::MutexGuard aGuard( m_aMutex );
785
786 ClearInterceptorInternally();
787
788 uno::Reference< frame::XDispatchProviderInterceptor > xInterceptor( m_pInterceptor = new Interceptor( m_xOleAccess, this, m_bLink ) );
789 m_xInterceptorLocker = xInterceptor;
790 return xInterceptor;
791 }
792
ClearInterceptorInternally()793 void DocumentHolder::ClearInterceptorInternally()
794 {
795 ::osl::MutexGuard aGuard( m_aMutex );
796 uno::Reference< frame::XDispatchProviderInterceptor > xInterceptor( m_xInterceptorLocker );
797 if ( xInterceptor.is() && m_pInterceptor )
798 m_pInterceptor->DisconnectDocHolder();
799
800 m_xInterceptorLocker.clear();
801 m_pInterceptor = nullptr;
802 }
803
ClearInterceptor()804 void DocumentHolder::ClearInterceptor()
805 {
806 ::osl::MutexGuard aGuard( m_aMutex );
807 m_xInterceptorLocker.clear();
808 m_pInterceptor = nullptr;
809 }
810
811
show()812 void DocumentHolder::show()
813 {
814 try
815 {
816 if(m_xFrame.is())
817 {
818 m_xFrame->activate();
819 uno::Reference<awt::XTopWindow> xTopWindow(
820 m_xFrame->getContainerWindow(),uno::UNO_QUERY);
821 if(xTopWindow.is())
822 xTopWindow->toFront();
823 }
824 else if( DocumentFrame().is() )
825 {
826 LoadDocInFrame( false );
827
828 // get rid of second closer if it is there
829 uno::Reference< beans::XPropertySet > xLMProps( m_xFrame->getLayoutManager(), uno::UNO_QUERY );
830 if ( xLMProps.is() )
831 {
832 xLMProps->setPropertyValue("MenuBarCloser",
833 uno::makeAny( uno::Reference< frame::XStatusListener >() ) );
834 }
835
836 if ( !m_bLink )
837 {
838 try
839 {
840 uno::Reference< util::XModifyBroadcaster > xModifiable( m_xDocument, uno::UNO_QUERY_THROW );
841 xModifiable->addModifyListener( static_cast<util::XModifyListener*>(this) );
842 }
843 catch( const uno::Exception& )
844 {}
845 }
846
847 if ( !m_bLink )
848 setTitle(m_aDocumentNamePart);
849 }
850 }
851 catch( const uno::Exception& )
852 {
853 OSL_FAIL( "Can not show the frame!" );
854 }
855
856 }
857
resizeWin(const SIZEL & rNewSize)858 void DocumentHolder::resizeWin( const SIZEL& rNewSize )
859 {
860 LockedEmbedDocument_Impl aDocLock;
861
862 if ( m_xOleAccess.is() )
863 aDocLock = m_xOleAccess->GetEmbedDocument();
864
865 if ( m_xFrame.is() && aDocLock.GetEmbedDocument() )
866 {
867 uno::Reference< awt::XWindow > xWindow = m_xFrame->getContainerWindow();
868 uno::Reference< awt::XView > xView( xWindow, uno::UNO_QUERY );
869
870 if ( xWindow.is() && xView.is() )
871 {
872 float fScale = 1;
873 xView->setZoom( fScale, fScale );
874
875 SIZEL aOldSize;
876 GetExtent( &aOldSize );
877
878 if ( aOldSize.cx != rNewSize.cx || aOldSize.cy != rNewSize.cy )
879 {
880 HDC hdc = GetDC( nullptr );
881 SetMapMode( hdc, MM_HIMETRIC );
882
883 POINT aOldOffset;
884 aOldOffset.x = aOldSize.cx;
885 aOldOffset.y = aOldSize.cy;
886 BOOL bIsOk = LPtoDP( hdc, &aOldOffset, 1 );
887
888 POINT aNewOffset;
889 aNewOffset.x = rNewSize.cx;
890 aNewOffset.y = rNewSize.cy;
891 bIsOk = LPtoDP( hdc, &aNewOffset, 1 );
892
893 ReleaseDC( nullptr, hdc );
894
895 awt::Rectangle aWinRect = xWindow->getPosSize();
896
897 sal_Int32 aWidthDelta = aWinRect.Width - aOldOffset.x;
898 sal_Int32 aHeightDelta = aWinRect.Height - aOldOffset.y;
899
900 if ( aWidthDelta > 0 && aHeightDelta > 0 )
901 xWindow->setPosSize(0,
902 0,
903 aNewOffset.x + aWidthDelta,
904 aNewOffset.y + aHeightDelta,
905 awt::PosSize::SIZE );
906 }
907 }
908 }
909 }
910
setTitle(const OUString & aDocumentName)911 void DocumentHolder::setTitle(const OUString& aDocumentName)
912 {
913 if(m_xFrame.is())
914 {
915 if(m_aFilterName.getLength() == 0)
916 {
917 OUString aFilterName;
918 uno::Sequence<beans::PropertyValue> aSeq;
919 if(m_xDocument.is())
920 {
921 aSeq =
922 m_xDocument->getArgs();
923 for(sal_Int32 j = 0; j < aSeq.getLength(); ++j)
924 {
925 if(aSeq[j].Name == "FilterName")
926 {
927 aSeq[j].Value >>= aFilterName;
928 break;
929 }
930 }
931 }
932
933 if(aFilterName.getLength())
934 {
935 uno::Reference<container::XNameAccess> xNameAccess(
936 m_xFactory->createInstance("com.sun.star.document.FilterFactory"),
937 uno::UNO_QUERY);
938 try {
939 if(xNameAccess.is() &&
940 (xNameAccess->getByName(aFilterName) >>= aSeq))
941 {
942 for(sal_Int32 j = 0; j < aSeq.getLength(); ++j)
943 if(aSeq[j].Name ==
944 "UIName")
945 {
946 aSeq[j].Value >>= m_aFilterName;
947 break;
948 }
949 }
950 }
951 catch(const uno::Exception& ) {
952 // nothing better to do here
953 m_aFilterName = aFilterName;
954 }
955 }
956 }
957 // set the title
958 static const sal_Unicode u[] = { ' ','(',0 };
959 static const sal_Unicode c[] = { ')',0 };
960 OUString aTotalName(m_aFilterName);
961 aTotalName += OUString(u);
962 aTotalName += aDocumentName;
963 aTotalName += OUString(c);
964 try {
965 m_xFrame->setTitle( aTotalName );
966 }
967 catch( const uno::Exception& ) {
968 }
969 }
970
971 m_aDocumentNamePart = aDocumentName;
972
973 if(m_pInterceptor)
974 {
975 ::osl::ClearableMutexGuard aGuard( m_aMutex );
976
977 Interceptor* pTmpInter = nullptr;
978 uno::Reference< frame::XDispatchProviderInterceptor > xLock( m_xInterceptorLocker );
979 if ( xLock.is() && m_pInterceptor )
980 pTmpInter = m_pInterceptor;
981
982 aGuard.clear();
983
984 if ( pTmpInter )
985 pTmpInter->generateFeatureStateEvent();
986 }
987 }
988
989
setContainerName(const OUString & aContainerName)990 void DocumentHolder::setContainerName(const OUString& aContainerName)
991 {
992 m_aContainerName = aContainerName;
993 }
994
995
hide()996 void DocumentHolder::hide()
997 {
998 if(m_xFrame.is()) m_xFrame->deactivate();
999
1000 //todo: sendadvise
1001 // after hiding the window it is always allowed to InPlaceActivate it
1002 m_bAllowInPlace = true;
1003 }
1004
GetIDispatch()1005 IDispatch* DocumentHolder::GetIDispatch()
1006 {
1007 if ( !m_pIDispatch && m_xDocument.is() )
1008 {
1009 const OUString aServiceName (
1010 "com.sun.star.bridge.OleBridgeSupplier2" );
1011 uno::Reference< bridge::XBridgeSupplier2 > xSupplier(
1012 m_xFactory->createInstance( aServiceName ), uno::UNO_QUERY );
1013
1014 if ( xSupplier.is() )
1015 {
1016 uno::Sequence< sal_Int8 > aProcId( 16 );
1017 rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8*>(aProcId.getArray()) );
1018
1019 try {
1020 uno::Any anyResult = xSupplier->createBridge(
1021 uno::makeAny( m_xDocument ),
1022 aProcId,
1023 bridge::ModelDependent::UNO,
1024 bridge::ModelDependent::OLE );
1025
1026 if ( auto var = o3tl::tryAccess<sal_uIntPtr>(anyResult) )
1027 {
1028 VARIANT* pVariant = reinterpret_cast<VARIANT*>(*var);
1029 if ( pVariant->vt == VT_DISPATCH )
1030 m_pIDispatch = pVariant->pdispVal;
1031
1032 VariantClear( pVariant );
1033 CoTaskMemFree( pVariant );
1034 }
1035 }
1036 catch ( const uno::Exception& )
1037 {}
1038 }
1039 }
1040
1041 return m_pIDispatch;
1042 }
1043
GetDocumentBorder(RECT * pRect)1044 HRESULT DocumentHolder::GetDocumentBorder( RECT *pRect )
1045 {
1046 if ( pRect && m_xDocument.is() )
1047 {
1048 uno::Sequence< beans::PropertyValue > aArgs = m_xDocument->getArgs();
1049 for ( sal_Int32 nInd = 0; nInd < aArgs.getLength(); nInd++ )
1050 if ( aArgs[nInd].Name == "DocumentBorder" )
1051 {
1052 uno::Sequence< sal_Int32 > aRect;
1053 if ( ( aArgs[nInd].Value >>= aRect ) && aRect.getLength() == 4 )
1054 {
1055 pRect->left = aRect[0];
1056 pRect->top = aRect[1];
1057 pRect->right = aRect[2];
1058 pRect->bottom = aRect[3];
1059
1060 return S_OK;
1061 }
1062
1063 break;
1064 }
1065 }
1066
1067 return E_FAIL;
1068 }
1069
SetExtent(const SIZEL * pSize)1070 HRESULT DocumentHolder::SetExtent( const SIZEL *pSize )
1071 {
1072 if ( pSize )
1073 {
1074 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1075 if ( xVisObj.is() )
1076 {
1077 try
1078 {
1079 awt::Size aNewSize( pSize->cx, pSize->cy );
1080
1081 sal_Int32 aMapMode = xVisObj->getMapUnit( DVASPECT_CONTENT );
1082
1083 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1084 if ( aMapMode == embed::EmbedMapUnits::TWIP )
1085 {
1086 // conversion from ONE_100TH_MM
1087 aNewSize.Width = aNewSize.Width * 144 / 254;
1088 aNewSize.Height = aNewSize.Height * 144 / 254;
1089 }
1090
1091
1092 xVisObj->setVisualAreaSize( DVASPECT_CONTENT, aNewSize );
1093
1094 return S_OK;
1095 }
1096 catch( const uno::Exception& )
1097 {}
1098 }
1099 }
1100
1101 return E_FAIL;
1102 }
1103
GetExtent(SIZEL * pSize)1104 HRESULT DocumentHolder::GetExtent( SIZEL *pSize )
1105 {
1106 if ( pSize )
1107 {
1108 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1109 if ( xVisObj.is() )
1110 {
1111 try
1112 {
1113 awt::Size aDocSize = xVisObj->getVisualAreaSize( DVASPECT_CONTENT );
1114
1115 sal_Int32 aMapMode = xVisObj->getMapUnit( DVASPECT_CONTENT );
1116
1117 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1118 if ( aMapMode == embed::EmbedMapUnits::TWIP )
1119 {
1120 // conversion to ONE_100TH_MM
1121 aDocSize.Width = aDocSize.Width * 254 / 144;
1122 aDocSize.Height = aDocSize.Height * 254 / 144;
1123 }
1124
1125 pSize->cx = aDocSize.Width;
1126 pSize->cy = aDocSize.Height;
1127
1128 return S_OK;
1129 }
1130 catch( const uno::Exception& )
1131 {}
1132 }
1133 }
1134
1135 return E_FAIL;
1136 }
1137
1138
SetContRects(LPCRECT aRect)1139 HRESULT DocumentHolder::SetContRects(LPCRECT aRect)
1140 {
1141 if(m_xContainerWindow.is()) {
1142 RECT wi = {};
1143 if(m_pIOleIPFrame) {
1144 m_pIOleIPFrame->GetBorder(&wi);
1145 m_xContainerWindow->setPosSize(
1146 0,0,
1147 wi.right - wi.left,
1148 wi.bottom - wi.top,
1149 awt::PosSize::POSSIZE);
1150 }
1151 else
1152 m_xContainerWindow->setPosSize(
1153 0,0,
1154 aRect->right - aRect->left,
1155 aRect->bottom - aRect->top,
1156 awt::PosSize::POSSIZE);
1157 return NOERROR;
1158 }
1159 else {
1160 return ERROR;
1161 }
1162 }
1163
1164
SetObjectRects(LPCRECT aRect,LPCRECT aClip)1165 HRESULT DocumentHolder::SetObjectRects(LPCRECT aRect, LPCRECT aClip)
1166 {
1167 auto rect = *aRect;
1168 rect.left -= m_aBorder.left;
1169 rect.right += m_aBorder.right;
1170 rect.top -= m_aBorder.top;
1171 rect.bottom += m_aBorder.bottom;
1172 auto clip = *aClip;
1173 clip.left -= m_aBorder.left;
1174 clip.right += m_aBorder.right;
1175 clip.top -= m_aBorder.top;
1176 clip.bottom += m_aBorder.bottom;
1177
1178 if(m_pCHatchWin)
1179 m_pCHatchWin->RectsSet(&rect, &clip);
1180 if(m_xEditWindow.is()) {
1181 m_xEditWindow->setVisible(false);
1182 m_xEditWindow->setPosSize(
1183 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
1184 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
1185 rect.right - rect.left,
1186 rect.bottom - rect.top,
1187 awt::PosSize::POSSIZE);
1188 m_xEditWindow->setVisible(true);
1189 }
1190 return NOERROR;
1191 }
1192
1193
getContainerWindow()1194 css::uno::Reference< css::awt::XWindow> SAL_CALL DocumentHolder::getContainerWindow()
1195 {
1196 if(m_xContainerWindow.is())
1197 return m_xContainerWindow;
1198
1199 uno::Reference<awt::XWindow> xWin;
1200
1201 uno::Reference<awt::XToolkit2> xToolkit = awt::Toolkit::create( comphelper::getComponentContext(m_xFactory) );
1202
1203 if(m_pIOleIPFrame) {
1204 HWND hWnd;
1205 m_pIOleIPFrame->GetWindow(&hWnd);
1206
1207 uno::Sequence<sal_Int8> aProcessIdent(16);
1208 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
1209
1210 xWin.set(
1211 xToolkit->createSystemChild(
1212 uno::Any(sal_Int32(hWnd)),
1213 aProcessIdent,
1214 lang::SystemDependent::SYSTEM_WIN32),
1215 uno::UNO_QUERY);
1216
1217 RECT wi = {};
1218 if(xWin.is() && m_pIOleIPFrame->GetBorder(&wi) == NOERROR) {
1219 xWin->setVisible(true);
1220 xWin->setPosSize(
1221 0,0,
1222 wi.right-wi.left,
1223 wi.bottom - wi.top,
1224 awt::PosSize::POSSIZE);
1225
1226 uno::Reference<awt::XSystemDependentWindowPeer> xSysWin(
1227 xWin,uno::UNO_QUERY);
1228 if(xSysWin.is()) {
1229 uno::Any aAny = xSysWin->getWindowHandle(
1230 aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
1231 sal_Int64 tmp;
1232 if( aAny >>= tmp )
1233 SetContainerWindowHandle(reinterpret_cast<HWND>(tmp));
1234 }
1235 }
1236 }
1237
1238 m_xContainerWindow= xWin;
1239 return xWin;
1240 }
1241
1242
requestDockingAreaSpace(const css::awt::Rectangle & RequestedSpace)1243 sal_Bool SAL_CALL DocumentHolder::requestDockingAreaSpace( const css::awt::Rectangle& RequestedSpace )
1244 {
1245 if(m_bOnDeactivate)
1246 return true;
1247
1248 BORDERWIDTHS bw;
1249 SetRect(&bw,
1250 RequestedSpace.X,RequestedSpace.Y,
1251 RequestedSpace.Width,RequestedSpace.Height);
1252 if( m_pIOleIPFrame )
1253 return m_pIOleIPFrame->RequestBorderSpace(&bw) == NOERROR ;
1254 else
1255 return false;
1256 }
1257
1258
setDockingAreaSpace(const css::awt::Rectangle & BorderSpace)1259 void SAL_CALL DocumentHolder::setDockingAreaSpace( const css::awt::Rectangle& BorderSpace )
1260 {
1261 if(m_bOnDeactivate)
1262 return;
1263
1264 BORDERWIDTHS bw;
1265 SetRect(&bw,
1266 BorderSpace.X,BorderSpace.Y,
1267 BorderSpace.Width,BorderSpace.Height);
1268 if( m_pIOleIPFrame ) {
1269 RECT aRect;
1270 GetClientRect(m_hWndxWinCont,&aRect);
1271 HRGN hrgn1 = CreateRectRgn(
1272 0,0,
1273 aRect.right,BorderSpace.Y);
1274 HRGN hrgn2 = CreateRectRgn(aRect.right-BorderSpace.Width,0,aRect.right,aRect.bottom);
1275 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1276 DeleteObject(hrgn2);
1277 hrgn2 = CreateRectRgn(0,aRect.bottom-BorderSpace.Height,aRect.right,aRect.bottom);
1278 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1279 DeleteObject(hrgn2);
1280 hrgn2 = CreateRectRgn(0,0,BorderSpace.X,aRect.bottom);
1281 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1282 DeleteObject(hrgn2);
1283
1284 SetWindowRgn(m_hWndxWinCont,hrgn1,true);
1285 // not:: DeleteObject(hrgn1);
1286 m_pIOleIPFrame->SetBorderSpace(&bw);
1287 }
1288 }
1289
1290
disposing(const css::lang::EventObject & aSource)1291 void SAL_CALL DocumentHolder::disposing( const css::lang::EventObject& aSource )
1292 {
1293 if ( m_xDocument.is() && m_xDocument == aSource.Source )
1294 {
1295 m_pIDispatch = nullptr;
1296 m_xDocument.clear();
1297 }
1298
1299 if( m_xFrame.is() && m_xFrame == aSource.Source )
1300 m_xFrame.clear();
1301 }
1302
1303
1304 void SAL_CALL
queryClosing(const lang::EventObject & aSource,sal_Bool)1305 DocumentHolder::queryClosing(
1306 const lang::EventObject& aSource,
1307 sal_Bool /*bGetsOwnership*/
1308 )
1309 {
1310 if (!m_bLink
1311 && ((m_xDocument.is() && m_xDocument == aSource.Source)
1312 || (m_xFrame.is() && m_xFrame == aSource.Source)))
1313 throw util::CloseVetoException();
1314 }
1315
1316
1317 void SAL_CALL
notifyClosing(const lang::EventObject & aSource)1318 DocumentHolder::notifyClosing(
1319 const lang::EventObject& aSource )
1320 {
1321 try
1322 {
1323 uno::Reference< util::XCloseBroadcaster > xEventBroadcaster(
1324 aSource.Source, uno::UNO_QUERY_THROW );
1325 xEventBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
1326 }
1327 catch( const uno::Exception& )
1328 {}
1329
1330 if ( m_xDocument.is() && m_xDocument == aSource.Source )
1331 {
1332 // can happen only in case of links
1333 m_pIDispatch = nullptr;
1334 m_xDocument.clear();
1335 m_xFrame.clear();
1336
1337 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
1338 if ( aDocLock.GetEmbedDocument() )
1339 aDocLock.GetEmbedDocument()->OLENotifyClosing();
1340 }
1341 else if( m_xFrame.is() && m_xFrame == aSource.Source )
1342 m_xFrame.clear();
1343 }
1344
1345 void SAL_CALL
queryTermination(const lang::EventObject &)1346 DocumentHolder::queryTermination(
1347 const lang::EventObject& /*aSource*/
1348 )
1349 {
1350 if ( m_xDocument.is() )
1351 throw frame::TerminationVetoException();
1352 }
1353
1354 void SAL_CALL
notifyTermination(const lang::EventObject & aSource)1355 DocumentHolder::notifyTermination(
1356 const lang::EventObject& aSource
1357 )
1358 {
1359 OSL_ENSURE( !m_xDocument.is(), "Just a disaster..." );
1360 uno::Reference< frame::XDesktop > xDesktop(
1361 aSource.Source, uno::UNO_QUERY );
1362
1363 if ( xDesktop.is() )
1364 xDesktop->removeTerminateListener( static_cast<frame::XTerminateListener*>(this) );
1365 }
1366
1367
modified(const lang::EventObject &)1368 void SAL_CALL DocumentHolder::modified( const lang::EventObject& /*aEvent*/ )
1369 {
1370 if ( m_xOleAccess.is() )
1371 {
1372 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
1373 if ( aDocLock.GetEmbedDocument() )
1374 aDocLock.GetEmbedDocument()->notify();
1375 }
1376 }
1377
1378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1379