1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "dlgevtatt.hxx"
21 
22 #include "dlgprov.hxx"
23 
24 #include <sfx2/strings.hrc>
25 #include <sfx2/app.hxx>
26 #include <sfx2/sfxresid.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <tools/diagnose_ex.h>
30 
31 #include <com/sun/star/awt/XControl.hpp>
32 #include <com/sun/star/awt/XControlContainer.hpp>
33 #include <com/sun/star/awt/XDialogEventHandler.hpp>
34 #include <com/sun/star/awt/XContainerWindowEventHandler.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
37 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
38 #include <com/sun/star/script/provider/XScriptProvider.hpp>
39 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
40 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
41 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
42 #include <com/sun/star/lang/NoSuchMethodException.hpp>
43 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
44 #include <com/sun/star/reflection/XIdlMethod.hpp>
45 #include <com/sun/star/beans/MethodConcept.hpp>
46 #include <com/sun/star/beans/XMaterialHolder.hpp>
47 
48 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
49 
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::awt;
52 using namespace ::com::sun::star::beans;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::script;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::reflection;
57 
58 
59 namespace dlgprov
60 {
61 
62   class DialogSFScriptListenerImpl : public DialogScriptListenerImpl
63     {
64         protected:
65         Reference< frame::XModel >  m_xModel;
66         virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
67         public:
DialogSFScriptListenerImpl(const Reference<XComponentContext> & rxContext,const Reference<frame::XModel> & rxModel)68         DialogSFScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogScriptListenerImpl( rxContext ), m_xModel( rxModel ) {}
69     };
70 
71   class DialogLegacyScriptListenerImpl : public DialogSFScriptListenerImpl
72     {
73         protected:
74         virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
75         public:
DialogLegacyScriptListenerImpl(const Reference<XComponentContext> & rxContext,const Reference<frame::XModel> & rxModel)76         DialogLegacyScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogSFScriptListenerImpl( rxContext, rxModel ){}
77     };
78 
79   class DialogUnoScriptListenerImpl : public DialogSFScriptListenerImpl
80     {
81     Reference< awt::XControl > m_xControl;
82         Reference< XInterface > m_xHandler;
83     Reference< beans::XIntrospectionAccess > m_xIntrospectionAccess;
84     bool const m_bDialogProviderMode;
85 
86         virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
87 
88     public:
89         DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext,
90             const Reference< frame::XModel >& rxModel,
91             const Reference< awt::XControl >& rxControl,
92             const Reference< XInterface >& rxHandler,
93             const Reference< beans::XIntrospectionAccess >& rxIntrospectionAccess,
94             bool bDialogProviderMode );     // false: ContainerWindowProvider mode
95 
96     };
97 
98   class DialogVBAScriptListenerImpl : public DialogScriptListenerImpl
99     {
100         protected:
101         OUString msDialogCodeName;
102         OUString const msDialogLibName;
103         Reference<  script::XScriptListener > mxListener;
104         virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
105         public:
106         DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, const OUString& sDialogLibName );
107     };
108 
DialogVBAScriptListenerImpl(const Reference<XComponentContext> & rxContext,const Reference<awt::XControl> & rxControl,const Reference<frame::XModel> & xModel,const OUString & sDialogLibName)109     DialogVBAScriptListenerImpl::DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, const OUString& sDialogLibName ) : DialogScriptListenerImpl( rxContext ), msDialogLibName( sDialogLibName )
110     {
111         Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
112         Sequence< Any > args(1);
113         if ( xSMgr.is() )
114         {
115             args[0] <<= xModel;
116             mxListener.set( xSMgr->createInstanceWithArgumentsAndContext( "ooo.vba.EventListener", args, m_xContext ), UNO_QUERY );
117         }
118         if ( rxControl.is() )
119         {
120             try
121             {
122                 Reference< XPropertySet > xProps( rxControl->getModel(), UNO_QUERY_THROW );
123                 xProps->getPropertyValue("Name") >>= msDialogCodeName;
124                 xProps.set( mxListener, UNO_QUERY_THROW );
125                 xProps->setPropertyValue("Model", args[ 0 ] );
126             }
127             catch( const Exception& )
128             {
129                 DBG_UNHANDLED_EXCEPTION("scripting");
130             }
131         }
132 
133     }
134 
firing_impl(const script::ScriptEvent & aScriptEvent,uno::Any *)135     void DialogVBAScriptListenerImpl::firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* )
136     {
137         if ( aScriptEvent.ScriptType == "VBAInterop" && mxListener.is() )
138         {
139             ScriptEvent aScriptEventCopy( aScriptEvent );
140             aScriptEventCopy.ScriptCode = msDialogLibName.concat( "." ).concat( msDialogCodeName );
141             try
142             {
143                 mxListener->firing( aScriptEventCopy );
144             }
145             catch( const Exception& )
146             {
147                 DBG_UNHANDLED_EXCEPTION("scripting");
148             }
149         }
150     }
151 
152 
153     // DialogEventsAttacherImpl
154 
155 
DialogEventsAttacherImpl(const Reference<XComponentContext> & rxContext,const Reference<frame::XModel> & rxModel,const Reference<awt::XControl> & rxControl,const Reference<XInterface> & rxHandler,const Reference<beans::XIntrospectionAccess> & rxIntrospect,bool bProviderMode,const Reference<script::XScriptListener> & rxRTLListener,const OUString & sDialogLibName)156     DialogEventsAttacherImpl::DialogEventsAttacherImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel, const Reference< awt::XControl >& rxControl, const Reference< XInterface >& rxHandler, const Reference< beans::XIntrospectionAccess >& rxIntrospect, bool bProviderMode, const Reference< script::XScriptListener >& rxRTLListener, const OUString& sDialogLibName )
157         :mbUseFakeVBAEvents( false ), m_xContext( rxContext )
158     {
159         // key listeners by protocol when ScriptType = 'Script'
160         // otherwise key is the ScriptType e.g. StarBasic
161         if ( rxRTLListener.is() ) // set up handler for RTL_BASIC
162             listenersForTypes[ OUString("StarBasic") ] = rxRTLListener;
163         else
164             listenersForTypes[ OUString("StarBasic") ] = new DialogLegacyScriptListenerImpl( rxContext, rxModel );
165         // handler for Script & OUString("vnd.sun.star.UNO:")
166         listenersForTypes[ OUString("vnd.sun.star.UNO") ] = new DialogUnoScriptListenerImpl( rxContext, rxModel, rxControl, rxHandler, rxIntrospect, bProviderMode );
167         listenersForTypes[ OUString("vnd.sun.star.script") ] = new DialogSFScriptListenerImpl( rxContext, rxModel );
168 
169         // determine the VBA compatibility mode from the Basic library container
170         try
171         {
172             uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW );
173             uno::Reference< script::vba::XVBACompatibility > xVBACompat(
174                 xModelProps->getPropertyValue("BasicLibraries"), uno::UNO_QUERY_THROW );
175             mbUseFakeVBAEvents = xVBACompat->getVBACompatibilityMode();
176         }
177         catch( uno::Exception& )
178         {
179         }
180         if ( mbUseFakeVBAEvents )
181             listenersForTypes[ OUString("VBAInterop") ] = new DialogVBAScriptListenerImpl( rxContext, rxControl, rxModel, sDialogLibName );
182     }
183 
184 
~DialogEventsAttacherImpl()185     DialogEventsAttacherImpl::~DialogEventsAttacherImpl()
186     {
187     }
188 
189 
190     Reference< script::XScriptListener > const &
getScriptListenerForKey(const OUString & sKey)191     DialogEventsAttacherImpl::getScriptListenerForKey( const OUString& sKey )
192     {
193         ListenerHash::iterator it = listenersForTypes.find( sKey );
194         if ( it == listenersForTypes.end() )
195             throw RuntimeException(); // more text info here please
196         return it->second;
197     }
getFakeVbaEventsSupplier(const Reference<XControl> & xControl,OUString const & sControlName)198     Reference< XScriptEventsSupplier > DialogEventsAttacherImpl::getFakeVbaEventsSupplier( const Reference< XControl >& xControl, OUString const & sControlName )
199     {
200         Reference< XScriptEventsSupplier > xEventsSupplier;
201         Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
202         if ( xSMgr.is() )
203         {
204             Reference< ooo::vba::XVBAToOOEventDescGen > xVBAToOOEvtDesc( xSMgr->createInstanceWithContext("ooo.vba.VBAToOOEventDesc", m_xContext ), UNO_QUERY );
205             if ( xVBAToOOEvtDesc.is() )
206                 xEventsSupplier = xVBAToOOEvtDesc->getEventSupplier( xControl, sControlName );
207 
208         }
209         return xEventsSupplier;
210     }
211 
212 
attachEventsToControl(const Reference<XControl> & xControl,const Reference<XScriptEventsSupplier> & xEventsSupplier,const Any & Helper)213     void DialogEventsAttacherImpl::attachEventsToControl( const Reference< XControl>& xControl, const Reference< XScriptEventsSupplier >& xEventsSupplier, const Any& Helper )
214     {
215         if ( xEventsSupplier.is() )
216         {
217             Reference< container::XNameContainer > xEventCont = xEventsSupplier->getEvents();
218 
219             Reference< XControlModel > xControlModel = xControl->getModel();
220             Reference< XPropertySet > xProps( xControlModel, uno::UNO_QUERY );
221             if ( xEventCont.is() )
222             {
223                 const Sequence< OUString > aNames = xEventCont->getElementNames();
224 
225                 for ( const OUString& rName : aNames )
226                 {
227                     ScriptEventDescriptor aDesc;
228 
229                     Any aElement = xEventCont->getByName( rName );
230                     aElement >>= aDesc;
231                     OUString sKey = aDesc.ScriptType;
232                     if ( aDesc.ScriptType == "Script" || aDesc.ScriptType == "UNO" )
233                     {
234                         sal_Int32 nIndex = aDesc.ScriptCode.indexOf( ':' );
235                         sKey = aDesc.ScriptCode.copy( 0, nIndex );
236                     }
237                     Reference< XAllListener > xAllListener =
238                         new DialogAllListenerImpl( getScriptListenerForKey( sKey ), aDesc.ScriptType, aDesc.ScriptCode );
239 
240                     // try first to attach event to the ControlModel
241                     bool bSuccess = false;
242                     try
243                     {
244                         Reference< XEventListener > xListener_ = m_xEventAttacher->attachSingleEventListener(
245                             xControlModel, xAllListener, Helper, aDesc.ListenerType,
246                             aDesc.AddListenerParam, aDesc.EventMethod );
247 
248                         if ( xListener_.is() )
249                             bSuccess = true;
250                     }
251                     catch ( const Exception& )
252                     {
253                         DBG_UNHANDLED_EXCEPTION("scripting");
254                     }
255 
256                     try
257                     {
258                         // if we had no success, try to attach to the control
259                         if ( !bSuccess )
260                         {
261                             m_xEventAttacher->attachSingleEventListener(
262                                 xControl, xAllListener, Helper, aDesc.ListenerType,
263                                 aDesc.AddListenerParam, aDesc.EventMethod );
264                         }
265                     }
266                     catch ( const Exception& )
267                     {
268                         DBG_UNHANDLED_EXCEPTION("scripting");
269                     }
270                 }
271             }
272         }
273     }
274 
275 
nestedAttachEvents(const Sequence<Reference<XInterface>> & Objects,const Any & Helper,OUString & sDialogCodeName)276     void DialogEventsAttacherImpl::nestedAttachEvents( const Sequence< Reference< XInterface > >& Objects, const Any& Helper, OUString& sDialogCodeName )
277     {
278         for ( const Reference< XInterface >& rObject : Objects )
279         {
280             // We know that we have to do with instances of XControl.
281             // Otherwise this is not the right implementation for
282             // XScriptEventsAttacher and we have to give up.
283             Reference< XControl > xControl( rObject, UNO_QUERY );
284             Reference< XControlContainer > xControlContainer( xControl, UNO_QUERY );
285             Reference< XDialog > xDialog( xControl, UNO_QUERY );
286             if ( !xControl.is() )
287                 throw IllegalArgumentException();
288 
289             // get XEventsSupplier from control model
290             Reference< XControlModel > xControlModel = xControl->getModel();
291             Reference< XScriptEventsSupplier > xEventsSupplier( xControlModel, UNO_QUERY );
292             attachEventsToControl( xControl, xEventsSupplier, Helper );
293             if ( mbUseFakeVBAEvents )
294             {
295                 xEventsSupplier.set( getFakeVbaEventsSupplier( xControl, sDialogCodeName ) );
296                 Any newHelper(xControl );
297                 attachEventsToControl( xControl, xEventsSupplier, newHelper );
298             }
299             if ( xControlContainer.is() && !xDialog.is() )
300             {
301                 Sequence< Reference< XControl > > aControls = xControlContainer->getControls();
302                 sal_Int32 nControlCount = aControls.getLength();
303 
304                 Sequence< Reference< XInterface > > aObjects( nControlCount );
305                 Reference< XInterface >* pObjects2 = aObjects.getArray();
306                 const Reference< XControl >* pControls = aControls.getConstArray();
307 
308                 for ( sal_Int32 i2 = 0; i2 < nControlCount; ++i2 )
309                 {
310                     pObjects2[i2].set( pControls[i2], UNO_QUERY );
311                 }
312                 nestedAttachEvents( aObjects, Helper, sDialogCodeName );
313             }
314         }
315     }
316 
317 
318     // XScriptEventsAttacher
319 
320 
attachEvents(const Sequence<Reference<XInterface>> & Objects,const css::uno::Reference<css::script::XScriptListener> &,const Any & Helper)321     void SAL_CALL DialogEventsAttacherImpl::attachEvents( const Sequence< Reference< XInterface > >& Objects,
322         const css::uno::Reference<css::script::XScriptListener>&,
323         const Any& Helper )
324     {
325         // get EventAttacher
326         {
327             ::osl::MutexGuard aGuard( getMutex() );
328 
329             if ( !m_xEventAttacher.is() )
330             {
331                 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
332                 if ( !xSMgr.is() )
333                     throw RuntimeException();
334 
335                 m_xEventAttacher.set( xSMgr->createInstanceWithContext(
336                     "com.sun.star.script.EventAttacher", m_xContext ), UNO_QUERY );
337 
338                 if ( !m_xEventAttacher.is() )
339                     throw ServiceNotRegisteredException();
340             }
341         }
342         OUString sDialogCodeName;
343         sal_Int32 nObjCount = Objects.getLength();
344         Reference< awt::XControl > xDlgControl( Objects[ nObjCount - 1 ], uno::UNO_QUERY ); // last object is the dialog
345         if ( xDlgControl.is() )
346         {
347             Reference< XPropertySet > xProps( xDlgControl->getModel(), UNO_QUERY );
348             try
349             {
350                 xProps->getPropertyValue("Name") >>= sDialogCodeName;
351             }
352             catch( Exception& ){}
353         }
354         // go over all objects
355         nestedAttachEvents( Objects, Helper, sDialogCodeName );
356     }
357 
358 
359     // DialogAllListenerImpl
360 
361 
DialogAllListenerImpl(const Reference<XScriptListener> & rxListener,const OUString & rScriptType,const OUString & rScriptCode)362     DialogAllListenerImpl::DialogAllListenerImpl( const Reference< XScriptListener >& rxListener,
363         const OUString& rScriptType, const OUString& rScriptCode )
364         :m_xScriptListener( rxListener )
365         ,m_sScriptType( rScriptType )
366         ,m_sScriptCode( rScriptCode )
367     {
368     }
369 
370 
~DialogAllListenerImpl()371     DialogAllListenerImpl::~DialogAllListenerImpl()
372     {
373     }
374 
375 
firing_impl(const AllEventObject & Event,Any * pRet)376     void DialogAllListenerImpl::firing_impl( const AllEventObject& Event, Any* pRet )
377     {
378         ScriptEvent aScriptEvent;
379         aScriptEvent.Source         = static_cast<OWeakObject *>(this);  // get correct XInterface
380         aScriptEvent.ListenerType   = Event.ListenerType;
381         aScriptEvent.MethodName     = Event.MethodName;
382         aScriptEvent.Arguments      = Event.Arguments;
383         aScriptEvent.Helper         = Event.Helper;
384         aScriptEvent.ScriptType     = m_sScriptType;
385         aScriptEvent.ScriptCode     = m_sScriptCode;
386 
387         if ( m_xScriptListener.is() )
388         {
389             if ( pRet )
390                 *pRet = m_xScriptListener->approveFiring( aScriptEvent );
391             else
392                 m_xScriptListener->firing( aScriptEvent );
393         }
394     }
395 
396 
397     // XEventListener
398 
399 
disposing(const EventObject &)400     void DialogAllListenerImpl::disposing(const EventObject& )
401     {
402     }
403 
404 
405     // XAllListener
406 
407 
firing(const AllEventObject & Event)408     void DialogAllListenerImpl::firing( const AllEventObject& Event )
409     {
410         //::osl::MutexGuard aGuard( getMutex() );
411 
412         firing_impl( Event, nullptr );
413     }
414 
415 
approveFiring(const AllEventObject & Event)416     Any DialogAllListenerImpl::approveFiring( const AllEventObject& Event )
417     {
418         //::osl::MutexGuard aGuard( getMutex() );
419 
420         Any aReturn;
421         firing_impl( Event, &aReturn );
422         return aReturn;
423     }
424 
425 
426     // DialogScriptListenerImpl
427 
428 
DialogUnoScriptListenerImpl(const Reference<XComponentContext> & rxContext,const Reference<css::frame::XModel> & rxModel,const Reference<css::awt::XControl> & rxControl,const Reference<css::uno::XInterface> & rxHandler,const Reference<css::beans::XIntrospectionAccess> & rxIntrospectionAccess,bool bDialogProviderMode)429     DialogUnoScriptListenerImpl::DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext,
430             const Reference< css::frame::XModel >& rxModel,
431             const Reference< css::awt::XControl >& rxControl,
432             const Reference< css::uno::XInterface >& rxHandler,
433             const Reference< css::beans::XIntrospectionAccess >& rxIntrospectionAccess,
434             bool bDialogProviderMode )
435         : DialogSFScriptListenerImpl( rxContext, rxModel )
436         ,m_xControl( rxControl )
437         ,m_xHandler( rxHandler )
438         ,m_xIntrospectionAccess( rxIntrospectionAccess )
439         ,m_bDialogProviderMode( bDialogProviderMode )
440     {
441     }
442 
443 
~DialogScriptListenerImpl()444     DialogScriptListenerImpl::~DialogScriptListenerImpl()
445     {
446     }
447 
448 
firing_impl(const ScriptEvent & aScriptEvent,Any * pRet)449     void DialogSFScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
450     {
451         try
452         {
453             Reference< provider::XScriptProvider > xScriptProvider;
454             if ( m_xModel.is() )
455             {
456                 Reference< provider::XScriptProviderSupplier > xSupplier( m_xModel, UNO_QUERY );
457                 OSL_ENSURE( xSupplier.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider supplier" );
458                 if ( xSupplier.is() )
459                     xScriptProvider.set( xSupplier->getScriptProvider() );
460             }
461             else
462             {
463                 OSL_ASSERT( m_xContext.is() );
464                 if ( m_xContext.is() )
465                 {
466                     Reference< provider::XScriptProviderFactory > xFactory =
467                         provider::theMasterScriptProviderFactory::get( m_xContext );
468 
469                     Any aCtx;
470                     aCtx <<= OUString("user");
471                     xScriptProvider = xFactory->createScriptProvider( aCtx );
472                 }
473             }
474 
475             OSL_ENSURE( xScriptProvider.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider" );
476 
477             if ( xScriptProvider.is() )
478             {
479                 Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode );
480                 OSL_ENSURE( xScript.is(), "DialogScriptListenerImpl::firing_impl: failed to get script" );
481 
482                 if ( xScript.is() )
483                 {
484                     Sequence< Any > aInParams;
485                     Sequence< sal_Int16 > aOutParamsIndex;
486                     Sequence< Any > aOutParams;
487 
488                     // get arguments for script
489                     aInParams = aScriptEvent.Arguments;
490 
491                     Any aResult = xScript->invoke( aInParams, aOutParamsIndex, aOutParams );
492                     if ( pRet )
493                         *pRet = aResult;
494                 }
495             }
496         }
497         catch ( const Exception& )
498         {
499             DBG_UNHANDLED_EXCEPTION("scripting");
500         }
501     }
502 
firing_impl(const ScriptEvent & aScriptEvent,Any * pRet)503     void DialogLegacyScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
504     {
505         OUString sScriptURL;
506         OUString sScriptCode( aScriptEvent.ScriptCode );
507 
508         if ( aScriptEvent.ScriptType == "StarBasic" )
509         {
510             // StarBasic script: convert ScriptCode to scriptURL
511             sal_Int32 nIndex = sScriptCode.indexOf( ':' );
512             if ( nIndex >= 0 && nIndex < sScriptCode.getLength() )
513             {
514                 sScriptURL = "vnd.sun.star.script:" +
515                     sScriptCode.copy( nIndex + 1 ) +
516                     "?language=Basic&location=" +
517                     sScriptCode.copy( 0, nIndex );
518             }
519             ScriptEvent aSFScriptEvent( aScriptEvent );
520             aSFScriptEvent.ScriptCode = sScriptURL;
521             DialogSFScriptListenerImpl::firing_impl( aSFScriptEvent, pRet );
522         }
523     }
524 
firing_impl(const ScriptEvent & aScriptEvent,Any * pRet)525     void DialogUnoScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
526     {
527         OUString aMethodName = aScriptEvent.ScriptCode.copy( strlen("vnd.sun.star.UNO:") );
528 
529         const Any* pArguments = aScriptEvent.Arguments.getConstArray();
530         Any aEventObject = pArguments[0];
531 
532         bool bHandled = false;
533         if( m_xHandler.is() )
534         {
535             if( m_bDialogProviderMode )
536             {
537                 Reference< XDialogEventHandler > xDialogEventHandler( m_xHandler, UNO_QUERY );
538                 if( xDialogEventHandler.is() )
539                 {
540                     Reference< XDialog > xDialog( m_xControl, UNO_QUERY );
541                     bHandled = xDialogEventHandler->callHandlerMethod( xDialog, aEventObject, aMethodName );
542                 }
543             }
544             else
545             {
546                 Reference< XContainerWindowEventHandler > xContainerWindowEventHandler( m_xHandler, UNO_QUERY );
547                 if( xContainerWindowEventHandler.is() )
548                 {
549                     Reference< XWindow > xWindow( m_xControl, UNO_QUERY );
550                     bHandled = xContainerWindowEventHandler->callHandlerMethod( xWindow, aEventObject, aMethodName );
551                 }
552             }
553         }
554 
555         Any aRet;
556         if( !bHandled && m_xIntrospectionAccess.is() )
557         {
558             try
559             {
560                 // call method
561                 const Reference< XIdlMethod >& rxMethod = m_xIntrospectionAccess->
562                     getMethod( aMethodName, MethodConcept::ALL - MethodConcept::DANGEROUS );
563 
564                 Reference< XMaterialHolder > xMaterialHolder =
565                     Reference< XMaterialHolder >::query( m_xIntrospectionAccess );
566                 Any aHandlerObject = xMaterialHolder->getMaterial();
567 
568                 Sequence< Reference< XIdlClass > > aParamTypeSeq = rxMethod->getParameterTypes();
569                 sal_Int32 nParamCount = aParamTypeSeq.getLength();
570                 if( nParamCount == 0 )
571                 {
572                     Sequence<Any> args;
573                     rxMethod->invoke( aHandlerObject, args );
574                     bHandled = true;
575                 }
576                 else if( nParamCount == 2 )
577                 {
578                     // Signature check automatically done by reflection
579                     Sequence<Any> Args(2);
580                     Any* pArgs = Args.getArray();
581                     if( m_bDialogProviderMode )
582                     {
583                         Reference< XDialog > xDialog( m_xControl, UNO_QUERY );
584                         pArgs[0] <<= xDialog;
585                     }
586                     else
587                     {
588                         Reference< XWindow > xWindow( m_xControl, UNO_QUERY );
589                         pArgs[0] <<= xWindow;
590                     }
591                     pArgs[1] = aEventObject;
592                     aRet = rxMethod->invoke( aHandlerObject, Args );
593                     bHandled = true;
594                 }
595             }
596             catch( const Exception& )
597             {
598                 DBG_UNHANDLED_EXCEPTION("scripting");
599             }
600         }
601 
602         if( bHandled )
603         {
604             if( pRet )
605                 *pRet = aRet;
606         }
607         else
608         {
609             OUString aRes(SfxResId(STR_ERRUNOEVENTBINDUNG));
610             OUString aQuoteChar( "\"" );
611 
612             sal_Int32 nIndex = aRes.indexOf( '%' );
613 
614             OUString aOUFinal =
615                 aRes.copy( 0, nIndex ) +
616                 aQuoteChar + aMethodName + aQuoteChar +
617                 aRes.copy( nIndex + 2 );
618 
619             std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
620                                                       VclMessageType::Warning, VclButtonsType::Ok, aOUFinal));
621             xBox->run();
622         }
623     }
624 
625 
626     // XEventListener
627 
628 
disposing(const EventObject &)629     void DialogScriptListenerImpl::disposing(const EventObject& )
630     {
631     }
632 
633 
634     // XScriptListener
635 
636 
firing(const ScriptEvent & aScriptEvent)637     void DialogScriptListenerImpl::firing( const ScriptEvent& aScriptEvent )
638     {
639         //::osl::MutexGuard aGuard( getMutex() );
640 
641         firing_impl( aScriptEvent, nullptr );
642     }
643 
644 
approveFiring(const ScriptEvent & aScriptEvent)645     Any DialogScriptListenerImpl::approveFiring( const ScriptEvent& aScriptEvent )
646     {
647         //::osl::MutexGuard aGuard( getMutex() );
648 
649         Any aReturn;
650         firing_impl( aScriptEvent, &aReturn );
651         return aReturn;
652     }
653 
654 
655 }   // namespace dlgprov
656 
657 
658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
659