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 <comphelper/processfactory.hxx>
22 #include <comphelper/string.hxx>
24 #include <com/sun/star/awt/XControlContainer.hpp>
25 #include <com/sun/star/awt/XControl.hpp>
26 #include <com/sun/star/awt/DialogProvider.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/container/XEnumerationAccess.hpp>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/frame/Desktop.hpp>
32 #include <com/sun/star/script/XLibraryContainer.hpp>
33 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
34 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
35 #include <com/sun/star/script/provider/XScriptProvider.hpp>
36 #include <com/sun/star/io/XInputStreamProvider.hpp>
38 #include <basic/basicmanagerrepository.hxx>
39 #include <basic/basmgr.hxx>
41 #include <sal/log.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <vcl/svapp.hxx>
44 #include <sbunoobj.hxx>
45 #include <basic/sberrors.hxx>
46 #include <basic/sbstar.hxx>
47 #include <basic/sbmeth.hxx>
48 #include <basic/sbuno.hxx>
49 #include <runtime.hxx>
50 #include <sbintern.hxx>
51 #include <eventatt.hxx>
53 #include <cppuhelper/implbase.hxx>
55 using namespace ::com::sun::star
;
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::script
;
58 using namespace ::com::sun::star::lang
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::container
;
61 using namespace ::com::sun::star::reflection
;
62 using namespace ::com::sun::star::awt
;
63 using namespace ::com::sun::star::io
;
64 using namespace ::cppu
;
68 void SFURL_firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
, const Reference
< frame::XModel
>& xModel
)
70 SAL_INFO("basic", "Processing script url " << aScriptEvent
.ScriptCode
);
73 Reference
< provider::XScriptProvider
> xScriptProvider
;
76 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
77 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
79 xScriptProvider
.set( xSupplier
->getScriptProvider() );
83 Reference
< XComponentContext
> xContext(
84 comphelper::getProcessComponentContext() );
85 Reference
< provider::XScriptProviderFactory
> xFactory
=
86 provider::theMasterScriptProviderFactory::get( xContext
);
89 aCtx
<<= OUString("user");
90 xScriptProvider
= xFactory
->createScriptProvider( aCtx
);
93 if ( !xScriptProvider
.is() )
95 SAL_INFO("basic", "Failed to create msp");
98 Sequence
< Any
> inArgs( 0 );
99 Sequence
< Any
> outArgs( 0 );
100 Sequence
< sal_Int16
> outIndex
;
102 // get Arguments for script
103 inArgs
= aScriptEvent
.Arguments
;
105 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
109 SAL_INFO("basic", "Failed to Failed to obtain XScript");
113 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
119 catch ( const RuntimeException
& )
121 TOOLS_INFO_EXCEPTION("basic", "" );
123 catch ( const Exception
& )
125 TOOLS_INFO_EXCEPTION("basic", "" );
131 class BasicScriptListener_Impl
: public WeakImplHelper
< XScriptListener
>
133 StarBASICRef maBasicRef
;
134 Reference
< frame::XModel
> m_xModel
;
136 void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
139 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
140 : maBasicRef( pBasic
), m_xModel( xModel
) {}
142 // Methods of XAllListener
143 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
) override
;
144 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
) override
;
146 // Methods of XEventListener
147 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
150 // Methods XAllListener
151 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
)
155 firing_impl( aScriptEvent
, nullptr );
158 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
163 firing_impl( aScriptEvent
, &aRetAny
);
167 // Methods XEventListener
168 void BasicScriptListener_Impl::disposing(const EventObject
& )
171 //SolarMutexGuard aGuard;
176 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
178 if( aScriptEvent
.ScriptType
== "StarBasic" )
180 // Full qualified name?
181 OUString
aMacro( aScriptEvent
.ScriptCode
);
184 if( comphelper::string::getTokenCount(aMacro
, '.') == 3 )
187 OUString aFullLibName
= aMacro
.getToken( 0, '.', nLast
);
189 sal_Int32 nIndex
= aFullLibName
.indexOf( ':' );
192 aLocation
= aFullLibName
.copy( 0, nIndex
);
193 aLibName
= aFullLibName
.copy( nIndex
+ 1 );
196 aMacro
= aMacro
.copy( nLast
);
199 SbxObject
* p
= maBasicRef
.get();
200 SbxObject
* pParent
= p
->GetParent();
201 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : nullptr;
203 StarBASICRef xAppStandardBasic
;
204 StarBASICRef xDocStandardBasic
;
207 // Own basic must be document library
208 xAppStandardBasic
= static_cast<StarBASIC
*>(pParentParent
);
209 xDocStandardBasic
= static_cast<StarBASIC
*>(pParent
);
213 OUString aName
= p
->GetName();
214 if( aName
== "Standard" )
216 // Own basic is doc standard lib
217 xDocStandardBasic
= static_cast<StarBASIC
*>(p
);
219 xAppStandardBasic
= static_cast<StarBASIC
*>(pParent
);
223 xAppStandardBasic
= static_cast<StarBASIC
*>(p
);
226 bool bSearchLib
= true;
227 StarBASICRef xLibSearchBasic
;
228 if( aLocation
== "application" )
230 xLibSearchBasic
= xAppStandardBasic
;
232 else if( aLocation
== "document" )
234 xLibSearchBasic
= xDocStandardBasic
;
240 SbxVariable
* pMethVar
= nullptr;
241 // Be still tolerant and make default search if no search basic exists
242 if( bSearchLib
&& xLibSearchBasic
.is() )
244 sal_Int16 nCount
= xLibSearchBasic
->GetObjects()->Count();
245 for( sal_Int16 nObj
= -1; nObj
< nCount
; nObj
++ )
250 pBasic
= xLibSearchBasic
.get();
254 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get( nObj
);
255 pBasic
= dynamic_cast<StarBASIC
*>( pVar
);
259 OUString aName
= pBasic
->GetName();
260 if( aName
== aLibName
)
262 // Search only in the lib, not automatically in application basic
263 SbxFlagBits nFlags
= pBasic
->GetFlags();
264 pBasic
->ResetFlag( SbxFlagBits::GlobalSearch
);
265 pMethVar
= pBasic
->Find( aMacro
, SbxClassType::DontCare
);
266 pBasic
->SetFlags( nFlags
);
273 // Default: Be tolerant and search everywhere
274 if( (!pMethVar
|| dynamic_cast<const SbMethod
*>( pMethVar
) == nullptr) && maBasicRef
.is() )
276 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxClassType::DontCare
);
278 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pMethVar
);
285 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
288 xArray
= new SbxArray
;
289 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
290 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
292 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
293 unoToSbxValue( xVar
.get(), pArgs
[i
] );
294 xArray
->Put( xVar
.get(), sal::static_int_cast
< sal_uInt16
>(i
+1) );
299 SbxVariableRef xValue
= pRet
? new SbxVariable
: nullptr;
302 pMeth
->SetParameters( xArray
.get() );
304 pMeth
->Call( xValue
.get() );
307 *pRet
= sbxToUnoValue( xValue
.get() );
309 pMeth
->SetParameters( nullptr );
311 else // scripting framework script
313 //callBasic via scripting framework
314 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
318 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
320 css::uno::Reference
< css::container::XNameContainer
> aRetDlgLib
;
322 SbxVariable
* pDlgLibContVar
= pBasic
->Find("DialogLibraries", SbxClassType::Object
);
323 if( auto pDlgLibContUnoObj
= dynamic_cast<SbUnoObject
*>( pDlgLibContVar
) )
325 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
327 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
328 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
329 if( xDlgLibContNameAccess
.is() )
331 Sequence
< OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
332 const OUString
* pLibNames
= aLibNames
.getConstArray();
333 sal_Int32 nLibNameCount
= aLibNames
.getLength();
335 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
337 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
338 // if the library isn't loaded, then the dialog cannot originate from this lib
341 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
343 Reference
< XNameContainer
> xDlgLibNameCont( aDlgLibAny
, UNO_QUERY
);
344 OSL_ENSURE( xDlgLibNameCont
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
345 if( xDlgLibNameCont
.is() )
347 Sequence
< OUString
> aDlgNames
= xDlgLibNameCont
->getElementNames();
348 const OUString
* pDlgNames
= aDlgNames
.getConstArray();
349 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
351 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
353 Any aDlgAny
= xDlgLibNameCont
->getByName( pDlgNames
[ iDlg
] );
354 if( aDlgAny
== rDlgAny
)
356 aRetDlgLib
= xDlgLibNameCont
;
368 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
370 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
371 // Find dialog library for dialog, direct access is not possible here
372 StarBASIC
* pStartedBasic
= static_cast<StarBASIC
*>(pBasic
);
373 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : nullptr;
374 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : nullptr;
376 SbxObject
* pSearchBasic1
= nullptr;
377 SbxObject
* pSearchBasic2
= nullptr;
378 if( pParentParentBasic
)
380 pSearchBasic1
= pParentBasic
;
381 pSearchBasic2
= pParentParentBasic
;
385 pSearchBasic1
= pStartedBasic
;
386 pSearchBasic2
= pParentBasic
;
390 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
393 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic1
);
395 else if( pSearchBasic2
)
397 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
399 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic2
);
407 void RTL_Impl_CreateUnoDialog( SbxArray
& rPar
)
409 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
411 // We need at least 1 parameter
412 if ( rPar
.Count() < 2 )
414 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
419 SbxBaseRef pObj
= rPar
.Get( 1 )->GetObject();
420 if( !(pObj
.is() && dynamic_cast<const SbUnoObject
*>( pObj
.get() ) != nullptr) )
422 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
425 SbUnoObject
* pUnoObj
= static_cast<SbUnoObject
*>(pObj
.get());
426 Any aAnyISP
= pUnoObj
->getUnoAny();
427 TypeClass eType
= aAnyISP
.getValueType().getTypeClass();
429 if( eType
!= TypeClass_INTERFACE
)
431 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
435 // Create new uno dialog
436 Reference
< XNameContainer
> xDialogModel( xContext
->getServiceManager()->createInstanceWithContext(
437 "com.sun.star.awt.UnoControlDialogModel", xContext
), UNO_QUERY
);
438 if( !xDialogModel
.is() )
442 Reference
< XInputStreamProvider
> xISP
;
449 // Import the DialogModel
450 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
452 // i83963 Force decoration
453 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
454 if( xDlgModPropSet
.is() )
458 bool bDecoration
= true;
459 OUString
aDecorationPropName("Decoration");
460 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
461 aDecorationAny
>>= bDecoration
;
464 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, Any( true ) );
465 xDlgModPropSet
->setPropertyValue( "Title", Any( OUString() ) );
468 catch(const UnknownPropertyException
& )
472 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
473 bool bDocDialog
= false;
474 StarBASIC
* pFoundBasic
= nullptr;
475 SAL_INFO("basic", "About to try get a hold of ThisComponent");
476 Reference
< frame::XModel
> xModel
= StarBASIC::GetModelFromBasic( GetSbData()->pInst
->GetBasic() ) ;
477 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, GetSbData()->pInst
->GetBasic(), pFoundBasic
);
478 // If we found the dialog then it belongs to the Search basic
481 Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( xContext
);
482 Reference
< container::XEnumeration
> xModels
;
483 Reference
< container::XEnumerationAccess
> xComponents
= xDesktop
->getComponents();
484 if ( xComponents
.is() )
486 xModels
= xComponents
->createEnumeration();
490 while ( xModels
->hasMoreElements() )
492 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
493 if ( xNextModel
.is() )
495 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
498 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
512 bDocDialog
= pFoundBasic
->IsDocBasic();
514 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( GetSbData()->pInst
->GetBasic(), xModel
);
516 // Create a "living" Dialog
517 Reference
< XControl
> xCntrl
;
520 Reference
< XDialogProvider
> xDlgProv
;
522 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, xModel
, xInput
, aDlgLib
, xScriptListener
);
524 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, uno::Reference
< frame::XModel
>(), xInput
, aDlgLib
, xScriptListener
);
526 xCntrl
.set( xDlgProv
->createDialog(OUString() ), UNO_QUERY_THROW
);
527 // Add dialog model to dispose vector
528 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
529 GetSbData()->pInst
->getComponentVector().push_back( xDlgComponent
);
530 // need ThisComponent from calling script
532 // preserve existing bad behaviour, it's possible... but probably
533 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
534 // create dialog fails. So, in this case let's not throw, just leave basic
535 // detect the unset object.
536 catch(const uno::Exception
& )
543 SbxVariableRef refVar
= rPar
.Get(0);
544 unoToSbxValue( refVar
.get(), aRetVal
);
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */