1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: eventhelper.cxx,v $
10  * $Revision: 1.0 $
11  *
12  * This file is part of OpenOffice.org.
13  *
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.
17  *
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).
23  *
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.
28  *
29  ************************************************************************/
30 
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_scripting.hxx"
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/uno3.hxx>
35 #include <comphelper/proparrhlp.hxx>
36 #include <comphelper/propertycontainer.hxx>
37 
38 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
39 
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/beans/XIntrospection.hpp>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 
44 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
45 #include <com/sun/star/lang/XServiceName.hpp>
46 #include <com/sun/star/lang/XServiceInfo.hpp>
47 #include <com/sun/star/lang/XInitialization.hpp>
48 
49 #include <com/sun/star/frame/XModel.hpp>
50 
51 #include <com/sun/star/script/XLibraryContainer.hpp>
52 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
53 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
54 
55 #include <com/sun/star/drawing/XControlShape.hpp>
56 
57 #include <com/sun/star/awt/XControl.hpp>
58 #include <com/sun/star/awt/XDialog.hpp>
59 #include <com/sun/star/awt/KeyEvent.hpp>
60 #include <com/sun/star/awt/MouseEvent.hpp>
61 #include <com/sun/star/awt/XFixedText.hpp> //liuchen 2009-6-5
62 #include <com/sun/star/awt/XTextComponent.hpp> //liuchen 2009-6-5
63 #include <com/sun/star/awt/XComboBox.hpp> //liuchen 2009-6-18
64 #include <com/sun/star/awt/XRadioButton.hpp> //liuchen 2009-7-30
65 
66 #include <msforms/ReturnInteger.hpp>
67 
68 #include <sfx2/objsh.hxx>
69 #include <basic/sbstar.hxx>
70 #include <basic/basmgr.hxx>
71 #include <basic/sbmeth.hxx>
72 #include <basic/sbmod.hxx>
73 #include <basic/sbx.hxx>
74 
75 
76 
77 
78 // for debug
79 #include <comphelper/anytostring.hxx>
80 
81 
82 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
83 #include <com/sun/star/script/XScriptListener.hpp>
84 #include <cppuhelper/implbase1.hxx>
85 #include <cppuhelper/implbase2.hxx>
86 #include <comphelper/evtmethodhelper.hxx>
87 
88 #include <set>
89 #include <list>
90 #include <hash_map>
91 
92 using namespace ::com::sun::star;
93 using namespace ::com::sun::star::script;
94 using namespace ::com::sun::star::uno;
95 using namespace ::ooo::vba;
96 
97 #define MAP_CHAR_LEN(x) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))//liuchen 2009-6-8
98 #define GET_TYPE(x) ::getCppuType((uno::Reference< x > *)0);
99 
100 // Some constants
101 const static rtl::OUString DELIM = rtl::OUString::createFromAscii( "::" );
102 const static sal_Int32 DELIMLEN = DELIM.getLength();
103 
104 #if 0
105 void dumpListeners( const Reference< beans::XIntrospection >& xIntrospection, const Reference<XInterface>& xIfc)
106 {
107     Reference< beans::XIntrospectionAccess > xIntrospectionAccess;
108     if ( xIntrospection.is() )
109     {
110         xIntrospectionAccess = xIntrospection->inspect(
111             makeAny( xIfc ) );
112         Sequence< Type > aControlListeners =
113             xIntrospectionAccess->getSupportedListeners();
114         sal_Int32 nLength = aControlListeners.getLength();
115 
116         for ( sal_Int32 i = 0; i< nLength; ++i )
117         {
118             Type& listType = aControlListeners[ i ];
119             rtl::OUString sFullTypeName = listType.getTypeName();
120             rtl::OUString sTypeName = listType.getTypeName();
121             sal_Int32 lastDotIndex = -1;
122             if ( ( lastDotIndex = sFullTypeName.lastIndexOf( '.' ) ) > -1 )
123             {
124                 sTypeName = sFullTypeName.copy( lastDotIndex + 1 );
125             }
126             Sequence< ::rtl::OUString > sMeths = comphelper::getEventMethodsForType( listType );
127             sal_Int32 sMethLen = sMeths.getLength();
128             for ( sal_Int32 j=0 ; j < sMethLen; ++j )
129             {
130                 OSL_TRACE("**Listener [%d] Type[%s] Method[%s]",j,
131                     rtl::OUStringToOString( sTypeName,
132                         RTL_TEXTENCODING_UTF8 ).getStr(),
133                     rtl::OUStringToOString( sMeths[ j ],
134                         RTL_TEXTENCODING_UTF8 ).getStr() );
135             }
136         }
137 
138     }
139 }
140 
141 void dumpEvent( const ScriptEvent& evt )
142 {
143     OSL_TRACE("dumpEvent: Source %s",
144         rtl::OUStringToOString( comphelper::anyToString( makeAny(evt.Source)),
145             RTL_TEXTENCODING_UTF8 ).getStr() );
146 
147     OSL_TRACE("dumpEvent: ScriptType %s",
148         rtl::OUStringToOString( evt.ScriptType,
149             RTL_TEXTENCODING_UTF8 ).getStr() );
150 
151     OSL_TRACE("dumpEvent: ScriptCode %s",
152         rtl::OUStringToOString( evt.ScriptCode,
153             RTL_TEXTENCODING_UTF8 ).getStr() );
154 
155     OSL_TRACE("dumpEvent: ListenerType %s",
156         rtl::OUStringToOString( evt.ListenerType.getTypeName(),
157             RTL_TEXTENCODING_UTF8 ).getStr() );
158 
159     OSL_TRACE("dumpEvent: Listener methodname %s",
160         rtl::OUStringToOString( evt.MethodName,
161             RTL_TEXTENCODING_UTF8 ).getStr() );
162 
163     OSL_TRACE("dumpEvent: arguments;");
164     sal_Int32 nLen = evt.Arguments.getLength();
165     for ( sal_Int32 index=0; index < nLen; ++index )
166     {
167         OSL_TRACE("\t [%d] %s", index,
168         rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[ index ] ),
169             RTL_TEXTENCODING_UTF8 ).getStr() );
170 
171     }
172 }
173 
174 #endif
175 
176 bool isKeyEventOk( awt::KeyEvent& evt, const Sequence< Any >& params )
177 {
178     if ( !( params.getLength() > 0 ) ||
179         !( params[ 0 ] >>= evt ) )
180         return false;
181     return true;
182 }
183 
184 bool isMouseEventOk( awt::MouseEvent& evt, const Sequence< Any >& params )
185 {
186     if ( !( params.getLength() > 0 ) ||
187         !( params[ 0 ] >>= evt ) )
188         return false;
189     return true;
190 }
191 
192 Sequence< Any > ooMouseEvtToVBADblClick( const Sequence< Any >& params )
193 {
194     Sequence< Any > translatedParams;
195     awt::MouseEvent evt;
196 
197     if ( !( isMouseEventOk(evt, params)) ||
198         (evt.ClickCount != 2) )
199         return Sequence< Any >();
200     // give back orig params, this will signal that the event is good
201     return params;
202 }
203 
204 Sequence< Any > ooMouseEvtToVBAMouseEvt( const Sequence< Any >& params )
205 {
206     Sequence< Any > translatedParams;
207     awt::MouseEvent evt;
208 
209     if ( !isMouseEventOk(evt, params) )
210         return Sequence< Any >();
211 
212     translatedParams.realloc(4);
213 
214     // Buttons
215     translatedParams[ 0 ] <<= evt.Buttons;
216     // Shift
217     translatedParams[ 1 ] <<= evt.Modifiers;
218     // X
219     translatedParams[ 2 ] <<= evt.X;
220     // Y
221     translatedParams[ 3 ] <<= evt.Y;
222     return translatedParams;
223 }
224 
225 Sequence< Any > ooKeyPressedToVBAKeyPressed( const Sequence< Any >& params )
226 {
227     Sequence< Any > translatedParams;
228     awt::KeyEvent evt;
229 
230     if ( !isKeyEventOk( evt, params ) )
231         return Sequence< Any >();
232 
233     translatedParams.realloc(1);
234 
235     msforms::ReturnInteger keyCode;
236     keyCode.Value = evt.KeyCode;
237     translatedParams[0] <<= keyCode;
238     return  translatedParams;
239 }
240 
241 Sequence< Any > ooKeyPressedToVBAKeyUpDown( const Sequence< Any >& params )
242 {
243     Sequence< Any > translatedParams;
244     awt::KeyEvent evt;
245 
246     if ( !isKeyEventOk( evt, params ) )
247         return Sequence< Any >();
248 
249     translatedParams.realloc(2);
250 
251     msforms::ReturnInteger keyCode;
252     sal_Int8 shift = sal::static_int_cast<sal_Int8>( evt.Modifiers );
253 
254     // #TODO check whether values from OOO conform to values generated from vba
255     keyCode.Value = evt.KeyCode;
256     translatedParams[0] <<= keyCode;
257     translatedParams[1] <<= shift;
258     return  translatedParams;
259 }
260 
261 typedef Sequence< Any > (*Translator)(const Sequence< Any >&);
262 
263 //liuchen 2009-6-23
264 //expand the "TranslateInfo" struct to support more kinds of events
265 struct TranslateInfo
266 {
267     rtl::OUString sVBAName; //vba event name
268     Translator toVBA;       //the method to convert OO event parameters to VBA event parameters
269 	bool (*ApproveRule)(const ScriptEvent& evt, void* pPara); //this method is used to determine which types of controls should execute the event
270 	void *pPara;			//Parameters for the above approve method
271 };
272 
273 
274 typedef std::hash_map< rtl::OUString,
275 std::list< TranslateInfo >,
276 ::rtl::OUStringHash,
277 ::std::equal_to< ::rtl::OUString > > EventInfoHash;
278 
279 //liuchen 2009-6-23
280 struct TranslatePropMap
281 {
282 	rtl::OUString sEventInfo;   //OO event name
283 	TranslateInfo aTransInfo;
284 };
285 
286 bool ApproveAll(const ScriptEvent& evt, void* pPara); //allow all types of controls to execute the event
287 bool ApproveType(const ScriptEvent& evt, void* pPara); //certain types of controls should execute the event, those types are given by pPara
288 bool DenyType(const ScriptEvent& evt, void* pPara);    //certain types of controls should not execute the event, those types are given by pPara
289 bool DenyMouseDrag(const ScriptEvent& evt, void* pPara); //used for VBA MouseMove event when "Shift" key is pressed
290 
291 struct TypeList
292 {
293 	uno::Type* pTypeList;
294 	int nListLength;
295 };
296 
297 Type typeXFixedText = GET_TYPE(awt::XFixedText)
298 Type typeXTextComponent = GET_TYPE(awt::XTextComponent)
299 Type typeXComboBox = GET_TYPE(awt::XComboBox)
300 Type typeXRadioButton = GET_TYPE(awt::XRadioButton)
301 
302 
303 TypeList fixedTextList = {&typeXFixedText, 1};
304 TypeList textCompList = {&typeXTextComponent, 1};
305 TypeList radioButtonList = {&typeXRadioButton, 1};
306 TypeList comboBoxList = {&typeXComboBox, 1};
307 
308 //this array stores the OO event to VBA event translation info
309 static TranslatePropMap aTranslatePropMap_Impl[] =
310 {
311 	// actionPerformed ooo event
312 	{ MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Click"), NULL, ApproveAll, NULL } },
313 	{ MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Change"), NULL, DenyType, (void*)(&radioButtonList) } },  //liuchen 2009-7-30, OptionalButton_Change event is not the same as OptionalButton_Click event
314 
315 	// itemStateChanged ooo event
316 	{ MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL, ApproveType, (void*)(&comboBoxList) } },  //liuchen, add to support VBA ComboBox_Click event
317 	{ MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveType, (void*)(&radioButtonList) } }, //liuchen 2009-7-30, OptionalButton_Change event should be triggered when the button state is changed
318 
319 	// changed ooo event
320 	{ MAP_CHAR_LEN("changed"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },
321 
322 	// focusGained ooo event
323 	{ MAP_CHAR_LEN("focusGained"), { MAP_CHAR_LEN("_GotFocus"), NULL, ApproveAll, NULL } },
324 
325 	// focusLost ooo event
326 	{ MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_LostFocus"), NULL, ApproveAll, NULL } },
327 	{ MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_Exit"), NULL, ApproveType, (void*)(&textCompList) } }, //liuchen, add to support VBA TextBox_Exit event
328 
329 	// adjustmentValueChanged ooo event
330 	{ MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Scroll"), NULL, ApproveAll, NULL } },
331 	{ MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },
332 
333 	// textChanged ooo event
334 	{ MAP_CHAR_LEN("textChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } },
335 
336 	// keyReleased ooo event
337 	{ MAP_CHAR_LEN("keyReleased"), { MAP_CHAR_LEN("_KeyUp"), ooKeyPressedToVBAKeyUpDown, ApproveAll, NULL } },
338 
339 	// mouseReleased ooo event
340 	{ MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_Click"), ooMouseEvtToVBAMouseEvt, ApproveType, (void*)(&fixedTextList) } }, //liuchen, add to support VBA Label_Click event
341 	{ MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_MouseUp"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },
342 
343 	// mousePressed ooo event
344 	{ MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_MouseDown"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },
345 	{ MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_DblClick"), ooMouseEvtToVBADblClick, ApproveAll, NULL } },
346 
347 	// mouseMoved ooo event
348 	{ MAP_CHAR_LEN("mouseMoved"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } },
349 	{ MAP_CHAR_LEN("mouseDragged"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, DenyMouseDrag, NULL } }, //liuchen, add to support VBA MouseMove event when the "Shift" key is pressed
350 
351 	// keyPressed ooo event
352 	{ MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyDown"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } },
353 	{ MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyPress"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } }
354 };
355 
356 EventInfoHash& getEventTransInfo()
357 {
358     static bool initialised = false;
359     static EventInfoHash eventTransInfo;
360     if ( !initialised )
361     {
362         rtl::OUString sEventInfo = MAP_CHAR_LEN("");
363         TranslatePropMap* pTransProp = aTranslatePropMap_Impl;
364         int nCount = sizeof(aTranslatePropMap_Impl) / sizeof(aTranslatePropMap_Impl[0]);
365 
366         int i = 0;
367         while (i < nCount)
368         {
369             sEventInfo = pTransProp->sEventInfo;
370             std::list< TranslateInfo > infoList;
371             do
372             {
373                 infoList.push_back( pTransProp->aTransInfo );
374                 pTransProp++;
375                 i++;
376             }while(i < nCount && sEventInfo == pTransProp->sEventInfo);
377             eventTransInfo[sEventInfo] = infoList;
378         }
379         initialised = true;
380     }
381     return eventTransInfo;
382 }
383 //liuchen 2009-6-23 end
384 
385 // Helper class
386 
387 class ScriptEventHelper
388 {
389 public:
390     ScriptEventHelper( const Reference< XInterface >& xControl );
391     Sequence< ScriptEventDescriptor > createEvents( const rtl::OUString& sCodeName );
392     Sequence< rtl::OUString > getEventListeners();
393 private:
394     Reference< XComponentContext > m_xCtx;
395     Reference< XInterface > m_xControl;
396 };
397 
398 bool
399 eventMethodToDescriptor( const ::rtl::OUString& rEventMethod, ScriptEventDescriptor& evtDesc, const ::rtl::OUString& sCodeName )
400 {
401     // format of ControlListener is TypeName::methodname e.g.
402     // "com.sun.star.awt.XActionListener::actionPerformed" or
403     // "XActionListener::actionPerformed
404 
405     ::rtl::OUString sMethodName;
406     ::rtl::OUString sTypeName;
407     sal_Int32 nDelimPos = rEventMethod.indexOf( DELIM );
408     if ( nDelimPos == -1 )
409     {
410         return false;
411     }
412     sMethodName = rEventMethod.copy( nDelimPos + DELIMLEN );
413     sTypeName = rEventMethod.copy( 0, nDelimPos );
414 
415     EventInfoHash& infos = getEventTransInfo();
416 
417     // Only create an ScriptEventDescriptor for an event we can translate
418     // or emulate
419     if ( sMethodName.getLength()
420          && sTypeName.getLength()
421          && ( infos.find( sMethodName ) != infos.end() ) )
422     {
423         // just fill in CodeName, when the event fires the other
424 	// info is gathered from the event source to determine what
425 	// event handler we try to call
426         evtDesc.ScriptCode = sCodeName;
427         evtDesc.ListenerType = sTypeName;
428         evtDesc.EventMethod = sMethodName;
429 
430         // set this it VBAInterop, ensures that it doesn't
431         // get persisted or shown in property editors
432         evtDesc.ScriptType = rtl::OUString::createFromAscii(
433             "VBAInterop" );
434         return true;
435     }
436     return false;
437 
438 }
439 
440 ScriptEventHelper::ScriptEventHelper( const Reference< XInterface >& xControl ) : m_xControl( xControl )
441 {
442     Reference < beans::XPropertySet > xProps(
443         ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
444     m_xCtx.set( xProps->getPropertyValue( rtl::OUString(
445         RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))),
446         uno::UNO_QUERY_THROW );
447 }
448 
449 Sequence< rtl::OUString >
450 ScriptEventHelper::getEventListeners()
451 {
452     Reference< lang::XMultiComponentFactory > xMFac(
453         m_xCtx->getServiceManager(), UNO_QUERY );
454     std::list< rtl::OUString > eventMethods;
455 
456     if ( xMFac.is() )
457     {
458         Reference< beans::XIntrospection > xIntrospection(
459             xMFac->createInstanceWithContext( rtl::OUString(
460                 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection"  ) ), m_xCtx ), UNO_QUERY );
461 #if 0
462         dumpListeners( xIntrospection, m_xControl );
463         dumpListeners( xIntrospection, m_xControl->getModel() );
464 #endif
465         Reference< beans::XIntrospectionAccess > xIntrospectionAccess;
466 	if  ( xIntrospection.is() )
467 	{
468             xIntrospectionAccess = xIntrospection->inspect(
469                 makeAny( m_xControl ) );
470             Sequence< Type > aControlListeners =
471                 xIntrospectionAccess->getSupportedListeners();
472             sal_Int32 nLength = aControlListeners.getLength();
473             for ( sal_Int32 i = 0; i< nLength; ++i )
474             {
475                 Type& listType = aControlListeners[ i ];
476                 rtl::OUString sFullTypeName = listType.getTypeName();
477                 Sequence< ::rtl::OUString > sMeths =
478                     comphelper::getEventMethodsForType( listType );
479                 sal_Int32 sMethLen = sMeths.getLength();
480                 for ( sal_Int32 j=0 ; j < sMethLen; ++j )
481                 {
482                     rtl::OUString sEventMethod = sFullTypeName;
483                     sEventMethod += DELIM;
484                     sEventMethod += sMeths[ j ];
485                     eventMethods.push_back( sEventMethod );
486                 }
487             }
488 
489         }
490     }
491 
492     Sequence< rtl::OUString > sEventMethodNames( eventMethods.size() );
493     std::list< rtl::OUString >::const_iterator it = eventMethods.begin();
494     rtl::OUString* pDest = sEventMethodNames.getArray();
495 
496     for ( ; it != eventMethods.end(); ++it, ++pDest )
497         *pDest = *it;
498 
499     return sEventMethodNames;
500 }
501 
502 Sequence< ScriptEventDescriptor >
503 ScriptEventHelper::createEvents( const rtl::OUString& sCodeName )
504 {
505     Sequence< rtl::OUString > aControlListeners = getEventListeners();
506     rtl::OUString* pSrc = aControlListeners.getArray();
507     sal_Int32 nLength = aControlListeners.getLength();
508 
509     Sequence< ScriptEventDescriptor > aDest( nLength );
510     sal_Int32 nEvts = 0;
511     for ( sal_Int32 i = 0; i< nLength; ++i, ++pSrc )
512     {
513         // from getListeners eventName is of form
514         // "com.sun.star.awt.XActionListener::actionPerformed"
515         // we need to strip "com.sun.star.awt." from that for form
516         // controls
517     	ScriptEventDescriptor evtDesc;
518         if ( eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) )
519         {
520             sal_Int32 dIndex = nEvts;
521             ++nEvts;
522             if ( nEvts > aDest.getLength() )
523                 aDest.realloc( nEvts );// should never happen
524             aDest[ dIndex ] = evtDesc;
525         }
526     }
527     aDest.realloc( nEvts );
528 
529     return aDest;
530 }
531 
532 
533 typedef ::cppu::WeakImplHelper1< container::XNameContainer > NameContainer_BASE;
534 
535 class ReadOnlyEventsNameContainer : public NameContainer_BASE
536 {
537 public:
538     ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName );
539     // XNameContainer
540 
541     virtual void SAL_CALL insertByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, RuntimeException)
542     {
543         throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
544 
545     }
546     virtual void SAL_CALL removeByName( const ::rtl::OUString& ) throw (::com::sun::star::container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
547     {
548         throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
549     }
550 
551     // XNameReplace
552     virtual void SAL_CALL replaceByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
553     {
554         throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() );
555 
556     }
557 
558     // XNameAccess
559     virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException);
560     virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
561     virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (RuntimeException);
562 
563     // XElementAccess
564     virtual Type SAL_CALL getElementType(  ) throw (RuntimeException)
565     { return getCppuType(static_cast< const rtl::OUString * >(0) ); }
566     virtual ::sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException)
567     { return ( ( m_hEvents.size() > 0 ? sal_True : sal_False ) ); }
568 private:
569 
570 typedef std::hash_map< rtl::OUString, Any, ::rtl::OUStringHash,
571 ::std::equal_to< ::rtl::OUString > > EventSupplierHash;
572 
573     EventSupplierHash m_hEvents;
574 };
575 
576 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName )
577 {
578     const rtl::OUString* pSrc = eventMethods.getConstArray();
579     sal_Int32 nLen = eventMethods.getLength();
580     for ( sal_Int32 index = 0; index < nLen; ++index, ++pSrc )
581     {
582         Any aDesc;
583         ScriptEventDescriptor evtDesc;
584         if (  eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) )
585         {
586             aDesc <<= evtDesc;
587             m_hEvents[ *pSrc ] = aDesc;
588         }
589     }
590 }
591 
592 Any SAL_CALL
593 ReadOnlyEventsNameContainer::getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException){
594     EventSupplierHash::const_iterator it = m_hEvents.find( aName );
595     if ( it == m_hEvents.end() )
596         throw container::NoSuchElementException();
597     return it->second;
598 }
599 
600 Sequence< ::rtl::OUString > SAL_CALL
601 ReadOnlyEventsNameContainer::getElementNames(  ) throw (RuntimeException)
602 {
603     Sequence< ::rtl::OUString > names(m_hEvents.size());
604     rtl::OUString* pDest = names.getArray();
605     EventSupplierHash::const_iterator it = m_hEvents.begin();
606     EventSupplierHash::const_iterator it_end = m_hEvents.end();
607     for ( sal_Int32 index = 0; it != it_end; ++index, ++pDest, ++it )
608         *pDest = it->first;
609     return names;
610 }
611 
612 sal_Bool SAL_CALL
613 ReadOnlyEventsNameContainer::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException)
614 {
615     EventSupplierHash::const_iterator it = m_hEvents.find( aName );
616     if ( it == m_hEvents.end() )
617         return sal_False;
618     return sal_True;
619 }
620 
621 typedef ::cppu::WeakImplHelper1< XScriptEventsSupplier > EventsSupplier_BASE;
622 
623 class ReadOnlyEventsSupplier : public EventsSupplier_BASE
624 {
625 public:
626     ReadOnlyEventsSupplier( const Sequence< ::rtl::OUString >& eventMethods, const rtl::OUString& sCodeName )
627     { m_xNameContainer = new ReadOnlyEventsNameContainer( eventMethods, sCodeName ); }
628 
629     // XScriptEventSupplier
630     virtual Reference< container::XNameContainer > SAL_CALL getEvents(  ) throw (RuntimeException){ return m_xNameContainer; }
631 private:
632     Reference< container::XNameContainer > m_xNameContainer;
633 };
634 
635 typedef ::cppu::WeakImplHelper2< XScriptListener, lang::XInitialization > EventListener_BASE;
636 
637 #define EVENTLSTNR_PROPERTY_ID_MODEL         1
638 #define EVENTLSTNR_PROPERTY_MODEL            ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) )
639 
640 class EventListener : public EventListener_BASE
641     ,public ::comphelper::OMutexAndBroadcastHelper
642     ,public ::comphelper::OPropertyContainer
643     ,public ::comphelper::OPropertyArrayUsageHelper< EventListener >
644 
645 {
646 
647 public:
648     EventListener( const Reference< XComponentContext >& rxContext );
649     // XEventListener
650     virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( RuntimeException );
651 	using cppu::OPropertySetHelper::disposing;
652 
653     // XScriptListener
654     virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException);
655     virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException);
656     // XPropertySet
657     virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw (::com::sun::star::uno::RuntimeException);
658     // XInitialization
659     virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
660     // XInterface
661     DECLARE_XINTERFACE()
662 
663     // XTypeProvider
664     DECLARE_XTYPEPROVIDER()
665     virtual void SAL_CALL setFastPropertyValue( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
666     {
667         OPropertyContainer::setFastPropertyValue( nHandle, rValue );
668 	if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL )
669             setShellFromModel();
670     }
671 
672 protected:
673     // OPropertySetHelper
674     virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(  );
675 
676     // OPropertyArrayUsageHelper
677     virtual ::cppu::IPropertyArrayHelper* createArrayHelper(  ) const;
678 
679 private:
680     void setShellFromModel();
681     void firing_Impl( const  ScriptEvent& evt, Any *pSyncRet=NULL ) throw( RuntimeException );
682 
683     Reference< XComponentContext > m_xContext;
684     Reference< frame::XModel > m_xModel;
685     SfxObjectShell* mpShell;
686 
687 };
688 
689 EventListener::EventListener( const Reference< XComponentContext >& rxContext ) :
690 OPropertyContainer(GetBroadcastHelper()), m_xContext( rxContext ), mpShell( 0 )
691 {
692     registerProperty( EVENTLSTNR_PROPERTY_MODEL, EVENTLSTNR_PROPERTY_ID_MODEL,
693         beans::PropertyAttribute::TRANSIENT, &m_xModel, ::getCppuType( &m_xModel ) );
694 
695 }
696 
697 void
698 EventListener::setShellFromModel()
699 {
700 	// reset mpShell
701 	mpShell = 0;
702 	SfxObjectShell* pShell = SfxObjectShell::GetFirst();
703 	while ( m_xModel.is() && pShell )
704 	{
705 		if ( pShell->GetModel() == m_xModel )
706 		{
707 			mpShell = pShell;
708 			break;
709 		}
710 		pShell = SfxObjectShell::GetNext( *pShell );
711 	}
712 }
713 
714 //XEventListener
715 void
716 EventListener::disposing(const lang::EventObject&)  throw( RuntimeException )
717 {
718 }
719 
720 //XScriptListener
721 
722 void SAL_CALL
723 EventListener::firing(const ScriptEvent& evt) throw(RuntimeException)
724 {
725     firing_Impl( evt );
726 }
727 
728 Any SAL_CALL
729 EventListener::approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException)
730 {
731     Any ret;
732     firing_Impl( evt, &ret );
733     return ret;
734 }
735 
736 // XInitialization
737 void SAL_CALL
738 EventListener::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
739 {
740     if ( aArguments.getLength() == 1 )
741         aArguments[0] >>= m_xModel;
742     OSL_TRACE("EventListener::initialize() args %d m_xModel %d", aArguments.getLength(), m_xModel.is() );
743 }
744 
745 // XInterface
746 
747 IMPLEMENT_FORWARD_XINTERFACE2( EventListener, EventListener_BASE, OPropertyContainer )
748 
749 // XTypeProvider
750 
751 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener, EventListener_BASE, OPropertyContainer )
752 
753 // OPropertySetHelper
754 
755 ::cppu::IPropertyArrayHelper&
756 EventListener::getInfoHelper(  )
757 {
758     return *getArrayHelper();
759 }
760 
761 // OPropertyArrayUsageHelper
762 
763 ::cppu::IPropertyArrayHelper*
764 EventListener::createArrayHelper(  ) const
765 {
766     Sequence< beans::Property > aProps;
767     describeProperties( aProps );
768     return new ::cppu::OPropertyArrayHelper( aProps );
769 }
770 
771 // XPropertySet
772 Reference< beans::XPropertySetInfo >
773 EventListener::getPropertySetInfo(  ) throw (RuntimeException)
774 {
775     Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
776     return xInfo;
777 }
778 
779 //liuchen 2009-6-23
780 //decide if the control should execute the event
781 bool ApproveAll(const ScriptEvent&, void* )
782 {
783 	return true;
784 }
785 
786 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
787 bool FindControl(const ScriptEvent& evt, void* pPara)
788 {
789 	lang::EventObject aEvent;
790 	evt.Arguments[ 0 ] >>= aEvent;
791 	uno::Reference< uno::XInterface > xInterface( aEvent.Source, uno::UNO_QUERY );
792 
793 	TypeList* pTypeListInfo = static_cast<TypeList*>(pPara);
794 	Type* pType = pTypeListInfo->pTypeList;
795 	int nLen = pTypeListInfo->nListLength;
796 
797 	for (int i = 0; i < nLen; i++)
798 	{
799 		if ( xInterface->queryInterface( *pType ).hasValue() )
800 		{
801 			return true;
802 		}
803 		pType++;
804 	}
805 
806 	return false;
807 }
808 
809 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
810 bool ApproveType(const ScriptEvent& evt, void* pPara)
811 {
812 	return FindControl(evt, pPara);
813 }
814 
815 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
816 bool DenyType(const ScriptEvent& evt, void* pPara)
817 {
818 	return !FindControl(evt, pPara);
819 }
820 
821 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
822 //the former should be denyed, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is
823 //pressed can be correctly triggered
824 bool DenyMouseDrag(const ScriptEvent& evt, void* )
825 {
826 	awt::MouseEvent aEvent;
827 	evt.Arguments[ 0 ] >>= aEvent;
828 	if (aEvent.Buttons == 0 )
829 	{
830 		return true;
831 	}
832 	else
833 	{
834 		return false;
835 	}
836 }
837 
838 
839 
840 //liuchen 2009-6-23
841 // EventListener
842 
843 void
844 EventListener::firing_Impl(const ScriptEvent& evt, Any* /*pRet*/ ) throw(RuntimeException)
845 {
846 	OSL_TRACE("EventListener::firing_Impl( FAKE VBA_EVENTS )");
847     static const ::rtl::OUString vbaInterOp =
848         ::rtl::OUString::createFromAscii("VBAInterop");
849 
850     // let default handlers deal with non vba stuff
851     if ( !evt.ScriptType.equals( vbaInterOp ) )
852         return;
853     lang::EventObject aEvent;
854     evt.Arguments[ 0 ] >>= aEvent;
855 	OSL_TRACE("Argument[0] is  %s", rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[0] ), RTL_TEXTENCODING_UTF8 ).getStr() );
856 	OSL_TRACE("Getting Control");
857     uno::Reference< awt::XControl > xControl( aEvent.Source, uno::UNO_QUERY_THROW );
858 	OSL_TRACE("Getting properties");
859     uno::Reference< beans::XPropertySet > xProps( xControl->getModel(), uno::UNO_QUERY_THROW );
860 
861     rtl::OUString sName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm") );
862 	OSL_TRACE("Getting Name");
863 
864     uno::Reference< awt::XDialog > xDlg( aEvent.Source, uno::UNO_QUERY );
865     if ( !xDlg.is() )
866         xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) ) >>= sName;
867     //dumpEvent( evt );
868     EventInfoHash& infos = getEventTransInfo();
869     EventInfoHash::const_iterator eventInfo_it = infos.find( evt.MethodName );
870     EventInfoHash::const_iterator it_end = infos.end();
871     if ( eventInfo_it == it_end )
872     {
873         OSL_TRACE("Bogus event for %s",
874             rtl::OUStringToOString( evt.ScriptType, RTL_TEXTENCODING_UTF8 ).getStr() );
875         return;
876     }
877 
878     uno::Reference< script::provider::XScriptProviderSupplier > xSPS( m_xModel, uno::UNO_QUERY );
879     uno::Reference< script::provider::XScriptProvider > xScriptProvider;
880     if ( xSPS.is() )
881         xScriptProvider =  xSPS->getScriptProvider();
882     if ( xScriptProvider.is() && mpShell )
883     {
884         std::list< TranslateInfo > matchingMethods;
885         std::list< TranslateInfo >::const_iterator txInfo =
886             eventInfo_it->second.begin();
887         std::list< TranslateInfo >::const_iterator txInfo_end = eventInfo_it->second.end();
888         rtl::OUString sMacroLoc = rtl::OUString::createFromAscii("Standard.").concat( evt.ScriptCode ).concat( rtl::OUString::createFromAscii(".") );
889 
890         StarBASIC* pBasic = mpShell->GetBasic();
891         SbModule* pModule = pBasic->FindModule( evt.ScriptCode );
892         for ( ; pModule && txInfo != txInfo_end; ++txInfo )
893         {
894             // see if we have a match for the handlerextension
895             // where ScriptCode is methodname_handlerextension
896             rtl::OUString sTemp = sName.concat( (*txInfo).sVBAName );
897 
898             OSL_TRACE("*** trying to invoke %s ",
899                 rtl::OUStringToOString( sTemp, RTL_TEXTENCODING_UTF8 ).getStr() );
900             SbMethod* pMeth = static_cast< SbMethod* >( pModule->Find( sTemp, SbxCLASS_METHOD ) );
901             if ( pMeth )
902             {
903 				//liuchen 2009-6-8
904 				if (! txInfo->ApproveRule(evt, txInfo->pPara) )
905 				{
906 					continue;
907 				}
908 				//liuchen 2009-6-8
909                 // !! translate arguments & emulate events where necessary
910                 Sequence< Any > aArguments;
911                 if  ( (*txInfo).toVBA )
912                     aArguments = (*txInfo).toVBA( evt.Arguments );
913                 else
914                     aArguments = evt.Arguments;
915                 if ( aArguments.getLength() )
916                 {
917                     // call basic event handlers for event
918 
919                     static rtl::OUString part1 = rtl::OUString::createFromAscii( "vnd.sun.star.script:");
920                     static rtl::OUString part2 = rtl::OUString::createFromAscii("?language=Basic&location=document");
921 
922                     // create script url
923                     rtl::OUString url = part1 + sMacroLoc + sTemp + part2;
924 
925                     OSL_TRACE("script url = %s",
926                         rtl::OUStringToOString( url,
927                             RTL_TEXTENCODING_UTF8 ).getStr() );
928                     Sequence< sal_Int16 > aOutArgsIndex;
929                     Sequence< Any > aOutArgs;
930                     try
931                     {
932                         if ( mpShell )
933                         {
934                             uno::Any aRet;
935                             mpShell->CallXScript( url,
936                                 aArguments, aRet, aOutArgsIndex, aOutArgs, false );
937                         }
938                     }
939                     catch ( uno::Exception& e )
940                     {
941                         OSL_TRACE("event script raised %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
942                     }
943                }
944            }
945        }
946     }
947 }
948 
949 typedef ::cppu::WeakImplHelper1< XVBAToOOEventDescGen > VBAToOOEventDescGen_BASE;
950 
951 
952 class VBAToOOEventDescGen : public VBAToOOEventDescGen_BASE
953 {
954 public:
955     VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext );
956 
957     // XVBAToOOEventDescGen
958     virtual Sequence< ScriptEventDescriptor > SAL_CALL getEventDescriptions( const Reference< XInterface >& control, const rtl::OUString& sCodeName ) throw (RuntimeException);
959     virtual Reference< XScriptEventsSupplier > SAL_CALL getEventSupplier( const Reference< XInterface >& xControl,  const rtl::OUString& sCodeName ) throw (::com::sun::star::uno::RuntimeException);
960 private:
961     Reference< XComponentContext > m_xContext;
962 
963 };
964 
965 VBAToOOEventDescGen::VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext ):m_xContext( rxContext ) {}
966 
967 Sequence< ScriptEventDescriptor > SAL_CALL
968 VBAToOOEventDescGen::getEventDescriptions( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName ) throw (RuntimeException)
969 {
970     ScriptEventHelper evntHelper( xControl );
971     return evntHelper.createEvents( sCodeName );
972 }
973 
974 Reference< XScriptEventsSupplier > SAL_CALL
975 VBAToOOEventDescGen::getEventSupplier( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName  ) throw (::com::sun::star::uno::RuntimeException)
976 {
977     ScriptEventHelper evntHelper( xControl );
978     Reference< XScriptEventsSupplier > xSupplier =
979         new ReadOnlyEventsSupplier(
980             evntHelper.getEventListeners(), sCodeName ) ;
981     return xSupplier;
982 }
983 
984 // Component related
985 
986 namespace evtlstner
987 {
988     ::rtl::OUString SAL_CALL getImplementationName()
989     {
990         static ::rtl::OUString* pImplName = 0;
991         if ( !pImplName )
992         {
993             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
994             if ( !pImplName )
995             {
996                 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.EventListener" ) );
997                 pImplName = &aImplName;
998             }
999         }
1000         return *pImplName;
1001     }
1002 
1003     uno::Reference< XInterface > SAL_CALL create(
1004     Reference< XComponentContext > const & xContext )
1005     SAL_THROW( () )
1006     {
1007         return static_cast< lang::XTypeProvider * >( new EventListener( xContext ) );
1008     }
1009 
1010     Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
1011     {
1012         const ::rtl::OUString strName( ::evtlstner::getImplementationName() );
1013         return Sequence< ::rtl::OUString >( &strName, 1 );
1014     }
1015 }
1016 namespace ooevtdescgen
1017 {
1018     ::rtl::OUString SAL_CALL getImplementationName()
1019     {
1020         static ::rtl::OUString* pImplName = 0;
1021         if ( !pImplName )
1022         {
1023             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
1024             if ( !pImplName )
1025             {
1026                 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAToOOEventDesc" ) );
1027                 pImplName = &aImplName;
1028             }
1029         }
1030         return *pImplName;
1031     }
1032 
1033     uno::Reference< XInterface > SAL_CALL create(
1034         Reference< XComponentContext > const & xContext )
1035         SAL_THROW( () )
1036     {
1037         return static_cast< lang::XTypeProvider * >( new VBAToOOEventDescGen( xContext ) );
1038     }
1039 
1040     Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
1041     {
1042     	const ::rtl::OUString strName( ::ooevtdescgen::getImplementationName() );
1043         return Sequence< ::rtl::OUString >( &strName, 1 );
1044     }
1045 }
1046