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