/**************************************************************
 * 
 * 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_scripting.hxx"
#include <comphelper/processfactory.hxx>
#include <comphelper/uno3.hxx>
#include <comphelper/proparrhlp.hxx>
#include <comphelper/propertycontainer.hxx>

#include <ooo/vba/XVBAToOOEventDescGen.hpp>

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>

#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>

#include <com/sun/star/util/XCloseListener.hpp>
#include <com/sun/star/util/XCloseBroadcaster.hpp>

#include <com/sun/star/frame/XModel.hpp>

#include <com/sun/star/script/XLibraryContainer.hpp>
#include <com/sun/star/script/ScriptEventDescriptor.hpp>
#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>

#include <com/sun/star/drawing/XControlShape.hpp>

#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/awt/XDialog.hpp>
#include <com/sun/star/awt/KeyEvent.hpp>
#include <com/sun/star/awt/MouseEvent.hpp>
#include <com/sun/star/awt/XFixedText.hpp> //liuchen 2009-6-5
#include <com/sun/star/awt/XTextComponent.hpp> //liuchen 2009-6-5
#include <com/sun/star/awt/XComboBox.hpp> //liuchen 2009-6-18
#include <com/sun/star/awt/XRadioButton.hpp> //liuchen 2009-7-30

#include <msforms/ReturnInteger.hpp>

#include <sfx2/objsh.hxx>
#include <basic/sbstar.hxx>
#include <basic/basmgr.hxx>
#include <basic/sbmeth.hxx>
#include <basic/sbmod.hxx>
#include <basic/sbx.hxx>




// for debug
#include <comphelper/anytostring.hxx>


#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/script/XScriptListener.hpp>
#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase3.hxx>
#include <comphelper/evtmethodhelper.hxx>

#include <set>
#include <list>
#include <hash_map>

using namespace ::com::sun::star;
using namespace ::com::sun::star::script;
using namespace ::com::sun::star::uno;
using namespace ::ooo::vba;

#define MAP_CHAR_LEN(x) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))//liuchen 2009-6-8
#define GET_TYPE(x) ::getCppuType((uno::Reference< x > *)0);

// Some constants 
const static rtl::OUString DELIM = rtl::OUString::createFromAscii( "::" );
const static sal_Int32 DELIMLEN = DELIM.getLength();

#if 0
void dumpListeners( const Reference< beans::XIntrospection >& xIntrospection, const Reference<XInterface>& xIfc)
{
    Reference< beans::XIntrospectionAccess > xIntrospectionAccess;
    if ( xIntrospection.is() )
    {
        xIntrospectionAccess = xIntrospection->inspect( 
            makeAny( xIfc ) );
        Sequence< Type > aControlListeners = 
            xIntrospectionAccess->getSupportedListeners();
        sal_Int32 nLength = aControlListeners.getLength();
             
        for ( sal_Int32 i = 0; i< nLength; ++i )
        {
            Type& listType = aControlListeners[ i ];
            rtl::OUString sFullTypeName = listType.getTypeName();
            rtl::OUString sTypeName = listType.getTypeName();
            sal_Int32 lastDotIndex = -1;
            if ( ( lastDotIndex = sFullTypeName.lastIndexOf( '.' ) ) > -1 )
            {
                sTypeName = sFullTypeName.copy( lastDotIndex + 1 );    
            } 
            Sequence< ::rtl::OUString > sMeths = comphelper::getEventMethodsForType( listType );    
            sal_Int32 sMethLen = sMeths.getLength();
            for ( sal_Int32 j=0 ; j < sMethLen; ++j )
            {
                OSL_TRACE("**Listener [%d] Type[%s] Method[%s]",j,
                    rtl::OUStringToOString( sTypeName, 
                        RTL_TEXTENCODING_UTF8 ).getStr(),
                    rtl::OUStringToOString( sMeths[ j ], 
                        RTL_TEXTENCODING_UTF8 ).getStr() );
            }
        }
       
    }
}

void dumpEvent( const ScriptEvent& evt )
{
    OSL_TRACE("dumpEvent: Source %s",
        rtl::OUStringToOString( comphelper::anyToString( makeAny(evt.Source)), 
            RTL_TEXTENCODING_UTF8 ).getStr() );

    OSL_TRACE("dumpEvent: ScriptType %s",
        rtl::OUStringToOString( evt.ScriptType, 
            RTL_TEXTENCODING_UTF8 ).getStr() );
    
    OSL_TRACE("dumpEvent: ScriptCode %s",
        rtl::OUStringToOString( evt.ScriptCode, 
            RTL_TEXTENCODING_UTF8 ).getStr() );

    OSL_TRACE("dumpEvent: ListenerType %s",
        rtl::OUStringToOString( evt.ListenerType.getTypeName(), 
            RTL_TEXTENCODING_UTF8 ).getStr() );
    
    OSL_TRACE("dumpEvent: Listener methodname %s",
        rtl::OUStringToOString( evt.MethodName, 
            RTL_TEXTENCODING_UTF8 ).getStr() );

    OSL_TRACE("dumpEvent: arguments;");
    sal_Int32 nLen = evt.Arguments.getLength();
    for ( sal_Int32 index=0; index < nLen; ++index )
    {
        OSL_TRACE("\t [%d] %s", index, 
        rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[ index ] ), 
            RTL_TEXTENCODING_UTF8 ).getStr() );

    }
}

#endif

bool isKeyEventOk( awt::KeyEvent& evt, const Sequence< Any >& params )
{
    if ( !( params.getLength() > 0 ) ||
        !( params[ 0 ] >>= evt ) )
        return false;
    return true;
}

bool isMouseEventOk( awt::MouseEvent& evt, const Sequence< Any >& params )
{
    if ( !( params.getLength() > 0 ) ||
        !( params[ 0 ] >>= evt ) )
        return false;
    return true;
}

Sequence< Any > ooMouseEvtToVBADblClick( const Sequence< Any >& params )
{
    Sequence< Any > translatedParams;
    awt::MouseEvent evt;

    if ( !( isMouseEventOk(evt, params)) || 
        (evt.ClickCount != 2) )
        return Sequence< Any >(); 
    // give back orig params, this will signal that the event is good
    return params;
}

Sequence< Any > ooMouseEvtToVBAMouseEvt( const Sequence< Any >& params )
{
    Sequence< Any > translatedParams;
    awt::MouseEvent evt;

    if ( !isMouseEventOk(evt, params) )
        return Sequence< Any >(); 

    translatedParams.realloc(4);

    // Buttons
    translatedParams[ 0 ] <<= evt.Buttons;
    // Shift
    translatedParams[ 1 ] <<= evt.Modifiers;
    // X
    translatedParams[ 2 ] <<= evt.X;
    // Y
    translatedParams[ 3 ] <<= evt.Y;
    return translatedParams;
}

Sequence< Any > ooKeyPressedToVBAKeyPressed( const Sequence< Any >& params )
{
    Sequence< Any > translatedParams;
    awt::KeyEvent evt;

    if ( !isKeyEventOk( evt, params ) )
        return Sequence< Any >(); 

    translatedParams.realloc(1);

    msforms::ReturnInteger keyCode;
    keyCode.Value = evt.KeyCode; 
    translatedParams[0] <<= keyCode;
    return  translatedParams;
}

Sequence< Any > ooKeyPressedToVBAKeyUpDown( const Sequence< Any >& params )
{
    Sequence< Any > translatedParams;
    awt::KeyEvent evt;

    if ( !isKeyEventOk( evt, params ) )
        return Sequence< Any >(); 

    translatedParams.realloc(2);

    msforms::ReturnInteger keyCode;
    sal_Int8 shift = sal::static_int_cast<sal_Int8>( evt.Modifiers );

    // #TODO check whether values from OOO conform to values generated from vba
    keyCode.Value = evt.KeyCode; 
    translatedParams[0] <<= keyCode;
    translatedParams[1] <<= shift;
    return  translatedParams;
}

typedef Sequence< Any > (*Translator)(const Sequence< Any >&);

//liuchen 2009-6-23
//expand the "TranslateInfo" struct to support more kinds of events 
struct TranslateInfo
{
    rtl::OUString sVBAName; //vba event name
    Translator toVBA;       //the method to convert OO event parameters to VBA event parameters	
	bool (*ApproveRule)(const ScriptEvent& evt, void* pPara); //this method is used to determine which types of controls should execute the event 
	void *pPara;			//Parameters for the above approve method
};


typedef std::hash_map< rtl::OUString, 
std::list< TranslateInfo >, 
::rtl::OUStringHash,
::std::equal_to< ::rtl::OUString > > EventInfoHash;

//liuchen 2009-6-23
struct TranslatePropMap
{
	rtl::OUString sEventInfo;   //OO event name
	TranslateInfo aTransInfo;   
};
 
bool ApproveAll(const ScriptEvent& evt, void* pPara); //allow all types of controls to execute the event
bool ApproveType(const ScriptEvent& evt, void* pPara); //certain types of controls should execute the event, those types are given by pPara
bool DenyType(const ScriptEvent& evt, void* pPara);    //certain types of controls should not execute the event, those types are given by pPara
bool DenyMouseDrag(const ScriptEvent& evt, void* pPara); //used for VBA MouseMove event when "Shift" key is pressed

struct TypeList
{
	uno::Type* pTypeList;
	int nListLength;
};

Type typeXFixedText = GET_TYPE(awt::XFixedText)
Type typeXTextComponent = GET_TYPE(awt::XTextComponent)
Type typeXComboBox = GET_TYPE(awt::XComboBox)
Type typeXRadioButton = GET_TYPE(awt::XRadioButton)


TypeList fixedTextList = {&typeXFixedText, 1};
TypeList textCompList = {&typeXTextComponent, 1};
TypeList radioButtonList = {&typeXRadioButton, 1};
TypeList comboBoxList = {&typeXComboBox, 1};

//this array stores the OO event to VBA event translation info
static TranslatePropMap aTranslatePropMap_Impl[] = 
{
	// actionPerformed ooo event
	{ MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Click"), NULL, ApproveAll, NULL } },	
	{ MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Change"), NULL, DenyType, (void*)(&radioButtonList) } },  //liuchen 2009-7-30, OptionalButton_Change event is not the same as OptionalButton_Click event

	// itemStateChanged ooo event
	{ MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL, ApproveType, (void*)(&comboBoxList) } },  //liuchen, add to support VBA ComboBox_Click event
	{ MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveType, (void*)(&radioButtonList) } }, //liuchen 2009-7-30, OptionalButton_Change event should be triggered when the button state is changed
	
	// changed ooo event
	{ MAP_CHAR_LEN("changed"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },	

	// focusGained ooo event
	{ MAP_CHAR_LEN("focusGained"), { MAP_CHAR_LEN("_GotFocus"), NULL, ApproveAll, NULL } },

	// focusLost ooo event
	{ MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_LostFocus"), NULL, ApproveAll, NULL } },
	{ MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_Exit"), NULL, ApproveType, (void*)(&textCompList) } }, //liuchen, add to support VBA TextBox_Exit event

	// adjustmentValueChanged ooo event
	{ MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Scroll"), NULL, ApproveAll, NULL } },
	{ MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },

	// textChanged ooo event
	{ MAP_CHAR_LEN("textChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },

	// keyReleased ooo event
	{ MAP_CHAR_LEN("keyReleased"), { MAP_CHAR_LEN("_KeyUp"), ooKeyPressedToVBAKeyUpDown, ApproveAll, NULL } },

	// mouseReleased ooo event
	{ MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_Click"), ooMouseEvtToVBAMouseEvt, ApproveType, (void*)(&fixedTextList) } }, //liuchen, add to support VBA Label_Click event
	{ MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_MouseUp"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },

	// mousePressed ooo event
	{ MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_MouseDown"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },
	{ MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_DblClick"), ooMouseEvtToVBADblClick, ApproveAll, NULL } },

	// mouseMoved ooo event	
	{ MAP_CHAR_LEN("mouseMoved"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },
	{ MAP_CHAR_LEN("mouseDragged"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, DenyMouseDrag, NULL } }, //liuchen, add to support VBA MouseMove event when the "Shift" key is pressed

	// keyPressed ooo event
	{ MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyDown"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } },
	{ MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyPress"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } }
};

EventInfoHash& getEventTransInfo()
{
    static bool initialised = false;
    static EventInfoHash eventTransInfo;
    if ( !initialised )
    {
        rtl::OUString sEventInfo = MAP_CHAR_LEN("");
        TranslatePropMap* pTransProp = aTranslatePropMap_Impl;
        int nCount = sizeof(aTranslatePropMap_Impl) / sizeof(aTranslatePropMap_Impl[0]);

        int i = 0;
        while (i < nCount)
        {		
            sEventInfo = pTransProp->sEventInfo;
            std::list< TranslateInfo > infoList;
            do
            {									
                infoList.push_back( pTransProp->aTransInfo );
                pTransProp++;
                i++;
            }while(i < nCount && sEventInfo == pTransProp->sEventInfo);
            eventTransInfo[sEventInfo] = infoList;			
        }	
        initialised = true;
    }
    return eventTransInfo;
}
//liuchen 2009-6-23 end

// Helper class

class ScriptEventHelper
{
public:
    ScriptEventHelper( const Reference< XInterface >& xControl );
    Sequence< ScriptEventDescriptor > createEvents( const rtl::OUString& sCodeName );   
    Sequence< rtl::OUString > getEventListeners();
private:
    Reference< XComponentContext > m_xCtx;
    Reference< XInterface > m_xControl;
};

bool
eventMethodToDescriptor( const ::rtl::OUString& rEventMethod, ScriptEventDescriptor& evtDesc, const ::rtl::OUString& sCodeName )
{
    // format of ControlListener is TypeName::methodname e.g.
    // "com.sun.star.awt.XActionListener::actionPerformed" or
    // "XActionListener::actionPerformed

    ::rtl::OUString sMethodName;
    ::rtl::OUString sTypeName;
    sal_Int32 nDelimPos = rEventMethod.indexOf( DELIM );
    if ( nDelimPos == -1 )
    {
        return false;
    }
    sMethodName = rEventMethod.copy( nDelimPos + DELIMLEN );
    sTypeName = rEventMethod.copy( 0, nDelimPos );
            
    EventInfoHash& infos = getEventTransInfo();

    // Only create an ScriptEventDescriptor for an event we can translate
    // or emulate
    if ( sMethodName.getLength() 
         && sTypeName.getLength()
         && ( infos.find( sMethodName ) != infos.end() ) )
    {
        // just fill in CodeName, when the event fires the other 
	// info is gathered from the event source to determine what
	// event handler we try to call
        evtDesc.ScriptCode = sCodeName;
        evtDesc.ListenerType = sTypeName;
        evtDesc.EventMethod = sMethodName;

        // set this it VBAInterop, ensures that it doesn't
        // get persisted or shown in property editors
        evtDesc.ScriptType = rtl::OUString::createFromAscii(
            "VBAInterop" );	
        return true;
    }
    return false;

}

ScriptEventHelper::ScriptEventHelper( const Reference< XInterface >& xControl ) : m_xControl( xControl )
{
    Reference < beans::XPropertySet > xProps(
        ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
    m_xCtx.set( xProps->getPropertyValue( rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), 
        uno::UNO_QUERY_THROW );
}

Sequence< rtl::OUString > 
ScriptEventHelper::getEventListeners()
{
    Reference< lang::XMultiComponentFactory > xMFac( 
        m_xCtx->getServiceManager(), UNO_QUERY );
    std::list< rtl::OUString > eventMethods;

    if ( xMFac.is() )
    {
        Reference< beans::XIntrospection > xIntrospection( 
            xMFac->createInstanceWithContext( rtl::OUString( 
                RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection"  ) ), m_xCtx ), UNO_QUERY );
#if 0
        dumpListeners( xIntrospection, m_xControl );
        dumpListeners( xIntrospection, m_xControl->getModel() );
#endif 
        Reference< beans::XIntrospectionAccess > xIntrospectionAccess;
	if  ( xIntrospection.is() )
	{
            xIntrospectionAccess = xIntrospection->inspect( 
                makeAny( m_xControl ) );
            Sequence< Type > aControlListeners = 
                xIntrospectionAccess->getSupportedListeners();
            sal_Int32 nLength = aControlListeners.getLength();             
            for ( sal_Int32 i = 0; i< nLength; ++i )
            {
                Type& listType = aControlListeners[ i ];
                rtl::OUString sFullTypeName = listType.getTypeName();
                Sequence< ::rtl::OUString > sMeths = 
                    comphelper::getEventMethodsForType( listType );    
                sal_Int32 sMethLen = sMeths.getLength();
                for ( sal_Int32 j=0 ; j < sMethLen; ++j )
                {
                    rtl::OUString sEventMethod = sFullTypeName;
                    sEventMethod += DELIM;
                    sEventMethod += sMeths[ j ];
                    eventMethods.push_back( sEventMethod );
                }
            }
            
        }
    }

    Sequence< rtl::OUString > sEventMethodNames( eventMethods.size() );
    std::list< rtl::OUString >::const_iterator it = eventMethods.begin();
    rtl::OUString* pDest = sEventMethodNames.getArray();

    for ( ; it != eventMethods.end(); ++it, ++pDest )
        *pDest = *it;         

    return sEventMethodNames;
}

Sequence< ScriptEventDescriptor > 
ScriptEventHelper::createEvents( const rtl::OUString& sCodeName )
{
    Sequence< rtl::OUString > aControlListeners = getEventListeners();
    rtl::OUString* pSrc = aControlListeners.getArray();
    sal_Int32 nLength = aControlListeners.getLength();             

    Sequence< ScriptEventDescriptor > aDest( nLength );
    sal_Int32 nEvts = 0; 
    for ( sal_Int32 i = 0; i< nLength; ++i, ++pSrc )
    {
        // from getListeners eventName is of form
        // "com.sun.star.awt.XActionListener::actionPerformed"
        // we need to strip "com.sun.star.awt." from that for form
        // controls
    	ScriptEventDescriptor evtDesc;
        if ( eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) )
        {
            sal_Int32 dIndex = nEvts;
            ++nEvts;
            if ( nEvts > aDest.getLength() )
                aDest.realloc( nEvts );// should never happen
            aDest[ dIndex ] = evtDesc;
        }
    }
    aDest.realloc( nEvts );

    return aDest;
}


typedef ::cppu::WeakImplHelper1< container::XNameContainer > NameContainer_BASE;

class ReadOnlyEventsNameContainer : public NameContainer_BASE
{
public:
    ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName );
    // XNameContainer

    virtual void SAL_CALL insertByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, RuntimeException)
    {
        throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
 
    }
    virtual void SAL_CALL removeByName( const ::rtl::OUString& ) throw (::com::sun::star::container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
    {
        throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
    }

    // XNameReplace
    virtual void SAL_CALL replaceByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
    {
        throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
 
    }
                                                                                
    // XNameAccess
    virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException);
    virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
    virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (RuntimeException);

    // XElementAccess
    virtual Type SAL_CALL getElementType(  ) throw (RuntimeException)
    { return getCppuType(static_cast< const rtl::OUString * >(0) ); }
    virtual ::sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException)
    { return ( ( m_hEvents.size() > 0 ? sal_True : sal_False ) ); }
private:

typedef std::hash_map< rtl::OUString, Any, ::rtl::OUStringHash,
::std::equal_to< ::rtl::OUString > > EventSupplierHash;

    EventSupplierHash m_hEvents;
};

ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName )
{
    const rtl::OUString* pSrc = eventMethods.getConstArray();
    sal_Int32 nLen = eventMethods.getLength();
    for ( sal_Int32 index = 0; index < nLen; ++index, ++pSrc )
    {
        Any aDesc;
        ScriptEventDescriptor evtDesc;
        if (  eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) )
        {
            aDesc <<= evtDesc; 
            m_hEvents[ *pSrc ] = aDesc;
        }
    }
}

Any SAL_CALL 
ReadOnlyEventsNameContainer::getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException){
    EventSupplierHash::const_iterator it = m_hEvents.find( aName );
    if ( it == m_hEvents.end() )
        throw container::NoSuchElementException();
    return it->second;
}

Sequence< ::rtl::OUString > SAL_CALL 
ReadOnlyEventsNameContainer::getElementNames(  ) throw (RuntimeException)
{
    Sequence< ::rtl::OUString > names(m_hEvents.size());
    rtl::OUString* pDest = names.getArray();
    EventSupplierHash::const_iterator it = m_hEvents.begin();
    EventSupplierHash::const_iterator it_end = m_hEvents.end();
    for ( sal_Int32 index = 0; it != it_end; ++index, ++pDest, ++it )
        *pDest = it->first;
    return names;
}

sal_Bool SAL_CALL 
ReadOnlyEventsNameContainer::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException)
{
    EventSupplierHash::const_iterator it = m_hEvents.find( aName );
    if ( it == m_hEvents.end() )
        return sal_False;
    return sal_True;
}

typedef ::cppu::WeakImplHelper1< XScriptEventsSupplier > EventsSupplier_BASE;

class ReadOnlyEventsSupplier : public EventsSupplier_BASE
{
public:
    ReadOnlyEventsSupplier( const Sequence< ::rtl::OUString >& eventMethods, const rtl::OUString& sCodeName )
    { m_xNameContainer = new ReadOnlyEventsNameContainer( eventMethods, sCodeName ); }
    
    // XScriptEventSupplier
    virtual Reference< container::XNameContainer > SAL_CALL getEvents(  ) throw (RuntimeException){ return m_xNameContainer; }
private:
    Reference< container::XNameContainer > m_xNameContainer;
};

typedef ::cppu::WeakImplHelper3< XScriptListener, util::XCloseListener, lang::XInitialization > EventListener_BASE;

#define EVENTLSTNR_PROPERTY_ID_MODEL         1
#define EVENTLSTNR_PROPERTY_MODEL            ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) )

class EventListener : public EventListener_BASE
    ,public ::comphelper::OMutexAndBroadcastHelper
    ,public ::comphelper::OPropertyContainer
    ,public ::comphelper::OPropertyArrayUsageHelper< EventListener >

{
    
public:
    EventListener( const Reference< XComponentContext >& rxContext );
    // XEventListener
    virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( RuntimeException );
	using cppu::OPropertySetHelper::disposing;

    // XScriptListener
    virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException);
    virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException);
    // XCloseListener
    virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
    virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
    // XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw (::com::sun::star::uno::RuntimeException);    
    // XInitialization
    virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
    // XInterface
    DECLARE_XINTERFACE()

    // XTypeProvider
    DECLARE_XTYPEPROVIDER()
    virtual void SAL_CALL setFastPropertyValue( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
    {
        if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL )
        {
            uno::Reference< frame::XModel > xModel( rValue, uno::UNO_QUERY );
            if( xModel != m_xModel)
            {
                // Remove the listener from the old XCloseBroadcaster.
                uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xModel, uno::UNO_QUERY );
                if (xCloseBroadcaster.is())
                {
                    xCloseBroadcaster->removeCloseListener( this );
                }
                // Add the listener into the new XCloseBroadcaster.
                xCloseBroadcaster = uno::Reference< util::XCloseBroadcaster >( xModel, uno::UNO_QUERY );
                if (xCloseBroadcaster.is())
                {
                    xCloseBroadcaster->addCloseListener( this );
                }
            }
        }
        OPropertyContainer::setFastPropertyValue( nHandle, rValue );
        if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL )
            setShellFromModel();
    }

protected:
    // OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(  );

    // OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper(  ) const;

private:
    void setShellFromModel();
    void firing_Impl( const  ScriptEvent& evt, Any *pSyncRet=NULL ) throw( RuntimeException );

    Reference< XComponentContext > m_xContext;
    Reference< frame::XModel > m_xModel;
    sal_Bool m_bDocClosed;
    SfxObjectShell* mpShell;
    
};

EventListener::EventListener( const Reference< XComponentContext >& rxContext ) :
OPropertyContainer(GetBroadcastHelper()), m_xContext( rxContext ), m_bDocClosed(sal_False), mpShell( 0 )
{
    registerProperty( EVENTLSTNR_PROPERTY_MODEL, EVENTLSTNR_PROPERTY_ID_MODEL,
        beans::PropertyAttribute::TRANSIENT, &m_xModel, ::getCppuType( &m_xModel ) );

}

void
EventListener::setShellFromModel()
{
	// reset mpShell
	mpShell = 0;
	SfxObjectShell* pShell = SfxObjectShell::GetFirst();
	while ( m_xModel.is() && pShell )
	{
		if ( pShell->GetModel() == m_xModel )
		{
			mpShell = pShell;
			break;
		}
		pShell = SfxObjectShell::GetNext( *pShell );
	}    
}

//XEventListener
void
EventListener::disposing(const lang::EventObject&)  throw( RuntimeException )
{
}

//XScriptListener

void SAL_CALL 
EventListener::firing(const ScriptEvent& evt) throw(RuntimeException)
{
    firing_Impl( evt );
}

Any SAL_CALL 
EventListener::approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException)
{
    Any ret;
    firing_Impl( evt, &ret );
    return ret;
}

// XCloseListener
void SAL_CALL 
EventListener::queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException)
{
    //Nothing to do
}

void SAL_CALL 
EventListener::notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException)
{
    m_bDocClosed = sal_True;
    uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xModel, uno::UNO_QUERY );
    if (xCloseBroadcaster.is())
    {
        xCloseBroadcaster->removeCloseListener( this );
    }
}

// XInitialization
void SAL_CALL 
EventListener::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
{
    if ( aArguments.getLength() == 1 )
        aArguments[0] >>= m_xModel;
    OSL_TRACE("EventListener::initialize() args %d m_xModel %d", aArguments.getLength(), m_xModel.is() );
}

// XInterface

IMPLEMENT_FORWARD_XINTERFACE2( EventListener, EventListener_BASE, OPropertyContainer )

// XTypeProvider

IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener, EventListener_BASE, OPropertyContainer )

// OPropertySetHelper

::cppu::IPropertyArrayHelper& 
EventListener::getInfoHelper(  )
{
    return *getArrayHelper();
}

// OPropertyArrayUsageHelper

::cppu::IPropertyArrayHelper* 
EventListener::createArrayHelper(  ) const
{
    Sequence< beans::Property > aProps;
    describeProperties( aProps );
    return new ::cppu::OPropertyArrayHelper( aProps );
}

// XPropertySet
Reference< beans::XPropertySetInfo > 
EventListener::getPropertySetInfo(  ) throw (RuntimeException)
{
    Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
    return xInfo;
}

//liuchen 2009-6-23
//decide if the control should execute the event
bool ApproveAll(const ScriptEvent&, void* )
{
	return true;
}

//for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
bool FindControl(const ScriptEvent& evt, void* pPara)
{
	lang::EventObject aEvent;
	evt.Arguments[ 0 ] >>= aEvent;
	uno::Reference< uno::XInterface > xInterface( aEvent.Source, uno::UNO_QUERY );

	TypeList* pTypeListInfo = static_cast<TypeList*>(pPara);
	Type* pType = pTypeListInfo->pTypeList;
	int nLen = pTypeListInfo->nListLength;

	for (int i = 0; i < nLen; i++)
	{
		if ( xInterface->queryInterface( *pType ).hasValue() )
		{
			return true;
		}
		pType++;
	}

	return false;
}

//if the the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
bool ApproveType(const ScriptEvent& evt, void* pPara)
{
	return FindControl(evt, pPara);
}

//if the the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
bool DenyType(const ScriptEvent& evt, void* pPara)
{
	return !FindControl(evt, pPara);
}

//when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
//the former should be denyed, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is 
//pressed can be correctly triggered
bool DenyMouseDrag(const ScriptEvent& evt, void* )
{
	awt::MouseEvent aEvent;
	evt.Arguments[ 0 ] >>= aEvent;
	if (aEvent.Buttons == 0 )
	{
		return true;
	}
	else
	{
		return false;
	}
}



//liuchen 2009-6-23
// EventListener

void
EventListener::firing_Impl(const ScriptEvent& evt, Any* /*pRet*/ ) throw(RuntimeException)
{
	OSL_TRACE("EventListener::firing_Impl( FAKE VBA_EVENTS )");
    static const ::rtl::OUString vbaInterOp =
        ::rtl::OUString::createFromAscii("VBAInterop");

    // let default handlers deal with non vba stuff
    if ( !evt.ScriptType.equals( vbaInterOp ) )
        return;
    lang::EventObject aEvent;
    evt.Arguments[ 0 ] >>= aEvent;
	OSL_TRACE("Argument[0] is  %s", rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[0] ), RTL_TEXTENCODING_UTF8 ).getStr() );
	OSL_TRACE("Getting Control");
    uno::Reference< awt::XControl > xControl( aEvent.Source, uno::UNO_QUERY_THROW );
	OSL_TRACE("Getting properties");
    uno::Reference< beans::XPropertySet > xProps( xControl->getModel(), uno::UNO_QUERY_THROW );

    rtl::OUString sName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm") );
	OSL_TRACE("Getting Name");

    uno::Reference< awt::XDialog > xDlg( aEvent.Source, uno::UNO_QUERY );
    if ( !xDlg.is() )
        xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) ) >>= sName;
    //dumpEvent( evt );
    EventInfoHash& infos = getEventTransInfo();
    EventInfoHash::const_iterator eventInfo_it = infos.find( evt.MethodName );
    EventInfoHash::const_iterator it_end = infos.end();
    if ( eventInfo_it == it_end )
    {
        OSL_TRACE("Bogus event for %s",
            rtl::OUStringToOString( evt.ScriptType, RTL_TEXTENCODING_UTF8 ).getStr() );
        return;
    }

    uno::Reference< script::provider::XScriptProviderSupplier > xSPS( m_xModel, uno::UNO_QUERY );
    uno::Reference< script::provider::XScriptProvider > xScriptProvider;
    if ( xSPS.is() )
        xScriptProvider =  xSPS->getScriptProvider();
    if ( xScriptProvider.is() && mpShell )
    {
        std::list< TranslateInfo > matchingMethods;
        std::list< TranslateInfo >::const_iterator txInfo =
            eventInfo_it->second.begin();
        std::list< TranslateInfo >::const_iterator txInfo_end = eventInfo_it->second.end();
        rtl::OUString sMacroLoc = rtl::OUString::createFromAscii("Standard.").concat( evt.ScriptCode ).concat( rtl::OUString::createFromAscii(".") );
       
        StarBASIC* pBasic = mpShell->GetBasic();
        SbModule* pModule = pBasic->FindModule( evt.ScriptCode );
        for ( ; pModule && txInfo != txInfo_end; ++txInfo )
        {
	    // #i106270#: If the document is closed, we should not execute macro.
	    if (m_bDocClosed)
	    {
		break;
	    }
            // see if we have a match for the handlerextension
            // where ScriptCode is methodname_handlerextension 
            rtl::OUString sTemp = sName.concat( (*txInfo).sVBAName ); 
            
            OSL_TRACE("*** trying to invoke %s ",
                rtl::OUStringToOString( sTemp, RTL_TEXTENCODING_UTF8 ).getStr() );
            SbMethod* pMeth = static_cast< SbMethod* >( pModule->Find( sTemp, SbxCLASS_METHOD ) );
            if ( pMeth )
            {
				//liuchen 2009-6-8
				if (! txInfo->ApproveRule(evt, txInfo->pPara) )
				{
					continue;
				}
				//liuchen 2009-6-8
                // !! translate arguments & emulate events where necessary 
                Sequence< Any > aArguments;
                if  ( (*txInfo).toVBA )
                    aArguments = (*txInfo).toVBA( evt.Arguments );
                else
                    aArguments = evt.Arguments;
                if ( aArguments.getLength() )
                {
                    // call basic event handlers for event

                    static rtl::OUString part1 = rtl::OUString::createFromAscii( "vnd.sun.star.script:");
                    static rtl::OUString part2 = rtl::OUString::createFromAscii("?language=Basic&location=document"); 

                    // create script url
                    rtl::OUString url = part1 + sMacroLoc + sTemp + part2;
                 
                    OSL_TRACE("script url = %s",
                        rtl::OUStringToOString( url, 
                            RTL_TEXTENCODING_UTF8 ).getStr() );
                    Sequence< sal_Int16 > aOutArgsIndex;
                    Sequence< Any > aOutArgs;
                    try
                    {
                        if ( mpShell )
                        {
                            uno::Any aRet;
                            mpShell->CallXScript( url,
                                aArguments, aRet, aOutArgsIndex, aOutArgs, false );
                        }
                    }
                    catch ( uno::Exception& e )
                    {
                        OSL_TRACE("event script raised %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
                    }
               } 
           }
       }
    }
}

