/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_scripting.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 ::com::sun::star::awt;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::script;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::document;
using namespace ::sf_misc;

//.........................................................................
namespace dlgprov
{
//.........................................................................

static ::rtl::OUString aResourceResolverPropName = ::rtl::OUString::createFromAscii( "ResourceResolver" );
    // =============================================================================
    // 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 )
    {
        Reference< XMultiComponentFactory > xSMgr_( m_xContext->getServiceManager(), UNO_QUERY_THROW );
        Reference< container::XNameContainer > xControlModel( xSMgr_->createInstanceWithContext( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ), m_xContext ), UNO_QUERY_THROW );
        return xControlModel;
    }

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

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

        // #TODO we really need to detect the source of the Dialog, is it
        // located in the document or not. m_xModel need not be the location of
        // the dialog. E.g. if the dialog was created from basic ( then we just
        // can't tell  where its from )
        // If we are happy to always substitute the form model for the awt
        // one then maybe the presence of a document model is enough to trigger
        // swapping out the models ( or perhaps we only want to do this
        // for vba mode ) there are a number of feasible and valid possibilities
        ::xmlscript::importDialogModel( xInput, xDialogModel, m_xContext, m_xModel );
        // Set resource property
        if( xStringResourceManager.is() )
        {
            Reference< beans::XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY );
            Any aStringResourceManagerAny;
            aStringResourceManagerAny <<= xStringResourceManager;
            xDlgPSet->setPropertyValue( aResourceResolverPropName, aStringResourceManagerAny );
        }

        return xDialogModel;
    }

    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< ::com::sun::star::ucb::XSimpleFileAccess > xSFI =
                Reference< ::com::sun::star::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();
            msDialogLibName = sLibName;
        }

        // import dialog model
        Reference< XControlModel > xCtrlModel;
        if ( xInput.is() && m_xContext.is() )
        {
            Reference< resource::XStringResourceManager > xStringResourceManager;
            if( bSingleDialog )
            {
                INetURLObject aInetObj( aURL );
                ::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_( m_xContext->getServiceManager(), UNO_QUERY_THROW );
                // TODO: Ctor
                xStringResourceManager = Reference< resource::XStringResourceManager >( xSMgr_->createInstanceWithContext
                    ( ::rtl::OUString::createFromAscii( "com.sun.star.resource.StringResourceWithLocation" ),
                        m_xContext ), UNO_QUERY );
                if( xStringResourceManager.is() )
                {
                    Reference< XInitialization > xInit( xStringResourceManager, UNO_QUERY );
                    if( xInit.is() )
                        xInit->initialize( aArgs );
                }
            }
            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, const rtl::OUString& sDialogLibName )
    {
        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 ), msDialogLibName );

                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 );
            // allow null mxDlgLib, a document dialog instantiated from
            // from application basic is unable to provide ( or find ) it's
            // Library
            aArguments[ 2 ] >>= m_BasicInfo->mxDlgLib;
            // 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, msDialogLibName );
            }
        }

        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 (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::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
        },
        { 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;
    }

    sal_Bool SAL_CALL component_writeInfo(
        lang::XMultiServiceFactory * pServiceManager, registry::XRegistryKey * pRegistryKey )
    {
        return ::cppu::component_writeInfoHelper(
            pServiceManager, pRegistryKey, ::dlgprov::s_component_entries );
    }

    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 );
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
