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