LCOV - code coverage report
Current view: top level - sc/source/ui/vba - vbaeventshelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 167 406 41.1 %
Date: 2012-08-25 Functions: 16 44 36.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 261 1009 25.9 %

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

Generated by: LCOV version 1.10