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>
50 //==================================================================================================
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>
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 OSL_TRACE("SFURL_firing_impl() processing script url %s",
79 OUStringToOString( aScriptEvent
.ScriptCode
,
80 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
83 Reference
< provider::XScriptProvider
> xScriptProvider
;
86 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
87 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
89 xScriptProvider
.set( xSupplier
->getScriptProvider() );
93 Reference
< XComponentContext
> xContext(
94 comphelper::getProcessComponentContext() );
95 Reference
< provider::XScriptProviderFactory
> xFactory
=
96 provider::theMasterScriptProviderFactory::get( xContext
);
99 aCtx
<<= OUString("user");
100 xScriptProvider
.set( xFactory
->createScriptProvider( aCtx
), UNO_QUERY
);
103 if ( !xScriptProvider
.is() )
105 OSL_TRACE("SFURL_firing_impl() Failed to create msp");
108 Sequence
< Any
> inArgs( 0 );
109 Sequence
< Any
> outArgs( 0 );
110 Sequence
< sal_Int16
> outIndex
;
112 // get Arguments for script
113 inArgs
= aScriptEvent
.Arguments
;
115 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
119 OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript");
123 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
129 catch ( const RuntimeException
& re
)
131 OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.",
132 OUStringToOString( re
.Message
,
133 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
135 catch ( const Exception
& e
)
137 OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.",
138 OUStringToOString( e
.Message
,
139 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
145 class BasicScriptListener_Impl
: public WeakImplHelper1
< XScriptListener
>
147 StarBASICRef maBasicRef
;
148 Reference
< frame::XModel
> m_xModel
;
150 virtual void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
153 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
154 : maBasicRef( pBasic
), m_xModel( xModel
) {}
156 // Methods of XAllListener
157 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
)
158 throw( RuntimeException
);
159 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
)
160 throw( InvocationTargetException
, RuntimeException
);
162 // Methods of XEventListener
163 virtual void SAL_CALL
disposing(const EventObject
& Source
)
164 throw( RuntimeException
);
167 // Methods XAllListener
168 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
) throw ( RuntimeException
)
170 firing_impl( aScriptEvent
, NULL
);
173 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
174 throw ( InvocationTargetException
, RuntimeException
)
177 firing_impl( aScriptEvent
, &aRetAny
);
181 // Methods XEventListener
182 void BasicScriptListener_Impl::disposing(const EventObject
& ) throw ( RuntimeException
)
185 //SolarMutexGuard aGuard;
190 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
192 if( aScriptEvent
.ScriptType
.compareToAscii( "StarBasic" ) == 0 )
194 // Full qualified name?
195 OUString
aMacro( aScriptEvent
.ScriptCode
);
198 if( comphelper::string::getTokenCount(aMacro
, '.') == 3 )
201 OUString aFullLibName
= aMacro
.getToken( (sal_Int32
)0, (sal_Unicode
)'.', nLast
);
203 sal_Int32 nIndex
= aFullLibName
.indexOf( (sal_Unicode
)':' );
206 aLocation
= aFullLibName
.copy( 0, nIndex
);
207 aLibName
= aFullLibName
.copy( nIndex
+ 1 );
210 aMacro
= aMacro
.copy( nLast
);
213 SbxObject
* p
= maBasicRef
;
214 SbxObject
* pParent
= p
->GetParent();
215 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
217 StarBASICRef xAppStandardBasic
;
218 StarBASICRef xDocStandardBasic
;
221 // Own basic must be document library
222 xAppStandardBasic
= (StarBASIC
*)pParentParent
;
223 xDocStandardBasic
= (StarBASIC
*)pParent
;
227 OUString aName
= p
->GetName();
228 if( aName
.equalsAscii("Standard") )
230 // Own basic is doc standard lib
231 xDocStandardBasic
= (StarBASIC
*)p
;
233 xAppStandardBasic
= (StarBASIC
*)pParent
;
237 xAppStandardBasic
= (StarBASIC
*)p
;
240 bool bSearchLib
= true;
241 StarBASICRef xLibSearchBasic
;
242 if( aLocation
.equalsAscii("application") )
244 xLibSearchBasic
= xAppStandardBasic
;
246 else if( aLocation
.equalsAscii("document") )
248 xLibSearchBasic
= xDocStandardBasic
;
254 SbxVariable
* pMethVar
= NULL
;
255 // Be still tolerant and make default search if no search basic exists
256 if( bSearchLib
&& xLibSearchBasic
.Is() )
258 StarBASICRef xLibBasic
;
259 sal_Int16 nCount
= xLibSearchBasic
->GetObjects()->Count();
260 for( sal_Int16 nObj
= -1; nObj
< nCount
; nObj
++ )
265 pBasic
= (StarBASIC
*)xLibSearchBasic
;
269 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get( nObj
);
270 pBasic
= PTR_CAST(StarBASIC
,pVar
);
274 OUString aName
= pBasic
->GetName();
275 if( aName
== aLibName
)
277 // Search only in the lib, not automatically in application basic
278 sal_uInt16 nFlags
= pBasic
->GetFlags();
279 pBasic
->ResetFlag( SBX_GBLSEARCH
);
280 pMethVar
= pBasic
->Find( aMacro
, SbxCLASS_DONTCARE
);
281 pBasic
->SetFlags( nFlags
);
288 // Default: Be tolerant and search everywhere
289 if( (!pMethVar
|| !pMethVar
->ISA(SbMethod
)) && maBasicRef
.Is() )
291 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxCLASS_DONTCARE
);
293 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pMethVar
);
300 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
303 xArray
= new SbxArray
;
304 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
305 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
307 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
308 unoToSbxValue( (SbxVariable
*)xVar
, pArgs
[i
] );
309 xArray
->Put( xVar
, sal::static_int_cast
< sal_uInt16
>(i
+1) );
314 SbxVariableRef xValue
= pRet
? new SbxVariable
: 0;
317 pMeth
->SetParameters( xArray
);
319 pMeth
->Call( xValue
);
322 *pRet
= sbxToUnoValue( xValue
);
324 pMeth
->SetParameters( NULL
);
326 else // scripting framework script
328 //callBasic via scripting framework
329 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
333 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
335 css::uno::Reference
< css::container::XNameContainer
> aRetDlgLib
;
337 SbxVariable
* pDlgLibContVar
= pBasic
->Find(OUString("DialogLibraries"), SbxCLASS_OBJECT
);
338 if( pDlgLibContVar
&& pDlgLibContVar
->ISA(SbUnoObject
) )
340 SbUnoObject
* pDlgLibContUnoObj
= (SbUnoObject
*)(SbxBase
*)pDlgLibContVar
;
341 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
343 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
344 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
345 if( xDlgLibContNameAccess
.is() )
347 Sequence
< OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
348 const OUString
* pLibNames
= aLibNames
.getConstArray();
349 sal_Int32 nLibNameCount
= aLibNames
.getLength();
351 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
353 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
354 // if the library isn't loaded, then the dialog cannot originate from this lib
357 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
359 Reference
< XNameContainer
> xDlgLibNameCont( aDlgLibAny
, UNO_QUERY
);
360 OSL_ENSURE( xDlgLibNameCont
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
361 if( xDlgLibNameCont
.is() )
363 Sequence
< OUString
> aDlgNames
= xDlgLibNameCont
->getElementNames();
364 const OUString
* pDlgNames
= aDlgNames
.getConstArray();
365 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
367 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
369 Any aDlgAny
= xDlgLibNameCont
->getByName( pDlgNames
[ iDlg
] );
370 if( aDlgAny
== rDlgAny
)
372 aRetDlgLib
= xDlgLibNameCont
;
384 css::uno::Reference
< css::container::XNameContainer
> implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
386 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
387 // Find dialog library for dialog, direct access is not possible here
388 StarBASIC
* pStartedBasic
= (StarBASIC
*)pBasic
;
389 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : NULL
;
390 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : NULL
;
392 SbxObject
* pSearchBasic1
= NULL
;
393 SbxObject
* pSearchBasic2
= NULL
;
394 if( pParentParentBasic
)
396 pSearchBasic1
= pParentBasic
;
397 pSearchBasic2
= pParentParentBasic
;
401 pSearchBasic1
= pStartedBasic
;
402 pSearchBasic2
= pParentBasic
;
406 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
409 pFoundBasic
= (StarBASIC
*)pSearchBasic1
;
411 else if( pSearchBasic2
)
413 aDlgLib
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
415 pFoundBasic
= (StarBASIC
*)pSearchBasic2
;
421 void RTL_Impl_CreateUnoDialog( StarBASIC
* pBasic
, SbxArray
& rPar
, sal_Bool bWrite
)
426 Reference
< XMultiServiceFactory
> xMSF( comphelper::getProcessServiceFactory() );
428 // We need at least 1 parameter
429 if ( rPar
.Count() < 2 )
431 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
436 SbxBaseRef pObj
= (SbxBase
*)rPar
.Get( 1 )->GetObject();
437 if( !(pObj
&& pObj
->ISA(SbUnoObject
)) )
439 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
442 SbUnoObject
* pUnoObj
= (SbUnoObject
*)(SbxBase
*)pObj
;
443 Any aAnyISP
= pUnoObj
->getUnoAny();
444 TypeClass eType
= aAnyISP
.getValueType().getTypeClass();
446 if( eType
!= TypeClass_INTERFACE
)
448 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
452 // Create new uno dialog
453 Reference
< XNameContainer
> xDialogModel( xMSF
->createInstance(
454 OUString("com.sun.star.awt.UnoControlDialogModel")), UNO_QUERY
);
455 if( !xDialogModel
.is() )
459 Reference
< XInputStreamProvider
> xISP
;
465 Reference
< XComponentContext
> xContext( comphelper::getComponentContext( xMSF
) );
467 // Import the DialogModel
468 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
470 // i83963 Force decoration
471 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
472 if( xDlgModPropSet
.is() )
474 bool bDecoration
= true;
477 OUString
aDecorationPropName("Decoration");
478 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
479 aDecorationAny
>>= bDecoration
;
482 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, makeAny( true ) );
484 OUString
aTitlePropName("Title");
485 xDlgModPropSet
->setPropertyValue( aTitlePropName
, makeAny( OUString() ) );
488 catch(const UnknownPropertyException
& )
492 css::uno::Reference
< css::container::XNameContainer
> aDlgLib
;
493 bool bDocDialog
= false;
494 StarBASIC
* pFoundBasic
= NULL
;
495 OSL_TRACE("About to try get a hold of ThisComponent");
496 Reference
< frame::XModel
> xModel
= StarBASIC::GetModelFromBasic( GetSbData()->pInst
->GetBasic() ) ;
497 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, GetSbData()->pInst
->GetBasic(), pFoundBasic
);
498 // If we found the dialog then it belongs to the Search basic
501 Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( xContext
);
502 Reference
< container::XEnumeration
> xModels
;
503 Reference
< container::XEnumerationAccess
> xComponents( xDesktop
->getComponents(), UNO_QUERY
);
504 if ( xComponents
.is() )
506 xModels
.set( xComponents
->createEnumeration(), UNO_QUERY
);
510 while ( xModels
->hasMoreElements() )
512 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
513 if ( xNextModel
.is() )
515 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
518 aDlgLib
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
532 bDocDialog
= pFoundBasic
->IsDocBasic();
534 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( GetSbData()->pInst
->GetBasic(), xModel
);
536 // Create a "living" Dialog
537 Reference
< XControl
> xCntrl
;
540 Reference
< XDialogProvider
> xDlgProv
;;
542 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, xModel
, xInput
, aDlgLib
, xScriptListener
);
544 xDlgProv
= css::awt::DialogProvider::createWithModelAndScripting( xContext
, uno::Reference
< frame::XModel
>(), xInput
, aDlgLib
, xScriptListener
);
546 xCntrl
.set( xDlgProv
->createDialog(OUString() ), UNO_QUERY_THROW
);
547 // Add dialog model to dispose vector
548 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
549 GetSbData()->pInst
->getComponentVector().push_back( xDlgComponent
);
550 // need ThisCompoent from calling script
552 // preserve existing bad behaviour, it's possible... but probably
553 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
554 // create dialog fails. So, in this case let's not throw, just leave basic
555 // detect the unset object.
556 catch(const uno::Exception
& )
563 SbxVariableRef refVar
= rPar
.Get(0);
564 unoToSbxValue( (SbxVariable
*)refVar
, aRetVal
);
568 //===================================================================
570 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */