Line data Source code
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 "vbaeventshelper.hxx"
21 :
22 : #include <com/sun/star/awt/XTopWindow.hpp>
23 : #include <com/sun/star/awt/XTopWindowListener.hpp>
24 : #include <com/sun/star/awt/XWindowListener.hpp>
25 : #include <com/sun/star/frame/XBorderResizeListener.hpp>
26 : #include <com/sun/star/frame/XControllerBorder.hpp>
27 : #include <com/sun/star/script/ModuleType.hpp>
28 : #include <com/sun/star/script/vba/VBAEventId.hpp>
29 : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
30 : #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
31 : #include <com/sun/star/table/XCellRange.hpp>
32 : #include <com/sun/star/util/XChangesListener.hpp>
33 : #include <com/sun/star/util/XChangesNotifier.hpp>
34 :
35 : #include <cppuhelper/implbase4.hxx>
36 : #include <toolkit/helper/vclunohelper.hxx>
37 : #include <unotools/eventcfg.hxx>
38 : #include <vcl/svapp.hxx>
39 : #include <vcl/window.hxx>
40 :
41 : #include "cellsuno.hxx"
42 : #include "convuno.hxx"
43 : #include "vbaapplication.hxx"
44 :
45 : using namespace ::com::sun::star;
46 : using namespace ::com::sun::star::script::vba::VBAEventId;
47 : using namespace ::ooo::vba;
48 :
49 : namespace {
50 :
51 : /** Extracts a sheet index from the specified element of the passed sequence.
52 : The element may be an integer, a Calc range or ranges object, or a VBA Range object. */
53 2008 : SCTAB lclGetTabFromArgs( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException, uno::RuntimeException)
54 : {
55 2008 : VbaEventsHelperBase::checkArgument( rArgs, nIndex );
56 :
57 : // first try to extract a sheet index
58 2008 : sal_Int32 nTab = -1;
59 2008 : if( rArgs[ nIndex ] >>= nTab )
60 : {
61 754 : if( (nTab < 0) || (nTab > MAXTAB) )
62 0 : throw lang::IllegalArgumentException();
63 754 : return static_cast< SCTAB >( nTab );
64 : }
65 :
66 : // try VBA Range object
67 1254 : uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex );
68 1254 : if( xVbaRange.is() )
69 : {
70 1092 : uno::Reference< XHelperInterface > xVbaHelper( xVbaRange, uno::UNO_QUERY_THROW );
71 : // TODO: in the future, the parent may be an excel::XChart (chart sheet) -> will there be a common base interface?
72 2184 : uno::Reference< excel::XWorksheet > xVbaSheet( xVbaHelper->getParent(), uno::UNO_QUERY_THROW );
73 : // VBA sheet index is 1-based
74 2184 : return static_cast< SCTAB >( xVbaSheet->getIndex() - 1 );
75 : }
76 :
77 : // try single UNO range object
78 324 : uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable = getXSomethingFromArgs< sheet::XCellRangeAddressable >( rArgs, nIndex );
79 162 : if( xCellRangeAddressable.is() )
80 140 : return xCellRangeAddressable->getRangeAddress().Sheet;
81 :
82 : // at last, try UNO range list
83 44 : uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex );
84 22 : if( xRanges.is() )
85 : {
86 6 : uno::Sequence< table::CellRangeAddress > aRangeAddresses = xRanges->getRangeAddresses();
87 6 : if( aRangeAddresses.getLength() > 0 )
88 6 : return aRangeAddresses[ 0 ].Sheet;
89 : }
90 :
91 1270 : throw lang::IllegalArgumentException();
92 : }
93 :
94 : /** Returns the AWT container window of the passed controller. */
95 100 : uno::Reference< awt::XWindow > lclGetWindowForController( const uno::Reference< frame::XController >& rxController )
96 : {
97 100 : if( rxController.is() ) try
98 : {
99 100 : uno::Reference< frame::XFrame > xFrame( rxController->getFrame(), uno::UNO_SET_THROW );
100 100 : return xFrame->getContainerWindow();
101 : }
102 0 : catch( uno::Exception& )
103 : {
104 : }
105 0 : return 0;
106 : }
107 :
108 : } // namespace
109 :
110 : typedef ::cppu::WeakImplHelper4< awt::XTopWindowListener, awt::XWindowListener, frame::XBorderResizeListener, util::XChangesListener > ScVbaEventListener_BASE;
111 :
112 : // This class is to process Workbook window related event
113 : class ScVbaEventListener : public ScVbaEventListener_BASE
114 : {
115 : public :
116 : ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell );
117 : virtual ~ScVbaEventListener();
118 :
119 : /** Starts listening to the passed document controller. */
120 : void startControllerListening( const uno::Reference< frame::XController >& rxController );
121 : /** Stops listening to the passed document controller. */
122 : void stopControllerListening( const uno::Reference< frame::XController >& rxController );
123 :
124 : // XTopWindowListener
125 : virtual void SAL_CALL windowOpened( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
126 : virtual void SAL_CALL windowClosing( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
127 : virtual void SAL_CALL windowClosed( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
128 : virtual void SAL_CALL windowMinimized( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
129 : virtual void SAL_CALL windowNormalized( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
130 : virtual void SAL_CALL windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
131 : virtual void SAL_CALL windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
132 :
133 : // XWindowListener
134 : virtual void SAL_CALL windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
135 : virtual void SAL_CALL windowMoved( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
136 : virtual void SAL_CALL windowShown( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
137 : virtual void SAL_CALL windowHidden( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
138 :
139 : // XBorderResizeListener
140 : virtual void SAL_CALL borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& aNewSize ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
141 :
142 : // XChangesListener
143 : virtual void SAL_CALL changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
144 :
145 : // XEventListener
146 : virtual void SAL_CALL disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
147 :
148 : private:
149 : /** Starts listening to the document model. */
150 : void startModelListening();
151 : /** Stops listening to the document model. */
152 : void stopModelListening();
153 :
154 : /** Returns the controller for the passed VCL window. */
155 : uno::Reference< frame::XController > getControllerForWindow( vcl::Window* pWindow ) const;
156 :
157 : /** Calls the Workbook_Window[Activate|Deactivate] event handler. */
158 : void processWindowActivateEvent( vcl::Window* pWindow, bool bActivate );
159 : /** Posts a Workbook_WindowResize user event. */
160 : void postWindowResizeEvent( vcl::Window* pWindow );
161 : /** Callback link for Application::PostUserEvent(). */
162 : DECL_LINK( processWindowResizeEvent, vcl::Window* );
163 :
164 : private:
165 : typedef ::std::map< vcl::Window*, uno::Reference< frame::XController > > WindowControllerMap;
166 :
167 : ::osl::Mutex maMutex;
168 : ScVbaEventsHelper& mrVbaEvents;
169 : uno::Reference< frame::XModel > mxModel;
170 : ScDocShell* mpDocShell;
171 : WindowControllerMap maControllers; /// Maps VCL top windows to their controllers.
172 : vcl::Window* mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation.
173 : bool mbWindowResized; /// True = window resize system event processed.
174 : bool mbBorderChanged; /// True = borders changed system event processed.
175 : bool mbDisposed;
176 : };
177 :
178 50 : ScVbaEventListener::ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ) :
179 : mrVbaEvents( rVbaEvents ),
180 : mxModel( rxModel ),
181 : mpDocShell( pDocShell ),
182 : mpActiveWindow( 0 ),
183 : mbWindowResized( false ),
184 : mbBorderChanged( false ),
185 50 : mbDisposed( !rxModel.is() )
186 : {
187 50 : if( !mxModel.is() )
188 50 : return;
189 :
190 50 : startModelListening();
191 : try
192 : {
193 50 : uno::Reference< frame::XController > xController( mxModel->getCurrentController(), uno::UNO_QUERY_THROW );
194 50 : startControllerListening( xController );
195 : }
196 0 : catch( uno::Exception& )
197 : {
198 : }
199 : }
200 :
201 0 : ScVbaEventListener::~ScVbaEventListener()
202 : {
203 0 : }
204 :
205 50 : void ScVbaEventListener::startControllerListening( const uno::Reference< frame::XController >& rxController )
206 : {
207 50 : ::osl::MutexGuard aGuard( maMutex );
208 :
209 100 : uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController );
210 50 : if( xWindow.is() )
211 50 : try { xWindow->addWindowListener( this ); } catch( uno::Exception& ) {}
212 :
213 100 : uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY );
214 50 : if( xTopWindow.is() )
215 50 : try { xTopWindow->addTopWindowListener( this ); } catch( uno::Exception& ) {}
216 :
217 100 : uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY );
218 50 : if( xControllerBorder.is() )
219 50 : try { xControllerBorder->addBorderResizeListener( this ); } catch( uno::Exception& ) {}
220 :
221 50 : if( vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) )
222 100 : maControllers[ pWindow ] = rxController;
223 50 : }
224 :
225 50 : void ScVbaEventListener::stopControllerListening( const uno::Reference< frame::XController >& rxController )
226 : {
227 50 : ::osl::MutexGuard aGuard( maMutex );
228 :
229 100 : uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController );
230 50 : if( xWindow.is() )
231 50 : try { xWindow->removeWindowListener( this ); } catch( uno::Exception& ) {}
232 :
233 100 : uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY );
234 50 : if( xTopWindow.is() )
235 50 : try { xTopWindow->removeTopWindowListener( this ); } catch( uno::Exception& ) {}
236 :
237 100 : uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY );
238 50 : if( xControllerBorder.is() )
239 50 : try { xControllerBorder->removeBorderResizeListener( this ); } catch( uno::Exception& ) {}
240 :
241 50 : if( vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) )
242 : {
243 50 : maControllers.erase( pWindow );
244 50 : if( pWindow == mpActiveWindow )
245 10 : mpActiveWindow = 0;
246 50 : }
247 50 : }
248 :
249 8 : void SAL_CALL ScVbaEventListener::windowOpened( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
250 : {
251 8 : }
252 :
253 0 : void SAL_CALL ScVbaEventListener::windowClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
254 : {
255 0 : }
256 :
257 8 : void SAL_CALL ScVbaEventListener::windowClosed( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
258 : {
259 8 : }
260 :
261 0 : void SAL_CALL ScVbaEventListener::windowMinimized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
262 : {
263 0 : }
264 :
265 0 : void SAL_CALL ScVbaEventListener::windowNormalized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
266 : {
267 0 : }
268 :
269 112 : void SAL_CALL ScVbaEventListener::windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception)
270 : {
271 112 : ::osl::MutexGuard aGuard( maMutex );
272 :
273 112 : if( !mbDisposed )
274 : {
275 112 : uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY );
276 112 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
277 : OSL_TRACE( "ScVbaEventListener::windowActivated - pWindow = 0x%p, mpActiveWindow = 0x%p", pWindow, mpActiveWindow );
278 : // do not fire activation event multiple time for the same window
279 112 : if( pWindow && (pWindow != mpActiveWindow) )
280 : {
281 : // if another window is active, fire deactivation event first
282 112 : if( mpActiveWindow )
283 0 : processWindowActivateEvent( mpActiveWindow, false );
284 : // fire activation event for the new window
285 112 : processWindowActivateEvent( pWindow, true );
286 112 : mpActiveWindow = pWindow;
287 112 : }
288 112 : }
289 112 : }
290 :
291 112 : void SAL_CALL ScVbaEventListener::windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception)
292 : {
293 112 : ::osl::MutexGuard aGuard( maMutex );
294 :
295 112 : if( !mbDisposed )
296 : {
297 112 : uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY );
298 112 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
299 : OSL_TRACE( "ScVbaEventListener::windowDeactivated - pWindow = 0x%p, mpActiveWindow = 0x%p", pWindow, mpActiveWindow );
300 : // do not fire the deactivation event, if the window is not active (prevent multiple deactivation)
301 112 : if( pWindow && (pWindow == mpActiveWindow) )
302 102 : processWindowActivateEvent( pWindow, false );
303 : // forget pointer to the active window
304 112 : mpActiveWindow = 0;
305 112 : }
306 112 : }
307 :
308 58 : void SAL_CALL ScVbaEventListener::windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException, std::exception)
309 : {
310 58 : ::osl::MutexGuard aGuard( maMutex );
311 :
312 58 : mbWindowResized = true;
313 58 : if( !mbDisposed && mbBorderChanged )
314 : {
315 12 : uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY );
316 12 : postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) );
317 58 : }
318 58 : }
319 :
320 58 : void SAL_CALL ScVbaEventListener::windowMoved( const awt::WindowEvent& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
321 : {
322 58 : }
323 :
324 8 : void SAL_CALL ScVbaEventListener::windowShown( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
325 : {
326 8 : }
327 :
328 8 : void SAL_CALL ScVbaEventListener::windowHidden( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException, std::exception)
329 : {
330 8 : }
331 :
332 72 : void SAL_CALL ScVbaEventListener::borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& /*aNewSize*/ ) throw (uno::RuntimeException, std::exception)
333 : {
334 72 : ::osl::MutexGuard aGuard( maMutex );
335 :
336 72 : mbBorderChanged = true;
337 72 : if( !mbDisposed && mbWindowResized )
338 : {
339 0 : uno::Reference< frame::XController > xController( rSource, uno::UNO_QUERY );
340 0 : uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( xController );
341 0 : postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) );
342 72 : }
343 72 : }
344 :
345 0 : void SAL_CALL ScVbaEventListener::changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException, std::exception)
346 : {
347 0 : ::osl::MutexGuard aGuard( maMutex );
348 :
349 0 : sal_Int32 nCount = rEvent.Changes.getLength();
350 0 : if( mbDisposed || !mpDocShell || (nCount == 0) )
351 0 : return;
352 :
353 0 : util::ElementChange aChange = rEvent.Changes[ 0 ];
354 0 : OUString sOperation;
355 0 : aChange.Accessor >>= sOperation;
356 0 : if( !sOperation.equalsIgnoreAsciiCase("cell-change") )
357 0 : return;
358 :
359 0 : if( nCount == 1 )
360 : {
361 0 : uno::Reference< table::XCellRange > xRangeObj;
362 0 : aChange.ReplacedElement >>= xRangeObj;
363 0 : if( xRangeObj.is() )
364 : {
365 0 : uno::Sequence< uno::Any > aArgs( 1 );
366 0 : aArgs[0] <<= xRangeObj;
367 0 : mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs );
368 : }
369 0 : return;
370 : }
371 :
372 0 : ScRangeList aRangeList;
373 0 : for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
374 : {
375 0 : aChange = rEvent.Changes[ nIndex ];
376 0 : aChange.Accessor >>= sOperation;
377 0 : uno::Reference< table::XCellRange > xRangeObj;
378 0 : aChange.ReplacedElement >>= xRangeObj;
379 0 : if( xRangeObj.is() && sOperation.equalsIgnoreAsciiCase("cell-change") )
380 : {
381 0 : uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable( xRangeObj, uno::UNO_QUERY );
382 0 : if( xCellRangeAddressable.is() )
383 : {
384 0 : ScRange aRange;
385 0 : ScUnoConversion::FillScRange( aRange, xCellRangeAddressable->getRangeAddress() );
386 0 : aRangeList.Append( aRange );
387 0 : }
388 : }
389 0 : }
390 :
391 0 : if (!aRangeList.empty())
392 : {
393 0 : uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( mpDocShell, aRangeList ) );
394 0 : uno::Sequence< uno::Any > aArgs(1);
395 0 : aArgs[0] <<= xRanges;
396 0 : mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs );
397 0 : }
398 : }
399 :
400 50 : void SAL_CALL ScVbaEventListener::disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException, std::exception)
401 : {
402 50 : ::osl::MutexGuard aGuard( maMutex );
403 :
404 50 : uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY );
405 50 : if( xModel.is() )
406 : {
407 : OSL_ENSURE( xModel.get() == mxModel.get(), "ScVbaEventListener::disposing - disposing from unknown model" );
408 0 : stopModelListening();
409 0 : mbDisposed = true;
410 0 : return;
411 : }
412 :
413 50 : uno::Reference< frame::XController > xController( rEvent.Source, uno::UNO_QUERY );
414 50 : if( xController.is() )
415 : {
416 50 : stopControllerListening( xController );
417 50 : return;
418 0 : }
419 : }
420 :
421 : // private --------------------------------------------------------------------
422 :
423 50 : void ScVbaEventListener::startModelListening()
424 : {
425 : try
426 : {
427 50 : uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW );
428 50 : xChangesNotifier->addChangesListener( this );
429 : }
430 0 : catch( uno::Exception& )
431 : {
432 : }
433 50 : }
434 :
435 0 : void ScVbaEventListener::stopModelListening()
436 : {
437 : try
438 : {
439 0 : uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW );
440 0 : xChangesNotifier->removeChangesListener( this );
441 : }
442 0 : catch( uno::Exception& )
443 : {
444 : }
445 0 : }
446 :
447 222 : uno::Reference< frame::XController > ScVbaEventListener::getControllerForWindow( vcl::Window* pWindow ) const
448 : {
449 222 : WindowControllerMap::const_iterator aIt = maControllers.find( pWindow );
450 222 : return (aIt == maControllers.end()) ? uno::Reference< frame::XController >() : aIt->second;
451 : }
452 :
453 214 : void ScVbaEventListener::processWindowActivateEvent( vcl::Window* pWindow, bool bActivate )
454 : {
455 214 : uno::Reference< frame::XController > xController = getControllerForWindow( pWindow );
456 214 : if( xController.is() )
457 : {
458 214 : uno::Sequence< uno::Any > aArgs( 1 );
459 214 : aArgs[ 0 ] <<= xController;
460 214 : mrVbaEvents.processVbaEventNoThrow( bActivate ? WORKBOOK_WINDOWACTIVATE : WORKBOOK_WINDOWDEACTIVATE, aArgs );
461 214 : }
462 214 : }
463 :
464 12 : void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow )
465 : {
466 : // check that the passed window is still alive (it must be registered in maControllers)
467 12 : if( pWindow && (maControllers.count( pWindow ) > 0) )
468 : {
469 12 : mbWindowResized = mbBorderChanged = false;
470 12 : acquire(); // ensure we don't get deleted before the timer fires
471 12 : Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow );
472 : }
473 12 : }
474 :
475 24 : IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, EMPTYARG pWindow )
476 : {
477 12 : ::osl::MutexGuard aGuard( maMutex );
478 :
479 : /* Check that the passed window is still alive (it must be registered in
480 : maControllers). While closing a document, postWindowResizeEvent() may
481 : be called on the last window which posts a user event via
482 : Application::PostUserEvent to call this event handler. VCL will trigger
483 : the handler some time later. Sometimes, the window gets deleted before.
484 : This is handled via the disposing() function which removes the window
485 : pointer from the member maControllers. Thus, checking whether
486 : maControllers contains pWindow ensures that the window is still alive. */
487 12 : if( !mbDisposed && pWindow && (maControllers.count( pWindow ) > 0) )
488 : {
489 : // do not fire event unless all mouse buttons have been released
490 8 : vcl::Window::PointerState aPointerState = pWindow->GetPointerState();
491 8 : if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 )
492 : {
493 8 : uno::Reference< frame::XController > xController = getControllerForWindow( pWindow );
494 8 : if( xController.is() )
495 : {
496 8 : uno::Sequence< uno::Any > aArgs( 1 );
497 8 : aArgs[ 0 ] <<= xController;
498 : // #163419# do not throw exceptions into application core
499 8 : mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs );
500 8 : }
501 : }
502 : }
503 12 : release();
504 12 : return 0;
505 : }
506 :
507 52 : ScVbaEventsHelper::ScVbaEventsHelper( const uno::Sequence< uno::Any >& rArgs, const uno::Reference< uno::XComponentContext >& xContext ) :
508 : VbaEventsHelperBase( rArgs, xContext ),
509 52 : mbOpened( false )
510 : {
511 52 : mpDocShell = dynamic_cast< ScDocShell* >( mpShell ); // mpShell from base class
512 52 : mpDoc = mpDocShell ? &mpDocShell->GetDocument() : 0;
513 :
514 52 : if( !mxModel.is() || !mpDocShell || !mpDoc )
515 52 : return;
516 :
517 : #define REGISTER_EVENT( eventid, moduletype, classname, eventname, cancelindex, worksheet ) \
518 : registerEventHandler( eventid, moduletype, classname "_" eventname, cancelindex, uno::Any( worksheet ) )
519 : #define REGISTER_AUTO_EVENT( eventid, eventname ) \
520 : REGISTER_EVENT( AUTO_##eventid, script::ModuleType::NORMAL, "Auto", eventname, -1, false )
521 : #define REGISTER_WORKBOOK_EVENT( eventid, eventname, cancelindex ) \
522 : REGISTER_EVENT( WORKBOOK_##eventid, script::ModuleType::DOCUMENT, "Workbook", eventname, cancelindex, false )
523 : #define REGISTER_WORKSHEET_EVENT( eventid, eventname, cancelindex ) \
524 : REGISTER_EVENT( WORKSHEET_##eventid, script::ModuleType::DOCUMENT, "Worksheet", eventname, cancelindex, true ); \
525 : REGISTER_EVENT( (USERDEFINED_START + WORKSHEET_##eventid), script::ModuleType::DOCUMENT, "Workbook", "Sheet" eventname, (((cancelindex) >= 0) ? ((cancelindex) + 1) : -1), false )
526 :
527 : // global
528 52 : REGISTER_AUTO_EVENT( OPEN, "Open" );
529 52 : REGISTER_AUTO_EVENT( CLOSE, "Close" );
530 :
531 : // Workbook
532 52 : REGISTER_WORKBOOK_EVENT( ACTIVATE, "Activate", -1 );
533 52 : REGISTER_WORKBOOK_EVENT( DEACTIVATE, "Deactivate", -1 );
534 52 : REGISTER_WORKBOOK_EVENT( OPEN, "Open", -1 );
535 52 : REGISTER_WORKBOOK_EVENT( BEFORECLOSE, "BeforeClose", 0 );
536 52 : REGISTER_WORKBOOK_EVENT( BEFOREPRINT, "BeforePrint", 0 );
537 52 : REGISTER_WORKBOOK_EVENT( BEFORESAVE, "BeforeSave", 1 );
538 52 : REGISTER_WORKBOOK_EVENT( AFTERSAVE, "AfterSave", -1 );
539 52 : REGISTER_WORKBOOK_EVENT( NEWSHEET, "NewSheet", -1 );
540 52 : REGISTER_WORKBOOK_EVENT( WINDOWACTIVATE, "WindowActivate", -1 );
541 52 : REGISTER_WORKBOOK_EVENT( WINDOWDEACTIVATE, "WindowDeactivate", -1 );
542 52 : REGISTER_WORKBOOK_EVENT( WINDOWRESIZE, "WindowResize", -1 );
543 :
544 : // Worksheet events. All events have a corresponding workbook event.
545 52 : REGISTER_WORKSHEET_EVENT( ACTIVATE, "Activate", -1 );
546 52 : REGISTER_WORKSHEET_EVENT( DEACTIVATE, "Deactivate", -1 );
547 52 : REGISTER_WORKSHEET_EVENT( BEFOREDOUBLECLICK, "BeforeDoubleClick", 1 );
548 52 : REGISTER_WORKSHEET_EVENT( BEFORERIGHTCLICK, "BeforeRightClick", 1 );
549 52 : REGISTER_WORKSHEET_EVENT( CALCULATE, "Calculate", -1 );
550 52 : REGISTER_WORKSHEET_EVENT( CHANGE, "Change", -1 );
551 52 : REGISTER_WORKSHEET_EVENT( SELECTIONCHANGE, "SelectionChange", -1 );
552 52 : REGISTER_WORKSHEET_EVENT( FOLLOWHYPERLINK, "FollowHyperlink", -1 );
553 :
554 : #undef REGISTER_WORKSHEET_EVENT
555 : #undef REGISTER_WORKBOOK_EVENT
556 : #undef REGISTER_AUTO_EVENT
557 : #undef REGISTER_EVENT
558 : }
559 :
560 0 : ScVbaEventsHelper::~ScVbaEventsHelper()
561 : {
562 0 : }
563 :
564 510 : void SAL_CALL ScVbaEventsHelper::notifyEvent( const css::document::EventObject& rEvent ) throw (css::uno::RuntimeException, std::exception)
565 : {
566 510 : static const uno::Sequence< uno::Any > saEmptyArgs;
567 1944 : if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_OPENDOC )) ||
568 1434 : (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CREATEDOC )) ) // CREATEDOC triggered e.g. during VBA Workbooks.Add
569 : {
570 50 : processVbaEventNoThrow( WORKBOOK_OPEN, saEmptyArgs );
571 : }
572 460 : else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_ACTIVATEDOC ) )
573 : {
574 48 : processVbaEventNoThrow( WORKBOOK_ACTIVATE, saEmptyArgs );
575 : }
576 412 : else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_DEACTIVATEDOC ) )
577 : {
578 2 : processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs );
579 : }
580 2460 : else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCDONE )) ||
581 2866 : (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCDONE )) ||
582 1226 : (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCDONE )) )
583 : {
584 2 : uno::Sequence< uno::Any > aArgs( 1 );
585 2 : aArgs[ 0 ] <<= true;
586 2 : processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs );
587 : }
588 2448 : else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCFAILED )) ||
589 2856 : (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCFAILED )) ||
590 1224 : (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCFAILED )) )
591 : {
592 0 : uno::Sequence< uno::Any > aArgs( 1 );
593 0 : aArgs[ 0 ] <<= false;
594 0 : processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs );
595 : }
596 408 : else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ) )
597 : {
598 : /* Trigger the WORKBOOK_WINDOWDEACTIVATE and WORKBOOK_DEACTIVATE
599 : events and stop listening to the model (done in base class). */
600 52 : uno::Reference< frame::XController > xController( mxModel->getCurrentController() );
601 52 : if( xController.is() )
602 : {
603 52 : uno::Sequence< uno::Any > aArgs( 1 );
604 52 : aArgs[ 0 ] <<= xController;
605 52 : processVbaEventNoThrow( WORKBOOK_WINDOWDEACTIVATE, aArgs );
606 : }
607 52 : processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs );
608 : }
609 356 : else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_VIEWCREATED ) )
610 : {
611 48 : uno::Reference< frame::XController > xController( mxModel->getCurrentController() );
612 48 : if( mxListener.get() && xController.is() )
613 0 : mxListener->startControllerListening( xController );
614 : }
615 510 : VbaEventsHelperBase::notifyEvent( rEvent );
616 510 : }
617 :
618 : // protected ------------------------------------------------------------------
619 :
620 3864 : bool ScVbaEventsHelper::implPrepareEvent( EventQueue& rEventQueue,
621 : const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) throw (uno::RuntimeException)
622 : {
623 : // document and document shell are needed during event processing
624 3864 : if( !mpShell || !mpDoc )
625 0 : throw uno::RuntimeException();
626 :
627 : /* For document events: check if events are enabled via the
628 : Application.EnableEvents symbol (this is an Excel-only attribute).
629 : Check this again for every event, as the event handler may change the
630 : state of the EnableEvents symbol. Global events such as AUTO_OPEN and
631 : AUTO_CLOSE are always enabled. */
632 3864 : bool bExecuteEvent = (rInfo.mnModuleType != script::ModuleType::DOCUMENT) || ScVbaApplication::getDocumentEventsEnabled();
633 :
634 : // framework and Calc fire a few events before 'OnLoad', ignore them
635 3864 : if( bExecuteEvent )
636 3864 : bExecuteEvent = (rInfo.mnEventId == WORKBOOK_OPEN) ? !mbOpened : mbOpened;
637 :
638 : // special handling for some events
639 3864 : if( bExecuteEvent ) switch( rInfo.mnEventId )
640 : {
641 : case WORKBOOK_OPEN:
642 : {
643 : // execute delayed Activate event too (see above)
644 50 : rEventQueue.push_back( WORKBOOK_ACTIVATE );
645 50 : uno::Sequence< uno::Any > aArgs( 1 );
646 50 : aArgs[ 0 ] <<= mxModel->getCurrentController();
647 50 : rEventQueue.push_back( EventQueueEntry( WORKBOOK_WINDOWACTIVATE, aArgs ) );
648 50 : rEventQueue.push_back( AUTO_OPEN );
649 : // remember initial selection
650 50 : maOldSelection <<= mxModel->getCurrentSelection();
651 : }
652 50 : break;
653 : case WORKSHEET_SELECTIONCHANGE:
654 : // if selection is not changed, then do not fire the event
655 620 : bExecuteEvent = isSelectionChanged( rArgs, 0 );
656 620 : break;
657 : }
658 :
659 3864 : if( bExecuteEvent )
660 : {
661 : // add workbook event associated to a sheet event
662 3054 : bool bSheetEvent = false;
663 3054 : if( (rInfo.maUserData >>= bSheetEvent) && bSheetEvent )
664 1270 : rEventQueue.push_back( EventQueueEntry( rInfo.mnEventId + USERDEFINED_START, rArgs ) );
665 : }
666 :
667 3864 : return bExecuteEvent;
668 : }
669 :
670 68 : uno::Sequence< uno::Any > ScVbaEventsHelper::implBuildArgumentList( const EventHandlerInfo& rInfo,
671 : const uno::Sequence< uno::Any >& rArgs ) throw (lang::IllegalArgumentException, uno::RuntimeException)
672 : {
673 : // fill arguments for workbook events associated to sheet events according to sheet events, sheet will be added below
674 68 : bool bSheetEventAsBookEvent = rInfo.mnEventId > USERDEFINED_START;
675 68 : sal_Int32 nEventId = bSheetEventAsBookEvent ? (rInfo.mnEventId - USERDEFINED_START) : rInfo.mnEventId;
676 :
677 68 : uno::Sequence< uno::Any > aVbaArgs;
678 68 : switch( nEventId )
679 : {
680 : // *** Workbook ***
681 :
682 : // no arguments
683 : case WORKBOOK_ACTIVATE:
684 : case WORKBOOK_DEACTIVATE:
685 : case WORKBOOK_OPEN:
686 0 : break;
687 : // 1 arg: cancel
688 : case WORKBOOK_BEFORECLOSE:
689 : case WORKBOOK_BEFOREPRINT:
690 0 : aVbaArgs.realloc( 1 );
691 : // current cancel state will be inserted by caller
692 0 : break;
693 : // 2 args: saveAs, cancel
694 : case WORKBOOK_BEFORESAVE:
695 0 : aVbaArgs.realloc( 2 );
696 0 : checkArgumentType< bool >( rArgs, 0 );
697 0 : aVbaArgs[ 0 ] = rArgs[ 0 ];
698 : // current cancel state will be inserted by caller
699 0 : break;
700 : // 1 arg: success
701 : case WORKBOOK_AFTERSAVE:
702 0 : aVbaArgs.realloc( 1 );
703 0 : checkArgumentType< bool >( rArgs, 0 );
704 0 : aVbaArgs[ 0 ] = rArgs[ 0 ];
705 0 : break;
706 : // 1 arg: window
707 : case WORKBOOK_WINDOWACTIVATE:
708 : case WORKBOOK_WINDOWDEACTIVATE:
709 : case WORKBOOK_WINDOWRESIZE:
710 0 : aVbaArgs.realloc( 1 );
711 0 : aVbaArgs[ 0 ] = createWindow( rArgs, 0 );
712 0 : break;
713 : // 1 arg: worksheet
714 : case WORKBOOK_NEWSHEET:
715 0 : aVbaArgs.realloc( 1 );
716 0 : aVbaArgs[ 0 ] = createWorksheet( rArgs, 0 );
717 0 : break;
718 :
719 : // *** Worksheet ***
720 :
721 : // no arguments
722 : case WORKSHEET_ACTIVATE:
723 : case WORKSHEET_CALCULATE:
724 : case WORKSHEET_DEACTIVATE:
725 0 : break;
726 : // 1 arg: range
727 : case WORKSHEET_CHANGE:
728 : case WORKSHEET_SELECTIONCHANGE:
729 68 : aVbaArgs.realloc( 1 );
730 68 : aVbaArgs[ 0 ] = createRange( rArgs, 0 );
731 68 : break;
732 : // 2 args: range, cancel
733 : case WORKSHEET_BEFOREDOUBLECLICK:
734 : case WORKSHEET_BEFORERIGHTCLICK:
735 0 : aVbaArgs.realloc( 2 );
736 0 : aVbaArgs[ 0 ] = createRange( rArgs, 0 );
737 : // current cancel state will be inserted by caller
738 0 : break;
739 : // 1 arg: hyperlink
740 : case WORKSHEET_FOLLOWHYPERLINK:
741 0 : aVbaArgs.realloc( 1 );
742 0 : aVbaArgs[ 0 ] = createHyperlink( rArgs, 0 );
743 0 : break;
744 : }
745 :
746 : /* For workbook events associated to sheet events, the workbook event gets
747 : the same arguments but with a Worksheet object in front of them. */
748 68 : if( bSheetEventAsBookEvent )
749 : {
750 0 : sal_Int32 nLength = aVbaArgs.getLength();
751 0 : uno::Sequence< uno::Any > aVbaArgs2( nLength + 1 );
752 0 : aVbaArgs2[ 0 ] = createWorksheet( rArgs, 0 );
753 0 : for( sal_Int32 nIndex = 0; nIndex < nLength; ++nIndex )
754 0 : aVbaArgs2[ nIndex + 1 ] = aVbaArgs[ nIndex ];
755 0 : aVbaArgs = aVbaArgs2;
756 : }
757 :
758 68 : return aVbaArgs;
759 : }
760 :
761 3848 : void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue,
762 : const EventHandlerInfo& rInfo, bool bCancel ) throw (uno::RuntimeException)
763 : {
764 3848 : switch( rInfo.mnEventId )
765 : {
766 : case WORKBOOK_OPEN:
767 52 : mbOpened = true;
768 : // register the listeners
769 52 : if( !mxListener.is() )
770 50 : mxListener = new ScVbaEventListener( *this, mxModel, mpDocShell );
771 52 : break;
772 : case WORKBOOK_BEFORECLOSE:
773 : /* Execute Auto_Close only if not cancelled by event handler, but
774 : before UI asks user whether to cancel closing the document. */
775 2 : if( !bCancel )
776 2 : rEventQueue.push_back( AUTO_CLOSE );
777 2 : break;
778 : }
779 3848 : }
780 :
781 4390 : OUString ScVbaEventsHelper::implGetDocumentModuleName( const EventHandlerInfo& rInfo,
782 : const uno::Sequence< uno::Any >& rArgs ) const
783 : throw (lang::IllegalArgumentException, uno::RuntimeException)
784 : {
785 4390 : bool bSheetEvent = false;
786 4390 : rInfo.maUserData >>= bSheetEvent;
787 4390 : SCTAB nTab = bSheetEvent ? lclGetTabFromArgs( rArgs, 0 ) : -1;
788 4374 : if( bSheetEvent && (nTab < 0) )
789 0 : throw lang::IllegalArgumentException();
790 :
791 4374 : OUString aCodeName;
792 4374 : if( bSheetEvent )
793 1992 : mpDoc->GetCodeName( nTab, aCodeName );
794 : else
795 2382 : aCodeName = mpDoc->GetCodeName();
796 4374 : return aCodeName;
797 : }
798 :
799 : // private --------------------------------------------------------------------
800 :
801 : namespace {
802 :
803 : /** Compares the passed range lists representing sheet selections. Ignores
804 : selections that refer to different sheets (returns false in this case). */
805 600 : bool lclSelectionChanged( const ScRangeList& rLeft, const ScRangeList& rRight )
806 : {
807 : // one of the range lists empty? -> return false, if both lists empty
808 600 : bool bLeftEmpty = rLeft.empty();
809 600 : bool bRightEmpty = rRight.empty();
810 600 : if( bLeftEmpty || bRightEmpty )
811 0 : return !(bLeftEmpty && bRightEmpty);
812 :
813 : // check sheet indexes of the range lists (assuming that all ranges in a list are on the same sheet)
814 600 : if (rLeft[0]->aStart.Tab() != rRight[0]->aStart.Tab())
815 8 : return false;
816 :
817 : // compare all ranges
818 592 : return rLeft != rRight;
819 : }
820 :
821 : } // namespace
822 :
823 620 : bool ScVbaEventsHelper::isSelectionChanged( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException, uno::RuntimeException)
824 : {
825 620 : uno::Reference< uno::XInterface > xOldSelection( maOldSelection, uno::UNO_QUERY );
826 1240 : uno::Reference< uno::XInterface > xNewSelection = getXSomethingFromArgs< uno::XInterface >( rArgs, nIndex, false );
827 620 : ScCellRangesBase* pOldCellRanges = ScCellRangesBase::getImplementation( xOldSelection );
828 620 : ScCellRangesBase* pNewCellRanges = ScCellRangesBase::getImplementation( xNewSelection );
829 620 : bool bChanged = !pOldCellRanges || !pNewCellRanges || lclSelectionChanged( pOldCellRanges->GetRangeList(), pNewCellRanges->GetRangeList() );
830 620 : maOldSelection <<= xNewSelection;
831 1240 : return bChanged;
832 : }
833 :
834 0 : uno::Any ScVbaEventsHelper::createWorksheet( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const
835 : throw (lang::IllegalArgumentException, uno::RuntimeException)
836 : {
837 : // extract sheet index, will throw, if parameter is invalid
838 0 : SCTAB nTab = lclGetTabFromArgs( rArgs, nIndex );
839 0 : return uno::Any( excel::getUnoSheetModuleObj( mxModel, nTab ) );
840 : }
841 :
842 68 : uno::Any ScVbaEventsHelper::createRange( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const
843 : throw (lang::IllegalArgumentException, uno::RuntimeException)
844 : {
845 : // it is possible to pass an existing VBA Range object
846 68 : uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex );
847 68 : if( !xVbaRange.is() )
848 : {
849 36 : uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex );
850 72 : uno::Reference< table::XCellRange > xRange = getXSomethingFromArgs< table::XCellRange >( rArgs, nIndex );
851 36 : if ( !xRanges.is() && !xRange.is() )
852 0 : throw lang::IllegalArgumentException();
853 :
854 72 : uno::Sequence< uno::Any > aArgs( 2 );
855 36 : if ( xRanges.is() )
856 : {
857 4 : aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xRanges );
858 4 : aArgs[ 1 ] <<= xRanges;
859 : }
860 : else
861 : {
862 32 : aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xRange );
863 32 : aArgs[ 1 ] <<= xRange;
864 : }
865 72 : xVbaRange.set( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Range", aArgs ), uno::UNO_QUERY_THROW );
866 : }
867 68 : return uno::Any( xVbaRange );
868 : }
869 :
870 0 : uno::Any ScVbaEventsHelper::createHyperlink( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const
871 : throw (lang::IllegalArgumentException, uno::RuntimeException)
872 : {
873 0 : uno::Reference< table::XCell > xCell = getXSomethingFromArgs< table::XCell >( rArgs, nIndex, false );
874 0 : uno::Sequence< uno::Any > aArgs( 2 );
875 0 : aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xCell );
876 0 : aArgs[ 1 ] <<= xCell;
877 0 : uno::Reference< uno::XInterface > xHyperlink( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Hyperlink", aArgs ), uno::UNO_SET_THROW );
878 0 : return uno::Any( xHyperlink );
879 : }
880 :
881 0 : uno::Any ScVbaEventsHelper::createWindow( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const
882 : throw (lang::IllegalArgumentException, uno::RuntimeException)
883 : {
884 0 : uno::Sequence< uno::Any > aArgs( 3 );
885 0 : aArgs[ 0 ] <<= getVBADocument( mxModel );
886 0 : aArgs[ 1 ] <<= mxModel;
887 0 : aArgs[ 2 ] <<= getXSomethingFromArgs< frame::XController >( rArgs, nIndex, false );
888 0 : uno::Reference< uno::XInterface > xWindow( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Window", aArgs ), uno::UNO_SET_THROW );
889 0 : return uno::Any( xWindow );
890 : }
891 :
892 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
893 52 : ScVbaEventsHelper_get_implementation(
894 : css::uno::XComponentContext *context,
895 : css::uno::Sequence<css::uno::Any> const &arguments)
896 : {
897 52 : return cppu::acquire(new ScVbaEventsHelper(arguments, context));
898 12 : }
899 :
900 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|