diff options
-rw-r--r-- | filter/inc/filter/msfilter/msvbahelper.hxx | 2 | ||||
-rw-r--r-- | filter/source/msfilter/msvbahelper.cxx | 50 | ||||
-rw-r--r-- | oox/source/ole/vbamodule.cxx | 36 | ||||
-rw-r--r-- | vbahelper/source/vbahelper/vbaapplicationbase.cxx | 28 |
4 files changed, 87 insertions, 29 deletions
diff --git a/filter/inc/filter/msfilter/msvbahelper.hxx b/filter/inc/filter/msfilter/msvbahelper.hxx index 99b20c152400..e7e653347626 100644 --- a/filter/inc/filter/msfilter/msvbahelper.hxx +++ b/filter/inc/filter/msfilter/msvbahelper.hxx @@ -34,6 +34,7 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/script/vba/XVBAMacroResolver.hpp> #include <com/sun/star/awt/KeyEvent.hpp> +#include <com/sun/star/frame/XModel.hpp> #include "filter/msfilter/msfilterdllapi.h" namespace ooo { namespace vba { @@ -56,6 +57,7 @@ MSFILTER_DLLPUBLIC ::rtl::OUString resolveVBAMacro( SfxObjectShell* pShell, cons 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); +MSFILTER_DLLPUBLIC void applyShortCutKeyBinding ( const ::com::sun::star::uno::Reference< com::sun::star::frame::XModel >& rxDoc, const ::com::sun::star::awt::KeyEvent& rKeyEvent, const ::rtl::OUString& sMacro ) throw (::com::sun::star::uno::RuntimeException); // ============================================================================ typedef ::cppu::WeakImplHelper3< diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx index fb4fd3d40939..4c7d3f9804e7 100644 --- a/filter/source/msfilter/msvbahelper.cxx +++ b/filter/source/msfilter/msvbahelper.cxx @@ -44,6 +44,8 @@ #include <com/sun/star/awt/KeyModifier.hpp> #include <svtools/acceleratorexecute.hxx> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManager.hpp> #include <map> using namespace ::com::sun::star; @@ -584,6 +586,7 @@ 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[] = "+^%"; @@ -607,11 +610,17 @@ 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; + if ( isupper( c ) ) + nVclKey |= KEY_SHIFT; + } else if ( isdigit( c ) ) nVclKey |= ( c - '0' ) + KEY_0; else if ( c == '~' ) // special case nVclKey = KEY_RETURN; + else if ( c == ' ' ) // special case + nVclKey = KEY_SPACE; else // I guess we have a problem ( but not sure if locale specific keys might come into play here ) throw uno::RuntimeException(); return nVclKey; @@ -640,6 +649,9 @@ KeyCodeEntry aMSKeyCodesData[] = { { "PGDN", KEY_PAGEDOWN }, { "PGUP", KEY_PAGEUP }, { "INSERT", KEY_INSERT }, + { "SCROLLLOCK", KEY_SCROLLLOCK }, + { "NUMLOCK", KEY_NUMLOCK }, + { "TAB", KEY_TAB }, { "F1", KEY_F1 }, { "F2", KEY_F2 }, { "F3", KEY_F3 }, @@ -675,7 +687,7 @@ awt::KeyEvent parseKeyEvent( const ::rtl::OUString& Key ) throw ( uno::RuntimeEx { if ( ! getModifier( Key[ i ], nVclKey ) ) { - sKeyCode = Key.copy( i ).trim(); + sKeyCode = Key.copy( i ); break; } } @@ -709,6 +721,42 @@ awt::KeyEvent parseKeyEvent( const ::rtl::OUString& Key ) throw ( uno::RuntimeEx return aKeyEvent; } +void applyShortCutKeyBinding ( const uno::Reference< frame::XModel >& rxModel, const awt::KeyEvent& rKeyEvent, const ::rtl::OUString& rMacroName ) throw (uno::RuntimeException) +{ + rtl::OUString MacroName( rMacroName ); + 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(); + SfxObjectShell* pShell = NULL; + if ( rxModel.is() ) + { + uno::Reference< lang::XUnoTunnel > xObjShellTunnel( rxModel, uno::UNO_QUERY_THROW ); + pShell = reinterpret_cast<SfxObjectShell*>( xObjShellTunnel->getSomething(SfxObjectShell::getUnoTunnelId())); + if ( !pShell ) + throw uno::RuntimeException(); + } + MacroResolvedInfo aMacroInfo = resolveVBAMacro( pShell, 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(rxModel, 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( rKeyEvent ); + else + xAcc->setKeyEvent( rKeyEvent, ooo::vba::makeMacroURL( MacroName ) ); + +} // ============================================================================ } // namespace vba diff --git a/oox/source/ole/vbamodule.cxx b/oox/source/ole/vbamodule.cxx index d4b041b2e1bf..9f0e5ffe6bf8 100644 --- a/oox/source/ole/vbamodule.cxx +++ b/oox/source/ole/vbamodule.cxx @@ -33,7 +33,9 @@ #include <com/sun/star/script/ModuleInfo.hpp> #include <com/sun/star/script/ModuleType.hpp> #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> +#include <com/sun/star/awt/KeyEvent.hpp> #include <cppuhelper/implbase1.hxx> +#include <filter/msfilter/msvbahelper.hxx> #include "oox/helper/binaryinputstream.hxx" #include "oox/helper/storagebase.hxx" #include "oox/helper/textinputstream.hxx" @@ -54,6 +56,7 @@ using namespace ::com::sun::star::uno; using ::rtl::OUString; using ::rtl::OUStringBuffer; +using ::com::sun::star::awt::KeyEvent; // ============================================================================ typedef ::cppu::WeakImplHelper1< XIndexContainer > OleIdToNameContainer_BASE; typedef boost::unordered_map< sal_Int32, rtl::OUString > ObjIdToName; @@ -249,7 +252,38 @@ OUString VbaModule::readSourceCode( StorageBase& rVbaStrg, const Reference< XNam if( aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) ) { // attribute - extractOleOverrideFromAttr( aCodeLine, rxOleNameOverrides ); + int index = aCodeLine.indexOf( ".VB_ProcData.VB_Invoke_Func = " ); + if ( index != -1 ) + { + // format is + // 'Attribute Procedure.VB_ProcData.VB_Invoke_Func = "*\n14"' + // where 'Procedure' is the procedure name and '*' is the shortcut key + // note: his is only relevant for Excel, seems that + // word doesn't store the shortcut in the module + // attributes + int nSpaceIndex = aCodeLine.indexOf(' '); + rtl::OUString sProc = aCodeLine.copy( nSpaceIndex + 1, index - nSpaceIndex - 1); + // for Excel short cut key seems limited to cntrl+'a-z, A-Z' + rtl::OUString sKey = aCodeLine.copy( aCodeLine.lastIndexOf("= ") + 3, 1 ); + // only alpha key valid for key shortcut, however the api will accept other keys + if ( !isalpha( (char)sKey[ 0 ] ) ) + { + // cntrl modifier is explicit ( but could be cntrl+shift ), parseKeyEvent + // will handle and uppercase letter appropriately + rtl::OUString sApiKey = "^"; + sApiKey += sKey; + try + { + KeyEvent aKeyEvent = ooo::vba::parseKeyEvent( sApiKey ); + ooo::vba::applyShortCutKeyBinding( mxDocModel, aKeyEvent, sProc ); + } + catch( Exception& ) + { + } + } + } + else + extractOleOverrideFromAttr( aCodeLine, rxOleNameOverrides ); } else { diff --git a/vbahelper/source/vbahelper/vbaapplicationbase.cxx b/vbahelper/source/vbahelper/vbaapplicationbase.cxx index f1ec673e8270..05f2fcf4ddca 100644 --- a/vbahelper/source/vbahelper/vbaapplicationbase.cxx +++ b/vbahelper/source/vbahelper/vbaapplicationbase.cxx @@ -42,10 +42,7 @@ #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> #include <com/sun/star/document/XEmbeddedScripts.hpp> #include <com/sun/star/awt/XWindow2.hpp> -#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> -#include <com/sun/star/ui/XUIConfigurationManager.hpp> -#include <svtools/acceleratorexecute.hxx> #include <boost/unordered_map.hpp> #include <filter/msfilter/msvbahelper.hxx> #include <tools/datetime.hxx> @@ -300,30 +297,7 @@ VbaApplicationBase::OnKey( const ::rtl::OUString& Key, const uno::Any& Procedure 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 ) ); + applyShortCutKeyBinding( xModel, aKeyEvent, MacroName ); } uno::Any SAL_CALL |