/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#include "eventhandler.hxx"
#include "propctrlr.hrc"
#include "formbrowsertools.hxx"
#include "formresid.hrc"
#include "formstrings.hxx"
#include "handlerhelper.hxx"
#include "modulepcr.hxx"
#include "pcrcommon.hxx"
#include "pcrstrings.hxx"
#include "propertycontrolextender.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/awt/XTabControllerModel.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/beans/XIntrospectionAccess.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/form/FormComponentType.hpp>
#include <com/sun/star/form/XForm.hpp>
#include <com/sun/star/form/runtime/XFormController.hpp>
#include <com/sun/star/inspection/PropertyControlType.hpp>
#include <com/sun/star/lang/NullPointerException.hpp>
#include <com/sun/star/script/XEventAttacherManager.hpp>
#include <com/sun/star/script/XScriptEventsSupplier.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
/** === end UNO includes === **/

#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/evtmethodhelper.hxx>
#include <comphelper/types.hxx>
#include <cppuhelper/implbase1.hxx>
#include <rtl/ref.hxx>
#include <rtl/ustrbuf.hxx>
#include <sfx2/app.hxx>
#include <svl/eitem.hxx>
#include <svl/itemset.hxx>
#include <svx/svxdlg.hxx>
#include <svx/svxids.hrc>
#include <tools/diagnose_ex.h>
#include <vcl/msgbox.hxx>

#include <map>
#include <algorithm>

//------------------------------------------------------------------------
extern "C" void SAL_CALL createRegistryInfo_EventHandler()
{
	::pcr::OAutoRegistration< ::pcr::EventHandler > aAutoRegistration;
}

