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