1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eventatt.cxx,v $
10 * $Revision: 1.35.40.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 //#include <stl_queue.h>
35 #include <osl/mutex.hxx>
36 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/script/XEventAttacher.hpp>
40 #include <com/sun/star/script/XAllListener.hpp>
41 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
42 #include <com/sun/star/script/XScriptEventsAttacher.hpp>
43 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
44 #include <com/sun/star/script/XLibraryContainer.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/container/XNameContainer.hpp>
47 #include <com/sun/star/resource/XStringResourceSupplier.hpp>
48 #include <com/sun/star/resource/XStringResourceManager.hpp>
49 #include <com/sun/star/awt/XControlContainer.hpp>
50 #include <com/sun/star/awt/XControlModel.hpp>
51 #include <com/sun/star/awt/XControl.hpp>
52 #include <com/sun/star/awt/XDialog.hpp>
53 #include <com/sun/star/awt/XWindow.hpp>
54 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
56 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
57 #include <com/sun/star/script/provider/XScriptProvider.hpp>
58 #include <com/sun/star/awt/XDialogProvider.hpp>
60 #include <com/sun/star/frame/XModel.hpp>
61 #include <com/sun/star/frame/XDesktop.hpp>
62 #include <com/sun/star/container/XEnumerationAccess.hpp>
63 #include <basic/basicmanagerrepository.hxx>
64 #include <basic/basmgr.hxx>
65 //==================================================================================================
67 #include <xmlscript/xmldlg_imexp.hxx>
68 #include <sbunoobj.hxx>
69 #include <basic/sbstar.hxx>
70 #include <basic/sbmeth.hxx>
71 #include <runtime.hxx>
72 #include <sbintern.hxx>
75 #include <cppuhelper/implbase1.hxx>
76 using namespace ::com::sun::star
;
77 using namespace ::com::sun::star::uno
;
78 using namespace ::com::sun::star::script
;
79 using namespace ::com::sun::star::resource
;
81 using namespace ::com::sun::star::uno
;
82 using namespace ::com::sun::star::lang
;
83 using namespace ::com::sun::star::beans
;
84 using namespace ::com::sun::star::script
;
85 using namespace ::com::sun::star::container
;
86 using namespace ::com::sun::star::reflection
;
87 using namespace ::com::sun::star::awt
;
88 using namespace ::com::sun::star::io
;
89 using namespace ::cppu
;
90 using namespace ::osl
;
94 //===================================================================
95 void unoToSbxValue( SbxVariable
* pVar
, const Any
& aValue
);
96 Any
sbxToUnoValue( SbxVariable
* pVar
);
99 Reference
< frame::XModel
> getModelFromBasic( SbxObject
* pBasic
)
101 Reference
< frame::XModel
> xModel
;
103 SbxObject
* basicChosen
= pBasic
;
105 if ( basicChosen
== NULL
)
107 OSL_TRACE("getModelFromBasic() StarBASIC* is NULL" );
110 SbxObject
* p
= pBasic
;
111 SbxObject
* pParent
= p
->GetParent();
112 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
116 basicChosen
= pParentParent
;
120 basicChosen
= pParent
;
125 SbxVariable
*pCompVar
= basicChosen
->Find( UniString(RTL_CONSTASCII_USTRINGPARAM("ThisComponent")), SbxCLASS_OBJECT
);
129 aModel
= sbxToUnoValue( pCompVar
);
130 if ( sal_False
== ( aModel
>>= xModel
) ||
133 OSL_TRACE("Failed to extract model from thisComponent ");
138 OSL_TRACE("Have model ThisComponent points to url %s",
139 ::rtl::OUStringToOString( xModel
->getURL(),
140 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
146 OSL_TRACE("Failed to get ThisComponent");
151 void SFURL_firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
, const Reference
< frame::XModel
>& xModel
)
153 OSL_TRACE("SFURL_firing_impl() processing script url %s",
154 ::rtl::OUStringToOString( aScriptEvent
.ScriptCode
,
155 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
158 Reference
< provider::XScriptProvider
> xScriptProvider
;
161 Reference
< provider::XScriptProviderSupplier
> xSupplier( xModel
, UNO_QUERY
);
162 OSL_ENSURE( xSupplier
.is(), "SFURL_firing_impl: failed to get script provider supplier" );
163 if ( xSupplier
.is() )
164 xScriptProvider
.set( xSupplier
->getScriptProvider() );
168 Reference
< XComponentContext
> xContext
;
169 Reference
< XPropertySet
> xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY
);
170 OSL_ASSERT( xProps
.is() );
171 OSL_VERIFY( xProps
->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ) >>= xContext
);
174 Reference
< provider::XScriptProviderFactory
> xFactory(
175 xContext
->getValueByName(
176 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory" ) ),
178 OSL_ENSURE( xFactory
.is(), "SFURL_firing_impl: failed to get master script provider factory" );
182 aCtx
<<= ::rtl::OUString::createFromAscii( "user" );
183 xScriptProvider
.set( xFactory
->createScriptProvider( aCtx
), UNO_QUERY
);
188 if ( !xScriptProvider
.is() )
190 OSL_TRACE("SFURL_firing_impl() Failed to create msp");
193 Sequence
< Any
> inArgs( 0 );
194 Sequence
< Any
> outArgs( 0 );
195 Sequence
< sal_Int16
> outIndex
;
197 // get Arguments for script
198 inArgs
= aScriptEvent
.Arguments
;
200 Reference
< provider::XScript
> xScript
= xScriptProvider
->getScript( aScriptEvent
.ScriptCode
);
204 OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript");
208 Any result
= xScript
->invoke( inArgs
, outIndex
, outArgs
);
214 catch ( RuntimeException
& re
)
216 OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.",
217 ::rtl::OUStringToOString( re
.Message
,
218 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
220 catch ( Exception
& e
)
222 OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.",
223 ::rtl::OUStringToOString( e
.Message
,
224 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
230 class BasicScriptListener_Impl
: public WeakImplHelper1
< XScriptListener
>
232 StarBASICRef maBasicRef
;
233 Reference
< frame::XModel
> m_xModel
;
235 virtual void firing_impl(const ScriptEvent
& aScriptEvent
, Any
* pRet
);
238 BasicScriptListener_Impl( StarBASIC
* pBasic
, const Reference
< frame::XModel
>& xModel
)
239 : maBasicRef( pBasic
), m_xModel( xModel
) {}
241 // Methods of XAllListener
242 virtual void SAL_CALL
firing(const ScriptEvent
& aScriptEvent
)
243 throw( RuntimeException
);
244 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& aScriptEvent
)
245 throw( InvocationTargetException
, RuntimeException
);
247 // Methods of XEventListener
248 virtual void SAL_CALL
disposing(const EventObject
& Source
)
249 throw( RuntimeException
);
252 // Methods XAllListener
253 void BasicScriptListener_Impl::firing( const ScriptEvent
& aScriptEvent
) throw ( RuntimeException
)
255 firing_impl( aScriptEvent
, NULL
);
258 Any
BasicScriptListener_Impl::approveFiring( const ScriptEvent
& aScriptEvent
)
259 throw ( InvocationTargetException
, RuntimeException
)
262 firing_impl( aScriptEvent
, &aRetAny
);
266 // Methods XEventListener
267 void BasicScriptListener_Impl::disposing(const EventObject
& ) throw ( RuntimeException
)
270 //NAMESPACE_VOS(OGuard) guard( Application::GetSolarMutex() );
275 void BasicScriptListener_Impl::firing_impl( const ScriptEvent
& aScriptEvent
, Any
* pRet
)
277 //Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
279 if( aScriptEvent
.ScriptType
.compareToAscii( "StarBasic" ) == 0 )
281 // Full qualified name?
282 String
aMacro( aScriptEvent
.ScriptCode
);
285 if( aMacro
.GetTokenCount( '.' ) == 3 )
287 sal_uInt16 nLast
= 0;
288 ::rtl::OUString aFullLibName
= aMacro
.GetToken( 0, '.', nLast
);
290 sal_Int32 nIndex
= aFullLibName
.indexOf( (sal_Unicode
)':' );
293 aLocation
= aFullLibName
.copy( 0, nIndex
);
294 aLibName
= aFullLibName
.copy( nIndex
+ 1 );
297 String aModul
= aMacro
.GetToken( 0, '.', nLast
);
298 aMacro
.Erase( 0, nLast
);
301 SbxObject
* p
= maBasicRef
;
302 SbxObject
* pParent
= p
->GetParent();
303 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
305 StarBASICRef xAppStandardBasic
;
306 StarBASICRef xDocStandardBasic
;
309 // Own basic must be document library
310 xAppStandardBasic
= (StarBASIC
*)pParentParent
;
311 xDocStandardBasic
= (StarBASIC
*)pParent
;
315 String aName
= p
->GetName();
316 if( aName
.EqualsAscii("Standard") )
318 // Own basic is doc standard lib
319 xDocStandardBasic
= (StarBASIC
*)p
;
321 xAppStandardBasic
= (StarBASIC
*)pParent
;
325 xAppStandardBasic
= (StarBASIC
*)p
;
328 sal_Bool bSearchLib
= true;
329 StarBASICRef xLibSearchBasic
;
330 if( aLocation
.EqualsAscii("application") )
331 xLibSearchBasic
= xAppStandardBasic
;
332 else if( aLocation
.EqualsAscii("document") )
333 xLibSearchBasic
= xDocStandardBasic
;
337 SbxVariable
* pMethVar
= NULL
;
338 // Be still tolerant and make default search if no search basic exists
339 if( bSearchLib
&& xLibSearchBasic
.Is() )
341 StarBASICRef xLibBasic
;
342 sal_Int16 nCount
= xLibSearchBasic
->GetObjects()->Count();
343 for( sal_Int16 nObj
= -1; nObj
< nCount
; nObj
++ )
348 pBasic
= (StarBASIC
*)xLibSearchBasic
;
352 SbxVariable
* pVar
= xLibSearchBasic
->GetObjects()->Get( nObj
);
353 pBasic
= PTR_CAST(StarBASIC
,pVar
);
357 String aName
= pBasic
->GetName();
358 if( aName
== aLibName
)
360 // Search only in the lib, not automatically in application basic
361 USHORT nFlags
= pBasic
->GetFlags();
362 pBasic
->ResetFlag( SBX_GBLSEARCH
);
363 pMethVar
= pBasic
->Find( aMacro
, SbxCLASS_DONTCARE
);
364 pBasic
->SetFlags( nFlags
);
371 // Default: Be tolerant and search everywhere
372 if( (!pMethVar
|| !pMethVar
->ISA(SbMethod
)) && maBasicRef
.Is() )
373 pMethVar
= maBasicRef
->FindQualified( aMacro
, SbxCLASS_DONTCARE
);
375 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pMethVar
);
382 sal_Int32 nCnt
= aScriptEvent
.Arguments
.getLength();
385 xArray
= new SbxArray
;
386 const Any
*pArgs
= aScriptEvent
.Arguments
.getConstArray();
387 for( sal_Int32 i
= 0; i
< nCnt
; i
++ )
389 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
390 unoToSbxValue( (SbxVariable
*)xVar
, pArgs
[i
] );
391 xArray
->Put( xVar
, sal::static_int_cast
< USHORT
>(i
+1) );
396 SbxVariableRef xValue
= pRet
? new SbxVariable
: 0;
398 pMeth
->SetParameters( xArray
);
399 pMeth
->Call( xValue
);
401 *pRet
= sbxToUnoValue( xValue
);
402 pMeth
->SetParameters( NULL
);
404 else // scripting framework script
406 //callBasic via scripting framework
407 SFURL_firing_impl( aScriptEvent
, pRet
, m_xModel
);
412 Any
implFindDialogLibForDialog( const Any
& rDlgAny
, SbxObject
* pBasic
)
416 SbxVariable
* pDlgLibContVar
= pBasic
->Find
417 ( String::CreateFromAscii("DialogLibraries"), SbxCLASS_OBJECT
);
418 if( pDlgLibContVar
&& pDlgLibContVar
->ISA(SbUnoObject
) )
420 SbUnoObject
* pDlgLibContUnoObj
= (SbUnoObject
*)(SbxBase
*)pDlgLibContVar
;
421 Any aDlgLibContAny
= pDlgLibContUnoObj
->getUnoAny();
423 Reference
< XLibraryContainer
> xDlgLibContNameAccess( aDlgLibContAny
, UNO_QUERY
);
424 OSL_ENSURE( xDlgLibContNameAccess
.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
425 if( xDlgLibContNameAccess
.is() )
427 Sequence
< ::rtl::OUString
> aLibNames
= xDlgLibContNameAccess
->getElementNames();
428 const ::rtl::OUString
* pLibNames
= aLibNames
.getConstArray();
429 sal_Int32 nLibNameCount
= aLibNames
.getLength();
431 for( sal_Int32 iLib
= 0 ; iLib
< nLibNameCount
; iLib
++ )
433 if ( !xDlgLibContNameAccess
->isLibraryLoaded( pLibNames
[ iLib
] ) )
434 // if the library isn't loaded, then the dialog cannot originate from this lib
437 Any aDlgLibAny
= xDlgLibContNameAccess
->getByName( pLibNames
[ iLib
] );
439 Reference
< XNameAccess
> xDlgLibNameAccess( aDlgLibAny
, UNO_QUERY
);
440 OSL_ENSURE( xDlgLibNameAccess
.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
441 if( xDlgLibNameAccess
.is() )
443 Sequence
< ::rtl::OUString
> aDlgNames
= xDlgLibNameAccess
->getElementNames();
444 const ::rtl::OUString
* pDlgNames
= aDlgNames
.getConstArray();
445 sal_Int32 nDlgNameCount
= aDlgNames
.getLength();
447 for( sal_Int32 iDlg
= 0 ; iDlg
< nDlgNameCount
; iDlg
++ )
449 Any aDlgAny
= xDlgLibNameAccess
->getByName( pDlgNames
[ iDlg
] );
450 if( aDlgAny
== rDlgAny
)
452 aRetDlgLibAny
= aDlgLibAny
;
461 return aRetDlgLibAny
;
464 Any
implFindDialogLibForDialogBasic( const Any
& aAnyISP
, SbxObject
* pBasic
, StarBASIC
*& pFoundBasic
)
467 // Find dialog library for dialog, direct access is not possible here
468 StarBASIC
* pStartedBasic
= (StarBASIC
*)pBasic
;
469 SbxObject
* pParentBasic
= pStartedBasic
? pStartedBasic
->GetParent() : NULL
;
470 SbxObject
* pParentParentBasic
= pParentBasic
? pParentBasic
->GetParent() : NULL
;
472 SbxObject
* pSearchBasic1
= NULL
;
473 SbxObject
* pSearchBasic2
= NULL
;
474 if( pParentParentBasic
)
476 pSearchBasic1
= pParentBasic
;
477 pSearchBasic2
= pParentParentBasic
;
481 pSearchBasic1
= pStartedBasic
;
482 pSearchBasic2
= pParentBasic
;
486 aDlgLibAny
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic1
);
488 if ( aDlgLibAny
.hasValue() )
489 pFoundBasic
= (StarBASIC
*)pSearchBasic1
;
491 else if( pSearchBasic2
)
493 aDlgLibAny
= implFindDialogLibForDialog( aAnyISP
, pSearchBasic2
);
494 if ( aDlgLibAny
.hasValue() )
495 pFoundBasic
= (StarBASIC
*)pSearchBasic2
;
501 static ::rtl::OUString aDecorationPropName
=
502 ::rtl::OUString::createFromAscii( "Decoration" );
503 static ::rtl::OUString aTitlePropName
=
504 ::rtl::OUString::createFromAscii( "Title" );
506 void RTL_Impl_CreateUnoDialog( StarBASIC
* pBasic
, SbxArray
& rPar
, BOOL bWrite
)
508 static ::rtl::OUString aResourceResolverPropName
= ::rtl::OUString::createFromAscii( "ResourceResolver" );
513 Reference
< XMultiServiceFactory
> xMSF( comphelper::getProcessServiceFactory() );
517 // We need at least 1 parameter
518 if ( rPar
.Count() < 2 )
520 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
525 SbxBaseRef pObj
= (SbxBase
*)rPar
.Get( 1 )->GetObject();
526 if( !(pObj
&& pObj
->ISA(SbUnoObject
)) )
528 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
531 SbUnoObject
* pUnoObj
= (SbUnoObject
*)(SbxBase
*)pObj
;
532 Any aAnyISP
= pUnoObj
->getUnoAny();
533 TypeClass eType
= aAnyISP
.getValueType().getTypeClass();
535 if( eType
!= TypeClass_INTERFACE
)
537 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
541 // Create new uno dialog
542 Reference
< XNameContainer
> xDialogModel( xMSF
->createInstance
543 ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ) ),
545 if( !xDialogModel
.is() )
548 Reference
< XInputStreamProvider
> xISP
;
553 Reference
< XComponentContext
> xContext
;
554 Reference
< XPropertySet
> xProps( xMSF
, UNO_QUERY
);
555 OSL_ASSERT( xProps
.is() );
556 OSL_VERIFY( xProps
->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext
);
558 // Import the DialogModel
559 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
561 // i83963 Force decoration
562 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xDialogModel
, uno::UNO_QUERY
);
563 if( xDlgModPropSet
.is() )
565 bool bDecoration
= true;
568 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
569 aDecorationAny
>>= bDecoration
;
572 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, makeAny( true ) );
573 xDlgModPropSet
->setPropertyValue( aTitlePropName
, makeAny( ::rtl::OUString() ) );
576 catch( UnknownPropertyException
& )
581 bool bDocDialog
= false;
582 StarBASIC
* pFoundBasic
= NULL
;
583 OSL_TRACE("About to try get a hold of ThisComponent");
584 Reference
< frame::XModel
> xModel
= getModelFromBasic( pINST
->GetBasic() ) ;
585 aDlgLibAny
= implFindDialogLibForDialogBasic( aAnyISP
, pINST
->GetBasic(), pFoundBasic
);
586 // If we found the dialog then it belongs to the Search basic
589 Reference
< frame::XDesktop
> xDesktop( xMSF
->createInstance
590 ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ),
592 Reference
< container::XEnumeration
> xModels
;
595 Reference
< container::XEnumerationAccess
> xComponents( xDesktop
->getComponents(), UNO_QUERY
);
596 if ( xComponents
.is() )
597 xModels
.set( xComponents
->createEnumeration(), UNO_QUERY
);
600 while ( xModels
->hasMoreElements() )
602 Reference
< frame::XModel
> xNextModel( xModels
->nextElement(), UNO_QUERY
);
603 if ( xNextModel
.is() )
605 BasicManager
* pMgr
= basic::BasicManagerRepository::getDocumentBasicManager( xNextModel
);
607 aDlgLibAny
= implFindDialogLibForDialogBasic( aAnyISP
, pMgr
->GetLib(0), pFoundBasic
);
608 if ( aDlgLibAny
.hasValue() )
620 bDocDialog
= pFoundBasic
->IsDocBasic();
621 Reference
< XScriptListener
> xScriptListener
= new BasicScriptListener_Impl( pINST
->GetBasic(), xModel
);
623 Sequence
< Any
> aArgs( 4 );
624 aArgs
[ 0 ] <<= bDocDialog
? xModel
: uno::Reference
< uno::XInterface
>();
625 aArgs
[ 1 ] <<= xInput
;
626 aArgs
[ 2 ] = aDlgLibAny
;
627 aArgs
[ 3 ] <<= xScriptListener
;
628 // Create a "living" Dialog
629 Reference
< XControl
> xCntrl
;
632 Reference
< XDialogProvider
> xDlgProv( xMSF
->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.DialogProvider" ) ), aArgs
), UNO_QUERY
);
633 xCntrl
.set( xDlgProv
->createDialog( rtl::OUString() ), UNO_QUERY_THROW
);
634 // Add dialog model to dispose vector
635 Reference
< XComponent
> xDlgComponent( xCntrl
->getModel(), UNO_QUERY
);
636 pINST
->getComponentVector().push_back( xDlgComponent
);
637 // need ThisCompoent from calling script
639 // preserve existing bad behaviour, it's possible... but probably
640 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
641 // create dialog fails. So, in this case let's not throw, just leave basic
642 // detect the unset object.
643 catch( uno::Exception
& )
650 SbxVariableRef refVar
= rPar
.Get(0);
651 unoToSbxValue( (SbxVariable
*)refVar
, aRetVal
);
655 //===================================================================