//........................................................................
namespace pcr
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::XComponentContext;
    using ::com::sun::star::beans::XPropertySet;
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::TypeClass_STRING;
    using ::com::sun::star::uno::Type;
    using ::com::sun::star::beans::XPropertyChangeListener;
    using ::com::sun::star::beans::Property;
    using ::com::sun::star::beans::PropertyState;
    using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::script::ScriptEventDescriptor;
    using ::com::sun::star::script::XScriptEventsSupplier;
    using ::com::sun::star::lang::NullPointerException;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::container::XChild;
    using ::com::sun::star::container::XIndexAccess;
    using ::com::sun::star::script::XEventAttacherManager;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::beans::XIntrospection;
    using ::com::sun::star::beans::XIntrospectionAccess;
    using ::com::sun::star::container::XNameContainer;
    using ::com::sun::star::awt::XTabControllerModel;
    using ::com::sun::star::form::XForm;
    using ::com::sun::star::form::runtime::XFormController;
    using ::com::sun::star::beans::UnknownPropertyException;
    using ::com::sun::star::uno::makeAny;
    using ::com::sun::star::container::NoSuchElementException;
    using ::com::sun::star::beans::XPropertySetInfo;
    using ::com::sun::star::container::XNameReplace;
    using ::com::sun::star::lang::IllegalArgumentException;
    using ::com::sun::star::lang::WrappedTargetException;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::inspection::LineDescriptor;
    using ::com::sun::star::inspection::XPropertyControlFactory;
    using ::com::sun::star::inspection::InteractiveSelectionResult;
    using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled;
    using ::com::sun::star::inspection::InteractiveSelectionResult_Success;
    using ::com::sun::star::inspection::XObjectInspectorUI;
    using ::com::sun::star::util::XModifiable;
    using ::com::sun::star::beans::PropertyChangeEvent;
    using ::com::sun::star::frame::XFrame;
    using ::com::sun::star::frame::XModel;
    using ::com::sun::star::frame::XController;
    using ::com::sun::star::uno::UNO_SET_THROW;
    using com::sun::star::uri::UriReferenceFactory;
    using com::sun::star::uri::XUriReferenceFactory;
    using com::sun::star::uri::XVndSunStarScriptUrlReference;
    using ::com::sun::star::lang::XEventListener;
    /** === end UNO using === **/
    namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType;
    namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
    namespace FormComponentType = ::com::sun::star::form::FormComponentType;

    //====================================================================
    //= EventDescription
    //====================================================================
    EventDescription::EventDescription( EventId _nId, const sal_Char* _pListenerNamespaceAscii, const sal_Char* _pListenerClassAsciiName,
            const sal_Char* _pListenerMethodAsciiName, sal_uInt16 _nDisplayNameResId, const rtl::OString& _sHelpId, const rtl::OString& _sUniqueBrowseId )
        :sDisplayName( String( PcrRes( _nDisplayNameResId ) ) )
        ,sListenerMethodName( ::rtl::OUString::createFromAscii( _pListenerMethodAsciiName ) )
        ,sHelpId( _sHelpId )
        ,sUniqueBrowseId( _sUniqueBrowseId )
        ,nId( _nId )
    {
        ::rtl::OUStringBuffer aQualifiedListenerClass;
        aQualifiedListenerClass.appendAscii( "com.sun.star." );
        aQualifiedListenerClass.appendAscii( _pListenerNamespaceAscii );
        aQualifiedListenerClass.appendAscii( "." );
        aQualifiedListenerClass.appendAscii( _pListenerClassAsciiName );
        sListenerClassName = aQualifiedListenerClass.makeStringAndClear();
    }

    //========================================================================
    //= helper
    //========================================================================
    namespace
    {
        //....................................................................
        #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \
            s_aKnownEvents.insert( EventMap::value_type( \
                ::rtl::OUString::createFromAscii( asciimethod ), \
                EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) )

        //....................................................................
        bool lcl_getEventDescriptionForMethod( const ::rtl::OUString& _rMethodName, EventDescription& _out_rDescription )
        {
            static EventMap s_aKnownEvents;
            if ( s_aKnownEvents.empty() )
            {
                ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
                if ( s_aKnownEvents.empty() )
                {
                    static sal_Int32 nEventId = 0;

                    DESCRIBE_EVENT( "form", "XApproveActionListener",       "approveAction",            APPROVEACTIONPERFORMED );
                    DESCRIBE_EVENT( "awt",  "XActionListener",              "actionPerformed",          ACTIONPERFORMED );
                    DESCRIBE_EVENT( "form", "XChangeListener",              "changed",                  CHANGED );
                    DESCRIBE_EVENT( "awt",  "XTextListener",                "textChanged",              TEXTCHANGED );
                    DESCRIBE_EVENT( "awt",  "XItemListener",                "itemStateChanged",         ITEMSTATECHANGED );
                    DESCRIBE_EVENT( "awt",  "XFocusListener",               "focusGained",              FOCUSGAINED );
                    DESCRIBE_EVENT( "awt",  "XFocusListener",               "focusLost",                FOCUSLOST );
                    DESCRIBE_EVENT( "awt",  "XKeyListener",                 "keyPressed",               KEYTYPED );
                    DESCRIBE_EVENT( "awt",  "XKeyListener",                 "keyReleased",              KEYUP );
                    DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseEntered",             MOUSEENTERED );
                    DESCRIBE_EVENT( "awt",  "XMouseMotionListener",         "mouseDragged",             MOUSEDRAGGED );
                    DESCRIBE_EVENT( "awt",  "XMouseMotionListener",         "mouseMoved",               MOUSEMOVED );
                    DESCRIBE_EVENT( "awt",  "XMouseListener",               "mousePressed",             MOUSEPRESSED );
                    DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseReleased",            MOUSERELEASED );
                    DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseExited",              MOUSEEXITED );
                    DESCRIBE_EVENT( "form", "XResetListener",               "approveReset",             APPROVERESETTED );
                    DESCRIBE_EVENT( "form", "XResetListener",               "resetted",                 RESETTED );
                    DESCRIBE_EVENT( "form", "XSubmitListener",              "approveSubmit",            SUBMITTED );
                    DESCRIBE_EVENT( "form", "XUpdateListener",              "approveUpdate",            BEFOREUPDATE );
                    DESCRIBE_EVENT( "form", "XUpdateListener",              "updated",                  AFTERUPDATE );
                    DESCRIBE_EVENT( "form", "XLoadListener",                "loaded",                   LOADED );
                    DESCRIBE_EVENT( "form", "XLoadListener",                "reloading",                RELOADING );
                    DESCRIBE_EVENT( "form", "XLoadListener",                "reloaded",                 RELOADED );
                    DESCRIBE_EVENT( "form", "XLoadListener",                "unloading",                UNLOADING );
                    DESCRIBE_EVENT( "form", "XLoadListener",                "unloaded",                 UNLOADED );
                    DESCRIBE_EVENT( "form", "XConfirmDeleteListener",       "confirmDelete",            CONFIRMDELETE );
                    DESCRIBE_EVENT( "sdb",  "XRowSetApproveListener",       "approveRowChange",         APPROVEROWCHANGE );
                    DESCRIBE_EVENT( "sdbc", "XRowSetListener",              "rowChanged",               ROWCHANGE );
                    DESCRIBE_EVENT( "sdb",  "XRowSetApproveListener",       "approveCursorMove",        POSITIONING );
                    DESCRIBE_EVENT( "sdbc", "XRowSetListener",              "cursorMoved",              POSITIONED );
                    DESCRIBE_EVENT( "form", "XDatabaseParameterListener",   "approveParameter",         APPROVEPARAMETER );
                    DESCRIBE_EVENT( "sdb",  "XSQLErrorListener",            "errorOccured",             ERROROCCURED );
                    DESCRIBE_EVENT( "awt",  "XAdjustmentListener",          "adjustmentValueChanged",   ADJUSTMENTVALUECHANGED );
                }
            }

            EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName );
            if ( pos == s_aKnownEvents.end() )
                return false;

            _out_rDescription = pos->second;
            return true;
        }

        //....................................................................
        ::rtl::OUString lcl_getEventPropertyName( const ::rtl::OUString& _rListenerClassName, const ::rtl::OUString& _rMethodName )
        {
            ::rtl::OUStringBuffer aPropertyName;
            aPropertyName.append( _rListenerClassName );
            aPropertyName.append( (sal_Unicode)';' );
            aPropertyName.append( _rMethodName.getStr() );
            return aPropertyName.makeStringAndClear();
        }

        //................................................................
        ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const Sequence< ScriptEventDescriptor >& _rAllAssignedMacros )
        {
            ScriptEventDescriptor aScriptEvent;
            // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
            //  so this ScriptEventDescriptor properly describes the given event
            aScriptEvent.ListenerType = _rEvent.sListenerClassName;
            aScriptEvent.EventMethod = _rEvent.sListenerMethodName;

            const ScriptEventDescriptor* pAssignedEvent = _rAllAssignedMacros.getConstArray();
            sal_Int32 assignedEventCount( _rAllAssignedMacros.getLength() );
            for ( sal_Int32 assignedEvent = 0; assignedEvent < assignedEventCount; ++assignedEvent, ++pAssignedEvent )
            {
                if  (   ( pAssignedEvent->ListenerType != _rEvent.sListenerClassName )
                    ||  ( pAssignedEvent->EventMethod != _rEvent.sListenerMethodName )
                    )
                    continue;

                if  (   ( pAssignedEvent->ScriptCode.getLength() == 0 )
                    ||  ( pAssignedEvent->ScriptType.getLength() == 0 )
                    )
                {
                    DBG_ERROR( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
                    continue;
                }

                aScriptEvent = *pAssignedEvent;

                if ( !aScriptEvent.ScriptType.equalsAscii( "StarBasic" ) )
                    continue;

                // this is an old-style macro specification:
                // [document|application]:Library.Module.Function
                // we need to translate this to the new-style macro specification
                // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]

                sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' );
                OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" );
                ::rtl::OUString sLocation = aScriptEvent.ScriptCode.copy( 0, nPrefixLen );
                ::rtl::OUString sMacroPath = aScriptEvent.ScriptCode.copy( nPrefixLen + 1 );

                ::rtl::OUStringBuffer aNewStyleSpec;
                aNewStyleSpec.appendAscii( "vnd.sun.star.script:" );
                aNewStyleSpec.append     ( sMacroPath );
                aNewStyleSpec.appendAscii( "?language=Basic&location=" );
                aNewStyleSpec.append     ( sLocation );

                aScriptEvent.ScriptCode = aNewStyleSpec.makeStringAndClear();

                // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
                aScriptEvent.ScriptType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) );
            }
            return aScriptEvent;
        }

        //................................................................
        ::rtl::OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor )
        {
            EventDescription aKnownEvent;
            if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) )
                return aKnownEvent.sListenerClassName;
            DBG_ERROR( "lcl_getQualifiedKnownListenerName: unknown method name!" );
                // somebody assigned an script to a form component event which we don't know
                // Speaking strictly, this is not really an error - it is possible to do
                // this programmatically -, but it should rarely happen, since it's not possible
                // via UI
            return _rFormComponentEventDescriptor.ListenerType;
        }

        //................................................................
        typedef ::std::set< Type, TypeLessByName > TypeBag;

        //................................................................
        void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent,
            const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes )
        {
            if ( !_rxComponent.is() )
                return;
            OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" );

            Reference< XIntrospectionAccess > xIntrospectionAccess(
                _rxIntrospection->inspect( makeAny( _rxComponent ) ), UNO_QUERY_THROW );

            Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() );

            ::std::copy( aListeners.getConstArray(), aListeners.getConstArray() + aListeners.getLength(),
                ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
        }

        //................................................................
        bool operator ==( const ScriptEventDescriptor _lhs, const ScriptEventDescriptor _rhs )
        {
            return  (   ( _lhs.ListenerType         == _rhs.ListenerType        )
                    &&  ( _lhs.EventMethod          == _rhs.EventMethod         )
                    &&  ( _lhs.AddListenerParam     == _rhs.AddListenerParam    )
                    &&  ( _lhs.ScriptType           == _rhs.ScriptType          )
                    &&  ( _lhs.ScriptCode           == _rhs.ScriptCode          )
                    );
        }
    }

    //====================================================================
    //= EventHandler
    //====================================================================
    typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::container::XNameReplace
                                    >   EventHolder_Base;
    /** a UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg
    */
    class EventHolder : public EventHolder_Base
    {
    private:
        typedef ::std::hash_map< ::rtl::OUString, ScriptEventDescriptor, ::rtl::OUStringHash >  EventMap;
        typedef ::std::map< EventId, EventMap::iterator >                                       EventMapIndexAccess;

        EventMap            m_aEventNameAccess;
        EventMapIndexAccess m_aEventIndexAccess;

    public:
        EventHolder( );

        void addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent );

        /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird
            format used by the macro assignment dialog, it is returned directly
        */
        ScriptEventDescriptor getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const;

        // XNameReplace
        virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Any SAL_CALL getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException);
        virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);

    protected:
        ~EventHolder( );

    private:
        ScriptEventDescriptor impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const;
    };

    DBG_NAME( EventHolder )
	//------------------------------------------------------------------------
    EventHolder::EventHolder()
    {
        DBG_CTOR( EventHolder, NULL );
    }

	//------------------------------------------------------------------------
    EventHolder::~EventHolder()
    {
        m_aEventNameAccess.clear();
        m_aEventIndexAccess.clear();
        DBG_DTOR( EventHolder, NULL );
    }

	//------------------------------------------------------------------------
    void EventHolder::addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent )
    {
        ::std::pair< EventMap::iterator, bool > insertionResult =
            m_aEventNameAccess.insert( EventMap::value_type( _rEventName, _rScriptEvent ) );
        OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" );
        m_aEventIndexAccess[ _nId ] = insertionResult.first;
    }

    //------------------------------------------------------------------------
    ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const
    {
        return impl_getDescriptor_throw( _rEventName );
    }

    //------------------------------------------------------------------------
    ScriptEventDescriptor EventHolder::impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const
    {
        EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName );
        if ( pos == m_aEventNameAccess.end() )
            throw NoSuchElementException( ::rtl::OUString(), *const_cast< EventHolder* >( this ) );
        return pos->second;
    }

	//------------------------------------------------------------------------
    void SAL_CALL EventHolder::replaceByName( const ::rtl::OUString& _rName, const Any& _rElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
    {
        EventMap::iterator pos = m_aEventNameAccess.find( _rName );
        if ( pos == m_aEventNameAccess.end() )
            throw NoSuchElementException( ::rtl::OUString(), *this );

        Sequence< PropertyValue > aScriptDescriptor;
        OSL_VERIFY( _rElement >>= aScriptDescriptor );

        ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor );

        pos->second.ScriptType = aExtractor.getOrDefault( "EventType", ::rtl::OUString() );
        pos->second.ScriptCode = aExtractor.getOrDefault( "Script", ::rtl::OUString() );
    }

    //------------------------------------------------------------------------
    Any SAL_CALL EventHolder::getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
    {
        ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) );

        Any aRet;
        Sequence< PropertyValue > aScriptDescriptor( 2 );
        aScriptDescriptor[0].Name = ::rtl::OUString::createFromAscii( "EventType" );
        aScriptDescriptor[0].Value <<= aDescriptor.ScriptType;
        aScriptDescriptor[1].Name = ::rtl::OUString::createFromAscii( "Script" );
        aScriptDescriptor[1].Value <<= aDescriptor.ScriptCode;

        return makeAny( aScriptDescriptor );
    }

	//------------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL EventHolder::getElementNames(  ) throw (RuntimeException)
    {
        Sequence< ::rtl::OUString > aReturn( m_aEventIndexAccess.size() );
        ::rtl::OUString* pReturn = aReturn.getArray();

        // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
        // main access method is by name. In it's UI, it shows the possible events in exactly the
        // order in which XNameAccess::getElementNames returns them.
        // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
        // relative to the sequence returned by XNameAccess::getElementNames.
        // This is IMO weird, since it mixes index access with name access, which decreases efficiency
        // of the implementation.
        // Well, it means we're forced to return the events in getElementNames in exactly the same as they
        // appear in the property browser UI.
        for (   EventMapIndexAccess::const_iterator loop = m_aEventIndexAccess.begin();
                loop != m_aEventIndexAccess.end();
                ++loop, ++pReturn
            )
            *pReturn = loop->second->first;
        return aReturn;
    }

 	//------------------------------------------------------------------------
    sal_Bool SAL_CALL EventHolder::hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException)
    {
        EventMap::const_iterator pos = m_aEventNameAccess.find( _rName );
        return pos != m_aEventNameAccess.end();
    }

	//------------------------------------------------------------------------
    Type SAL_CALL EventHolder::getElementType(  ) throw (RuntimeException)
    {
        return ::getCppuType( static_cast< Sequence< PropertyValue >* >( NULL ) );
    }

	//------------------------------------------------------------------------
    sal_Bool SAL_CALL EventHolder::hasElements(  ) throw (RuntimeException)
    {
        return !m_aEventNameAccess.empty();
    }


    //====================================================================
    //= EventHandler
    //====================================================================
    DBG_NAME( EventHandler )
    //--------------------------------------------------------------------
    EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext )
        :EventHandler_Base( m_aMutex )
        ,m_aContext( _rxContext )
        ,m_aPropertyListeners( m_aMutex )
        ,m_bEventsMapInitialized( false )
        ,m_bIsDialogElement( false )
        ,m_nGridColumnType( -1 )
    {
        DBG_CTOR( EventHandler, NULL );
    }

    //--------------------------------------------------------------------
    EventHandler::~EventHandler()
    {
        DBG_DTOR( EventHandler, NULL );
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL EventHandler::getImplementationName(  ) throw (RuntimeException)
    {
        return getImplementationName_static();
    }

    //--------------------------------------------------------------------
    ::sal_Bool SAL_CALL EventHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
    {
        StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() );
        return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames(  ) throw (RuntimeException)
    {
        return getSupportedServiceNames_static();
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL EventHandler::getImplementationName_static(  ) throw (RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.EventHandler" ) );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
    {
        Sequence< ::rtl::OUString > aSupported( 1 );
        aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.EventHandler" ) );
        return aSupported;
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SAL_CALL EventHandler::Create( const Reference< XComponentContext >& _rxContext )
    {
        return *( new EventHandler( _rxContext ) );
    }

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        if ( !_rxIntrospectee.is() )
            throw NullPointerException();

        m_xComponent = Reference< XPropertySet >( _rxIntrospectee, UNO_QUERY_THROW );

        m_bEventsMapInitialized = false;
        EventMap aEmpty;
        m_aEvents.swap( aEmpty );

        m_bIsDialogElement = false;
        m_nGridColumnType = -1;
        try
        {
            Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() );
            m_bIsDialogElement = xPSI.is()
                              && xPSI->hasPropertyByName( PROPERTY_WIDTH )
                              && xPSI->hasPropertyByName( PROPERTY_HEIGHT )
                              && xPSI->hasPropertyByName( PROPERTY_POSITIONX )
                              && xPSI->hasPropertyByName( PROPERTY_POSITIONY );

            Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY );
            if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() )
            {
                if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) )
                {
                    m_nGridColumnType = classifyComponent( _rxIntrospectee );
                }
            }
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    Any SAL_CALL EventHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );

        Sequence< ScriptEventDescriptor > aEvents;
        impl_getComponentScriptEvents_nothrow( aEvents );

        sal_Int32 nEventCount = aEvents.getLength();
        const ScriptEventDescriptor* pEvents = aEvents.getConstArray();

        ScriptEventDescriptor aPropertyValue;
        for ( sal_Int32 event = 0; event < nEventCount; ++event, ++pEvents )
        {
            if  (   rEvent.sListenerClassName == pEvents->ListenerType
                &&  rEvent.sListenerMethodName == pEvents->EventMethod
                )
            {
                aPropertyValue = *pEvents;
                break;
            }
        }

        return makeAny( aPropertyValue );
    }

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );

        ScriptEventDescriptor aNewScriptEvent;
        OSL_VERIFY( _rValue >>= aNewScriptEvent );

        ScriptEventDescriptor aOldScriptEvent;
        OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent );
        if ( aOldScriptEvent == aNewScriptEvent )
            return;

        if ( m_bIsDialogElement )
            impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent );
        else
            impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent );

        Reference< XModifiable > xDoc( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY );
        if ( xDoc.is() )
            xDoc->setModified( sal_True );

        PropertyChangeEvent aEvent;
        aEvent.Source = m_xComponent;
        aEvent.PropertyHandle = rEvent.nId;
        aEvent.PropertyName = _rPropertyName;
        aEvent.OldValue <<= aOldScriptEvent;
        aEvent.NewValue <<= aNewScriptEvent;
        m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange );
    }

    //--------------------------------------------------------------------
    Any SAL_CALL EventHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        ::rtl::OUString sNewScriptCode;
        OSL_VERIFY( _rControlValue >>= sNewScriptCode );

        Sequence< ScriptEventDescriptor > aAllAssignedEvents;
        impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );

        const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
        ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents );

        OSL_ENSURE( !sNewScriptCode.getLength(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
        // Usually, there is no possibility for the user to change the content of an event binding directly in the
        // input field, this instead is done with the macro assignment dialog.
        // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
        // control content to an empty string. So this is the only scenario where this method is allowed to be called.

        // Strictly, we would be able to convert the display value to a property value,
        // using the "name (location, language)" format we used in convertToControlValue. However,
        // there is no need for this code ...

        aAssignedScript.ScriptCode = sNewScriptCode;
        return makeAny( aAssignedScript );
    }

    //--------------------------------------------------------------------
    Any SAL_CALL EventHandler::convertToControlValue( const ::rtl::OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        ScriptEventDescriptor aScriptEvent;
        OSL_VERIFY( _rPropertyValue >>= aScriptEvent );

        OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
            "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
        (void)_rControlValueType;

        ::rtl::OUString sScript( aScriptEvent.ScriptCode );
        if ( sScript.getLength() )
        {
            // format is: "name (location, language)"
            try
            {
                // parse
                Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() );
                Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW );

                ::rtl::OUStringBuffer aComposeBuffer;

                // name
                aComposeBuffer.append( xScriptUri->getName() );

                // location
                const ::rtl::OUString sLocationParamName( RTL_CONSTASCII_USTRINGPARAM( "location" ) );
                const ::rtl::OUString sLocation = xScriptUri->getParameter( sLocationParamName );
                const ::rtl::OUString sLangParamName( RTL_CONSTASCII_USTRINGPARAM( "language" ) );
                const ::rtl::OUString sLanguage = xScriptUri->getParameter( sLangParamName );

                if ( sLocation.getLength() || sLanguage.getLength() )
                {
                    aComposeBuffer.appendAscii( " (" );

                    // location
                    OSL_ENSURE( sLocation.getLength(), "EventHandler::convertToControlValue: unexpected: no location!" );
                    if ( sLocation.getLength() )
                    {
                        aComposeBuffer.append( sLocation );
                        aComposeBuffer.appendAscii( ", " );
                    }

                    // language
                    if ( sLanguage.getLength() )
                    {
                        aComposeBuffer.append( sLanguage );
                    }

                    aComposeBuffer.append( sal_Unicode( ')' ) );
                }

                sScript = aComposeBuffer.makeStringAndClear();
            }
            catch( const Exception& )
            {
        	    DBG_UNHANDLED_EXCEPTION();
            }
        }

        return makeAny( sScript );
    }

    //--------------------------------------------------------------------
    PropertyState SAL_CALL EventHandler::getPropertyState( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
    {
        return PropertyState_DIRECT_VALUE;
    }

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );
        if ( !_rxListener.is() )
            throw NullPointerException();
        m_aPropertyListeners.addListener( _rxListener );
    }

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );
        m_aPropertyListeners.removeListener( _rxListener );
    }

    //--------------------------------------------------------------------
    Sequence< Property > SAL_CALL EventHandler::getSupportedProperties() throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );
        if ( !m_bEventsMapInitialized )
        {
            const_cast< EventHandler* >( this )->m_bEventsMapInitialized = true;
            try
            {
                Sequence< Type > aListeners;
                impl_getCopmonentListenerTypes_nothrow( aListeners );
                sal_Int32 listenerCount = aListeners.getLength();

                Property aCurrentProperty;
                ::rtl::OUString sListenerClassName;

                // loop through all listeners and all methods, and see which we can present at the UI
                const Type* pListeners = aListeners.getConstArray();
                for ( sal_Int32 listener = 0; listener < listenerCount; ++listener, ++pListeners )
                {
                    aCurrentProperty = Property();

                    // the programmatic name of the listener, to be used as "property" name
                    sListenerClassName = pListeners->getTypeName();
                    OSL_ENSURE( sListenerClassName.getLength(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
                    if ( !sListenerClassName.getLength() )
                        continue;

                    // loop through all methods
                    Sequence< ::rtl::OUString > aMethods( comphelper::getEventMethodsForType( *pListeners ) );

                    const ::rtl::OUString* pMethods = aMethods.getConstArray();
                    sal_uInt32 methodCount = aMethods.getLength();

                    for (sal_uInt32 method = 0 ; method < methodCount ; ++method, ++pMethods )
                    {
                        EventDescription aEvent;
                        if ( !lcl_getEventDescriptionForMethod( *pMethods, aEvent ) )
                            continue;

                        if ( !impl_filterMethod_nothrow( aEvent ) )
                            continue;

                        const_cast< EventHandler* >( this )->m_aEvents.insert( EventMap::value_type(
                            lcl_getEventPropertyName( sListenerClassName, *pMethods ), aEvent ) );
                    }
                }

            }
            catch( const Exception& )
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }

        // sort them by ID - this is the relative ordering in the UI
        ::std::map< EventId, Property > aOrderedProperties;
        for (   EventMap::const_iterator loop = m_aEvents.begin();
                loop != m_aEvents.end();
                ++loop
            )
        {
            aOrderedProperties[ loop->second.nId ] = Property(
                loop->first, loop->second.nId,
                ::getCppuType( static_cast< const ::rtl::OUString* >( NULL ) ),
                PropertyAttribute::BOUND );
        }

        StlSyntaxSequence< Property > aReturn( aOrderedProperties.size() );
        ::std::transform( aOrderedProperties.begin(), aOrderedProperties.end(), aReturn.begin(),
            ::std::select2nd< ::std::map< EventId, Property >::value_type >() );
        return aReturn;
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupersededProperties( ) throw (RuntimeException)
    {
        // none
        return Sequence< ::rtl::OUString >( );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL EventHandler::getActuatingProperties( ) throw (RuntimeException)
    {
        // none
        return Sequence< ::rtl::OUString >( );
    }

    //--------------------------------------------------------------------
    LineDescriptor SAL_CALL EventHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
        const Reference< XPropertyControlFactory >& _rxControlFactory )
        throw (UnknownPropertyException, NullPointerException, RuntimeException)
    {
        if ( !_rxControlFactory.is() )
            throw NullPointerException();

        ::osl::MutexGuard aGuard( m_aMutex );

        LineDescriptor aDescriptor;

        aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, sal_True );
        Reference< XEventListener > xControlExtender = new PropertyControlExtender( aDescriptor.Control );

        const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
        aDescriptor.DisplayName = rEvent.sDisplayName;
        aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.sHelpId );
        aDescriptor.PrimaryButtonId = rtl::OStringToOUString(rEvent.sUniqueBrowseId, RTL_TEXTENCODING_UTF8);
        aDescriptor.HasPrimaryButton = sal_True;
        aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Events" ) );
        return aDescriptor;
    }

    //--------------------------------------------------------------------
    ::sal_Bool SAL_CALL EventHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
    {
        return sal_False;
    }

    //--------------------------------------------------------------------
    InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
    {
        if ( !_rxInspectorUI.is() )
            throw NullPointerException();

        ::osl::MutexGuard aGuard( m_aMutex );
        const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName );

        Sequence< ScriptEventDescriptor > aAllAssignedEvents;
        impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );

        // SvxMacroAssignDlg-compatible structure holding all event/assignments
        ::rtl::Reference< EventHolder >  pEventHolder( new EventHolder );

        for (   EventMap::const_iterator event = m_aEvents.begin();
                event != m_aEvents.end();
                ++event
            )
        {
            // the script which is assigned to the current event (if any)
            ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event->second, aAllAssignedEvents );
            pEventHolder->addEvent( event->second.nId, event->second.sListenerMethodName, aAssignedScript );
        }

        // the initial selection in the dialog
        Sequence< ::rtl::OUString > aNames( pEventHolder->getElementNames() );
        const ::rtl::OUString* pChosenEvent = ::std::find( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), rForEvent.sListenerMethodName );
        sal_uInt16 nInitialSelection = (sal_uInt16)( pChosenEvent - aNames.getConstArray() );

        // the dialog
        SvxAbstractDialogFactory* pFactory = SvxAbstractDialogFactory::Create();
        if ( !pFactory )
            return InteractiveSelectionResult_Cancelled;

        ::std::auto_ptr< VclAbstractDialog > pDialog( pFactory->CreateSvxMacroAssignDlg(
            PropertyHandlerHelper::getDialogParentWindow( m_aContext ),
            impl_getContextFrame_nothrow(),
            m_bIsDialogElement,
            pEventHolder.get(),
            nInitialSelection
        ) );

        if ( !pDialog.get() )
            return InteractiveSelectionResult_Cancelled;

        // DF definite problem here
        // OK & Cancel seem to be both returning 0
        if ( pDialog->Execute() == RET_CANCEL )
            return InteractiveSelectionResult_Cancelled;

        try
        {
            for (   EventMap::const_iterator event = m_aEvents.begin();
                    event != m_aEvents.end();
                    ++event
                )
            {
                ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event->second.sListenerMethodName ) );

                // set the new "property value"
                setPropertyValue(
                    lcl_getEventPropertyName( event->second.sListenerClassName, event->second.sListenerMethodName ),
                    makeAny( aScriptDescriptor )
                );
            }
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }

        return InteractiveSelectionResult_Success;
    }

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::actuatingPropertyChanged( const ::rtl::OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
    {
        DBG_ERROR( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
    }

    //--------------------------------------------------------------------
    IMPLEMENT_FORWARD_XCOMPONENT( EventHandler, EventHandler_Base )

    //--------------------------------------------------------------------
    void SAL_CALL EventHandler::disposing()
    {
        EventMap aEmpty;
        m_aEvents.swap( aEmpty );
        m_xComponent.clear();
    }

    //--------------------------------------------------------------------
    sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
    {
        return sal_True;
    }

    //------------------------------------------------------------------------
    Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const
    {
        Reference< XFrame > xContextFrame;

        try
        {
            Reference< XModel > xContextDocument( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW );
            Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW );
            xContextFrame.set( xController->getFrame(), UNO_SET_THROW );
        }
        catch( const Exception& )
        {
        	DBG_UNHANDLED_EXCEPTION();
        }

        return xContextFrame;
    }

    //--------------------------------------------------------------------
    sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const
    {
        Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
        Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW );

        // get the index of the inspected object within it's parent container
        sal_Int32 nElements = xParentAsIndexAccess->getCount();
        for ( sal_Int32 i=0; i<nElements; ++i )
        {
            Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW );
            if ( xElement == m_xComponent )
                return i;
        }
        throw NoSuchElementException();
    }

    //--------------------------------------------------------------------
    void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
    {
        _out_rEvents = Sequence < ScriptEventDescriptor >();
        try
        {
            Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
            Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
            _out_rEvents = xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() );

            // the form component script API has unqualified listener names, but for normalization
            // purpose, we want fully qualified ones
            ScriptEventDescriptor* pEvents = _out_rEvents.getArray();
            ScriptEventDescriptor* pEventsEnd = _out_rEvents.getArray() + _out_rEvents.getLength();
            while ( pEvents != pEventsEnd )
            {
                pEvents->ListenerType = lcl_getQualifiedKnownListenerName( *pEvents );
                ++pEvents;
            }
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence< Type >& _out_rTypes ) const
    {
        _out_rTypes.realloc( 0 );
        try
        {
            // we use a set to avoid duplicates
            TypeBag aListeners;

            Reference< XIntrospection > xIntrospection( m_aContext.createComponent( "com.sun.star.beans.Introspection" ), UNO_QUERY_THROW );

            // --- model listeners
            lcl_addListenerTypesFor_throw(
                m_xComponent, xIntrospection, aListeners );

            // --- "secondary component" (usually: "control" listeners)
            {
                Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
                lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners );
                ::comphelper::disposeComponent( xSecondaryComponent );
            }

            // now that they're disambiguated, copy these types into our member
            _out_rTypes.realloc( aListeners.size() );
            ::std::copy( aListeners.begin(), aListeners.end(), _out_rTypes.getArray() );
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
    {
        _out_rEvents = Sequence < ScriptEventDescriptor >();
        try
        {
            Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
            Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
            Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() );

            sal_Int32 nEventCount = aEventNames.getLength();
            _out_rEvents.realloc( nEventCount );

            const ::rtl::OUString* pNames = aEventNames.getConstArray();
            ScriptEventDescriptor* pDescs = _out_rEvents.getArray();

            for( sal_Int32 i = 0 ; i < nEventCount ; ++i, ++pNames, ++pDescs )
                OSL_VERIFY( xEvents->getByName( *pNames ) >>= *pDescs );
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
    {
        Reference< XInterface > xReturn;

        // if it's a form, create a form controller for the additional events
        Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY );
        if ( xComponentAsForm.is() )
        {
            Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW );
            Reference< XFormController > xController(
                m_aContext.createComponent( "com.sun.star.form.runtime.FormController" ), UNO_QUERY_THROW );
            xController->setModel( xComponentAsTCModel );

            xReturn = xController;
        }
        else
        {
            ::rtl::OUString sControlService;
            OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService );

            xReturn = m_aContext.createComponent( sControlService );
        }
        return xReturn;
    }

    //--------------------------------------------------------------------
    const EventDescription& EventHandler::impl_getEventForName_throw( const ::rtl::OUString& _rPropertyName ) const
    {
        EventMap::const_iterator pos = m_aEvents.find( _rPropertyName );
        if ( pos == m_aEvents.end() )
            throw UnknownPropertyException();
        return pos->second;
    }

    //--------------------------------------------------------------------
    namespace
    {
        static bool lcl_endsWith( const ::rtl::OUString& _rText, const ::rtl::OUString& _rCheck )
        {
            sal_Int32 nTextLen = _rText.getLength();
            sal_Int32 nCheckLen = _rCheck.getLength();
            if ( nCheckLen > nTextLen )
                return false;

            return _rText.indexOf( _rCheck ) == ( nTextLen - nCheckLen );
        }
    }
    //--------------------------------------------------------------------
    void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
    {
        try
        {
            ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
            ::rtl::OUString sScriptType( _rScriptEvent.ScriptType );
            bool bResetScript = ( sScriptCode.getLength() == 0 );

            sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw();
            Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
            Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
            Sequence< ScriptEventDescriptor > aEvents( xEventManager->getScriptEvents( nObjectIndex ) );

            // is there already a registered script for this event?
            ScriptEventDescriptor* pEvent = aEvents.getArray();
            sal_Int32 eventCount = aEvents.getLength(), event = 0;
            for ( event = 0; event < eventCount; ++event, ++pEvent )
            {
                if  (   ( pEvent->EventMethod == _rScriptEvent.EventMethod )
                    &&  ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) )
                          // (strange enough, the events we get from getScriptEvents are not fully qualified)
                    )
                {
                    // yes
                    if ( !bResetScript )
                    {
                        // set to something non-empty -> overwrite
                        pEvent->ScriptCode = sScriptCode;
                        pEvent->ScriptType = sScriptType;
                    }
                    else
                    {
                        // set to empty -> remove from sequence
                        ::std::copy( pEvent + 1, aEvents.getArray() + eventCount, pEvent );
                        aEvents.realloc( eventCount - 1 );
                        --eventCount;
                    }
                    break;
                }
            }
            if ( ( event >= eventCount ) && !bResetScript )
            {
                // no, did not find it -> append
                aEvents.realloc( eventCount + 1 );
                aEvents[ eventCount ] = _rScriptEvent;
            }

            xEventManager->revokeScriptEvents( nObjectIndex );
            xEventManager->registerScriptEvents( nObjectIndex, aEvents );

            PropertyHandlerHelper::setContextDocumentModified( m_aContext );
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
    {
        try
        {
            ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
            bool bResetScript = ( sScriptCode.getLength() == 0 );

            Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
            Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );

            ::rtl::OUStringBuffer aCompleteName;
            aCompleteName.append( _rScriptEvent.ListenerType );
            aCompleteName.appendAscii( "::" );
            aCompleteName.append( _rScriptEvent.EventMethod );
            ::rtl::OUString sCompleteName( aCompleteName.makeStringAndClear() );

            bool bExists = xEvents->hasByName( sCompleteName );

            if ( bResetScript )
            {
                if ( bExists )
                    xEvents->removeByName( sCompleteName );
            }
            else
            {
                Any aNewValue; aNewValue <<= _rScriptEvent;

                if ( bExists )
                    xEvents->replaceByName( sCompleteName, aNewValue );
                else
                    xEvents->insertByName( sCompleteName, aNewValue );
            }
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const
    {
        // some (control-triggered) events do not make sense for certain grid control columns. However,
        // our mechanism to retrieve control-triggered events does not know about this, so we do some
        // late filtering here.
        switch ( m_nGridColumnType )
        {
        case FormComponentType::COMBOBOX:
            if ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
                return false;
            break;
        case FormComponentType::LISTBOX:
            if  (   ( UID_BRWEVT_CHANGED == _rEvent.sUniqueBrowseId )
                ||  ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
                )
                return false;
            break;
        }

        return true;
    }

//........................................................................
} // namespace pcr
//........................................................................
