1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <filter/msfilter/msvbahelper.hxx>
23 #include <basic/sbstar.hxx>
24 #include <basic/basmgr.hxx>
25 #include <basic/sbmod.hxx>
26 #include <basic/sbmeth.hxx>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/document/XDocumentProperties.hpp>
30 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
31 #include <com/sun/star/script/ModuleType.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <comphelper/servicehelper.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <tools/urlobj.hxx>
36 #include <osl/file.hxx>
37 #include <sal/log.hxx>
38 #include <unotools/pathoptions.hxx>
39 #include <rtl/character.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <o3tl/string_view.hxx>
42 #include <svtools/acceleratorexecute.hxx>
43 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
44 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
45 #include <frozen/bits/defines.h>
46 #include <frozen/bits/elsa_std.h>
47 #include <frozen/unordered_map.h>
49 using namespace ::com::sun::star
;
53 constexpr OUStringLiteral
sUrlPart0( u
"vnd.sun.star.script:" );
54 constexpr OUStringLiteral
sUrlPart1( u
"?language=Basic&location=document" );
56 OUString
makeMacroURL( std::u16string_view sMacroName
)
58 return sUrlPart0
+ sMacroName
+ sUrlPart1
;
61 OUString
extractMacroName( std::u16string_view rMacroUrl
)
63 if( o3tl::starts_with(rMacroUrl
, sUrlPart0
) && o3tl::ends_with(rMacroUrl
, sUrlPart1
) )
65 return OUString(rMacroUrl
.substr( sUrlPart0
.getLength(),
66 rMacroUrl
.size() - sUrlPart0
.getLength() - sUrlPart1
.getLength() ));
71 static std::u16string_view
trimMacroName( std::u16string_view rMacroName
)
73 // the name may contain whitespaces and may be enclosed in apostrophs
74 std::u16string_view aMacroName
= o3tl::trim(rMacroName
);
75 size_t nMacroLen
= aMacroName
.size();
76 if( (nMacroLen
>= 2) && (aMacroName
[ 0 ] == '\'') && (aMacroName
[ nMacroLen
- 1 ] == '\'') )
77 aMacroName
= o3tl::trim(aMacroName
.substr( 1, nMacroLen
- 2 ));
81 #if HAVE_FEATURE_SCRIPTING
83 static SfxObjectShell
* findShellForUrl( const OUString
& sMacroURLOrPath
)
85 SfxObjectShell
* pFoundShell
=nullptr;
86 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
88 aObj
.SetURL( sMacroURLOrPath
);
89 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
92 aURL
= sMacroURLOrPath
;
95 osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath
, aURL
);
101 uno::Reference
< frame::XModel
> xModel
= pShell
->GetModel();
102 // are we searching for a template? if so we have to cater for the
103 // fact that in openoffice a document opened from a template is always
109 "shell " << pShell
<< " has model with url " << xModel
->getURL()
110 << " and we look for " << aURL
);
111 OUString aName
= xModel
->getURL() ;
114 uno::Reference
< frame::XFrame
> xFrame( xModel
->getCurrentController()->getFrame(), uno::UNO_SET_THROW
);
115 uno::Reference
< beans::XPropertySet
> xProps( xFrame
, uno::UNO_QUERY_THROW
);
116 xProps
->getPropertyValue("Title") >>= aName
;
117 aName
= o3tl::trim(o3tl::getToken(aName
, 0, '-'));
118 if( sMacroURLOrPath
.lastIndexOf( aName
) >= 0 )
120 pFoundShell
= pShell
;
125 if ( sMacroURLOrPath
.endsWithIgnoreAsciiCase( ".dot" ) )
127 uno::Reference
<document::XDocumentPropertiesSupplier
> const
128 xDocPropSupp(xModel
, uno::UNO_QUERY
);
129 if (xDocPropSupp
.is())
131 uno::Reference
< document::XDocumentProperties
> const
132 xDocProps(xDocPropSupp
->getDocumentProperties(),
134 OUString sCurrName
= xDocProps
->getTemplateName();
135 if( sMacroURLOrPath
.lastIndexOf( sCurrName
) >= 0 )
137 pFoundShell
= pShell
;
144 // sometimes just the name of the document ( without the path
146 bool bDocNameNoPathMatch
= false;
147 if ( !aURL
.isEmpty() && aURL
.indexOf( '/' ) == -1 )
149 sal_Int32 lastSlashIndex
= xModel
->getURL().lastIndexOf( '/' );
150 if ( lastSlashIndex
> -1 )
152 bDocNameNoPathMatch
= xModel
->getURL().subView( lastSlashIndex
+ 1 ) == aURL
;
153 if ( !bDocNameNoPathMatch
)
155 OUString aTmpName
= OUString::Concat("'") + xModel
->getURL().subView( lastSlashIndex
+ 1 ) + "'";
156 bDocNameNoPathMatch
= aTmpName
== aURL
;
161 if ( aURL
== xModel
->getURL() || bDocNameNoPathMatch
)
163 pFoundShell
= pShell
;
168 pShell
= SfxObjectShell::GetNext( *pShell
);
173 // sMod can be empty ( but we really need the library to search in )
174 // if sMod is empty and a macro is found then sMod is updated
175 // if sMod is empty, only standard modules will be searched (no class, document, form modules)
176 static bool hasMacro(SfxObjectShell
const* pShell
, const OUString
& sLibrary
, OUString
& sMod
,
177 const OUString
& sMacro
, bool bOnlyPublic
, const OUString
& sSkipModule
)
179 #if !HAVE_FEATURE_SCRIPTING
187 if (sLibrary
.isEmpty() || sMacro
.isEmpty())
190 BasicManager
* pBasicMgr
= pShell
->GetBasicManager();
194 StarBASIC
* pBasic
= pBasicMgr
->GetLib(sLibrary
);
197 sal_uInt16 nId
= pBasicMgr
->GetLibId(sLibrary
);
198 pBasicMgr
->LoadLib(nId
);
199 pBasic
= pBasicMgr
->GetLib(sLibrary
);
204 if (!sMod
.isEmpty()) // we wish to find the macro is a specific module
206 SbModule
* pModule
= pBasic
->FindModule(sMod
);
209 SbMethod
* pMeth
= pModule
->FindMethod(sMacro
, SbxClassType::Method
);
211 // Must be compiled before we can trust SbxFlagBits::Private
212 if (pMeth
&& bOnlyPublic
&& !pModule
->IsCompiled())
215 return pMeth
&& (!bOnlyPublic
|| !pMeth
->IsSet(SbxFlagBits::Private
));
218 for (auto const& rModuleRef
: pBasic
->GetModules())
220 SbMethod
* pMeth
= rModuleRef
->FindMethod(sMacro
, SbxClassType::Method
);
223 if (rModuleRef
->GetName() == sSkipModule
)
228 if (!rModuleRef
->IsCompiled())
229 rModuleRef
->Compile();
231 if (pMeth
->IsSet(SbxFlagBits::Private
))
234 sMod
= rModuleRef
->GetName();
244 #if HAVE_FEATURE_SCRIPTING
246 OUString
getDefaultProjectName( SfxObjectShell
const * pShell
)
249 if( BasicManager
* pBasicMgr
= pShell
? pShell
->GetBasicManager() : nullptr )
251 aPrjName
= pBasicMgr
->GetName();
252 if( aPrjName
.isEmpty() )
253 aPrjName
= "Standard";
258 static void parseMacro( const OUString
& sMacro
, OUString
& sContainer
, OUString
& sModule
, OUString
& sProcedure
)
260 sal_Int32 nMacroDot
= sMacro
.lastIndexOf( '.' );
262 if ( nMacroDot
!= -1 )
264 sProcedure
= sMacro
.copy( nMacroDot
+ 1 );
266 const sal_Int32 nContainerDot
= sMacro
.lastIndexOf('.', nMacroDot
);
267 if ( nContainerDot
!= -1 )
269 sModule
= sMacro
.copy( nContainerDot
+ 1, nMacroDot
- nContainerDot
- 1 );
270 sContainer
= sMacro
.copy( 0, nContainerDot
);
273 sModule
= sMacro
.copy( 0, nMacroDot
);
281 OUString
resolveVBAMacro(SfxObjectShell
const* pShell
, const OUString
& rLibName
,
282 const OUString
& rModuleName
, const OUString
& rMacroName
,
283 bool bOnlyPublic
, const OUString
& sSkipModule
)
285 #if !HAVE_FEATURE_SCRIPTING
295 OUString aLibName
= rLibName
.isEmpty() ? getDefaultProjectName( pShell
) : rLibName
;
296 OUString aModuleName
= rModuleName
;
297 if (hasMacro(pShell
, aLibName
, aModuleName
, rMacroName
, bOnlyPublic
, sSkipModule
))
298 return aLibName
+ "." + aModuleName
+ "." + rMacroName
;
304 MacroResolvedInfo
resolveVBAMacro( SfxObjectShell
* pShell
, const OUString
& MacroName
, bool bSearchGlobalTemplates
)
306 #if !HAVE_FEATURE_SCRIPTING
309 (void) bSearchGlobalTemplates
;
311 return MacroResolvedInfo();
314 return MacroResolvedInfo();
316 // the name may be enclosed in apostrophs
317 std::u16string_view aMacroName
= trimMacroName( MacroName
);
319 // parse the macro name
320 size_t nDocSepIndex
= aMacroName
.find( '!' );
321 if( nDocSepIndex
> 0 && nDocSepIndex
!= std::u16string_view::npos
)
323 // macro specified by document name
324 // find document shell for document name and call ourselves
327 // assume for now that the document name is *this* document
328 std::u16string_view sDocUrlOrPath
= aMacroName
.substr( 0, nDocSepIndex
);
329 aMacroName
= aMacroName
.substr( nDocSepIndex
+ 1 );
330 SAL_INFO("filter.ms", "doc search, current shell is " << pShell
);
331 SfxObjectShell
* pFoundShell
= nullptr;
332 if( bSearchGlobalTemplates
)
334 SvtPathOptions aPathOpt
;
335 const OUString
& aAddinPath
= aPathOpt
.GetAddinPath();
336 if( o3tl::starts_with(sDocUrlOrPath
, aAddinPath
) )
337 pFoundShell
= pShell
;
340 pFoundShell
= findShellForUrl( OUString(sDocUrlOrPath
) );
343 "doc search, after find, found shell is " << pFoundShell
);
344 return resolveVBAMacro( pFoundShell
, OUString(aMacroName
) );
347 // macro is contained in 'this' document ( or code imported from a template
348 // where that template is a global template or perhaps the template this
349 // document is created from )
351 MacroResolvedInfo
aRes( pShell
);
353 // macro format = Container.Module.Procedure
354 OUString sContainer
, sModule
, sProcedure
;
355 parseMacro( OUString(aMacroName
), sContainer
, sModule
, sProcedure
);
358 // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
359 // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
360 uno::Reference
< container::XNameContainer
> xPrjNameCache
;
361 uno::Reference
< lang::XMultiServiceFactory
> xSF( pShell
->GetModel(), uno::UNO_QUERY
);
364 xPrjNameCache
.set( xSF
->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY
);
366 catch( const uno::Exception
& ) // createInstance may throw
371 std::vector
< OUString
> sSearchList
;
373 if ( !sContainer
.isEmpty() )
375 // service VBAProjectNameProvider not implemented
377 // get the Project associated with the Container
378 if ( xPrjNameCache
.is() )
380 if ( xPrjNameCache
->hasByName( sContainer
) )
383 xPrjNameCache
->getByName( sContainer
) >>= sProject
;
384 sContainer
= sProject
;
388 sSearchList
.push_back( sContainer
); // First Lib to search
392 // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
393 // get the name of Project/Library for 'this' document
394 OUString
sThisProject( "Standard" );
397 uno::Reference
< beans::XPropertySet
> xProps( pShell
->GetModel(), uno::UNO_QUERY_THROW
);
398 uno::Reference
< script::vba::XVBACompatibility
> xVBAMode( xProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW
);
399 sThisProject
= xVBAMode
->getProjectName();
401 catch( const uno::Exception
& /*e*/) {}
403 sSearchList
.push_back( sThisProject
); // First Lib to search
405 // service VBAProjectNameProvider not implemented
407 if ( xPrjNameCache
.is() )
409 // is this document created from a template?
410 uno::Reference
< document::XDocumentPropertiesSupplier
> const
411 xDocPropSupp(pShell
->GetModel(), uno::UNO_QUERY_THROW
);
412 uno::Reference
< document::XDocumentProperties
> xDocProps( xDocPropSupp
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
414 OUString sCreatedFrom
= xDocProps
->getTemplateURL();
415 if ( !sCreatedFrom
.isEmpty() )
418 aObj
.SetURL( sCreatedFrom
);
419 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
425 osl::FileBase::getFileURLFromSystemPath( sCreatedFrom
, aURL
);
428 sCreatedFrom
= aObj
.GetLastName();
431 sal_Int32 nIndex
= sCreatedFrom
.lastIndexOf( '.' );
433 sCreatedFrom
= sCreatedFrom
.copy( 0, nIndex
);
436 if ( !sCreatedFrom
.isEmpty() && xPrjNameCache
->hasByName( sCreatedFrom
) )
438 xPrjNameCache
->getByName( sCreatedFrom
) >>= sPrj
;
439 // Make sure we don't double up with this project
440 if ( !sPrj
.equals( sThisProject
) )
441 sSearchList
.push_back( sPrj
);
444 // get list of global template Names
445 uno::Sequence
< OUString
> sTemplateNames
= xPrjNameCache
->getElementNames();
446 sal_Int32 nLen
= sTemplateNames
.getLength();
447 for ( sal_Int32 index
= 0; ( bSearchGlobalTemplates
&& index
< nLen
); ++index
)
450 if ( !sCreatedFrom
.equals( sTemplateNames
[ index
] ) )
452 if ( xPrjNameCache
->hasByName( sTemplateNames
[ index
] ) )
454 xPrjNameCache
->getByName( sTemplateNames
[ index
] ) >>= sPrj
;
455 // Make sure we don't double up with this project
456 if ( !sPrj
.equals( sThisProject
) )
457 sSearchList
.push_back( sPrj
);
466 for (auto const& search
: sSearchList
)
468 aRes
.mbFound
= hasMacro(pShell
, search
, sModule
, sProcedure
, /*bOnlyPublic=*/false, "");
475 //aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
476 aRes
.msResolvedMacro
= sContainer
+ "." + sModule
+ "." + sProcedure
;
482 // Treat the args as possible inputs (conversion at bottom of method)
483 bool executeMacro( SfxObjectShell
* pShell
, const OUString
& sMacroName
, uno::Sequence
< uno::Any
>& aArgs
, uno::Any
& aRet
, const uno::Any
& /*aCaller*/)
485 #if !HAVE_FEATURE_SCRIPTING
496 OUString sUrl
= makeMacroURL( sMacroName
);
498 uno::Sequence
< sal_Int16
> aOutArgsIndex
;
499 uno::Sequence
< uno::Any
> aOutArgs
;
503 ErrCode nErr
= pShell
->CallXScript(sUrl
, aArgs
, aRet
, aOutArgsIndex
, aOutArgs
, false);
504 sal_Int32 nLen
= aOutArgs
.getLength();
505 // convert any out params to seem like they were inputs
508 auto pArgs
= aArgs
.getArray();
509 for (sal_Int32 index
= 0; index
< nLen
; ++index
)
511 sal_Int32 nOutIndex
= aOutArgsIndex
[index
];
512 pArgs
[nOutIndex
] = aOutArgs
[index
];
515 bRes
= ( nErr
== ERRCODE_NONE
);
517 catch ( const uno::Exception
& )
527 VBAMacroResolver::VBAMacroResolver() :
528 mpObjShell( nullptr )
532 VBAMacroResolver::~VBAMacroResolver()
536 // com.sun.star.lang.XServiceInfo interface -----------------------------------
538 OUString SAL_CALL
VBAMacroResolver::getImplementationName()
540 return "com.sun.star.comp.vba.VBAMacroResolver";
543 sal_Bool SAL_CALL
VBAMacroResolver::supportsService( const OUString
& rService
)
545 return cppu::supportsService(this, rService
);
548 uno::Sequence
< OUString
> SAL_CALL
VBAMacroResolver::getSupportedServiceNames()
550 return { "com.sun.star.script.vba.VBAMacroResolver" };
553 // com.sun.star.lang.XInitialization interface --------------------------------
555 void SAL_CALL
VBAMacroResolver::initialize( const uno::Sequence
< uno::Any
>& rArgs
)
557 OSL_ENSURE( rArgs
.getLength() > 1, "VBAMacroResolver::initialize - missing arguments" );
558 if( rArgs
.getLength() < 2 )
559 throw uno::RuntimeException();
561 // first argument: document model
562 mxModel
.set( rArgs
[ 0 ], uno::UNO_QUERY_THROW
);
563 mpObjShell
= comphelper::getFromUnoTunnel
<SfxObjectShell
>(mxModel
);
565 throw uno::RuntimeException();
567 // second argument: VBA project name
568 if( !(rArgs
[ 1 ] >>= maProjectName
) || (maProjectName
.isEmpty()) )
569 throw uno::RuntimeException();
572 // com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
574 OUString SAL_CALL
VBAMacroResolver::resolveVBAMacroToScriptURL( const OUString
& rVBAMacroName
)
577 throw uno::RuntimeException();
579 // the name may be enclosed in apostrophs
580 OUString
aMacroName( trimMacroName( rVBAMacroName
) );
581 if( aMacroName
.isEmpty() )
582 throw lang::IllegalArgumentException();
584 // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
585 if( (aMacroName
[ 0 ] == '[') || (aMacroName
.indexOf( '!' ) >= 0) )
586 throw lang::IllegalArgumentException();
588 // check if macro name starts with project name, replace with "Standard"
589 // TODO: adjust this when custom VBA project name is supported
590 sal_Int32 nDotPos
= aMacroName
.indexOf( '.' );
591 if( (nDotPos
== 0) || (nDotPos
+ 1 == aMacroName
.getLength()) )
592 throw lang::IllegalArgumentException();
593 if( (nDotPos
> 0) && aMacroName
.matchIgnoreAsciiCase( maProjectName
) )
594 aMacroName
= aMacroName
.copy( nDotPos
+ 1 );
596 // try to find the macro
597 MacroResolvedInfo aInfo
= resolveVBAMacro( mpObjShell
, aMacroName
);
599 throw lang::IllegalArgumentException();
601 // build and return the script URL
602 return makeMacroURL( aInfo
.msResolvedMacro
);
605 OUString SAL_CALL
VBAMacroResolver::resolveScriptURLtoVBAMacro( const OUString
& /*rScriptURL*/ )
607 OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
608 throw uno::RuntimeException();
611 static bool getModifier( sal_Unicode c
, sal_uInt16
& mod
)
616 } else if ( c
== '^' ) {
619 } else if ( c
== '%' ) {
626 /// @throws uno::RuntimeException
627 static sal_uInt16
parseChar( sal_Unicode c
)
629 sal_uInt16 nVclKey
= 0;
630 // do we care about locale here for letters/digits? probably not
631 if ( rtl::isAsciiAlpha( c
) )
633 nVclKey
|= ( rtl::toAsciiUpperCase( c
) - 'A' ) + KEY_A
;
634 if ( rtl::isAsciiUpperCase( c
) )
635 nVclKey
|= KEY_SHIFT
;
637 else if ( rtl::isAsciiDigit( c
) )
638 nVclKey
|= ( c
- '0' ) + KEY_0
;
639 else if ( c
== '~' ) // special case
640 nVclKey
= KEY_RETURN
;
641 else if ( c
== ' ' ) // special case
643 else // I guess we have a problem ( but not sure if locale specific keys might come into play here )
644 throw uno::RuntimeException();
651 constexpr frozen::unordered_map
<std::u16string_view
, sal_uInt16
, 34> s_KeyCodes
653 { u
"BACKSPACE", KEY_BACKSPACE
},
654 { u
"BS", KEY_BACKSPACE
},
655 { u
"DELETE", KEY_DELETE
},
656 { u
"DEL", KEY_DELETE
},
657 { u
"DOWN", KEY_DOWN
},
659 { u
"LEFT", KEY_LEFT
},
660 { u
"RIGHT", KEY_RIGHT
},
662 { u
"ESCAPE", KEY_ESCAPE
},
663 { u
"ESC", KEY_ESCAPE
},
664 { u
"HELP", KEY_HELP
},
665 { u
"HOME", KEY_HOME
},
666 { u
"PGDN", KEY_PAGEDOWN
},
667 { u
"PGUP", KEY_PAGEUP
},
668 { u
"INSERT", KEY_INSERT
},
669 { u
"SCROLLLOCK", KEY_SCROLLLOCK
},
670 { u
"NUMLOCK", KEY_NUMLOCK
},
689 } // end anonymous namespace
691 awt::KeyEvent
parseKeyEvent( std::u16string_view Key
)
693 std::u16string_view sKeyCode
;
694 sal_uInt16 nVclKey
= 0;
696 // parse the modifier if any
697 for ( size_t i
=0; i
<Key
.size(); ++i
)
699 if ( ! getModifier( Key
[ i
], nVclKey
) )
701 sKeyCode
= Key
.substr( i
);
706 // check if keycode is surrounded by '{}', if so scoop out the contents
707 // else it should be just one char of ( 'a-z,A-Z,0-9' )
708 if ( sKeyCode
.size() == 1 ) // ( a single char )
710 nVclKey
|= parseChar( sKeyCode
[ 0 ] );
712 else // key should be enclosed in '{}'
714 if ( sKeyCode
.size() < 3 || sKeyCode
[0] != '{' || sKeyCode
[sKeyCode
.size() - 1 ] != '}' )
715 throw uno::RuntimeException();
717 sKeyCode
= sKeyCode
.substr(1, sKeyCode
.size() - 2 );
719 if ( sKeyCode
.size() == 1 )
720 nVclKey
|= parseChar( sKeyCode
[ 0 ] );
723 auto it
= s_KeyCodes
.find(sKeyCode
);
724 if ( it
== s_KeyCodes
.end() ) // unknown or unsupported
725 throw uno::RuntimeException();
726 nVclKey
|= it
->second
;
730 awt::KeyEvent aKeyEvent
= svt::AcceleratorExecute::st_VCLKey2AWTKey( vcl::KeyCode( nVclKey
) );
734 void applyShortCutKeyBinding ( const uno::Reference
< frame::XModel
>& rxModel
, const awt::KeyEvent
& rKeyEvent
, const OUString
& rMacroName
)
736 OUString
MacroName( rMacroName
);
737 if ( !MacroName
.isEmpty() )
739 OUString aMacroName
= MacroName
.trim();
740 if( aMacroName
.startsWith("!") )
741 aMacroName
= o3tl::trim(aMacroName
.subView(1));
742 SfxObjectShell
* pShell
= nullptr;
745 pShell
= comphelper::getFromUnoTunnel
<SfxObjectShell
>(rxModel
);
747 throw uno::RuntimeException();
749 MacroResolvedInfo aMacroInfo
= resolveVBAMacro( pShell
, aMacroName
);
750 if( !aMacroInfo
.mbFound
)
751 throw uno::RuntimeException( "The procedure doesn't exist" );
752 MacroName
= aMacroInfo
.msResolvedMacro
;
754 uno::Reference
< ui::XUIConfigurationManagerSupplier
> xCfgSupplier(rxModel
, uno::UNO_QUERY_THROW
);
755 uno::Reference
< ui::XUIConfigurationManager
> xCfgMgr
= xCfgSupplier
->getUIConfigurationManager();
757 uno::Reference
< ui::XAcceleratorConfiguration
> xAcc( xCfgMgr
->getShortCutManager(), uno::UNO_SET_THROW
);
758 if ( MacroName
.isEmpty() )
759 // I believe this should really restore the [application] default. Since
760 // afaik we don't actually setup application default bindings on import
761 // we don't even know what the 'default' would be for this key
762 xAcc
->removeKeyEvent( rKeyEvent
);
764 xAcc
->setKeyEvent( rKeyEvent
, ooo::vba::makeMacroURL( MacroName
) );
771 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
772 filter_VBAMacroResolver_get_implementation(
773 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
775 return cppu::acquire(new ooo::vba::VBAMacroResolver());
778 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */