1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 
31 #include "eventhandler.hxx"
32 #include "propctrlr.hrc"
33 #include "formbrowsertools.hxx"
34 #include "formresid.hrc"
35 #include "formstrings.hxx"
36 #include "handlerhelper.hxx"
37 #include "modulepcr.hxx"
38 #include "pcrcommon.hxx"
39 #include "pcrstrings.hxx"
40 #include "propertycontrolextender.hxx"
41 
42 /** === begin UNO includes === **/
43 #include <com/sun/star/awt/XTabControllerModel.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/beans/UnknownPropertyException.hpp>
46 #include <com/sun/star/beans/XIntrospection.hpp>
47 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
48 #include <com/sun/star/container/NoSuchElementException.hpp>
49 #include <com/sun/star/container/XChild.hpp>
50 #include <com/sun/star/container/XIndexAccess.hpp>
51 #include <com/sun/star/container/XNameContainer.hpp>
52 #include <com/sun/star/container/XNameReplace.hpp>
53 #include <com/sun/star/form/FormComponentType.hpp>
54 #include <com/sun/star/form/XForm.hpp>
55 #include <com/sun/star/form/runtime/XFormController.hpp>
56 #include <com/sun/star/inspection/PropertyControlType.hpp>
57 #include <com/sun/star/lang/NullPointerException.hpp>
58 #include <com/sun/star/script/XEventAttacherManager.hpp>
59 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
60 #include <com/sun/star/util/XModifiable.hpp>
61 #include <com/sun/star/uri/UriReferenceFactory.hpp>
62 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
63 /** === end UNO includes === **/
64 
65 #include <comphelper/namedvaluecollection.hxx>
66 #include <comphelper/evtmethodhelper.hxx>
67 #include <comphelper/types.hxx>
68 #include <cppuhelper/implbase1.hxx>
69 #include <rtl/ref.hxx>
70 #include <rtl/ustrbuf.hxx>
71 #include <sfx2/app.hxx>
72 #include <svl/eitem.hxx>
73 #include <svl/itemset.hxx>
74 #include <svx/svxdlg.hxx>
75 #include <svx/svxids.hrc>
76 #include <tools/diagnose_ex.h>
77 #include <vcl/msgbox.hxx>
78 
79 #include <map>
80 #include <algorithm>
81 
82 //------------------------------------------------------------------------
83 extern "C" void SAL_CALL createRegistryInfo_EventHandler()
84 {
85 	::pcr::OAutoRegistration< ::pcr::EventHandler > aAutoRegistration;
86 }
87 
88 //........................................................................
89 namespace pcr
90 {
91 //........................................................................
92 
93     /** === begin UNO using === **/
94     using ::com::sun::star::uno::Reference;
95     using ::com::sun::star::uno::XComponentContext;
96     using ::com::sun::star::beans::XPropertySet;
97     using ::com::sun::star::uno::Any;
98     using ::com::sun::star::uno::TypeClass_STRING;
99     using ::com::sun::star::uno::Type;
100     using ::com::sun::star::beans::XPropertyChangeListener;
101     using ::com::sun::star::beans::Property;
102     using ::com::sun::star::beans::PropertyState;
103     using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
104     using ::com::sun::star::uno::Sequence;
105     using ::com::sun::star::script::ScriptEventDescriptor;
106     using ::com::sun::star::script::XScriptEventsSupplier;
107     using ::com::sun::star::lang::NullPointerException;
108     using ::com::sun::star::uno::Exception;
109     using ::com::sun::star::container::XChild;
110     using ::com::sun::star::container::XIndexAccess;
111     using ::com::sun::star::script::XEventAttacherManager;
112     using ::com::sun::star::uno::UNO_QUERY;
113     using ::com::sun::star::uno::UNO_QUERY_THROW;
114     using ::com::sun::star::uno::XInterface;
115     using ::com::sun::star::beans::XIntrospection;
116     using ::com::sun::star::beans::XIntrospectionAccess;
117     using ::com::sun::star::container::XNameContainer;
118     using ::com::sun::star::awt::XTabControllerModel;
119     using ::com::sun::star::form::XForm;
120     using ::com::sun::star::form::runtime::XFormController;
121     using ::com::sun::star::beans::UnknownPropertyException;
122     using ::com::sun::star::uno::makeAny;
123     using ::com::sun::star::container::NoSuchElementException;
124     using ::com::sun::star::beans::XPropertySetInfo;
125     using ::com::sun::star::container::XNameReplace;
126     using ::com::sun::star::lang::IllegalArgumentException;
127     using ::com::sun::star::lang::WrappedTargetException;
128     using ::com::sun::star::uno::RuntimeException;
129     using ::com::sun::star::beans::PropertyValue;
130     using ::com::sun::star::inspection::LineDescriptor;
131     using ::com::sun::star::inspection::XPropertyControlFactory;
132     using ::com::sun::star::inspection::InteractiveSelectionResult;
133     using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled;
134     using ::com::sun::star::inspection::InteractiveSelectionResult_Success;
135     using ::com::sun::star::inspection::XObjectInspectorUI;
136     using ::com::sun::star::util::XModifiable;
137     using ::com::sun::star::beans::PropertyChangeEvent;
138     using ::com::sun::star::frame::XFrame;
139     using ::com::sun::star::frame::XModel;
140     using ::com::sun::star::frame::XController;
141     using ::com::sun::star::uno::UNO_SET_THROW;
142     using com::sun::star::uri::UriReferenceFactory;
143     using com::sun::star::uri::XUriReferenceFactory;
144     using com::sun::star::uri::XVndSunStarScriptUrlReference;
145     using ::com::sun::star::lang::XEventListener;
146     /** === end UNO using === **/
147     namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType;
148     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
149     namespace FormComponentType = ::com::sun::star::form::FormComponentType;
150 
151     //====================================================================
152     //= EventDescription
153     //====================================================================
154     EventDescription::EventDescription( EventId _nId, const sal_Char* _pListenerNamespaceAscii, const sal_Char* _pListenerClassAsciiName,
155             const sal_Char* _pListenerMethodAsciiName, sal_uInt16 _nDisplayNameResId, const rtl::OString& _sHelpId, const rtl::OString& _sUniqueBrowseId )
156         :sDisplayName( String( PcrRes( _nDisplayNameResId ) ) )
157         ,sListenerMethodName( ::rtl::OUString::createFromAscii( _pListenerMethodAsciiName ) )
158         ,sHelpId( _sHelpId )
159         ,sUniqueBrowseId( _sUniqueBrowseId )
160         ,nId( _nId )
161     {
162         ::rtl::OUStringBuffer aQualifiedListenerClass;
163         aQualifiedListenerClass.appendAscii( "com.sun.star." );
164         aQualifiedListenerClass.appendAscii( _pListenerNamespaceAscii );
165         aQualifiedListenerClass.appendAscii( "." );
166         aQualifiedListenerClass.appendAscii( _pListenerClassAsciiName );
167         sListenerClassName = aQualifiedListenerClass.makeStringAndClear();
168     }
169 
170     //========================================================================
171     //= helper
172     //========================================================================
173     namespace
174     {
175         //....................................................................
176         #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \
177             s_aKnownEvents.insert( EventMap::value_type( \
178                 ::rtl::OUString::createFromAscii( asciimethod ), \
179                 EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) )
180 
181         //....................................................................
182         bool lcl_getEventDescriptionForMethod( const ::rtl::OUString& _rMethodName, EventDescription& _out_rDescription )
183         {
184             static EventMap s_aKnownEvents;
185             if ( s_aKnownEvents.empty() )
186             {
187                 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
188                 if ( s_aKnownEvents.empty() )
189                 {
190                     static sal_Int32 nEventId = 0;
191 
192                     DESCRIBE_EVENT( "form", "XApproveActionListener",       "approveAction",            APPROVEACTIONPERFORMED );
193                     DESCRIBE_EVENT( "awt",  "XActionListener",              "actionPerformed",          ACTIONPERFORMED );
194                     DESCRIBE_EVENT( "form", "XChangeListener",              "changed",                  CHANGED );
195                     DESCRIBE_EVENT( "awt",  "XTextListener",                "textChanged",              TEXTCHANGED );
196                     DESCRIBE_EVENT( "awt",  "XItemListener",                "itemStateChanged",         ITEMSTATECHANGED );
197                     DESCRIBE_EVENT( "awt",  "XFocusListener",               "focusGained",              FOCUSGAINED );
198                     DESCRIBE_EVENT( "awt",  "XFocusListener",               "focusLost",                FOCUSLOST );
199                     DESCRIBE_EVENT( "awt",  "XKeyListener",                 "keyPressed",               KEYTYPED );
200                     DESCRIBE_EVENT( "awt",  "XKeyListener",                 "keyReleased",              KEYUP );
201                     DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseEntered",             MOUSEENTERED );
202                     DESCRIBE_EVENT( "awt",  "XMouseMotionListener",         "mouseDragged",             MOUSEDRAGGED );
203                     DESCRIBE_EVENT( "awt",  "XMouseMotionListener",         "mouseMoved",               MOUSEMOVED );
204                     DESCRIBE_EVENT( "awt",  "XMouseListener",               "mousePressed",             MOUSEPRESSED );
205                     DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseReleased",            MOUSERELEASED );
206                     DESCRIBE_EVENT( "awt",  "XMouseListener",               "mouseExited",              MOUSEEXITED );
207                     DESCRIBE_EVENT( "form", "XResetListener",               "approveReset",             APPROVERESETTED );
208                     DESCRIBE_EVENT( "form", "XResetListener",               "resetted",                 RESETTED );
209                     DESCRIBE_EVENT( "form", "XSubmitListener",              "approveSubmit",            SUBMITTED );
210                     DESCRIBE_EVENT( "form", "XUpdateListener",              "approveUpdate",            BEFOREUPDATE );
211                     DESCRIBE_EVENT( "form", "XUpdateListener",              "updated",                  AFTERUPDATE );
212                     DESCRIBE_EVENT( "form", "XLoadListener",                "loaded",                   LOADED );
213                     DESCRIBE_EVENT( "form", "XLoadListener",                "reloading",                RELOADING );
214                     DESCRIBE_EVENT( "form", "XLoadListener",                "reloaded",                 RELOADED );
215                     DESCRIBE_EVENT( "form", "XLoadListener",                "unloading",                UNLOADING );
216                     DESCRIBE_EVENT( "form", "XLoadListener",                "unloaded",                 UNLOADED );
217                     DESCRIBE_EVENT( "form", "XConfirmDeleteListener",       "confirmDelete",            CONFIRMDELETE );
218                     DESCRIBE_EVENT( "sdb",  "XRowSetApproveListener",       "approveRowChange",         APPROVEROWCHANGE );
219                     DESCRIBE_EVENT( "sdbc", "XRowSetListener",              "rowChanged",               ROWCHANGE );
220                     DESCRIBE_EVENT( "sdb",  "XRowSetApproveListener",       "approveCursorMove",        POSITIONING );
221                     DESCRIBE_EVENT( "sdbc", "XRowSetListener",              "cursorMoved",              POSITIONED );
222                     DESCRIBE_EVENT( "form", "XDatabaseParameterListener",   "approveParameter",         APPROVEPARAMETER );
223                     DESCRIBE_EVENT( "sdb",  "XSQLErrorListener",            "errorOccured",             ERROROCCURED );
224                     DESCRIBE_EVENT( "awt",  "XAdjustmentListener",          "adjustmentValueChanged",   ADJUSTMENTVALUECHANGED );
225                 }
226             }
227 
228             EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName );
229             if ( pos == s_aKnownEvents.end() )
230                 return false;
231 
232             _out_rDescription = pos->second;
233             return true;
234         }
235 
236         //....................................................................
237         ::rtl::OUString lcl_getEventPropertyName( const ::rtl::OUString& _rListenerClassName, const ::rtl::OUString& _rMethodName )
238         {
239             ::rtl::OUStringBuffer aPropertyName;
240             aPropertyName.append( _rListenerClassName );
241             aPropertyName.append( (sal_Unicode)';' );
242             aPropertyName.append( _rMethodName.getStr() );
243             return aPropertyName.makeStringAndClear();
244         }
245 
246         //................................................................
247         ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const Sequence< ScriptEventDescriptor >& _rAllAssignedMacros )
248         {
249             ScriptEventDescriptor aScriptEvent;
250             // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
251             //  so this ScriptEventDescriptor properly describes the given event
252             aScriptEvent.ListenerType = _rEvent.sListenerClassName;
253             aScriptEvent.EventMethod = _rEvent.sListenerMethodName;
254 
255             const ScriptEventDescriptor* pAssignedEvent = _rAllAssignedMacros.getConstArray();
256             sal_Int32 assignedEventCount( _rAllAssignedMacros.getLength() );
257             for ( sal_Int32 assignedEvent = 0; assignedEvent < assignedEventCount; ++assignedEvent, ++pAssignedEvent )
258             {
259                 if  (   ( pAssignedEvent->ListenerType != _rEvent.sListenerClassName )
260                     ||  ( pAssignedEvent->EventMethod != _rEvent.sListenerMethodName )
261                     )
262                     continue;
263 
264                 if  (   ( pAssignedEvent->ScriptCode.getLength() == 0 )
265                     ||  ( pAssignedEvent->ScriptType.getLength() == 0 )
266                     )
267                 {
268                     DBG_ERROR( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
269                     continue;
270                 }
271 
272                 aScriptEvent = *pAssignedEvent;
273 
274                 if ( !aScriptEvent.ScriptType.equalsAscii( "StarBasic" ) )
275                     continue;
276 
277                 // this is an old-style macro specification:
278                 // [document|application]:Library.Module.Function
279                 // we need to translate this to the new-style macro specification
280                 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]
281 
282                 sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' );
283                 OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" );
284                 ::rtl::OUString sLocation = aScriptEvent.ScriptCode.copy( 0, nPrefixLen );
285                 ::rtl::OUString sMacroPath = aScriptEvent.ScriptCode.copy( nPrefixLen + 1 );
286 
287                 ::rtl::OUStringBuffer aNewStyleSpec;
288                 aNewStyleSpec.appendAscii( "vnd.sun.star.script:" );
289                 aNewStyleSpec.append     ( sMacroPath );
290                 aNewStyleSpec.appendAscii( "?language=Basic&location=" );
291                 aNewStyleSpec.append     ( sLocation );
292 
293                 aScriptEvent.ScriptCode = aNewStyleSpec.makeStringAndClear();
294 
295                 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
296                 aScriptEvent.ScriptType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) );
297             }
298             return aScriptEvent;
299         }
300 
301         //................................................................
302         ::rtl::OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor )
303         {
304             EventDescription aKnownEvent;
305             if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) )
306                 return aKnownEvent.sListenerClassName;
307             DBG_ERROR( "lcl_getQualifiedKnownListenerName: unknown method name!" );
308                 // somebody assigned an script to a form component event which we don't know
309                 // Speaking strictly, this is not really an error - it is possible to do
310                 // this programmatically -, but it should rarely happen, since it's not possible
311                 // via UI
312             return _rFormComponentEventDescriptor.ListenerType;
313         }
314 
315         //................................................................
316         typedef ::std::set< Type, TypeLessByName > TypeBag;
317 
318         //................................................................
319         void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent,
320             const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes )
321         {
322             if ( !_rxComponent.is() )
323                 return;
324             OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" );
325 
326             Reference< XIntrospectionAccess > xIntrospectionAccess(
327                 _rxIntrospection->inspect( makeAny( _rxComponent ) ), UNO_QUERY_THROW );
328 
329             Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() );
330 
331             ::std::copy( aListeners.getConstArray(), aListeners.getConstArray() + aListeners.getLength(),
332                 ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
333         }
334 
335         //................................................................
336         bool operator ==( const ScriptEventDescriptor _lhs, const ScriptEventDescriptor _rhs )
337         {
338             return  (   ( _lhs.ListenerType         == _rhs.ListenerType        )
339                     &&  ( _lhs.EventMethod          == _rhs.EventMethod         )
340                     &&  ( _lhs.AddListenerParam     == _rhs.AddListenerParam    )
341                     &&  ( _lhs.ScriptType           == _rhs.ScriptType          )
342                     &&  ( _lhs.ScriptCode           == _rhs.ScriptCode          )
343                     );
344         }
345     }
346 
347     //====================================================================
348     //= EventHandler
349     //====================================================================
350     typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::container::XNameReplace
351                                     >   EventHolder_Base;
352     /** a UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg
353     */
354     class EventHolder : public EventHolder_Base
355     {
356     private:
357         typedef ::std::hash_map< ::rtl::OUString, ScriptEventDescriptor, ::rtl::OUStringHash >  EventMap;
358         typedef ::std::map< EventId, EventMap::iterator >                                       EventMapIndexAccess;
359 
360         EventMap            m_aEventNameAccess;
361         EventMapIndexAccess m_aEventIndexAccess;
362 
363     public:
364         EventHolder( );
365 
366         void addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent );
367 
368         /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird
369             format used by the macro assignment dialog, it is returned directly
370         */
371         ScriptEventDescriptor getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const;
372 
373         // XNameReplace
374         virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException);
375         virtual Any SAL_CALL getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
376         virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
377         virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException);
378         virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
379         virtual ::sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);
380 
381     protected:
382         ~EventHolder( );
383 
384     private:
385         ScriptEventDescriptor impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const;
386     };
387 
388     DBG_NAME( EventHolder )
389 	//------------------------------------------------------------------------
390     EventHolder::EventHolder()
391     {
392         DBG_CTOR( EventHolder, NULL );
393     }
394 
395 	//------------------------------------------------------------------------
396     EventHolder::~EventHolder()
397     {
398         m_aEventNameAccess.clear();
399         m_aEventIndexAccess.clear();
400         DBG_DTOR( EventHolder, NULL );
401     }
402 
403 	//------------------------------------------------------------------------
404     void EventHolder::addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent )
405     {
406         ::std::pair< EventMap::iterator, bool > insertionResult =
407             m_aEventNameAccess.insert( EventMap::value_type( _rEventName, _rScriptEvent ) );
408         OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" );
409         m_aEventIndexAccess[ _nId ] = insertionResult.first;
410     }
411 
412     //------------------------------------------------------------------------
413     ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const
414     {
415         return impl_getDescriptor_throw( _rEventName );
416     }
417 
418     //------------------------------------------------------------------------
419     ScriptEventDescriptor EventHolder::impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const
420     {
421         EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName );
422         if ( pos == m_aEventNameAccess.end() )
423             throw NoSuchElementException( ::rtl::OUString(), *const_cast< EventHolder* >( this ) );
424         return pos->second;
425     }
426 
427 	//------------------------------------------------------------------------
428     void SAL_CALL EventHolder::replaceByName( const ::rtl::OUString& _rName, const Any& _rElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
429     {
430         EventMap::iterator pos = m_aEventNameAccess.find( _rName );
431         if ( pos == m_aEventNameAccess.end() )
432             throw NoSuchElementException( ::rtl::OUString(), *this );
433 
434         Sequence< PropertyValue > aScriptDescriptor;
435         OSL_VERIFY( _rElement >>= aScriptDescriptor );
436 
437         ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor );
438 
439         pos->second.ScriptType = aExtractor.getOrDefault( "EventType", ::rtl::OUString() );
440         pos->second.ScriptCode = aExtractor.getOrDefault( "Script", ::rtl::OUString() );
441     }
442 
443     //------------------------------------------------------------------------
444     Any SAL_CALL EventHolder::getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
445     {
446         ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) );
447 
448         Any aRet;
449         Sequence< PropertyValue > aScriptDescriptor( 2 );
450         aScriptDescriptor[0].Name = ::rtl::OUString::createFromAscii( "EventType" );
451         aScriptDescriptor[0].Value <<= aDescriptor.ScriptType;
452         aScriptDescriptor[1].Name = ::rtl::OUString::createFromAscii( "Script" );
453         aScriptDescriptor[1].Value <<= aDescriptor.ScriptCode;
454 
455         return makeAny( aScriptDescriptor );
456     }
457 
458 	//------------------------------------------------------------------------
459     Sequence< ::rtl::OUString > SAL_CALL EventHolder::getElementNames(  ) throw (RuntimeException)
460     {
461         Sequence< ::rtl::OUString > aReturn( m_aEventIndexAccess.size() );
462         ::rtl::OUString* pReturn = aReturn.getArray();
463 
464         // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
465         // main access method is by name. In it's UI, it shows the possible events in exactly the
466         // order in which XNameAccess::getElementNames returns them.
467         // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
468         // relative to the sequence returned by XNameAccess::getElementNames.
469         // This is IMO weird, since it mixes index access with name access, which decreases efficiency
470         // of the implementation.
471         // Well, it means we're forced to return the events in getElementNames in exactly the same as they
472         // appear in the property browser UI.
473         for (   EventMapIndexAccess::const_iterator loop = m_aEventIndexAccess.begin();
474                 loop != m_aEventIndexAccess.end();
475                 ++loop, ++pReturn
476             )
477             *pReturn = loop->second->first;
478         return aReturn;
479     }
480 
481  	//------------------------------------------------------------------------
482     sal_Bool SAL_CALL EventHolder::hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException)
483     {
484         EventMap::const_iterator pos = m_aEventNameAccess.find( _rName );
485         return pos != m_aEventNameAccess.end();
486     }
487 
488 	//------------------------------------------------------------------------
489     Type SAL_CALL EventHolder::getElementType(  ) throw (RuntimeException)
490     {
491         return ::getCppuType( static_cast< Sequence< PropertyValue >* >( NULL ) );
492     }
493 
494 	//------------------------------------------------------------------------
495     sal_Bool SAL_CALL EventHolder::hasElements(  ) throw (RuntimeException)
496     {
497         return !m_aEventNameAccess.empty();
498     }
499 
500 
501     //====================================================================
502     //= EventHandler
503     //====================================================================
504     DBG_NAME( EventHandler )
505     //--------------------------------------------------------------------
506     EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext )
507         :EventHandler_Base( m_aMutex )
508         ,m_aContext( _rxContext )
509         ,m_aPropertyListeners( m_aMutex )
510         ,m_bEventsMapInitialized( false )
511         ,m_bIsDialogElement( false )
512         ,m_nGridColumnType( -1 )
513     {
514         DBG_CTOR( EventHandler, NULL );
515     }
516 
517     //--------------------------------------------------------------------
518     EventHandler::~EventHandler()
519     {
520         DBG_DTOR( EventHandler, NULL );
521     }
522 
523     //--------------------------------------------------------------------
524     ::rtl::OUString SAL_CALL EventHandler::getImplementationName(  ) throw (RuntimeException)
525     {
526         return getImplementationName_static();
527     }
528 
529     //--------------------------------------------------------------------
530     ::sal_Bool SAL_CALL EventHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
531     {
532         StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() );
533         return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
534     }
535 
536     //--------------------------------------------------------------------
537     Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames(  ) throw (RuntimeException)
538     {
539         return getSupportedServiceNames_static();
540     }
541 
542     //--------------------------------------------------------------------
543     ::rtl::OUString SAL_CALL EventHandler::getImplementationName_static(  ) throw (RuntimeException)
544     {
545         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.EventHandler" ) );
546     }
547 
548     //--------------------------------------------------------------------
549     Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
550     {
551         Sequence< ::rtl::OUString > aSupported( 1 );
552         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.EventHandler" ) );
553         return aSupported;
554     }
555 
556     //--------------------------------------------------------------------
557     Reference< XInterface > SAL_CALL EventHandler::Create( const Reference< XComponentContext >& _rxContext )
558     {
559         return *( new EventHandler( _rxContext ) );
560     }
561 
562     //--------------------------------------------------------------------
563     void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
564     {
565         ::osl::MutexGuard aGuard( m_aMutex );
566 
567         if ( !_rxIntrospectee.is() )
568             throw NullPointerException();
569 
570         m_xComponent = Reference< XPropertySet >( _rxIntrospectee, UNO_QUERY_THROW );
571 
572         m_bEventsMapInitialized = false;
573         EventMap aEmpty;
574         m_aEvents.swap( aEmpty );
575 
576         m_bIsDialogElement = false;
577         m_nGridColumnType = -1;
578         try
579         {
580             Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() );
581             m_bIsDialogElement = xPSI.is()
582                               && xPSI->hasPropertyByName( PROPERTY_WIDTH )
583                               && xPSI->hasPropertyByName( PROPERTY_HEIGHT )
584                               && xPSI->hasPropertyByName( PROPERTY_POSITIONX )
585                               && xPSI->hasPropertyByName( PROPERTY_POSITIONY );
586 
587             Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY );
588             if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() )
589             {
590                 if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) )
591                 {
592                     m_nGridColumnType = classifyComponent( _rxIntrospectee );
593                 }
594             }
595         }
596         catch( const Exception& )
597         {
598             DBG_UNHANDLED_EXCEPTION();
599         }
600     }
601 
602     //--------------------------------------------------------------------
603     Any SAL_CALL EventHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
604     {
605         ::osl::MutexGuard aGuard( m_aMutex );
606 
607         const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
608 
609         Sequence< ScriptEventDescriptor > aEvents;
610         impl_getComponentScriptEvents_nothrow( aEvents );
611 
612         sal_Int32 nEventCount = aEvents.getLength();
613         const ScriptEventDescriptor* pEvents = aEvents.getConstArray();
614 
615         ScriptEventDescriptor aPropertyValue;
616         for ( sal_Int32 event = 0; event < nEventCount; ++event, ++pEvents )
617         {
618             if  (   rEvent.sListenerClassName == pEvents->ListenerType
619                 &&  rEvent.sListenerMethodName == pEvents->EventMethod
620                 )
621             {
622                 aPropertyValue = *pEvents;
623                 break;
624             }
625         }
626 
627         return makeAny( aPropertyValue );
628     }
629 
630     //--------------------------------------------------------------------
631     void SAL_CALL EventHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
632     {
633         ::osl::MutexGuard aGuard( m_aMutex );
634 
635         const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
636 
637         ScriptEventDescriptor aNewScriptEvent;
638         OSL_VERIFY( _rValue >>= aNewScriptEvent );
639 
640         ScriptEventDescriptor aOldScriptEvent;
641         OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent );
642         if ( aOldScriptEvent == aNewScriptEvent )
643             return;
644 
645         if ( m_bIsDialogElement )
646             impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent );
647         else
648             impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent );
649 
650         Reference< XModifiable > xDoc( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY );
651         if ( xDoc.is() )
652             xDoc->setModified( sal_True );
653 
654         PropertyChangeEvent aEvent;
655         aEvent.Source = m_xComponent;
656         aEvent.PropertyHandle = rEvent.nId;
657         aEvent.PropertyName = _rPropertyName;
658         aEvent.OldValue <<= aOldScriptEvent;
659         aEvent.NewValue <<= aNewScriptEvent;
660         m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange );
661     }
662 
663     //--------------------------------------------------------------------
664     Any SAL_CALL EventHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
665     {
666         ::osl::MutexGuard aGuard( m_aMutex );
667 
668         ::rtl::OUString sNewScriptCode;
669         OSL_VERIFY( _rControlValue >>= sNewScriptCode );
670 
671         Sequence< ScriptEventDescriptor > aAllAssignedEvents;
672         impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
673 
674         const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
675         ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents );
676 
677         OSL_ENSURE( !sNewScriptCode.getLength(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
678         // Usually, there is no possibility for the user to change the content of an event binding directly in the
679         // input field, this instead is done with the macro assignment dialog.
680         // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
681         // control content to an empty string. So this is the only scenario where this method is allowed to be called.
682 
683         // Striclty, we would be able to convert the display value to a property value,
684         // using the "name (location, language)" format we used in convertToControlValue. However,
685         // there is no need for this code ...
686 
687         aAssignedScript.ScriptCode = sNewScriptCode;
688         return makeAny( aAssignedScript );
689     }
690 
691     //--------------------------------------------------------------------
692     Any SAL_CALL EventHandler::convertToControlValue( const ::rtl::OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
693     {
694         ::osl::MutexGuard aGuard( m_aMutex );
695 
696         ScriptEventDescriptor aScriptEvent;
697         OSL_VERIFY( _rPropertyValue >>= aScriptEvent );
698 
699         OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
700             "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
701         (void)_rControlValueType;
702 
703         ::rtl::OUString sScript( aScriptEvent.ScriptCode );
704         if ( sScript.getLength() )
705         {
706             // format is: "name (location, language)"
707             try
708             {
709                 // parse
710                 Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() );
711                 Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW );
712 
713                 ::rtl::OUStringBuffer aComposeBuffer;
714 
715                 // name
716                 aComposeBuffer.append( xScriptUri->getName() );
717 
718                 // location
719                 const ::rtl::OUString sLocationParamName( RTL_CONSTASCII_USTRINGPARAM( "location" ) );
720                 const ::rtl::OUString sLocation = xScriptUri->getParameter( sLocationParamName );
721                 const ::rtl::OUString sLangParamName( RTL_CONSTASCII_USTRINGPARAM( "language" ) );
722                 const ::rtl::OUString sLanguage = xScriptUri->getParameter( sLangParamName );
723 
724                 if ( sLocation.getLength() || sLanguage.getLength() )
725                 {
726                     aComposeBuffer.appendAscii( " (" );
727 
728                     // location
729                     OSL_ENSURE( sLocation.getLength(), "EventHandler::convertToControlValue: unexpected: no location!" );
730                     if ( sLocation.getLength() )
731                     {
732                         aComposeBuffer.append( sLocation );
733                         aComposeBuffer.appendAscii( ", " );
734                     }
735 
736                     // language
737                     if ( sLanguage.getLength() )
738                     {
739                         aComposeBuffer.append( sLanguage );
740                     }
741 
742                     aComposeBuffer.append( sal_Unicode( ')' ) );
743                 }
744 
745                 sScript = aComposeBuffer.makeStringAndClear();
746             }
747             catch( const Exception& )
748             {
749         	    DBG_UNHANDLED_EXCEPTION();
750             }
751         }
752 
753         return makeAny( sScript );
754     }
755 
756     //--------------------------------------------------------------------
757     PropertyState SAL_CALL EventHandler::getPropertyState( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
758     {
759         return PropertyState_DIRECT_VALUE;
760     }
761 
762     //--------------------------------------------------------------------
763     void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
764     {
765         ::osl::MutexGuard aGuard( m_aMutex );
766         if ( !_rxListener.is() )
767             throw NullPointerException();
768         m_aPropertyListeners.addListener( _rxListener );
769     }
770 
771     //--------------------------------------------------------------------
772     void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
773     {
774         ::osl::MutexGuard aGuard( m_aMutex );
775         m_aPropertyListeners.removeListener( _rxListener );
776     }
777 
778     //--------------------------------------------------------------------
779     Sequence< Property > SAL_CALL EventHandler::getSupportedProperties() throw (RuntimeException)
780     {
781         ::osl::MutexGuard aGuard( m_aMutex );
782         if ( !m_bEventsMapInitialized )
783         {
784             const_cast< EventHandler* >( this )->m_bEventsMapInitialized = true;
785             try
786             {
787                 Sequence< Type > aListeners;
788                 impl_getCopmonentListenerTypes_nothrow( aListeners );
789                 sal_Int32 listenerCount = aListeners.getLength();
790 
791                 Property aCurrentProperty;
792                 ::rtl::OUString sListenerClassName;
793 
794                 // loop through all listeners and all methods, and see which we can present at the UI
795                 const Type* pListeners = aListeners.getConstArray();
796                 for ( sal_Int32 listener = 0; listener < listenerCount; ++listener, ++pListeners )
797                 {
798                     aCurrentProperty = Property();
799 
800                     // the programmatic name of the listener, to be used as "property" name
801                     sListenerClassName = pListeners->getTypeName();
802                     OSL_ENSURE( sListenerClassName.getLength(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
803                     if ( !sListenerClassName.getLength() )
804                         continue;
805 
806                     // loop through all methods
807                     Sequence< ::rtl::OUString > aMethods( comphelper::getEventMethodsForType( *pListeners ) );
808 
809                     const ::rtl::OUString* pMethods = aMethods.getConstArray();
810                     sal_uInt32 methodCount = aMethods.getLength();
811 
812                     for (sal_uInt32 method = 0 ; method < methodCount ; ++method, ++pMethods )
813                     {
814                         EventDescription aEvent;
815                         if ( !lcl_getEventDescriptionForMethod( *pMethods, aEvent ) )
816                             continue;
817 
818                         if ( !impl_filterMethod_nothrow( aEvent ) )
819                             continue;
820 
821                         const_cast< EventHandler* >( this )->m_aEvents.insert( EventMap::value_type(
822                             lcl_getEventPropertyName( sListenerClassName, *pMethods ), aEvent ) );
823                     }
824                 }
825 
826             }
827             catch( const Exception& )
828             {
829                 DBG_UNHANDLED_EXCEPTION();
830             }
831         }
832 
833         // sort them by ID - this is the relative ordering in the UI
834         ::std::map< EventId, Property > aOrderedProperties;
835         for (   EventMap::const_iterator loop = m_aEvents.begin();
836                 loop != m_aEvents.end();
837                 ++loop
838             )
839         {
840             aOrderedProperties[ loop->second.nId ] = Property(
841                 loop->first, loop->second.nId,
842                 ::getCppuType( static_cast< const ::rtl::OUString* >( NULL ) ),
843                 PropertyAttribute::BOUND );
844         }
845 
846         StlSyntaxSequence< Property > aReturn( aOrderedProperties.size() );
847         ::std::transform( aOrderedProperties.begin(), aOrderedProperties.end(), aReturn.begin(),
848             ::std::select2nd< ::std::map< EventId, Property >::value_type >() );
849         return aReturn;
850     }
851 
852     //--------------------------------------------------------------------
853     Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupersededProperties( ) throw (RuntimeException)
854     {
855         // none
856         return Sequence< ::rtl::OUString >( );
857     }
858 
859     //--------------------------------------------------------------------
860     Sequence< ::rtl::OUString > SAL_CALL EventHandler::getActuatingProperties( ) throw (RuntimeException)
861     {
862         // none
863         return Sequence< ::rtl::OUString >( );
864     }
865 
866     //--------------------------------------------------------------------
867     LineDescriptor SAL_CALL EventHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
868         const Reference< XPropertyControlFactory >& _rxControlFactory )
869         throw (UnknownPropertyException, NullPointerException, RuntimeException)
870     {
871         if ( !_rxControlFactory.is() )
872             throw NullPointerException();
873 
874         ::osl::MutexGuard aGuard( m_aMutex );
875 
876         LineDescriptor aDescriptor;
877 
878         aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, sal_True );
879         Reference< XEventListener > xControlExtender = new PropertyControlExtender( aDescriptor.Control );
880 
881         const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
882         aDescriptor.DisplayName = rEvent.sDisplayName;
883         aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.sHelpId );
884         aDescriptor.PrimaryButtonId = rtl::OStringToOUString(rEvent.sUniqueBrowseId, RTL_TEXTENCODING_UTF8);
885         aDescriptor.HasPrimaryButton = sal_True;
886         aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Events" ) );
887         return aDescriptor;
888     }
889 
890     //--------------------------------------------------------------------
891     ::sal_Bool SAL_CALL EventHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
892     {
893         return sal_False;
894     }
895 
896     //--------------------------------------------------------------------
897     InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
898     {
899         if ( !_rxInspectorUI.is() )
900             throw NullPointerException();
901 
902         ::osl::MutexGuard aGuard( m_aMutex );
903         const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName );
904 
905         Sequence< ScriptEventDescriptor > aAllAssignedEvents;
906         impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
907 
908         // SvxMacroAssignDlg-compatible structure holding all event/assignments
909         ::rtl::Reference< EventHolder >  pEventHolder( new EventHolder );
910 
911         for (   EventMap::const_iterator event = m_aEvents.begin();
912                 event != m_aEvents.end();
913                 ++event
914             )
915         {
916             // the script which is assigned to the current event (if any)
917             ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event->second, aAllAssignedEvents );
918             pEventHolder->addEvent( event->second.nId, event->second.sListenerMethodName, aAssignedScript );
919         }
920 
921         // the inital selection in the dialog
922         Sequence< ::rtl::OUString > aNames( pEventHolder->getElementNames() );
923         const ::rtl::OUString* pChosenEvent = ::std::find( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), rForEvent.sListenerMethodName );
924         sal_uInt16 nInitialSelection = (sal_uInt16)( pChosenEvent - aNames.getConstArray() );
925 
926         // the dialog
927         SvxAbstractDialogFactory* pFactory = SvxAbstractDialogFactory::Create();
928         if ( !pFactory )
929             return InteractiveSelectionResult_Cancelled;
930 
931         ::std::auto_ptr< VclAbstractDialog > pDialog( pFactory->CreateSvxMacroAssignDlg(
932             PropertyHandlerHelper::getDialogParentWindow( m_aContext ),
933             impl_getContextFrame_nothrow(),
934             m_bIsDialogElement,
935             pEventHolder.get(),
936             nInitialSelection
937         ) );
938 
939         if ( !pDialog.get() )
940             return InteractiveSelectionResult_Cancelled;
941 
942         // DF definite problem here
943         // OK & Cancel seem to be both returning 0
944         if ( pDialog->Execute() == RET_CANCEL )
945             return InteractiveSelectionResult_Cancelled;
946 
947         try
948         {
949             for (   EventMap::const_iterator event = m_aEvents.begin();
950                     event != m_aEvents.end();
951                     ++event
952                 )
953             {
954                 ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event->second.sListenerMethodName ) );
955 
956                 // set the new "property value"
957                 setPropertyValue(
958                     lcl_getEventPropertyName( event->second.sListenerClassName, event->second.sListenerMethodName ),
959                     makeAny( aScriptDescriptor )
960                 );
961             }
962         }
963         catch( const Exception& )
964         {
965             DBG_UNHANDLED_EXCEPTION();
966         }
967 
968         return InteractiveSelectionResult_Success;
969     }
970 
971     //--------------------------------------------------------------------
972     void SAL_CALL EventHandler::actuatingPropertyChanged( const ::rtl::OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
973     {
974         DBG_ERROR( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
975     }
976 
977     //--------------------------------------------------------------------
978     IMPLEMENT_FORWARD_XCOMPONENT( EventHandler, EventHandler_Base )
979 
980     //--------------------------------------------------------------------
981     void SAL_CALL EventHandler::disposing()
982     {
983         EventMap aEmpty;
984         m_aEvents.swap( aEmpty );
985         m_xComponent.clear();
986     }
987 
988     //--------------------------------------------------------------------
989     sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
990     {
991         return sal_True;
992     }
993 
994     //------------------------------------------------------------------------
995     Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const
996     {
997         Reference< XFrame > xContextFrame;
998 
999         try
1000         {
1001             Reference< XModel > xContextDocument( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW );
1002             Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW );
1003             xContextFrame.set( xController->getFrame(), UNO_SET_THROW );
1004         }
1005         catch( const Exception& )
1006         {
1007         	DBG_UNHANDLED_EXCEPTION();
1008         }
1009 
1010         return xContextFrame;
1011     }
1012 
1013     //--------------------------------------------------------------------
1014     sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const
1015     {
1016         Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1017         Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW );
1018 
1019         // get the index of the inspected object within it's parent container
1020         sal_Int32 nElements = xParentAsIndexAccess->getCount();
1021         for ( sal_Int32 i=0; i<nElements; ++i )
1022         {
1023             Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW );
1024             if ( xElement == m_xComponent )
1025                 return i;
1026         }
1027         throw NoSuchElementException();
1028     }
1029 
1030     //--------------------------------------------------------------------
1031     void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1032     {
1033         _out_rEvents = Sequence < ScriptEventDescriptor >();
1034         try
1035         {
1036             Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1037             Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1038             _out_rEvents = xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() );
1039 
1040             // the form component script API has unqualified listener names, but for normalization
1041             // purpose, we want fully qualified ones
1042             ScriptEventDescriptor* pEvents = _out_rEvents.getArray();
1043             ScriptEventDescriptor* pEventsEnd = _out_rEvents.getArray() + _out_rEvents.getLength();
1044             while ( pEvents != pEventsEnd )
1045             {
1046                 pEvents->ListenerType = lcl_getQualifiedKnownListenerName( *pEvents );
1047                 ++pEvents;
1048             }
1049         }
1050         catch( const Exception& )
1051         {
1052             DBG_UNHANDLED_EXCEPTION();
1053         }
1054     }
1055 
1056     //--------------------------------------------------------------------
1057     void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence< Type >& _out_rTypes ) const
1058     {
1059         _out_rTypes.realloc( 0 );
1060         try
1061         {
1062             // we use a set to avoid duplicates
1063             TypeBag aListeners;
1064 
1065             Reference< XIntrospection > xIntrospection( m_aContext.createComponent( "com.sun.star.beans.Introspection" ), UNO_QUERY_THROW );
1066 
1067             // --- model listeners
1068             lcl_addListenerTypesFor_throw(
1069                 m_xComponent, xIntrospection, aListeners );
1070 
1071             // --- "secondary component" (usually: "control" listeners)
1072             {
1073                 Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
1074                 lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners );
1075                 ::comphelper::disposeComponent( xSecondaryComponent );
1076             }
1077 
1078             // now that they're disambiguated, copy these types into our member
1079             _out_rTypes.realloc( aListeners.size() );
1080             ::std::copy( aListeners.begin(), aListeners.end(), _out_rTypes.getArray() );
1081         }
1082         catch( const Exception& )
1083         {
1084             DBG_UNHANDLED_EXCEPTION();
1085         }
1086     }
1087 
1088     //--------------------------------------------------------------------
1089     void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1090     {
1091         _out_rEvents = Sequence < ScriptEventDescriptor >();
1092         try
1093         {
1094             Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1095             Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1096             Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() );
1097 
1098             sal_Int32 nEventCount = aEventNames.getLength();
1099             _out_rEvents.realloc( nEventCount );
1100 
1101             const ::rtl::OUString* pNames = aEventNames.getConstArray();
1102             ScriptEventDescriptor* pDescs = _out_rEvents.getArray();
1103 
1104             for( sal_Int32 i = 0 ; i < nEventCount ; ++i, ++pNames, ++pDescs )
1105                 OSL_VERIFY( xEvents->getByName( *pNames ) >>= *pDescs );
1106         }
1107         catch( const Exception& )
1108         {
1109             DBG_UNHANDLED_EXCEPTION();
1110         }
1111     }
1112 
1113     //--------------------------------------------------------------------
1114     Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
1115     {
1116         Reference< XInterface > xReturn;
1117 
1118         // if it's a form, create a form controller for the additional events
1119         Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY );
1120         if ( xComponentAsForm.is() )
1121         {
1122             Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW );
1123             Reference< XFormController > xController(
1124                 m_aContext.createComponent( "com.sun.star.form.runtime.FormController" ), UNO_QUERY_THROW );
1125             xController->setModel( xComponentAsTCModel );
1126 
1127             xReturn = xController;
1128         }
1129         else
1130         {
1131             ::rtl::OUString sControlService;
1132             OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService );
1133 
1134             xReturn = m_aContext.createComponent( sControlService );
1135         }
1136         return xReturn;
1137     }
1138 
1139     //--------------------------------------------------------------------
1140     const EventDescription& EventHandler::impl_getEventForName_throw( const ::rtl::OUString& _rPropertyName ) const
1141     {
1142         EventMap::const_iterator pos = m_aEvents.find( _rPropertyName );
1143         if ( pos == m_aEvents.end() )
1144             throw UnknownPropertyException();
1145         return pos->second;
1146     }
1147 
1148     //--------------------------------------------------------------------
1149     namespace
1150     {
1151         static bool lcl_endsWith( const ::rtl::OUString& _rText, const ::rtl::OUString& _rCheck )
1152         {
1153             sal_Int32 nTextLen = _rText.getLength();
1154             sal_Int32 nCheckLen = _rCheck.getLength();
1155             if ( nCheckLen > nTextLen )
1156                 return false;
1157 
1158             return _rText.indexOf( _rCheck ) == ( nTextLen - nCheckLen );
1159         }
1160     }
1161     //--------------------------------------------------------------------
1162     void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1163     {
1164         try
1165         {
1166             ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
1167             ::rtl::OUString sScriptType( _rScriptEvent.ScriptType );
1168             bool bResetScript = ( sScriptCode.getLength() == 0 );
1169 
1170             sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw();
1171             Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1172             Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1173             Sequence< ScriptEventDescriptor > aEvents( xEventManager->getScriptEvents( nObjectIndex ) );
1174 
1175             // is there already a registered script for this event?
1176             ScriptEventDescriptor* pEvent = aEvents.getArray();
1177             sal_Int32 eventCount = aEvents.getLength(), event = 0;
1178             for ( event = 0; event < eventCount; ++event, ++pEvent )
1179             {
1180                 if  (   ( pEvent->EventMethod == _rScriptEvent.EventMethod )
1181                     &&  ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) )
1182                           // (strange enough, the events we get from getScriptEvents are not fully qualified)
1183                     )
1184                 {
1185                     // yes
1186                     if ( !bResetScript )
1187                     {
1188                         // set to something non-empty -> overwrite
1189                         pEvent->ScriptCode = sScriptCode;
1190                         pEvent->ScriptType = sScriptType;
1191                     }
1192                     else
1193                     {
1194                         // set to empty -> remove from sequence
1195                         ::std::copy( pEvent + 1, aEvents.getArray() + eventCount, pEvent );
1196                         aEvents.realloc( eventCount - 1 );
1197                         --eventCount;
1198                     }
1199                     break;
1200                 }
1201             }
1202             if ( ( event >= eventCount ) && !bResetScript )
1203             {
1204                 // no, did not find it -> append
1205                 aEvents.realloc( eventCount + 1 );
1206                 aEvents[ eventCount ] = _rScriptEvent;
1207             }
1208 
1209             xEventManager->revokeScriptEvents( nObjectIndex );
1210             xEventManager->registerScriptEvents( nObjectIndex, aEvents );
1211 
1212             PropertyHandlerHelper::setContextDocumentModified( m_aContext );
1213         }
1214         catch( const Exception& )
1215         {
1216             DBG_UNHANDLED_EXCEPTION();
1217         }
1218     }
1219 
1220     //--------------------------------------------------------------------
1221     void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1222     {
1223         try
1224         {
1225             ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
1226             bool bResetScript = ( sScriptCode.getLength() == 0 );
1227 
1228             Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1229             Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1230 
1231             ::rtl::OUStringBuffer aCompleteName;
1232             aCompleteName.append( _rScriptEvent.ListenerType );
1233             aCompleteName.appendAscii( "::" );
1234             aCompleteName.append( _rScriptEvent.EventMethod );
1235             ::rtl::OUString sCompleteName( aCompleteName.makeStringAndClear() );
1236 
1237             bool bExists = xEvents->hasByName( sCompleteName );
1238 
1239             if ( bResetScript )
1240             {
1241                 if ( bExists )
1242                     xEvents->removeByName( sCompleteName );
1243             }
1244             else
1245             {
1246                 Any aNewValue; aNewValue <<= _rScriptEvent;
1247 
1248                 if ( bExists )
1249                     xEvents->replaceByName( sCompleteName, aNewValue );
1250                 else
1251                     xEvents->insertByName( sCompleteName, aNewValue );
1252             }
1253         }
1254         catch( const Exception& )
1255         {
1256             DBG_UNHANDLED_EXCEPTION();
1257         }
1258     }
1259 
1260     //--------------------------------------------------------------------
1261     bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const
1262     {
1263         // some (control-triggered) events do not make sense for certain grid control columns. However,
1264         // our mechnism to retrieve control-triggered events does not know about this, so we do some
1265         // late filtering here.
1266         switch ( m_nGridColumnType )
1267         {
1268         case FormComponentType::COMBOBOX:
1269             if ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
1270                 return false;
1271             break;
1272         case FormComponentType::LISTBOX:
1273             if  (   ( UID_BRWEVT_CHANGED == _rEvent.sUniqueBrowseId )
1274                 ||  ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
1275                 )
1276                 return false;
1277             break;
1278         }
1279 
1280         return true;
1281     }
1282 
1283 //........................................................................
1284 } // namespace pcr
1285 //........................................................................
1286 
1287