typedef ::cppu::WeakImplHelper1< XVBAToOOEventDescGen > VBAToOOEventDescGen_BASE;


class VBAToOOEventDescGen : public VBAToOOEventDescGen_BASE
{
public:
    VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext );

    // XVBAToOOEventDescGen
    virtual Sequence< ScriptEventDescriptor > SAL_CALL getEventDescriptions( const Reference< XInterface >& control, const rtl::OUString& sCodeName ) throw (RuntimeException);
    virtual Reference< XScriptEventsSupplier > SAL_CALL getEventSupplier( const Reference< XInterface >& xControl,  const rtl::OUString& sCodeName ) throw (::com::sun::star::uno::RuntimeException);
private:
    Reference< XComponentContext > m_xContext;
  
};

VBAToOOEventDescGen::VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext ):m_xContext( rxContext ) {}

Sequence< ScriptEventDescriptor > SAL_CALL 
VBAToOOEventDescGen::getEventDescriptions( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName ) throw (RuntimeException)
{
    ScriptEventHelper evntHelper( xControl ); 
    return evntHelper.createEvents( sCodeName ); 
}

Reference< XScriptEventsSupplier > SAL_CALL 
VBAToOOEventDescGen::getEventSupplier( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName  ) throw (::com::sun::star::uno::RuntimeException)
{
    ScriptEventHelper evntHelper( xControl ); 
    Reference< XScriptEventsSupplier > xSupplier = 
        new ReadOnlyEventsSupplier( 
            evntHelper.getEventListeners(), sCodeName ) ;
    return xSupplier;
}

