1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/mutex.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/string.hxx>
25 #include <com/sun/star/script/XEventAttacher.hpp>
26 #include <com/sun/star/script/XAllListener.hpp>
27 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
28 #include <com/sun/star/script/XScriptEventsAttacher.hpp>
29 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
30 #include <com/sun/star/script/XLibraryContainer.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/resource/XStringResourceSupplier.hpp>
34 #include <com/sun/star/resource/XStringResourceManager.hpp>
35 #include <com/sun/star/awt/XControlContainer.hpp>
36 #include <com/sun/star/awt/XControlModel.hpp>
37 #include <com/sun/star/awt/XControl.hpp>
38 #include <com/sun/star/awt/XDialog.hpp>
39 #include <com/sun/star/awt/XWindow.hpp>
40 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
42 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
43 #include <com/sun/star/script/provider/XScriptProvider.hpp>
44 #include <com/sun/star/awt/XDialogProvider.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/frame/XDesktop.hpp>
48 #include <com/sun/star/container/XEnumerationAccess.hpp>
49 #include <basic/basicmanagerrepository.hxx>
50 #include <basic/basmgr.hxx>
51 //==================================================================================================
53 #include <xmlscript/xmldlg_imexp.hxx>
54 #include <sbunoobj.hxx>
55 #include <basic/sbstar.hxx>
56 #include <basic/sbmeth.hxx>
57 #include <basic/sbuno.hxx>
58 #include <runtime.hxx>
59 #include <sbintern.hxx>
62 #include <cppuhelper/implbase1.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::uno
;
65 using namespace ::com::sun::star::script
;
66 using namespace ::com::sun::star::resource
;
68 using namespace ::com::sun::star::uno
;
69 using namespace ::com::sun::star::lang
;
70 using namespace ::com::sun::star::beans
;
71 using namespace ::com::sun::star::script
;
72 using namespace ::com::sun::star::container
;
73 using namespace ::com::sun::star::reflection
;
74 using namespace ::com::sun::star::awt
;
75 using namespace ::com::sun::star::io
;
76 using namespace ::cppu
;
77 using namespace ::osl
;
80 void SFURL_firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
, const Reference
< frame::XModel
>& xModel
)
82 OSL_TRACE("SFURL_firing_impl() processing script url %s",
83 ::rtl::OUStringToOString( aScriptEvent
.ScriptCode
,
84 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
87 Reference
< provider::XScriptProvider
> xScriptProvider
;
90 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
91 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
93 xScriptProvider
.set( xSupplier
->getScriptProvider() );
97 Reference
< XComponentContext
> xContext(
98 comphelper::getProcessComponentContext() );
99 Reference
< provider::XScriptProviderFactory
> xFactory(
100 xContext
->getValueByName(
101 OUString("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory")), UNO_QUERY
);
102 OSL_ENSURE( xFactory
.is(), "SFURL_firing_impl: failed to get master script provider factory" );
106 aCtx
<<= OUString("user");
107 xScriptProvider
.set( xFactory
->createScriptProvider( aCtx
), UNO_QUERY
);
111 if ( !xScriptProvider
.is() )
113 OSL_TRACE("SFURL_firing_impl() Failed to create msp");
116 Sequence
< Any
> inArgs( 0 );
117 Sequence
< Any
> outArgs( 0 );
118 Sequence
< sal_Int16
> outIndex
;
120 // get Arguments for script
121 inArgs
= aScriptEvent
.Arguments
;
123 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
127 OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript");
131 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
137 catch ( const RuntimeException
& re
)
139 OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.",
140 ::rtl::OUStringToOString( re
.Message
,
141 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
143 catch ( const Exception
& e
)
145 OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.",
146 ::rtl::OUStringToOString( e
.Message
,
147 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
153 class BasicScriptListener_Impl
: public WeakImplHelper1
< XScriptListener
>
155 StarBASICRef maBasicRef
;
156 Reference
< frame::XModel
> m_xModel
;
158 virtual void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
161 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
162 : maBasicRef( pBasic
), m_xModel( xModel
) {}
164 // Methods of XAllListener
165 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
)
166 throw( RuntimeException
);
167 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
)
168 throw( InvocationTargetException
, RuntimeException
);
170 // Methods of XEventListener
171 virtual void SAL_CALL
disposing(const EventObject
& Source
)
172 throw( RuntimeException
);
175 // Methods XAllListener
176 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
) throw ( RuntimeException
)
178 firing_impl( aScriptEvent
, NULL
);
181 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
182 throw ( InvocationTargetException
, RuntimeException
)
185 firing_impl( aScriptEvent
, &aRetAny
);
189 // Methods XEventListener
190 void BasicScriptListener_Impl::disposing(const EventObject
& ) throw ( RuntimeException
)
193 //SolarMutexGuard aGuard;
198 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
200 if( aScriptEvent
.ScriptType
.compareToAscii( "StarBasic" ) == 0 )
202 // Full qualified name?
203 OUString
aMacro( aScriptEvent
.ScriptCode
);
206 if( comphelper::string::getTokenCount(aMacro
, '.') == 3 )
209 ::rtl::OUString aFullLibName
= aMacro
.getToken( (sal_Int32
)0, (sal_Unicode
)'.', nLast
);
211 sal_Int32 nIndex
= aFullLibName
.indexOf( (sal_Unicode
)':' );
214 aLocation
= aFullLibName
.copy( 0, nIndex
);
215 aLibName
= aFullLibName
.copy( nIndex
+ 1 );
218 OUString aModul
= aMacro
.getToken( (sal_Int32
)0, (sal_Unicode
)'.', nLast
);
219 aMacro
= aMacro
.copy( nLast
);
222 SbxObject
* p
= maBasicRef
;
223 SbxObject
* pParent
= p
->GetParent();
224 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
226 StarBASICRef xAppStandardBasic
;
227 StarBASICRef xDocStandardBasic
;
230 // Own basic must be document library
231 xAppStandardBasic
= (StarBASIC
*)pParentParent
;
232 xDocStandardBasic
= (StarBASIC
*)pParent
;
236 OUString aName
= p
->GetName();
237 if( aName
.equalsAscii("Standard") )
239 // Own basic is doc standard lib
240 xDocStandardBasic
= (StarBASIC
*)p
;
242 xAppStandardBasic
= (StarBASIC
*)pParent
;
246 xAppStandardBasic
= (StarBASIC
*)p
;
249 bool bSearchLib
= true;
250 StarBASICRef xLibSearchBasic
;
251 if( aLocation
.equalsAscii("application") )
253 xLibSearchBasic
= xAppStandardBasic
;
255 else if( aLocation
.equalsAscii("document") )
257 xLibSearchBasic
= xDocStandardBasic
;
263 SbxVariable
* pMethVar
= NULL
;
264 // Be still tolerant and make default search if no search basic exists
265 if( bSearchLib
&& xLibSearchBasic
.Is() )
267 StarBASICRef xLibBasic
;
268 sal_Int16 nCount
= xLibSearchBasic
->GetObjects()->Count();
269 for( sal_Int16 nObj
= -1; nObj
< nCount
; nObj
++ )
274 pBasic
= (StarBASIC
*)xLibSearchBasic
;
278 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get( nObj
);
279 pBasic
= PTR_CAST(StarBASIC
,pVar
);
283 OUString aName
= pBasic
->GetName();
284 if( aName
== aLibName
)
286 // Search only in the lib, not automatically in application basic
287 sal_uInt16 nFlags
= pBasic
->GetFlags();
288 pBasic
->ResetFlag( SBX_GBLSEARCH
);
289 pMethVar
= pBasic
->Find( aMacro
, SbxCLASS_DONTCARE
);
290 pBasic
->SetFlags( nFlags
);
297 // Default: Be tolerant and search everywhere
298 if( (!pMethVar
|| !pMethVar
->ISA(SbMethod
)) && maBasicRef
.Is() )
300 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxCLASS_DONTCARE
);
302 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pMethVar
);
309 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
312 xArray
= new SbxArray
;
313 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
314 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
316 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
317 unoToSbxValue( (SbxVariable
*)xVar
, pArgs
[i
] );
318 xArray
->Put( xVar
, sal::static_int_cast
< sal_uInt16
>(i
+1) );
323 SbxVariableRef xValue
= pRet
? new SbxVariable
: 0;
326 pMeth
->SetParameters( xArray
);
328 pMeth
->Call( xValue
);
331 *pRet
= sbxToUnoValue( xValue
);
333 pMeth
->SetParameters( NULL
);
335 else // scripting framework script
337 //callBasic via scripting framework
338 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
342 Any
implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
346 SbxVariable
* pDlgLibContVar
= pBasic
->Find(rtl::OUString("DialogLibraries"), SbxCLASS_OBJECT
);
347 if( pDlgLibContVar
&& pDlgLibContVar
->ISA(SbUnoObject
) )
349 SbUnoObject
* pDlgLibContUnoObj
= (SbUnoObject
*)(SbxBase
*)pDlgLibContVar
;
350 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
352 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
353 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
354 if( xDlgLibContNameAccess
.is() )
356 Sequence
< ::rtl::OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
357 const ::rtl::OUString
* pLibNames
= aLibNames
.getConstArray();
358 sal_Int32 nLibNameCount
= aLibNames
.getLength();
360 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
362 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
363 // if the library isn't loaded, then the dialog cannot originate from this lib
366 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
368 Reference
< XNameAccess
> xDlgLibNameAccess( aDlgLibAny
, UNO_QUERY
);
369 OSL_ENSURE( xDlgLibNameAccess
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
370 if( xDlgLibNameAccess
.is() )
372 Sequence
< ::rtl::OUString
> aDlgNames
= xDlgLibNameAccess
->getElementNames();
373 const ::rtl::OUString
* pDlgNames
= aDlgNames
.getConstArray();
374 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
376 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
378 Any aDlgAny
= xDlgLibNameAccess
->getByName( pDlgNames
[ iDlg
] );
379 if( aDlgAny
== rDlgAny
)
381 aRetDlgLibAny
= aDlgLibAny
;
390 return aRetDlgLibAny
;
393 Any
implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
396 // Find dialog library for dialog, direct access is not possible here
397 StarBASIC
* pStartedBasic
= (StarBASIC
*)pBasic
;
398 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : NULL
;
399 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : NULL
;
401 SbxObject
* pSearchBasic1
= NULL
;
402 SbxObject
* pSearchBasic2
= NULL
;
403 if( pParentParentBasic
)
405 pSearchBasic1
= pParentBasic
;
406 pSearchBasic2
= pParentParentBasic
;
410 pSearchBasic1
= pStartedBasic
;
411 pSearchBasic2
= pParentBasic
;
415 aDlgLibAny
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
417 if ( aDlgLibAny
.hasValue() )
418 pFoundBasic
= (StarBASIC
*)pSearchBasic1
;
420 else if( pSearchBasic2
)
422 aDlgLibAny
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
423 if ( aDlgLibAny
.hasValue() )
424 pFoundBasic
= (StarBASIC
*)pSearchBasic2
;
430 void RTL_Impl_CreateUnoDialog( StarBASIC
* pBasic
, SbxArray
& rPar
, sal_Bool bWrite
)
435 Reference
< XMultiServiceFactory
> xMSF( comphelper::getProcessServiceFactory() );
439 // We need at least 1 parameter
440 if ( rPar
.Count() < 2 )
442 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
447 SbxBaseRef pObj
= (SbxBase
*)rPar
.Get( 1 )->GetObject();
448 if( !(pObj
&& pObj
->ISA(SbUnoObject
)) )
450 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
453 SbUnoObject
* pUnoObj
= (SbUnoObject
*)(SbxBase
*)pObj
;
454 Any aAnyISP
= pUnoObj
->getUnoAny();
455 TypeClass eType
= aAnyISP
.getValueType().getTypeClass();
457 if( eType
!= TypeClass_INTERFACE
)
459 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
463 // Create new uno dialog
464 Reference
< XNameContainer
> xDialogModel( xMSF
->createInstance(
465 ::rtl::OUString("com.sun.star.awt.UnoControlDialogModel")), UNO_QUERY
);
466 if( !xDialogModel
.is() )
470 Reference
< XInputStreamProvider
> xISP
;
476 Reference
< XComponentContext
> xContext(
477 comphelper::getComponentContext( xMSF
) );
479 // Import the DialogModel
480 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
482 // i83963 Force decoration
483 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
484 if( xDlgModPropSet
.is() )
486 bool bDecoration
= true;
489 OUString
aDecorationPropName("Decoration");
490 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
491 aDecorationAny
>>= bDecoration
;
494 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, makeAny( true ) );
496 OUString
aTitlePropName("Title");
497 xDlgModPropSet
->setPropertyValue( aTitlePropName
, makeAny( OUString() ) );
500 catch(const UnknownPropertyException
& )
505 bool bDocDialog
= false;
506 StarBASIC
* pFoundBasic
= NULL
;
507 OSL_TRACE("About to try get a hold of ThisComponent");
508 Reference
< frame::XModel
> xModel
= StarBASIC::GetModelFromBasic( GetSbData()->pInst
->GetBasic() ) ;
509 aDlgLibAny
= implFindDialogLibForDialogBasic( aAnyISP
, GetSbData()->pInst
->GetBasic(), pFoundBasic
);
510 // If we found the dialog then it belongs to the Search basic
513 Reference
< frame::XDesktop
> xDesktop( xMSF
->createInstance(OUString("com.sun.star.frame.Desktop")), UNO_QUERY
);
514 Reference
< container::XEnumeration
> xModels
;
517 Reference
< container::XEnumerationAccess
> xComponents( xDesktop
->getComponents(), UNO_QUERY
);
518 if ( xComponents
.is() )
520 xModels
.set( xComponents
->createEnumeration(), UNO_QUERY
);
524 while ( xModels
->hasMoreElements() )
526 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
527 if ( xNextModel
.is() )
529 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
532 aDlgLibAny
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
534 if ( aDlgLibAny
.hasValue() )
547 bDocDialog
= pFoundBasic
->IsDocBasic();
549 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( GetSbData()->pInst
->GetBasic(), xModel
);
551 Sequence
< Any
> aArgs( 4 );
554 aArgs
[ 0 ] <<= xModel
;
558 aArgs
[ 0 ] <<= uno::Reference
< uno::XInterface
>();
560 aArgs
[ 1 ] <<= xInput
;
561 aArgs
[ 2 ] = aDlgLibAny
;
562 aArgs
[ 3 ] <<= xScriptListener
;
563 // Create a "living" Dialog
564 Reference
< XControl
> xCntrl
;
567 Reference
< XDialogProvider
> xDlgProv( xMSF
->createInstanceWithArguments(OUString("com.sun.star.comp.scripting.DialogProvider" ), aArgs
), UNO_QUERY
);
568 xCntrl
.set( xDlgProv
->createDialog(OUString() ), UNO_QUERY_THROW
);
569 // Add dialog model to dispose vector
570 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
571 GetSbData()->pInst
->getComponentVector().push_back( xDlgComponent
);
572 // need ThisCompoent from calling script
574 // preserve existing bad behaviour, it's possible... but probably
575 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
576 // create dialog fails. So, in this case let's not throw, just leave basic
577 // detect the unset object.
578 catch(const uno::Exception
& )
585 SbxVariableRef refVar
= rPar
.Get(0);
586 unoToSbxValue( (SbxVariable
*)refVar
, aRetVal
);
590 //===================================================================
592 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */