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