diff --git a/filter/inc/filter/msfilter/msvbahelper.hxx b/filter/inc/filter/msfilter/msvbahelper.hxx index affc8b227346..99b20c152400 100644 --- a/filter/inc/filter/msfilter/msvbahelper.hxx +++ b/filter/inc/filter/msfilter/msvbahelper.hxx @@ -33,8 +33,8 @@ #include #include #include +#include #include "filter/msfilter/msfilterdllapi.h" - namespace ooo { namespace vba { @@ -55,7 +55,7 @@ MSFILTER_DLLPUBLIC ::rtl::OUString getDefaultProjectName( SfxObjectShell* pShell MSFILTER_DLLPUBLIC ::rtl::OUString resolveVBAMacro( SfxObjectShell* pShell, const ::rtl::OUString& rLibName, const ::rtl::OUString& rModuleName, const ::rtl::OUString& rMacroName ); MSFILTER_DLLPUBLIC MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const ::rtl::OUString& rMacroName, bool bSearchGlobalTemplates = false ); MSFILTER_DLLPUBLIC sal_Bool executeMacro( SfxObjectShell* pShell, const String& sMacroName, com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArgs, com::sun::star::uno::Any& aRet, const com::sun::star::uno::Any& aCaller ); - +MSFILTER_DLLPUBLIC ::com::sun::star::awt::KeyEvent parseKeyEvent( const ::rtl::OUString& sKey ) throw (::com::sun::star::uno::RuntimeException); // ============================================================================ typedef ::cppu::WeakImplHelper3< diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx index 07a40c05092b..fb4fd3d40939 100644 --- a/filter/source/msfilter/msvbahelper.cxx +++ b/filter/source/msfilter/msvbahelper.cxx @@ -42,6 +42,10 @@ #include #include +#include +#include +#include + using namespace ::com::sun::star; namespace ooo { @@ -580,6 +584,130 @@ void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rAr OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" ); throw uno::RuntimeException(); } +bool getModifier( char c, sal_uInt16& mod ) +{ + static const char modifiers[] = "+^%"; + static const sal_uInt16 KEY_MODS[] = {KEY_SHIFT, KEY_MOD1, KEY_MOD2}; + + for ( unsigned int i=0; i MSKeyCodeMap; + +sal_uInt16 parseChar( char c ) throw ( uno::RuntimeException ) +{ + sal_uInt16 nVclKey = 0; + // do we care about locale here for isupper etc. ? probably not + if ( isalpha( c ) ) + nVclKey |= ( toupper( c ) - 'A' ) + KEY_A; + else if ( isdigit( c ) ) + nVclKey |= ( c - '0' ) + KEY_0; + else if ( c == '~' ) // special case + nVclKey = KEY_RETURN; + else // I guess we have a problem ( but not sure if locale specific keys might come into play here ) + throw uno::RuntimeException(); + return nVclKey; +} + +struct KeyCodeEntry +{ + const char* sName; + sal_uInt16 nCode; +}; + +KeyCodeEntry aMSKeyCodesData[] = { + { "BACKSPACE", KEY_BACKSPACE }, + { "BS", KEY_BACKSPACE }, + { "DELETE", KEY_DELETE }, + { "DEL", KEY_DELETE }, + { "DOWN", KEY_DOWN }, + { "UP", KEY_UP }, + { "LEFT", KEY_LEFT }, + { "RIGHT", KEY_RIGHT }, + { "END", KEY_END }, + { "ESCAPE", KEY_ESCAPE }, + { "ESC", KEY_ESCAPE }, + { "HELP", KEY_HELP }, + { "HOME", KEY_HOME }, + { "PGDN", KEY_PAGEDOWN }, + { "PGUP", KEY_PAGEUP }, + { "INSERT", KEY_INSERT }, + { "F1", KEY_F1 }, + { "F2", KEY_F2 }, + { "F3", KEY_F3 }, + { "F4", KEY_F4 }, + { "F5", KEY_F5 }, + { "F6", KEY_F6 }, + { "F7", KEY_F7 }, + { "F8", KEY_F8 }, + { "F9", KEY_F1 }, + { "F10", KEY_F10 }, + { "F11", KEY_F11 }, + { "F12", KEY_F12 }, + { "F13", KEY_F13 }, + { "F14", KEY_F14 }, + { "F15", KEY_F15 }, +}; + +awt::KeyEvent parseKeyEvent( const ::rtl::OUString& Key ) throw ( uno::RuntimeException ) +{ + static MSKeyCodeMap msKeyCodes; + if ( msKeyCodes.empty() ) + { + for ( unsigned int i = 0; i < SAL_N_ELEMENTS( aMSKeyCodesData ); ++i ) + { + msKeyCodes[ rtl::OUString::createFromAscii( aMSKeyCodesData[ i ].sName ) ] = aMSKeyCodesData[ i ].nCode; + } + } + rtl::OUString sKeyCode; + sal_uInt16 nVclKey = 0; + + // parse the modifier if any + for ( int i=0; isecond; + } + } + + awt::KeyEvent aKeyEvent = svt::AcceleratorExecute::st_VCLKey2AWTKey( KeyCode( nVclKey ) ); + return aKeyEvent; +} // ============================================================================ diff --git a/oovbaapi/ooo/vba/XApplicationBase.idl b/oovbaapi/ooo/vba/XApplicationBase.idl index d46eb2446e31..93f39aed3ff7 100644 --- a/oovbaapi/ooo/vba/XApplicationBase.idl +++ b/oovbaapi/ooo/vba/XApplicationBase.idl @@ -47,7 +47,7 @@ interface XApplicationBase [attribute, readonly] any VBE; void Quit(); - + void OnKey( [in] string Key, [in] any Procedure ); any CommandBars( [in] any Index ); any Run([in] string MacroName, [in] /*Optional*/ any varg1, [in] /*Optional*/ any varg2, [in] /*Optional*/ any varg3, [in] /*Optional*/ any varg4, [in] /*Optional*/ any varg5, [in] /*Optional*/ any varg6, [in] /*Optional*/ any varg7, [in] /*Optional*/ any varg8, [in] /*Optional*/ any varg9, [in] /*Optional*/ any varg10, [in] /*Optional*/ any varg11, [in] /*Optional*/ any varg12, [in] /*Optional*/ any varg13, [in] /*Optional*/ any varg14, [in] /*Optional*/ any varg15, [in] /*Optional*/ any varg16, [in] /*Optional*/ any varg17, [in] /*Optional*/ any varg18, [in] /*Optional*/ any varg19, [in] /*Optional*/ any varg20, [in] /*Optional*/ any varg21, [in] /*Optional*/ any varg22, [in] /*Optional*/ any varg23, [in] /*Optional*/ any varg24, [in] /*Optional*/ any varg25, [in] /*Optional*/ any varg26, [in] /*Optional*/ any varg27, [in] /*Optional*/ any varg28, [in] /*Optional*/ any varg29, [in] /*Optional*/ any varg30); void OnTime( [in] any EarliestTime, [in] string Procedure, [in] any LatestTime, [in] any Schedule ); diff --git a/vbahelper/inc/vbahelper/vbaapplicationbase.hxx b/vbahelper/inc/vbahelper/vbaapplicationbase.hxx index 7d21d3ed453b..a27afa5d5b01 100644 --- a/vbahelper/inc/vbahelper/vbaapplicationbase.hxx +++ b/vbahelper/inc/vbahelper/vbaapplicationbase.hxx @@ -58,6 +58,7 @@ public: virtual void SAL_CALL setInteractive( ::sal_Bool bInteractive ) throw (css::uno::RuntimeException); virtual ::sal_Bool SAL_CALL getVisible() throw (css::uno::RuntimeException); virtual void SAL_CALL setVisible( ::sal_Bool bVisible ) throw (css::uno::RuntimeException); + virtual void SAL_CALL OnKey( const ::rtl::OUString& Key, const ::com::sun::star::uno::Any& Procedure ) throw (::com::sun::star::uno::RuntimeException); virtual css::uno::Any SAL_CALL CommandBars( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); virtual ::rtl::OUString SAL_CALL getVersion() throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getVBE() throw (css::uno::RuntimeException); diff --git a/vbahelper/source/vbahelper/vbaapplicationbase.cxx b/vbahelper/source/vbahelper/vbaapplicationbase.cxx index 293d6b0eaaf6..f1ec673e8270 100644 --- a/vbahelper/source/vbahelper/vbaapplicationbase.cxx +++ b/vbahelper/source/vbahelper/vbaapplicationbase.cxx @@ -42,7 +42,10 @@ #include #include #include +#include +#include +#include #include #include #include @@ -277,6 +280,52 @@ void SAL_CALL VbaApplicationBase::setVisible( sal_Bool bVisible ) throw (uno::Ru m_pImpl->mbVisible = bVisible; // dummy implementation } + +void SAL_CALL +VbaApplicationBase::OnKey( const ::rtl::OUString& Key, const uno::Any& Procedure ) throw (uno::RuntimeException) +{ + // parse the Key & modifiers + awt::KeyEvent aKeyEvent = parseKeyEvent( Key ); + rtl::OUString MacroName; + Procedure >>= MacroName; + uno::Reference< frame::XModel > xModel; + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if ( pMeth ) + { + SbModule* pMod = dynamic_cast< SbModule* >( pMeth->GetParent() ); + if ( pMod ) + xModel = StarBASIC::GetModelFromBasic( pMod ); + } + + if ( !xModel.is() ) + xModel = getCurrentDocument(); + + if ( !MacroName.isEmpty() ) + { + ::rtl::OUString sSeparator(RTL_CONSTASCII_USTRINGPARAM("/")); + ::rtl::OUString sMacroSeparator(RTL_CONSTASCII_USTRINGPARAM("!")); + ::rtl::OUString aMacroName = MacroName.trim(); + if (0 == aMacroName.indexOf('!')) + MacroName = aMacroName.copy(1).trim(); + + MacroResolvedInfo aMacroInfo = resolveVBAMacro( getSfxObjShell( xModel ), aMacroName ); + if( !aMacroInfo.mbFound ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("The procedure doesn't exist") ), uno::Reference< uno::XInterface >() ); + MacroName = aMacroInfo.msResolvedMacro; + } + uno::Reference< ui::XUIConfigurationManagerSupplier > xCfgSupplier(xModel, uno::UNO_QUERY_THROW); + uno::Reference< ui::XUIConfigurationManager > xCfgMgr = xCfgSupplier->getUIConfigurationManager(); + + uno::Reference< ui::XAcceleratorConfiguration > xAcc( xCfgMgr->getShortCutManager(), uno::UNO_QUERY_THROW ); + if ( MacroName.isEmpty() ) + // I believe this should really restore the [application] default. Since + // afaik we don't actually setup application default bindings on import + // we don't even know what the 'default' would be for this key + xAcc->removeKeyEvent( aKeyEvent ); + else + xAcc->setKeyEvent( aKeyEvent, ooo::vba::makeMacroURL( MacroName ) ); +} + uno::Any SAL_CALL VbaApplicationBase::CommandBars( const uno::Any& aIndex ) throw (uno::RuntimeException) {