// Component related 

namespace evtlstner
{
    ::rtl::OUString SAL_CALL getImplementationName()
    {
        static ::rtl::OUString* pImplName = 0;
        if ( !pImplName )
        {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
            if ( !pImplName )
            {
                static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.EventListener" ) );
                pImplName = &aImplName;
            }
        }
        return *pImplName;
    }

    uno::Reference< XInterface > SAL_CALL create(
    Reference< XComponentContext > const & xContext )
    SAL_THROW( () )
    {
        return static_cast< lang::XTypeProvider * >( new EventListener( xContext ) );
    }

    Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
    {
        const ::rtl::OUString strName( ::evtlstner::getImplementationName() );
        return Sequence< ::rtl::OUString >( &strName, 1 );
    }	
}
namespace ooevtdescgen 
{
    ::rtl::OUString SAL_CALL getImplementationName()
    {
        static ::rtl::OUString* pImplName = 0;
        if ( !pImplName )
        {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
            if ( !pImplName )
            {
                static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAToOOEventDesc" ) );
                pImplName = &aImplName;
            }
        }
        return *pImplName;
    }

    uno::Reference< XInterface > SAL_CALL create(
        Reference< XComponentContext > const & xContext )
        SAL_THROW( () )
    {
        return static_cast< lang::XTypeProvider * >( new VBAToOOEventDescGen( xContext ) );
    }

    Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
    {
    	const ::rtl::OUString strName( ::ooevtdescgen::getImplementationName() );
        return Sequence< ::rtl::OUString >( &strName, 1 );
    }	
}
