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/awt/XControlContainer.hpp>
26 #include <com/sun/star/awt/XControlModel.hpp>
27 #include <com/sun/star/awt/XControl.hpp>
28 #include <com/sun/star/awt/XDialog.hpp>
29 #include <com/sun/star/awt/XWindow.hpp>
30 #include <com/sun/star/awt/DialogProvider.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/container/XEnumerationAccess.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/Desktop.hpp>
36 #include <com/sun/star/resource/XStringResourceSupplier.hpp>
37 #include <com/sun/star/resource/XStringResourceManager.hpp>
38 #include <com/sun/star/script/XEventAttacher.hpp>
39 #include <com/sun/star/script/XAllListener.hpp>
40 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
41 #include <com/sun/star/script/XScriptEventsAttacher.hpp>
42 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
43 #include <com/sun/star/script/XLibraryContainer.hpp>
44 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
45 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
46 #include <com/sun/star/script/provider/XScriptProvider.hpp>
48 #include <basic/basicmanagerrepository.hxx>
49 #include <basic/basmgr.hxx>
51 #include <vcl/svapp.hxx>
52 #include <xmlscript/xmldlg_imexp.hxx>
53 #include <sbunoobj.hxx>
54 #include <basic/sbstar.hxx>
55 #include <basic/sbmeth.hxx>
56 #include <basic/sbuno.hxx>
57 #include <runtime.hxx>
58 #include <sbintern.hxx>
59 #include <eventatt.hxx>
61 #include <cppuhelper/implbase1.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::uno
;
64 using namespace ::com::sun::star::script
;
65 using namespace ::com::sun::star::resource
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::beans
;
68 using namespace ::com::sun::star::container
;
69 using namespace ::com::sun::star::reflection
;
70 using namespace ::com::sun::star::awt
;
71 using namespace ::com::sun::star::io
;
72 using namespace ::cppu
;
73 using namespace ::osl
;
76 void SFURL_firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
, const Reference
< frame::XModel
>& xModel
)
78 SAL_INFO("basic", "Processing script url " << aScriptEvent
.ScriptCode
);
81 Reference
< provider::XScriptProvider
> xScriptProvider
;
84 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
85 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
87 xScriptProvider
.set( xSupplier
->getScriptProvider() );
91 Reference
< XComponentContext
> xContext(
92 comphelper::getProcessComponentContext() );
93 Reference
< provider::XScriptProviderFactory
> xFactory
=
94 provider::theMasterScriptProviderFactory::get( xContext
);
97 aCtx
<<= OUString("user");
98 xScriptProvider
.set( xFactory
->createScriptProvider( aCtx
), UNO_QUERY
);
101 if ( !xScriptProvider
.is() )
103 SAL_INFO("basic", "Failed to create msp");
106 Sequence
< Any
> inArgs( 0 );
107 Sequence
< Any
> outArgs( 0 );
108 Sequence
< sal_Int16
> outIndex
;
110 // get Arguments for script
111 inArgs
= aScriptEvent
.Arguments
;
113 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
117 SAL_INFO("basic", "Failed to Failed to obtain XScript");
121 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
127 catch ( const RuntimeException
& re
)
129 SAL_INFO("basic", "Caught RuntimeException reason " << re
.Message
);
131 catch ( const Exception
& e
)
133 SAL_INFO("basic", "Caught Exception reason " << e
.Message
);
139 class BasicScriptListener_Impl
: public WeakImplHelper1
< XScriptListener
>
141 StarBASICRef maBasicRef
;
142 Reference
< frame::XModel
> m_xModel
;
144 void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
147 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
148 : maBasicRef( pBasic
), m_xModel( xModel
) {}
150 // Methods of XAllListener
151 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
)
152 throw( RuntimeException
, std::exception
) SAL_OVERRIDE
;
153 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
)
154 throw( InvocationTargetException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
156 // Methods of XEventListener
157 virtual void SAL_CALL
disposing(const EventObject
& Source
)
158 throw( RuntimeException
, std::exception
) SAL_OVERRIDE
;
161 // Methods XAllListener
162 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
) throw ( RuntimeException
, std::exception
)
166 firing_impl( aScriptEvent
, NULL
);
169 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
170 throw ( InvocationTargetException
, RuntimeException
, std::exception
)
175 firing_impl( aScriptEvent
, &aRetAny
);
179 // Methods XEventListener
180 void BasicScriptListener_Impl::disposing(const EventObject
& ) throw ( RuntimeException
, std::exception
)
183 //SolarMutexGuard aGuard;
188 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
190 if( aScriptEvent
.ScriptType
== "StarBasic" )
192 // Full qualified name?
193 OUString
aMacro( aScriptEvent
.ScriptCode
);
196 if( comphelper::string::getTokenCount(aMacro
, '.') == 3 )
199 OUString aFullLibName
= aMacro
.getToken( (sal_Int32
)0, (sal_Unicode
)'.', nLast
);
201 sal_Int32 nIndex
= aFullLibName
.indexOf( (sal_Unicode
)':' );
204 aLocation
= aFullLibName
.copy( 0, nIndex
);
205 aLibName
= aFullLibName
.copy( nIndex
+ 1 );
208 aMacro
= aMacro
.copy( nLast
);
211 SbxObject
* p
= maBasicRef
;
212 SbxObject
* pParent
= p
->GetParent();
213 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
215 StarBASICRef xAppStandardBasic
;
216 StarBASICRef xDocStandardBasic
;
219 // Own basic must be document library
220 xAppStandardBasic
= static_cast<StarBASIC
*>(pParentParent
);
221 xDocStandardBasic
= static_cast<StarBASIC
*>(pParent
);
225 OUString aName
= p
->GetName();
226 if( aName
== "Standard" )
228 // Own basic is doc standard lib
229 xDocStandardBasic
= static_cast<StarBASIC
*>(p
);
231 xAppStandardBasic
= static_cast<StarBASIC
*>(pParent
);
235 xAppStandardBasic
= static_cast<StarBASIC
*>(p
);
238 bool bSearchLib
= true;
239 StarBASICRef xLibSearchBasic
;
240 if( aLocation
== "application" )
242 xLibSearchBasic
= xAppStandardBasic
;
244 else if( aLocation
== "document" )
246 xLibSearchBasic
= xDocStandardBasic
;
252 SbxVariable
* pMethVar
= NULL
;
253 // Be still tolerant and make default search if no search basic exists
254 if( bSearchLib
&& xLibSearchBasic
.Is() )
256 StarBASICRef xLibBasic
;
257 sal_Int16 nCount
= xLibSearchBasic
->GetObjects()->Count();
258 for( sal_Int16 nObj
= -1; nObj
< nCount
; nObj
++ )
263 pBasic
= (StarBASIC
*)xLibSearchBasic
;
267 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get( nObj
);
268 pBasic
= PTR_CAST(StarBASIC
,pVar
);
272 OUString aName
= pBasic
->GetName();
273 if( aName
== aLibName
)
275 // Search only in the lib, not automatically in application basic
276 SbxFlagBits nFlags
= pBasic
->GetFlags();
277 pBasic
->ResetFlag( SBX_GBLSEARCH
);
278 pMethVar
= pBasic
->Find( aMacro
, SbxCLASS_DONTCARE
);
279 pBasic
->SetFlags( nFlags
);
286 // Default: Be tolerant and search everywhere
287 if( (!pMethVar
|| !pMethVar
->ISA(SbMethod
)) && maBasicRef
.Is() )
289 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxCLASS_DONTCARE
);
291 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pMethVar
);
298 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
301 xArray
= new SbxArray
;
302 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
303 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
305 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
306 unoToSbxValue( (SbxVariable
*)xVar
, pArgs
[i
] );
307 xArray
->Put( xVar
, sal::static_int_cast
< sal_uInt16
>(i
+1) );
312 SbxVariableRef xValue
= pRet
? new SbxVariable
: 0;
315 pMeth
->SetParameters( xArray
);
317 pMeth
->Call( xValue
);
320 *pRet
= sbxToUnoValue( xValue
);
322 pMeth
->SetParameters( NULL
);
324 else // scripting framework script
326 //callBasic via scripting framework
327 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
331 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
333 css::uno::Reference
< css::container::XNameContainer
> aRetDlgLib
;
335 SbxVariable
* pDlgLibContVar
= pBasic
->Find(OUString("DialogLibraries"), SbxCLASS_OBJECT
);
336 if( pDlgLibContVar
&& pDlgLibContVar
->ISA(SbUnoObject
) )
338 SbUnoObject
* pDlgLibContUnoObj
= static_cast<SbUnoObject
*>((SbxBase
*)pDlgLibContVar
);
339 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
341 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
342 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
343 if( xDlgLibContNameAccess
.is() )
345 Sequence
< OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
346 const OUString
* pLibNames
= aLibNames
.getConstArray();
347 sal_Int32 nLibNameCount
= aLibNames
.getLength();
349 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
351 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
352 // if the library isn't loaded, then the dialog cannot originate from this lib
355 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
357 Reference
< XNameContainer
> xDlgLibNameCont( aDlgLibAny
, UNO_QUERY
);
358 OSL_ENSURE( xDlgLibNameCont
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
359 if( xDlgLibNameCont
.is() )
361 Sequence
< OUString
> aDlgNames
= xDlgLibNameCont
->getElementNames();
362 const OUString
* pDlgNames
= aDlgNames
.getConstArray();
363 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
365 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
367 Any aDlgAny
= xDlgLibNameCont
->getByName( pDlgNames
[ iDlg
] );
368 if( aDlgAny
== rDlgAny
)
370 aRetDlgLib
= xDlgLibNameCont
;
382 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
384 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
385 // Find dialog library for dialog, direct access is not possible here
386 StarBASIC
* pStartedBasic
= static_cast<StarBASIC
*>(pBasic
);
387 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : NULL
;
388 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : NULL
;
390 SbxObject
* pSearchBasic1
= NULL
;
391 SbxObject
* pSearchBasic2
= NULL
;
392 if( pParentParentBasic
)
394 pSearchBasic1
= pParentBasic
;
395 pSearchBasic2
= pParentParentBasic
;
399 pSearchBasic1
= pStartedBasic
;
400 pSearchBasic2
= pParentBasic
;
404 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
407 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic1
);
409 else if( pSearchBasic2
)
411 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
413 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic2
);
419 void RTL_Impl_CreateUnoDialog( StarBASIC
* pBasic
, SbxArray
& rPar
, bool bWrite
)
424 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
426 // We need at least 1 parameter
427 if ( rPar
.Count() < 2 )
429 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
434 SbxBaseRef pObj
= rPar
.Get( 1 )->GetObject();
435 if( !(pObj
&& pObj
->ISA(SbUnoObject
)) )
437 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
440 SbUnoObject
* pUnoObj
= static_cast<SbUnoObject
*>((SbxBase
*)pObj
);
441 Any aAnyISP
= pUnoObj
->getUnoAny();
442 TypeClass eType
= aAnyISP
.getValueType().getTypeClass();
444 if( eType
!= TypeClass_INTERFACE
)
446 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
450 // Create new uno dialog
451 Reference
< XNameContainer
> xDialogModel( xContext
->getServiceManager()->createInstanceWithContext(
452 "com.sun.star.awt.UnoControlDialogModel", xContext
), UNO_QUERY
);
453 if( !xDialogModel
.is() )
457 Reference
< XInputStreamProvider
> xISP
;
464 // Import the DialogModel
465 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
467 // i83963 Force decoration
468 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
469 if( xDlgModPropSet
.is() )
473 bool bDecoration
= true;
474 OUString
aDecorationPropName("Decoration");
475 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
476 aDecorationAny
>>= bDecoration
;
479 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, makeAny( true ) );
481 OUString
aTitlePropName("Title");
482 xDlgModPropSet
->setPropertyValue( aTitlePropName
, makeAny( OUString() ) );
485 catch(const UnknownPropertyException
& )
489 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
490 bool bDocDialog
= false;
491 StarBASIC
* pFoundBasic
= NULL
;
492 SAL_INFO("basic", "About to try get a hold of ThisComponent");
493 Reference
< frame::XModel
> xModel
= StarBASIC::GetModelFromBasic( GetSbData()->pInst
->GetBasic() ) ;
494 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, GetSbData()->pInst
->GetBasic(), pFoundBasic
);
495 // If we found the dialog then it belongs to the Search basic
498 Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( xContext
);
499 Reference
< container::XEnumeration
> xModels
;
500 Reference
< container::XEnumerationAccess
> xComponents( xDesktop
->getComponents(), UNO_QUERY
);
501 if ( xComponents
.is() )
503 xModels
.set( xComponents
->createEnumeration(), UNO_QUERY
);
507 while ( xModels
->hasMoreElements() )
509 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
510 if ( xNextModel
.is() )
512 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
515 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
529 bDocDialog
= pFoundBasic
->IsDocBasic();
531 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( GetSbData()->pInst
->GetBasic(), xModel
);
533 // Create a "living" Dialog
534 Reference
< XControl
> xCntrl
;
537 Reference
< XDialogProvider
> xDlgProv
;;
539 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, xModel
, xInput
, aDlgLib
, xScriptListener
);
541 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, uno::Reference
< frame::XModel
>(), xInput
, aDlgLib
, xScriptListener
);
543 xCntrl
.set( xDlgProv
->createDialog(OUString() ), UNO_QUERY_THROW
);
544 // Add dialog model to dispose vector
545 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
546 GetSbData()->pInst
->getComponentVector().push_back( xDlgComponent
);
547 // need ThisCompoent from calling script
549 // preserve existing bad behaviour, it's possible... but probably
550 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
551 // create dialog fails. So, in this case let's not throw, just leave basic
552 // detect the unset object.
553 catch(const uno::Exception
& )
560 SbxVariableRef refVar
= rPar
.Get(0);
561 unoToSbxValue( (SbxVariable
*)refVar
, aRetVal
);
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */