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 <comphelper/diagnose_ex.hxx>
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::awt
;
62 using namespace ::com::sun::star::io
;
63 using namespace ::cppu
;
67 void SFURL_firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
, const Reference
< frame::XModel
>& xModel
)
69 SAL_INFO("basic", "Processing script url " << aScriptEvent
.ScriptCode
);
72 Reference
< provider::XScriptProvider
> xScriptProvider
;
75 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
76 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
78 xScriptProvider
.set( xSupplier
->getScriptProvider() );
82 const Reference
< XComponentContext
>& xContext(
83 comphelper::getProcessComponentContext() );
84 Reference
< provider::XScriptProviderFactory
> xFactory
=
85 provider::theMasterScriptProviderFactory::get( xContext
);
88 aCtx
<<= u
"user"_ustr
;
89 xScriptProvider
= xFactory
->createScriptProvider( aCtx
);
92 if ( !xScriptProvider
.is() )
94 SAL_INFO("basic", "Failed to create msp");
97 Sequence
< Any
> inArgs( 0 );
98 Sequence
< Any
> outArgs( 0 );
99 Sequence
< sal_Int16
> outIndex
;
101 // get Arguments for script
102 inArgs
= aScriptEvent
.Arguments
;
104 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
108 SAL_INFO("basic", "Failed to Failed to obtain XScript");
112 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
115 *pRet
= std::move(result
);
118 catch ( const RuntimeException
& )
120 TOOLS_INFO_EXCEPTION("basic", "" );
122 catch ( const Exception
& )
124 TOOLS_INFO_EXCEPTION("basic", "" );
130 class BasicScriptListener_Impl
: public WeakImplHelper
< XScriptListener
>
132 StarBASICRef maBasicRef
;
133 Reference
< frame::XModel
> m_xModel
;
135 void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
138 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
139 : maBasicRef( pBasic
), m_xModel( xModel
) {}
141 // Methods of XAllListener
142 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
) override
;
143 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
) override
;
145 // Methods of XEventListener
146 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
149 // Methods XAllListener
150 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
)
154 firing_impl( aScriptEvent
, nullptr );
157 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
162 firing_impl( aScriptEvent
, &aRetAny
);
166 // Methods XEventListener
167 void BasicScriptListener_Impl::disposing(const EventObject
& )
170 //SolarMutexGuard aGuard;
175 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
177 if( aScriptEvent
.ScriptType
== "StarBasic" )
179 // Full qualified name?
180 OUString
aMacro( aScriptEvent
.ScriptCode
);
183 if( comphelper::string::getTokenCount(aMacro
, '.') == 3 )
186 std::u16string_view aFullLibName
= o3tl::getToken(aMacro
, 0, '.', nLast
);
188 size_t nIndex
= aFullLibName
.find( ':' );
189 if (nIndex
!= std::u16string_view::npos
)
191 aLocation
= aFullLibName
.substr( 0, nIndex
);
192 aLibName
= aFullLibName
.substr( nIndex
+ 1 );
195 aMacro
= aMacro
.copy( nLast
);
198 SbxObject
* p
= maBasicRef
.get();
199 SbxObject
* pParent
= p
->GetParent();
200 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : nullptr;
202 StarBASICRef xAppStandardBasic
;
203 StarBASICRef xDocStandardBasic
;
206 // Own basic must be document library
207 xAppStandardBasic
= static_cast<StarBASIC
*>(pParentParent
);
208 xDocStandardBasic
= static_cast<StarBASIC
*>(pParent
);
212 OUString aName
= p
->GetName();
213 if( aName
== "Standard" )
215 // Own basic is doc standard lib
216 xDocStandardBasic
= static_cast<StarBASIC
*>(p
);
218 xAppStandardBasic
= static_cast<StarBASIC
*>(pParent
);
222 xAppStandardBasic
= static_cast<StarBASIC
*>(p
);
225 bool bSearchLib
= true;
226 StarBASICRef xLibSearchBasic
;
227 if( aLocation
== "application" )
229 xLibSearchBasic
= std::move(xAppStandardBasic
);
231 else if( aLocation
== "document" )
233 xLibSearchBasic
= std::move(xDocStandardBasic
);
239 SbxVariable
* pMethVar
= nullptr;
240 // Be still tolerant and make default search if no search basic exists
241 if( bSearchLib
&& xLibSearchBasic
.is() )
243 sal_Int32 nCount
= xLibSearchBasic
->GetObjects()->Count();
244 for( sal_Int32 nObj
= -1; nObj
< nCount
; nObj
++ )
249 pBasic
= xLibSearchBasic
.get();
253 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get(nObj
);
254 pBasic
= dynamic_cast<StarBASIC
*>( pVar
);
258 OUString aName
= pBasic
->GetName();
259 if( aName
== aLibName
)
261 // Search only in the lib, not automatically in application basic
262 SbxFlagBits nFlags
= pBasic
->GetFlags();
263 pBasic
->ResetFlag( SbxFlagBits::GlobalSearch
);
264 pMethVar
= pBasic
->Find( aMacro
, SbxClassType::DontCare
);
265 pBasic
->SetFlags( nFlags
);
272 // Default: Be tolerant and search everywhere
273 if( (!pMethVar
|| dynamic_cast<const SbMethod
*>( pMethVar
) == nullptr) && maBasicRef
.is() )
275 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxClassType::DontCare
);
277 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pMethVar
);
284 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
287 xArray
= new SbxArray
;
288 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
289 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
291 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
292 unoToSbxValue( xVar
.get(), pArgs
[i
] );
293 xArray
->Put(xVar
.get(), sal::static_int_cast
<sal_uInt32
>(i
+ 1));
298 SbxVariableRef xValue
= pRet
? new SbxVariable
: nullptr;
301 pMeth
->SetParameters( xArray
.get() );
303 pMeth
->Call( xValue
.get() );
306 *pRet
= sbxToUnoValue( xValue
.get() );
308 pMeth
->SetParameters( nullptr );
310 else // scripting framework script
312 //callBasic via scripting framework
313 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
317 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
319 css::uno::Reference
< css::container::XNameContainer
> aRetDlgLib
;
321 SbxVariable
* pDlgLibContVar
= pBasic
->Find(u
"DialogLibraries"_ustr
, SbxClassType::Object
);
322 if( auto pDlgLibContUnoObj
= dynamic_cast<SbUnoObject
*>( pDlgLibContVar
) )
324 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
326 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
327 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
328 if( xDlgLibContNameAccess
.is() )
330 Sequence
< OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
331 const OUString
* pLibNames
= aLibNames
.getConstArray();
332 sal_Int32 nLibNameCount
= aLibNames
.getLength();
334 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
336 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
337 // if the library isn't loaded, then the dialog cannot originate from this lib
340 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
342 Reference
< XNameContainer
> xDlgLibNameCont( aDlgLibAny
, UNO_QUERY
);
343 OSL_ENSURE( xDlgLibNameCont
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
344 if( xDlgLibNameCont
.is() )
346 Sequence
< OUString
> aDlgNames
= xDlgLibNameCont
->getElementNames();
347 const OUString
* pDlgNames
= aDlgNames
.getConstArray();
348 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
350 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
352 Any aDlgAny
= xDlgLibNameCont
->getByName( pDlgNames
[ iDlg
] );
353 if( aDlgAny
== rDlgAny
)
355 aRetDlgLib
= xDlgLibNameCont
;
367 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
369 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
370 // Find dialog library for dialog, direct access is not possible here
371 StarBASIC
* pStartedBasic
= static_cast<StarBASIC
*>(pBasic
);
372 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : nullptr;
373 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : nullptr;
375 SbxObject
* pSearchBasic1
= nullptr;
376 SbxObject
* pSearchBasic2
= nullptr;
377 if( pParentParentBasic
)
379 pSearchBasic1
= pParentBasic
;
380 pSearchBasic2
= pParentParentBasic
;
384 pSearchBasic1
= pStartedBasic
;
385 pSearchBasic2
= pParentBasic
;
389 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
392 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic1
);
394 else if( pSearchBasic2
)
396 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
398 pFoundBasic
= static_cast<StarBASIC
*>(pSearchBasic2
);
406 void RTL_Impl_CreateUnoDialog( SbxArray
& rPar
)
408 const Reference
< XComponentContext
>& xContext( comphelper::getProcessComponentContext() );
410 // We need at least 1 parameter
411 if (rPar
.Count() < 2)
413 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
418 SbxBaseRef pObj
= rPar
.Get(1)->GetObject();
419 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
.get());
422 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
425 Any aAnyISP
= pUnoObj
->getUnoAny();
426 TypeClass eType
= aAnyISP
.getValueTypeClass();
428 if( eType
!= TypeClass_INTERFACE
)
430 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
434 // Create new uno dialog
435 Reference
< XNameContainer
> xDialogModel( xContext
->getServiceManager()->createInstanceWithContext(
436 u
"com.sun.star.awt.UnoControlDialogModel"_ustr
, xContext
), UNO_QUERY
);
437 if( !xDialogModel
.is() )
441 Reference
< XInputStreamProvider
> xISP
;
448 // Import the DialogModel
449 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
451 // i83963 Force decoration
452 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
453 if( xDlgModPropSet
.is() )
457 bool bDecoration
= true;
458 OUString
aDecorationPropName(u
"Decoration"_ustr
);
459 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
460 aDecorationAny
>>= bDecoration
;
463 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, Any( true ) );
464 xDlgModPropSet
->setPropertyValue( u
"Title"_ustr
, Any( OUString() ) );
467 catch(const UnknownPropertyException
& )
471 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
472 bool bDocDialog
= false;
473 StarBASIC
* pFoundBasic
= nullptr;
474 SAL_INFO("basic", "About to try get a hold of ThisComponent");
475 Reference
< frame::XModel
> xModel
= StarBASIC::GetModelFromBasic( GetSbData()->pInst
->GetBasic() ) ;
476 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, GetSbData()->pInst
->GetBasic(), pFoundBasic
);
477 // If we found the dialog then it belongs to the Search basic
480 Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( xContext
);
481 Reference
< container::XEnumeration
> xModels
;
482 Reference
< container::XEnumerationAccess
> xComponents
= xDesktop
->getComponents();
483 if ( xComponents
.is() )
485 xModels
= xComponents
->createEnumeration();
489 while ( xModels
->hasMoreElements() )
491 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
492 if ( xNextModel
.is() )
494 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
497 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
502 xModel
= std::move(xNextModel
);
511 bDocDialog
= pFoundBasic
->IsDocBasic();
513 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( GetSbData()->pInst
->GetBasic(), xModel
);
515 // Create a "living" Dialog
516 Reference
< XControl
> xCntrl
;
519 Reference
< XDialogProvider
> xDlgProv
;
521 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, xModel
, xInput
, aDlgLib
, xScriptListener
);
523 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, uno::Reference
< frame::XModel
>(), xInput
, aDlgLib
, xScriptListener
);
525 xCntrl
.set( xDlgProv
->createDialog(OUString() ), UNO_QUERY_THROW
);
526 // Add dialog model to dispose vector
527 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
528 GetSbData()->pInst
->getComponentVector().push_back( xDlgComponent
);
529 // need ThisComponent from calling script
531 // preserve existing bad behaviour, it's possible... but probably
532 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
533 // create dialog fails. So, in this case let's not throw, just leave basic
534 // detect the unset object.
535 catch(const uno::Exception
& )
542 SbxVariableRef refVar
= rPar
.Get(0);
543 unoToSbxValue( refVar
.get(), aRetVal
);
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */