/**************************************************************
 * 
 * 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 "DialogModelProvider.hxx"
#include "dlgprov.hxx"
#include "dlgevtatt.hxx"
#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/io/XInputStreamProvider.hpp>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
#include <com/sun/star/script/XLibraryContainer.hpp>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/resource/XStringResourceSupplier.hpp>
#include <com/sun/star/resource/XStringResourceManager.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/resource/XStringResourceWithLocation.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>
#include <sfx2/app.hxx>
#include <sfx2/objsh.hxx>
#include <xmlscript/xmldlg_imexp.hxx>
#include <tools/urlobj.hxx>
#include <comphelper/namedvaluecollection.hxx>

#include <com/sun/star/uri/XUriReference.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
#include <com/sun/star/util/XMacroExpander.hpp>

#include <util/MiscUtils.hxx>

using namespace ::com::sun::star;
using namespace awt;
using namespace lang;
using namespace uno;
using namespace script;
using namespace beans;
using namespace document;
using namespace ::sf_misc;

// component helper namespace
namespace comp_DialogModelProvider 
{

    ::rtl::OUString SAL_CALL _getImplementationName() 
    {
        return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.scripting.DialogModelProvider"));
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
    {
        uno::Sequence< ::rtl::OUString > s(1);
        s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlDialogModelProvider"));
        return s;
    }

    uno::Reference< uno::XInterface > SAL_CALL _create(const uno::Reference< uno::XComponentContext > & context) SAL_THROW((uno::Exception))
    {
        return static_cast< ::cppu::OWeakObject * >(new dlgprov::DialogModelProvider(context));
    }
} // closing component helper namespace
//.........................................................................
namespace dlgprov
{
//.........................................................................

static ::rtl::OUString aResourceResolverPropName = ::rtl::OUString::createFromAscii( "ResourceResolver" );

    Reference< resource::XStringResourceManager > lcl_getStringResourceManager(const Reference< XComponentContext >& i_xContext,const ::rtl::OUString& i_sURL)
    {
        INetURLObject aInetObj( i_sURL );
	    ::rtl::OUString aDlgName = aInetObj.GetBase();
	    aInetObj.removeSegment();
	    ::rtl::OUString aDlgLocation = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
	    bool bReadOnly = true;
	    ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale();
	    ::rtl::OUString aComment;

	    Sequence<Any> aArgs( 6 );
	    aArgs[0] <<= aDlgLocation;
	    aArgs[1] <<= bReadOnly;
	    aArgs[2] <<= aLocale;
	    aArgs[3] <<= aDlgName;
	    aArgs[4] <<= aComment;

	    Reference< task::XInteractionHandler > xDummyHandler;
	    aArgs[5] <<= xDummyHandler;
	    Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_QUERY_THROW );
	    // TODO: Ctor
	    Reference< resource::XStringResourceManager > xStringResourceManager( xSMgr_->createInstanceWithContext
		    ( ::rtl::OUString::createFromAscii( "com.sun.star.resource.StringResourceWithLocation" ), 
			    i_xContext ), UNO_QUERY );
	    if( xStringResourceManager.is() )
	    {
		    Reference< XInitialization > xInit( xStringResourceManager, UNO_QUERY );
		    if( xInit.is() )
			    xInit->initialize( aArgs );
	    }
        return xStringResourceManager;
    }
    Reference< container::XNameContainer > lcl_createControlModel(const Reference< XComponentContext >& i_xContext)
    {
        Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_QUERY_THROW );
        Reference< container::XNameContainer > xControlModel( xSMgr_->createInstanceWithContext( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ), i_xContext ), UNO_QUERY_THROW );
        return xControlModel;
    }
    Reference< container::XNameContainer > lcl_createDialogModel( const Reference< XComponentContext >& i_xContext,
		const Reference< io::XInputStream >& xInput, 
		const Reference< resource::XStringResourceManager >& xStringResourceManager,
		const Any &aDialogSourceURL) throw ( Exception )
    {
        Reference< container::XNameContainer > xDialogModel(  lcl_createControlModel(i_xContext) );

		::rtl::OUString aDlgSrcUrlPropName( RTL_CONSTASCII_USTRINGPARAM( "DialogSourceURL" ) );
		Reference< beans::XPropertySet > xDlgPropSet( xDialogModel, UNO_QUERY );
		xDlgPropSet->setPropertyValue( aDlgSrcUrlPropName, aDialogSourceURL );

        ::xmlscript::importDialogModel( xInput, xDialogModel, i_xContext );
        // Set resource property
        if( xStringResourceManager.is() )
        {
            Reference< beans::XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY );
            Any aStringResourceManagerAny;
            aStringResourceManagerAny <<= xStringResourceManager;
            xDlgPSet->setPropertyValue( aResourceResolverPropName, aStringResourceManagerAny );
        }
	
        return xDialogModel; 
    }
    // =============================================================================
    // component operations
    // =============================================================================

    static ::rtl::OUString getImplementationName_DialogProviderImpl()
    {
        static ::rtl::OUString* pImplName = 0;
	    if ( !pImplName )
	    {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
            if ( !pImplName )
		    {
                static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.DialogProvider" ) );
			    pImplName = &aImplName;
		    }
	    }
	    return *pImplName;
    }

    // -----------------------------------------------------------------------------

    static Sequence< ::rtl::OUString > getSupportedServiceNames_DialogProviderImpl()
    {
        static Sequence< ::rtl::OUString >* pNames = 0;
	    if ( !pNames )
	    {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
		    if ( !pNames )
		    {
                static Sequence< ::rtl::OUString > aNames(3);
                aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider" ) );
                aNames.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) );
                aNames.getArray()[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.ContainerWindowProvider" ) );
                pNames = &aNames;
		    }
	    }
	    return *pNames;
    }


    // =============================================================================
    // mutex
    // =============================================================================

    ::osl::Mutex& getMutex()
    {
        static ::osl::Mutex* s_pMutex = 0;
        if ( !s_pMutex )
        {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
	        if ( !s_pMutex )
	        {
                static ::osl::Mutex s_aMutex;
		        s_pMutex = &s_aMutex;
	        }
        }
        return *s_pMutex;
    }


    // =============================================================================
    // DialogProviderImpl
    // =============================================================================

    DialogProviderImpl::DialogProviderImpl( const Reference< XComponentContext >& rxContext )
        :m_xContext( rxContext )
        ,m_xModel( 0 )
    {
    }

    // -----------------------------------------------------------------------------

    DialogProviderImpl::~DialogProviderImpl()
    {
    }

    // -----------------------------------------------------------------------------

	Reference< resource::XStringResourceManager > getStringResourceFromDialogLibrary
		( Reference< container::XNameContainer > xDialogLib )
	{
		Reference< resource::XStringResourceManager > xStringResourceManager;
		if( xDialogLib.is() )
		{
			Reference< resource::XStringResourceSupplier > xStringResourceSupplier( xDialogLib, UNO_QUERY );
			if( xStringResourceSupplier.is() )
			{
				Reference< resource::XStringResourceResolver >
					xStringResourceResolver = xStringResourceSupplier->getStringResource();

				xStringResourceManager = 
					Reference< resource::XStringResourceManager >( xStringResourceResolver, UNO_QUERY );
			}
		}
		return xStringResourceManager;
	}

    Reference< container::XNameContainer > DialogProviderImpl::createControlModel() throw ( Exception )
    {
        return lcl_createControlModel(m_xContext);
    }

    Reference< container::XNameContainer > DialogProviderImpl::createDialogModel( 
		const Reference< io::XInputStream >& xInput, 
		const Reference< resource::XStringResourceManager >& xStringResourceManager,
		const Any &aDialogSourceURL) throw ( Exception )
    {
        
	
        return lcl_createDialogModel(m_xContext,xInput,xStringResourceManager,aDialogSourceURL); 
    }

    Reference< XControlModel > DialogProviderImpl::createDialogModelForBasic() throw ( Exception )
    {
        if ( !m_BasicInfo.get() ) 
            // shouln't get here 
            throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("No information to create dialog" ) ), Reference< XInterface >() );
        Reference< resource::XStringResourceManager > xStringResourceManager = getStringResourceFromDialogLibrary( m_BasicInfo->mxDlgLib );
		
		rtl::OUString aURL(RTL_CONSTASCII_USTRINGPARAM("" ));
		Any aDialogSourceURL;
		aDialogSourceURL <<= aURL;
        Reference< XControlModel > xCtrlModel( createDialogModel( m_BasicInfo->mxInput, xStringResourceManager, aDialogSourceURL ), UNO_QUERY_THROW );
        return xCtrlModel;
    }

    Reference< XControlModel > DialogProviderImpl::createDialogModel( const ::rtl::OUString& sURL )
    {

        ::rtl::OUString aURL( sURL );

        // parse URL
        // TODO: use URL parsing class
        // TODO: decoding of location
        Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
        
        if ( !xSMgr.is() )
        {
            throw RuntimeException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::getDialogModel: Couldn't instantiate MultiComponent factory" ) ),
                    Reference< XInterface >() );
        }

        Reference< uri::XUriReferenceFactory > xFac (
            xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii(
            "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY );

        if  ( !xFac.is() )
        {
            throw RuntimeException(
                ::rtl::OUString::createFromAscii( "DialogProviderImpl::getDialogModel(), could not instatiate UriReferenceFactory." ),
                Reference< XInterface >() );
        }

		// i75778: Support non-script URLs 
		Reference< io::XInputStream > xInput;
        Reference< container::XNameContainer > xDialogLib;

		// Accept file URL to single dialog
		bool bSingleDialog = false;

		Reference< util::XMacroExpander > xMacroExpander(
            m_xContext->getValueByName(
            ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
            UNO_QUERY_THROW );

        Reference< uri::XUriReference > uriRef;
        for (;;)
        {
            uriRef = Reference< uri::XUriReference >( xFac->parse( aURL ), UNO_QUERY );
            if ( !uriRef.is() )
            {
                ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "DialogProviderImpl::getDialogModel: failed to parse URI: " );
                errorMsg += aURL;
                throw IllegalArgumentException( errorMsg,
                                                Reference< XInterface >(), 1 );
            }
            Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
            if( !sxUri.is() )
                break;

            aURL = sxUri->expand( xMacroExpander );
        }

		Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY );
        if( !sfUri.is() )
        {
			bSingleDialog = true;

			// Try any other URL with SimpleFileAccess
			Reference< ucb::XSimpleFileAccess > xSFI =
				Reference< ucb::XSimpleFileAccess >( xSMgr->createInstanceWithContext
				( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), m_xContext ), UNO_QUERY );

			try
			{
				xInput = xSFI->openFileRead( aURL );
			}
			catch( Exception& )
			{}
		}
		else
        {
			::rtl::OUString sDescription = sfUri->getName();
	        
			sal_Int32 nIndex = 0;

			::rtl::OUString sLibName = sDescription.getToken( 0, (sal_Unicode)'.', nIndex );
			::rtl::OUString sDlgName;
			if ( nIndex != -1 )
				sDlgName = sDescription.getToken( 0, (sal_Unicode)'.', nIndex );

			::rtl::OUString sLocation = sfUri->getParameter(
				::rtl::OUString::createFromAscii( "location" ) );


			// get dialog library container
			// TODO: dialogs in packages
			Reference< XLibraryContainer > xLibContainer;

			if ( sLocation == ::rtl::OUString::createFromAscii( "application" ) )
			{
				xLibContainer = Reference< XLibraryContainer >( SFX_APP()->GetDialogContainer(), UNO_QUERY );
			}
			else if ( sLocation == ::rtl::OUString::createFromAscii( "document" ) )
			{
                Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
                if ( xDocumentScripts.is() )
                {
                    xLibContainer.set( xDocumentScripts->getDialogLibraries(), UNO_QUERY );
                    OSL_ENSURE( xLibContainer.is(),
                        "DialogProviderImpl::createDialogModel: invalid dialog container!" );
                }
			}
			else
			{
                Sequence< ::rtl::OUString > aOpenDocsTdocURLs( MiscUtils::allOpenTDocUrls( m_xContext ) );
                const ::rtl::OUString* pTdocURL = aOpenDocsTdocURLs.getConstArray();
                const ::rtl::OUString* pTdocURLEnd = aOpenDocsTdocURLs.getConstArray() + aOpenDocsTdocURLs.getLength();
                for ( ; pTdocURL != pTdocURLEnd; ++pTdocURL )
                {
                    Reference< frame::XModel > xModel( MiscUtils::tDocUrlToModel( *pTdocURL ) );
                    OSL_ENSURE( xModel.is(), "DialogProviderImpl::createDialogModel: invalid document model!" );
                    if ( !xModel.is() )
                        continue;

                    ::rtl::OUString sDocURL = xModel->getURL();
					if ( sDocURL.getLength() == 0 )
					{
                        ::comphelper::NamedValueCollection aModelArgs( xModel->getArgs() );
                        sDocURL = aModelArgs.getOrDefault( "Title", sDocURL );
					}

					if ( sLocation != sDocURL )
                        continue;

                    Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
                    if ( !xDocumentScripts.is() )
                        continue;

                    xLibContainer.set( xDocumentScripts->getDialogLibraries(), UNO_QUERY );
                    OSL_ENSURE( xLibContainer.is(),
                        "DialogProviderImpl::createDialogModel: invalid dialog container!" );
                }
			}

			// get input stream provider
			Reference< io::XInputStreamProvider > xISP;
			if ( xLibContainer.is() )
			{
				// load dialog library
				if ( !xLibContainer->isLibraryLoaded( sLibName ) )
					xLibContainer->loadLibrary( sLibName );

				// get dialog library
				if ( xLibContainer->hasByName( sLibName ) )
				{
					Any aElement = xLibContainer->getByName( sLibName );
					aElement >>= xDialogLib;
				}

				if ( xDialogLib.is() )
				{
					// get input stream provider
					if ( xDialogLib->hasByName( sDlgName ) )
					{
						Any aElement = xDialogLib->getByName( sDlgName );
						aElement >>= xISP;
					}

					if ( !xISP.is() )
					{
						throw IllegalArgumentException(
							::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::getDialogModel: dialog not found!" ) ),
							Reference< XInterface >(), 1 );
					}
				}
				else
				{
					throw IllegalArgumentException(
						::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::getDialogModel: library not found!" ) ),
						Reference< XInterface >(), 1 );
				}
			}
			else
			{
				throw IllegalArgumentException(
					::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::getDialog: library container not found!" ) ),
					Reference< XInterface >(), 1 );
			}

			if ( xISP.is() )
				xInput = xISP->createInputStream();
		}

        // import dialog model
        Reference< XControlModel > xCtrlModel;
        if ( xInput.is() && m_xContext.is() )
        {
			Reference< resource::XStringResourceManager > xStringResourceManager;
			if( bSingleDialog )
			{
				xStringResourceManager = lcl_getStringResourceManager(m_xContext,aURL);
			}
			else if( xDialogLib.is() )
            {
				xStringResourceManager = getStringResourceFromDialogLibrary( xDialogLib );
			}

			Any aDialogSourceURLAny;
			aDialogSourceURLAny <<= aURL;
            
			Reference< container::XNameContainer > xDialogModel( createDialogModel( xInput , xStringResourceManager, aDialogSourceURLAny  ), UNO_QUERY_THROW);

			xCtrlModel = Reference< XControlModel >( xDialogModel, UNO_QUERY );
        }
        return xCtrlModel;
    }

    // -----------------------------------------------------------------------------

    Reference< XControl > DialogProviderImpl::createDialogControl
		( const Reference< XControlModel >& rxDialogModel, const Reference< XWindowPeer >& xParent )
    {
        OSL_ENSURE( rxDialogModel.is(), "DialogProviderImpl::getDialogControl: no dialog model" );

        Reference< XControl > xDialogControl;

        if ( m_xContext.is() )
        {
            Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );

            if ( xSMgr.is() )
            {
                xDialogControl = Reference< XControl >( xSMgr->createInstanceWithContext(
                    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialog" ) ), m_xContext ), UNO_QUERY );

                if ( xDialogControl.is() )
                {
                    // set the model
                    if ( rxDialogModel.is() )
                        xDialogControl->setModel( rxDialogModel );

                    // set visible
                    Reference< XWindow > xW( xDialogControl, UNO_QUERY );
                    if ( xW.is() )
                        xW->setVisible( sal_False );

                    // get the parent of the dialog control
                    Reference< XWindowPeer > xPeer;
					if( xParent.is() )
					{
						xPeer = xParent;
					}
                    else if ( m_xModel.is() )
                    {
                        Reference< frame::XController > xController( m_xModel->getCurrentController(), UNO_QUERY );
                        if ( xController.is() )
                        {
                            Reference< frame::XFrame > xFrame( xController->getFrame(), UNO_QUERY );
                            if ( xFrame.is() )
                                xPeer = Reference< XWindowPeer>( xFrame->getContainerWindow(), UNO_QUERY );
                        }
                    }

                    // create a peer
                    Reference< XToolkit> xToolkit( xSMgr->createInstanceWithContext( 
                        ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ), m_xContext ), UNO_QUERY );
                    if ( xToolkit.is() )
                        xDialogControl->createPeer( xToolkit, xPeer );
                }
            }
        }

        return xDialogControl;
    }

    // -----------------------------------------------------------------------------

    void DialogProviderImpl::attachControlEvents( 
		const Reference< XControl >& rxControl,
		const Reference< XInterface >& rxHandler,
		const Reference< XIntrospectionAccess >& rxIntrospectionAccess,
		bool bDialogProviderMode )
    {
        if ( rxControl.is() )
        {
            Reference< XControlContainer > xControlContainer( rxControl, UNO_QUERY );

            if ( xControlContainer.is() )
            {
                Sequence< Reference< XControl > > aControls = xControlContainer->getControls();
                const Reference< XControl >* pControls = aControls.getConstArray();
                sal_Int32 nControlCount = aControls.getLength();

                Sequence< Reference< XInterface > > aObjects( nControlCount + 1 );
                Reference< XInterface >* pObjects = aObjects.getArray();
                for ( sal_Int32 i = 0; i < nControlCount; ++i )
                {
                    pObjects[i] = Reference< XInterface >( pControls[i], UNO_QUERY );
                }

                // also add the dialog control itself to the sequence
                pObjects[nControlCount] = Reference< XInterface >( rxControl, UNO_QUERY );

				Reference< XScriptEventsAttacher > xScriptEventsAttacher = new DialogEventsAttacherImpl
					( m_xContext, m_xModel, rxControl, rxHandler, rxIntrospectionAccess, 
					  bDialogProviderMode, ( m_BasicInfo.get() ? m_BasicInfo->mxBasicRTLListener : NULL ) );

                Any aHelper;
                xScriptEventsAttacher->attachEvents( aObjects, Reference< XScriptListener >(), aHelper );
            }
        }
    }

	Reference< XIntrospectionAccess > DialogProviderImpl::inspectHandler( const Reference< XInterface >& rxHandler )
	{
		Reference< XIntrospectionAccess > xIntrospectionAccess;
		static Reference< XIntrospection > xIntrospection;

		if( !rxHandler.is() )
			return xIntrospectionAccess;

		if( !xIntrospection.is() )
		{
			Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
			if ( !xSMgr.is() )
			{
				throw RuntimeException(
					::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::getIntrospectionAccess: Couldn't instantiate MultiComponent factory" ) ),
						Reference< XInterface >() );
			}

			// Get introspection service
			Reference< XInterface > xI = xSMgr->createInstanceWithContext
				( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection"), m_xContext );
			if (xI.is())
				xIntrospection = Reference< XIntrospection >::query( xI );
		}

		if( xIntrospection.is() )
		{
			// Do introspection
			try
			{
		        Any aHandlerAny;
				aHandlerAny <<= rxHandler;
				xIntrospectionAccess = xIntrospection->inspect( aHandlerAny );
			}
			catch( RuntimeException& )
			{
				xIntrospectionAccess.clear();
			}
		}
		return xIntrospectionAccess;
	}


    // -----------------------------------------------------------------------------
    // XServiceInfo
    // -----------------------------------------------------------------------------

    ::rtl::OUString DialogProviderImpl::getImplementationName(  ) throw (RuntimeException)
    {
        return getImplementationName_DialogProviderImpl();
    }

    // -----------------------------------------------------------------------------

    sal_Bool DialogProviderImpl::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
    {
	    Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
	    const ::rtl::OUString* pNames = aNames.getConstArray();
	    const ::rtl::OUString* pEnd = pNames + aNames.getLength();
	    for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
		    ;

	    return pNames != pEnd;
    }

    // -----------------------------------------------------------------------------

    Sequence< ::rtl::OUString > DialogProviderImpl::getSupportedServiceNames(  ) throw (RuntimeException)
    {
        return getSupportedServiceNames_DialogProviderImpl();
    }

    // -----------------------------------------------------------------------------
    // XInitialization
    // -----------------------------------------------------------------------------

    void DialogProviderImpl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
    {
        ::osl::MutexGuard aGuard( getMutex() );

        if ( aArguments.getLength() == 1 )
        {
            aArguments[0] >>= m_xModel;

            if ( !m_xModel.is() )
            {
                throw RuntimeException(
                    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::initialize: invalid argument format!" ) ),
                    Reference< XInterface >() );
            }
        }
        else if ( aArguments.getLength() == 4 )
        {
            // call from RTL_Impl_CreateUnoDialog
            aArguments[0] >>= m_xModel;
            m_BasicInfo.reset( new BasicRTLParams() );
            m_BasicInfo->mxInput.set( aArguments[ 1 ], UNO_QUERY_THROW );
            m_BasicInfo->mxDlgLib.set( aArguments[ 2 ], UNO_QUERY_THROW );
            // leave the possibility to optionally allow the old dialog creation
            // to use the new XScriptListener ( which converts the old style macro
            // to a SF url )
            m_BasicInfo->mxBasicRTLListener.set( aArguments[ 3 ], UNO_QUERY);
        }
        else if ( aArguments.getLength() > 4 )
        {
            throw RuntimeException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::initialize: invalid number of arguments!" ) ),
                Reference< XInterface >() );
        }
    }

    // -----------------------------------------------------------------------------
    // XDialogProvider
    // -----------------------------------------------------------------------------

	static ::rtl::OUString aDecorationPropName =
		::rtl::OUString::createFromAscii( "Decoration" );
	static ::rtl::OUString aTitlePropName =
		::rtl::OUString::createFromAscii( "Title" );

	Reference < XControl > DialogProviderImpl::createDialogImpl(
		const ::rtl::OUString& URL, const Reference< XInterface >& xHandler,
		const Reference< XWindowPeer >& xParent, bool bDialogProviderMode )
			throw (IllegalArgumentException, RuntimeException)
	{
        // if the dialog is located in a document, the document must already be open!

        ::osl::MutexGuard aGuard( getMutex() );


		// m_xHandler = xHandler;

        //Reference< XDialog > xDialog;
		Reference< XControl > xCtrl;
        Reference< XControlModel > xCtrlMod;
        try
        {
            // add support for basic RTL_FUNCTION
            if ( m_BasicInfo.get() )
                xCtrlMod = createDialogModelForBasic();
            else
            {
                OSL_ENSURE( URL.getLength(), "DialogProviderImpl::getDialog: no URL!" );
                xCtrlMod = createDialogModel( URL );
            }
        }
        catch ( const RuntimeException& ) { throw; }
        catch ( const Exception& )
        {
            const Any aError( ::cppu::getCaughtException() );
            throw WrappedTargetRuntimeException( ::rtl::OUString(), *this, aError );
        }
        if ( xCtrlMod.is() )
        {
			// i83963 Force decoration
			if( bDialogProviderMode )
			{
				uno::Reference< beans::XPropertySet > xDlgModPropSet( xCtrlMod, uno::UNO_QUERY );
				if( xDlgModPropSet.is() )
				{
					bool bDecoration = true;
					try
					{
						Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName );
						aDecorationAny >>= bDecoration;
						if( !bDecoration )
						{
							xDlgModPropSet->setPropertyValue( aDecorationPropName, makeAny( true ) );
							xDlgModPropSet->setPropertyValue( aTitlePropName, makeAny( ::rtl::OUString() ) );
						}
					}
					catch( UnknownPropertyException& )
					{}
				}
			}

            xCtrl = Reference< XControl >( createDialogControl( xCtrlMod, xParent ) );
            if ( xCtrl.is() )
            {
                //xDialog = Reference< XDialog >( xCtrl, UNO_QUERY );
	            Reference< XIntrospectionAccess > xIntrospectionAccess = inspectHandler( xHandler );
                attachControlEvents( xCtrl, xHandler, xIntrospectionAccess, bDialogProviderMode );
            }
        }

        return xCtrl;
	}

    Reference < XDialog > DialogProviderImpl::createDialog( const ::rtl::OUString& URL )
        throw (IllegalArgumentException, RuntimeException)
    {
        Reference< XInterface > xDummyHandler;
		Reference< XWindowPeer > xDummyPeer;
		Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xDummyHandler, xDummyPeer, true );
	    Reference< XDialog > xDialog( xControl, UNO_QUERY );
        return xDialog;
    }

	Reference < XDialog > DialogProviderImpl::createDialogWithHandler(
		const ::rtl::OUString& URL, const Reference< XInterface >& xHandler )
			throw (IllegalArgumentException, RuntimeException)
	{
		if( !xHandler.is() )
		{
            throw IllegalArgumentException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::createDialogWithHandler: Invalid xHandler!" ) ),
                Reference< XInterface >(), 1 );
		}
		Reference< XWindowPeer > xDummyPeer;
		Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xDummyPeer, true );
	    Reference< XDialog > xDialog( xControl, UNO_QUERY );
        return xDialog;
	}

    Reference < XDialog > DialogProviderImpl::createDialogWithArguments(
		const ::rtl::OUString& URL, const Sequence< NamedValue >& Arguments )
			throw (IllegalArgumentException, RuntimeException)
	{
        ::comphelper::NamedValueCollection aArguments( Arguments );

        Reference< XWindowPeer > xParentPeer;
        if ( aArguments.has( "ParentWindow" ) )
        {
            const Any aParentWindow( aArguments.get( "ParentWindow" ) );
            if ( !( aParentWindow >>= xParentPeer ) )
            {
                const Reference< XControl > xParentControl( aParentWindow, UNO_QUERY );
                if ( xParentControl.is() )
                    xParentPeer = xParentControl->getPeer();
            }
        }

        const Reference< XInterface > xHandler( aArguments.get( "EventHandler" ), UNO_QUERY );

		Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParentPeer, true );
	    Reference< XDialog > xDialog( xControl, UNO_QUERY );
        return xDialog;
	}

    Reference< XWindow > DialogProviderImpl::createContainerWindow( 
		const ::rtl::OUString& URL, const ::rtl::OUString& WindowType, 
		const Reference< XWindowPeer >& xParent, const Reference< XInterface >& xHandler ) 
			throw (lang::IllegalArgumentException, RuntimeException)
	{
		(void)WindowType;	// for future use
		if( !xParent.is() )
		{
            throw IllegalArgumentException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogProviderImpl::createContainerWindow: Invalid xParent!" ) ),
                Reference< XInterface >(), 1 );
		}
		Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParent, false );
	    Reference< XWindow> xWindow( xControl, UNO_QUERY );
		return xWindow;
	}


    // =============================================================================
    // component operations
    // =============================================================================

    static Reference< XInterface > SAL_CALL create_DialogProviderImpl(
        Reference< XComponentContext > const & xContext )
        SAL_THROW( () )
    {
        return static_cast< lang::XTypeProvider * >( new DialogProviderImpl( xContext ) );
    }

    // -----------------------------------------------------------------------------

    static struct ::cppu::ImplementationEntry s_component_entries [] =
    {
        {create_DialogProviderImpl, getImplementationName_DialogProviderImpl,getSupportedServiceNames_DialogProviderImpl, ::cppu::createSingleComponentFactory,0, 0},
        { &comp_DialogModelProvider::_create,&comp_DialogModelProvider::_getImplementationName,&comp_DialogModelProvider::_getSupportedServiceNames,&::cppu::createSingleComponentFactory, 0, 0 },
        { 0, 0, 0, 0, 0, 0 }
    };

    // -----------------------------------------------------------------------------

//.........................................................................
}	// namespace dlgprov
//.........................................................................


// =============================================================================
// component exports
// =============================================================================

extern "C"
{
    void SAL_CALL component_getImplementationEnvironment( 
        const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
    {
		(void)ppEnv;

        *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
    }

    void * SAL_CALL component_getFactory( 
        const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager,
        registry::XRegistryKey * pRegistryKey )
    {
        return ::cppu::component_getFactoryHelper( 
            pImplName, pServiceManager, pRegistryKey, ::dlgprov::s_component_entries );
    }
}
