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 #include <rtl/ref.hxx>
67
68 using namespace ::com::sun::star;
69
70 // add mutex locking ???
71
DocumentHolder(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const::rtl::Reference<EmbeddedDocumentInstanceAccess_Impl> & xOleAccess)72 DocumentHolder::DocumentHolder(
73 const uno::Reference<lang::XMultiServiceFactory >& xFactory,
74 const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess )
75 :
76 m_bAllowInPlace(true),
77 m_pIOleIPSite(nullptr),
78 m_pIOleIPFrame(nullptr),
79 m_pIOleIPUIWindow(nullptr),
80 m_pCHatchWin(nullptr),
81 m_xOleAccess( xOleAccess ),
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 const uno::Sequence< beans::PropertyValue > aResArgs = m_xDocument->getArgs();
165 for ( beans::PropertyValue const & prop : aResArgs )
166 if ( prop.Name == "MacroExecutionMode" )
167 {
168 prop.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(reinterpret_cast<sal_Int64>(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 = reinterpret_cast<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.clear();
802 }
803
ClearInterceptor()804 void DocumentHolder::ClearInterceptor()
805 {
806 ::osl::MutexGuard aGuard( m_aMutex );
807 m_xInterceptorLocker.clear();
808 m_pInterceptor.clear();
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 = m_xDocument->getArgs();
922 for(beans::PropertyValue const & prop : std::as_const(aSeq))
923 {
924 if(prop.Name == "FilterName")
925 {
926 prop.Value >>= aFilterName;
927 break;
928 }
929 }
930 }
931
932 if(aFilterName.getLength())
933 {
934 uno::Reference<container::XNameAccess> xNameAccess(
935 m_xFactory->createInstance("com.sun.star.document.FilterFactory"),
936 uno::UNO_QUERY);
937 try {
938 if(xNameAccess.is() &&
939 (xNameAccess->getByName(aFilterName) >>= aSeq))
940 {
941 for(beans::PropertyValue const & prop : std::as_const(aSeq))
942 if(prop.Name == "UIName")
943 {
944 prop.Value >>= m_aFilterName;
945 break;
946 }
947 }
948 }
949 catch(const uno::Exception& ) {
950 // nothing better to do here
951 m_aFilterName = aFilterName;
952 }
953 }
954 }
955 // set the title
956 OUString aTotalName(m_aFilterName + " (" + aDocumentName + ")");
957 try {
958 m_xFrame->setTitle( aTotalName );
959 }
960 catch( const uno::Exception& ) {
961 }
962 }
963
964 m_aDocumentNamePart = aDocumentName;
965
966 if(m_pInterceptor)
967 {
968 ::osl::ClearableMutexGuard aGuard( m_aMutex );
969
970 rtl::Reference<Interceptor> pTmpInter;
971 uno::Reference< frame::XDispatchProviderInterceptor > xLock( m_xInterceptorLocker );
972 if ( xLock.is() && m_pInterceptor )
973 pTmpInter = m_pInterceptor;
974
975 aGuard.clear();
976
977 if ( pTmpInter )
978 pTmpInter->generateFeatureStateEvent();
979 }
980 }
981
982
setContainerName(const OUString & aContainerName)983 void DocumentHolder::setContainerName(const OUString& aContainerName)
984 {
985 m_aContainerName = aContainerName;
986 }
987
988
hide()989 void DocumentHolder::hide()
990 {
991 if(m_xFrame.is()) m_xFrame->deactivate();
992
993 //todo: sendadvise
994 // after hiding the window it is always allowed to InPlaceActivate it
995 m_bAllowInPlace = true;
996 }
997
GetIDispatch()998 IDispatch* DocumentHolder::GetIDispatch()
999 {
1000 if ( !m_pIDispatch && m_xDocument.is() )
1001 {
1002 uno::Reference< bridge::XBridgeSupplier2 > xSupplier(
1003 m_xFactory->createInstance( "com.sun.star.bridge.OleBridgeSupplier2" ), uno::UNO_QUERY );
1004
1005 if ( xSupplier.is() )
1006 {
1007 uno::Sequence< sal_Int8 > aProcId( 16 );
1008 rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8*>(aProcId.getArray()) );
1009
1010 try {
1011 uno::Any anyResult = xSupplier->createBridge(
1012 uno::makeAny( m_xDocument ),
1013 aProcId,
1014 bridge::ModelDependent::UNO,
1015 bridge::ModelDependent::OLE );
1016
1017 if ( auto var = o3tl::tryAccess<sal_uIntPtr>(anyResult) )
1018 {
1019 VARIANT* pVariant = reinterpret_cast<VARIANT*>(*var);
1020 if ( pVariant->vt == VT_DISPATCH )
1021 m_pIDispatch = pVariant->pdispVal;
1022
1023 VariantClear( pVariant );
1024 CoTaskMemFree( pVariant );
1025 }
1026 }
1027 catch ( const uno::Exception& )
1028 {}
1029 }
1030 }
1031
1032 return m_pIDispatch;
1033 }
1034
GetDocumentBorder(RECT * pRect)1035 HRESULT DocumentHolder::GetDocumentBorder( RECT *pRect )
1036 {
1037 if ( pRect && m_xDocument.is() )
1038 {
1039 const uno::Sequence< beans::PropertyValue > aArgs = m_xDocument->getArgs();
1040 for ( beans::PropertyValue const & prop : aArgs )
1041 if ( prop.Name == "DocumentBorder" )
1042 {
1043 uno::Sequence< sal_Int32 > aRect;
1044 if ( ( prop.Value >>= aRect ) && aRect.getLength() == 4 )
1045 {
1046 pRect->left = aRect[0];
1047 pRect->top = aRect[1];
1048 pRect->right = aRect[2];
1049 pRect->bottom = aRect[3];
1050
1051 return S_OK;
1052 }
1053
1054 break;
1055 }
1056 }
1057
1058 return E_FAIL;
1059 }
1060
SetExtent(const SIZEL * pSize)1061 HRESULT DocumentHolder::SetExtent( const SIZEL *pSize )
1062 {
1063 if ( pSize )
1064 {
1065 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1066 if ( xVisObj.is() )
1067 {
1068 try
1069 {
1070 awt::Size aNewSize( pSize->cx, pSize->cy );
1071
1072 sal_Int32 aMapMode = xVisObj->getMapUnit( DVASPECT_CONTENT );
1073
1074 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1075 if ( aMapMode == embed::EmbedMapUnits::TWIP )
1076 {
1077 // conversion from ONE_100TH_MM
1078 aNewSize.Width = aNewSize.Width * 144 / 254;
1079 aNewSize.Height = aNewSize.Height * 144 / 254;
1080 }
1081
1082
1083 xVisObj->setVisualAreaSize( DVASPECT_CONTENT, aNewSize );
1084
1085 return S_OK;
1086 }
1087 catch( const uno::Exception& )
1088 {}
1089 }
1090 }
1091
1092 return E_FAIL;
1093 }
1094
GetExtent(SIZEL * pSize)1095 HRESULT DocumentHolder::GetExtent( SIZEL *pSize )
1096 {
1097 if ( pSize )
1098 {
1099 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1100 if ( xVisObj.is() )
1101 {
1102 try
1103 {
1104 awt::Size aDocSize = xVisObj->getVisualAreaSize( DVASPECT_CONTENT );
1105
1106 sal_Int32 aMapMode = xVisObj->getMapUnit( DVASPECT_CONTENT );
1107
1108 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1109 if ( aMapMode == embed::EmbedMapUnits::TWIP )
1110 {
1111 // conversion to ONE_100TH_MM
1112 aDocSize.Width = aDocSize.Width * 254 / 144;
1113 aDocSize.Height = aDocSize.Height * 254 / 144;
1114 }
1115
1116 pSize->cx = aDocSize.Width;
1117 pSize->cy = aDocSize.Height;
1118
1119 return S_OK;
1120 }
1121 catch( const uno::Exception& )
1122 {}
1123 }
1124 }
1125
1126 return E_FAIL;
1127 }
1128
1129
SetContRects(LPCRECT aRect)1130 HRESULT DocumentHolder::SetContRects(LPCRECT aRect)
1131 {
1132 if(m_xContainerWindow.is()) {
1133 RECT wi = {};
1134 if(m_pIOleIPFrame) {
1135 m_pIOleIPFrame->GetBorder(&wi);
1136 m_xContainerWindow->setPosSize(
1137 0,0,
1138 wi.right - wi.left,
1139 wi.bottom - wi.top,
1140 awt::PosSize::POSSIZE);
1141 }
1142 else
1143 m_xContainerWindow->setPosSize(
1144 0,0,
1145 aRect->right - aRect->left,
1146 aRect->bottom - aRect->top,
1147 awt::PosSize::POSSIZE);
1148 return NOERROR;
1149 }
1150 else {
1151 return ERROR;
1152 }
1153 }
1154
1155
SetObjectRects(LPCRECT aRect,LPCRECT aClip)1156 HRESULT DocumentHolder::SetObjectRects(LPCRECT aRect, LPCRECT aClip)
1157 {
1158 auto rect = *aRect;
1159 rect.left -= m_aBorder.left;
1160 rect.right += m_aBorder.right;
1161 rect.top -= m_aBorder.top;
1162 rect.bottom += m_aBorder.bottom;
1163 auto clip = *aClip;
1164 clip.left -= m_aBorder.left;
1165 clip.right += m_aBorder.right;
1166 clip.top -= m_aBorder.top;
1167 clip.bottom += m_aBorder.bottom;
1168
1169 if(m_pCHatchWin)
1170 m_pCHatchWin->RectsSet(&rect, &clip);
1171 if(m_xEditWindow.is()) {
1172 m_xEditWindow->setVisible(false);
1173 m_xEditWindow->setPosSize(
1174 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
1175 m_pCHatchWin ? HATCHWIN_BORDERWIDTHDEFAULT : 0,
1176 rect.right - rect.left,
1177 rect.bottom - rect.top,
1178 awt::PosSize::POSSIZE);
1179 m_xEditWindow->setVisible(true);
1180 }
1181 return NOERROR;
1182 }
1183
1184
getContainerWindow()1185 css::uno::Reference< css::awt::XWindow> SAL_CALL DocumentHolder::getContainerWindow()
1186 {
1187 if(m_xContainerWindow.is())
1188 return m_xContainerWindow;
1189
1190 uno::Reference<awt::XWindow> xWin;
1191
1192 uno::Reference<awt::XToolkit2> xToolkit = awt::Toolkit::create( comphelper::getComponentContext(m_xFactory) );
1193
1194 if(m_pIOleIPFrame) {
1195 HWND hWnd;
1196 m_pIOleIPFrame->GetWindow(&hWnd);
1197
1198 uno::Sequence<sal_Int8> aProcessIdent(16);
1199 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
1200
1201 xWin.set(
1202 xToolkit->createSystemChild(
1203 uno::Any(reinterpret_cast<sal_Int64>(hWnd)),
1204 aProcessIdent,
1205 lang::SystemDependent::SYSTEM_WIN32),
1206 uno::UNO_QUERY);
1207
1208 RECT wi = {};
1209 if(xWin.is() && m_pIOleIPFrame->GetBorder(&wi) == NOERROR) {
1210 xWin->setVisible(true);
1211 xWin->setPosSize(
1212 0,0,
1213 wi.right-wi.left,
1214 wi.bottom - wi.top,
1215 awt::PosSize::POSSIZE);
1216
1217 uno::Reference<awt::XSystemDependentWindowPeer> xSysWin(
1218 xWin,uno::UNO_QUERY);
1219 if(xSysWin.is()) {
1220 uno::Any aAny = xSysWin->getWindowHandle(
1221 aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
1222 sal_Int64 tmp;
1223 if( aAny >>= tmp )
1224 SetContainerWindowHandle(reinterpret_cast<HWND>(tmp));
1225 }
1226 }
1227 }
1228
1229 m_xContainerWindow= xWin;
1230 return xWin;
1231 }
1232
1233
requestDockingAreaSpace(const css::awt::Rectangle & RequestedSpace)1234 sal_Bool SAL_CALL DocumentHolder::requestDockingAreaSpace( const css::awt::Rectangle& RequestedSpace )
1235 {
1236 if(m_bOnDeactivate)
1237 return true;
1238
1239 BORDERWIDTHS bw;
1240 SetRect(&bw,
1241 RequestedSpace.X,RequestedSpace.Y,
1242 RequestedSpace.Width,RequestedSpace.Height);
1243 if( m_pIOleIPFrame )
1244 return m_pIOleIPFrame->RequestBorderSpace(&bw) == NOERROR ;
1245 else
1246 return false;
1247 }
1248
1249
setDockingAreaSpace(const css::awt::Rectangle & BorderSpace)1250 void SAL_CALL DocumentHolder::setDockingAreaSpace( const css::awt::Rectangle& BorderSpace )
1251 {
1252 if(m_bOnDeactivate)
1253 return;
1254
1255 BORDERWIDTHS bw;
1256 SetRect(&bw,
1257 BorderSpace.X,BorderSpace.Y,
1258 BorderSpace.Width,BorderSpace.Height);
1259 if( m_pIOleIPFrame ) {
1260 RECT aRect;
1261 GetClientRect(m_hWndxWinCont,&aRect);
1262 HRGN hrgn1 = CreateRectRgn(
1263 0,0,
1264 aRect.right,BorderSpace.Y);
1265 HRGN hrgn2 = CreateRectRgn(aRect.right-BorderSpace.Width,0,aRect.right,aRect.bottom);
1266 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1267 DeleteObject(hrgn2);
1268 hrgn2 = CreateRectRgn(0,aRect.bottom-BorderSpace.Height,aRect.right,aRect.bottom);
1269 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1270 DeleteObject(hrgn2);
1271 hrgn2 = CreateRectRgn(0,0,BorderSpace.X,aRect.bottom);
1272 CombineRgn(hrgn1,hrgn1,hrgn2,RGN_OR);
1273 DeleteObject(hrgn2);
1274
1275 SetWindowRgn(m_hWndxWinCont,hrgn1,true);
1276 // not:: DeleteObject(hrgn1);
1277 m_pIOleIPFrame->SetBorderSpace(&bw);
1278 }
1279 }
1280
1281
disposing(const css::lang::EventObject & aSource)1282 void SAL_CALL DocumentHolder::disposing( const css::lang::EventObject& aSource )
1283 {
1284 if ( m_xDocument.is() && m_xDocument == aSource.Source )
1285 {
1286 m_pIDispatch = nullptr;
1287 m_xDocument.clear();
1288 }
1289
1290 if( m_xFrame.is() && m_xFrame == aSource.Source )
1291 m_xFrame.clear();
1292 }
1293
1294
1295 void SAL_CALL
queryClosing(const lang::EventObject & aSource,sal_Bool)1296 DocumentHolder::queryClosing(
1297 const lang::EventObject& aSource,
1298 sal_Bool /*bGetsOwnership*/
1299 )
1300 {
1301 if (!m_bLink
1302 && ((m_xDocument.is() && m_xDocument == aSource.Source)
1303 || (m_xFrame.is() && m_xFrame == aSource.Source)))
1304 throw util::CloseVetoException();
1305 }
1306
1307
1308 void SAL_CALL
notifyClosing(const lang::EventObject & aSource)1309 DocumentHolder::notifyClosing(
1310 const lang::EventObject& aSource )
1311 {
1312 try
1313 {
1314 uno::Reference< util::XCloseBroadcaster > xEventBroadcaster(
1315 aSource.Source, uno::UNO_QUERY_THROW );
1316 xEventBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
1317 }
1318 catch( const uno::Exception& )
1319 {}
1320
1321 if ( m_xDocument.is() && m_xDocument == aSource.Source )
1322 {
1323 // can happen only in case of links
1324 m_pIDispatch = nullptr;
1325 m_xDocument.clear();
1326 m_xFrame.clear();
1327
1328 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
1329 if ( aDocLock.GetEmbedDocument() )
1330 aDocLock.GetEmbedDocument()->OLENotifyClosing();
1331 }
1332 else if( m_xFrame.is() && m_xFrame == aSource.Source )
1333 m_xFrame.clear();
1334 }
1335
1336 void SAL_CALL
queryTermination(const lang::EventObject &)1337 DocumentHolder::queryTermination(
1338 const lang::EventObject& /*aSource*/
1339 )
1340 {
1341 if ( m_xDocument.is() )
1342 throw frame::TerminationVetoException();
1343 }
1344
1345 void SAL_CALL
notifyTermination(const lang::EventObject & aSource)1346 DocumentHolder::notifyTermination(
1347 const lang::EventObject& aSource
1348 )
1349 {
1350 OSL_ENSURE( !m_xDocument.is(), "Just a disaster..." );
1351 uno::Reference< frame::XDesktop > xDesktop(
1352 aSource.Source, uno::UNO_QUERY );
1353
1354 if ( xDesktop.is() )
1355 xDesktop->removeTerminateListener( static_cast<frame::XTerminateListener*>(this) );
1356 }
1357
1358
modified(const lang::EventObject &)1359 void SAL_CALL DocumentHolder::modified( const lang::EventObject& /*aEvent*/ )
1360 {
1361 if ( m_xOleAccess.is() )
1362 {
1363 LockedEmbedDocument_Impl aDocLock = m_xOleAccess->GetEmbedDocument();
1364 if ( aDocLock.GetEmbedDocument() )
1365 aDocLock.GetEmbedDocument()->notify();
1366 }
1367 }
1368
1369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1370