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/diagnose.h>
37 #include <osl/file.hxx>
38 #include <sal/log.hxx>
39 #include <unotools/pathoptions.hxx>
40 #include <rtl/character.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <o3tl/string_view.hxx>
43 #include <svtools/acceleratorexecute.hxx>
44 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
45 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
46 #include <frozen/bits/defines.h>
47 #include <frozen/bits/elsa_std.h>
48 #include <frozen/unordered_map.h>
50 using namespace ::com::sun::star
;
54 constexpr OUString
sUrlPart0( u
"vnd.sun.star.script:"_ustr
);
55 constexpr OUString
sUrlPart1( u
"?language=Basic&location=document"_ustr
);
57 OUString
makeMacroURL( std::u16string_view sMacroName
)
59 return sUrlPart0
+ sMacroName
+ sUrlPart1
;
62 OUString
extractMacroName( std::u16string_view rMacroUrl
)
64 if( o3tl::starts_with(rMacroUrl
, sUrlPart0
) && o3tl::ends_with(rMacroUrl
, sUrlPart1
) )
66 return OUString(rMacroUrl
.substr( sUrlPart0
.getLength(),
67 rMacroUrl
.size() - sUrlPart0
.getLength() - sUrlPart1
.getLength() ));
72 static std::u16string_view
trimMacroName( std::u16string_view rMacroName
)
74 // the name may contain whitespaces and may be enclosed in apostrophs
75 std::u16string_view aMacroName
= o3tl::trim(rMacroName
);
76 size_t nMacroLen
= aMacroName
.size();
77 if( (nMacroLen
>= 2) && (aMacroName
[ 0 ] == '\'') && (aMacroName
[ nMacroLen
- 1 ] == '\'') )
78 aMacroName
= o3tl::trim(aMacroName
.substr( 1, nMacroLen
- 2 ));
82 #if HAVE_FEATURE_SCRIPTING
84 static SfxObjectShell
* findShellForUrl( const OUString
& sMacroURLOrPath
)
86 SfxObjectShell
* pFoundShell
=nullptr;
87 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
89 aObj
.SetURL( sMacroURLOrPath
);
90 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
93 aURL
= sMacroURLOrPath
;
96 osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath
, aURL
);
102 uno::Reference
< frame::XModel
> xModel
= pShell
->GetModel();
103 // are we searching for a template? if so we have to cater for the
104 // fact that in openoffice a document opened from a template is always
110 "shell " << pShell
<< " has model with url " << xModel
->getURL()
111 << " and we look for " << aURL
);
112 OUString aName
= xModel
->getURL() ;
115 uno::Reference
< frame::XFrame
> xFrame( xModel
->getCurrentController()->getFrame(), uno::UNO_SET_THROW
);
116 uno::Reference
< beans::XPropertySet
> xProps( xFrame
, uno::UNO_QUERY_THROW
);
117 xProps
->getPropertyValue(u
"Title"_ustr
) >>= aName
;
118 aName
= o3tl::trim(o3tl::getToken(aName
, 0, '-'));
119 if( sMacroURLOrPath
.lastIndexOf( aName
) >= 0 )
121 pFoundShell
= pShell
;
126 if ( sMacroURLOrPath
.endsWithIgnoreAsciiCase( ".dot" ) )
128 uno::Reference
<document::XDocumentPropertiesSupplier
> const
129 xDocPropSupp(xModel
, uno::UNO_QUERY
);
130 if (xDocPropSupp
.is())
132 uno::Reference
< document::XDocumentProperties
> const
133 xDocProps(xDocPropSupp
->getDocumentProperties(),
135 OUString sCurrName
= xDocProps
->getTemplateName();
136 if( sMacroURLOrPath
.lastIndexOf( sCurrName
) >= 0 )
138 pFoundShell
= pShell
;
145 // sometimes just the name of the document ( without the path
147 bool bDocNameNoPathMatch
= false;
148 if ( !aURL
.isEmpty() && aURL
.indexOf( '/' ) == -1 )
150 sal_Int32 lastSlashIndex
= xModel
->getURL().lastIndexOf( '/' );
151 if ( lastSlashIndex
> -1 )
153 bDocNameNoPathMatch
= xModel
->getURL().subView( lastSlashIndex
+ 1 ) == aURL
;
154 if ( !bDocNameNoPathMatch
)
156 OUString aTmpName
= OUString::Concat("'") + xModel
->getURL().subView( lastSlashIndex
+ 1 ) + "'";
157 bDocNameNoPathMatch
= aTmpName
== aURL
;
162 if ( aURL
== xModel
->getURL() || bDocNameNoPathMatch
)
164 pFoundShell
= pShell
;
169 pShell
= SfxObjectShell::GetNext( *pShell
);
174 // sMod can be empty ( but we really need the library to search in )
175 // if sMod is empty and a macro is found then sMod is updated
176 // if sMod is empty, only standard modules will be searched (no class, document, form modules)
177 static bool hasMacro(SfxObjectShell
const* pShell
, const OUString
& sLibrary
, OUString
& sMod
,
178 const OUString
& sMacro
, bool bOnlyPublic
, const OUString
& sSkipModule
)
180 #if !HAVE_FEATURE_SCRIPTING
188 if (sLibrary
.isEmpty() || sMacro
.isEmpty())
191 BasicManager
* pBasicMgr
= pShell
->GetBasicManager();
195 StarBASIC
* pBasic
= pBasicMgr
->GetLib(sLibrary
);
198 sal_uInt16 nId
= pBasicMgr
->GetLibId(sLibrary
);
199 pBasicMgr
->LoadLib(nId
);
200 pBasic
= pBasicMgr
->GetLib(sLibrary
);
205 if (!sMod
.isEmpty()) // we wish to find the macro is a specific module
207 SbModule
* pModule
= pBasic
->FindModule(sMod
);
210 SbMethod
* pMeth
= pModule
->FindMethod(sMacro
, SbxClassType::Method
);
212 // Must be compiled before we can trust SbxFlagBits::Private
213 if (pMeth
&& bOnlyPublic
&& !pModule
->IsCompiled())
216 return pMeth
&& (!bOnlyPublic
|| !pMeth
->IsSet(SbxFlagBits::Private
));
219 for (auto const& rModuleRef
: pBasic
->GetModules())
221 SbMethod
* pMeth
= rModuleRef
->FindMethod(sMacro
, SbxClassType::Method
);
224 if (rModuleRef
->GetName() == sSkipModule
)
229 if (!rModuleRef
->IsCompiled())
230 rModuleRef
->Compile();
232 if (pMeth
->IsSet(SbxFlagBits::Private
))
235 sMod
= rModuleRef
->GetName();
245 #if HAVE_FEATURE_SCRIPTING
247 OUString
getDefaultProjectName( SfxObjectShell
const * pShell
)
250 if( BasicManager
* pBasicMgr
= pShell
? pShell
->GetBasicManager() : nullptr )
252 aPrjName
= pBasicMgr
->GetName();
253 if( aPrjName
.isEmpty() )
254 aPrjName
= "Standard";
259 static void parseMacro( const OUString
& sMacro
, OUString
& sContainer
, OUString
& sModule
, OUString
& sProcedure
)
261 sal_Int32 nMacroDot
= sMacro
.lastIndexOf( '.' );
263 if ( nMacroDot
!= -1 )
265 sProcedure
= sMacro
.copy( nMacroDot
+ 1 );
267 const sal_Int32 nContainerDot
= sMacro
.lastIndexOf('.', nMacroDot
);
268 if ( nContainerDot
!= -1 )
270 sModule
= sMacro
.copy( nContainerDot
+ 1, nMacroDot
- nContainerDot
- 1 );
271 sContainer
= sMacro
.copy( 0, nContainerDot
);
274 sModule
= sMacro
.copy( 0, nMacroDot
);
282 OUString
resolveVBAMacro(SfxObjectShell
const* pShell
, const OUString
& rLibName
,
283 const OUString
& rModuleName
, const OUString
& rMacroName
,
284 bool bOnlyPublic
, const OUString
& sSkipModule
)
286 #if !HAVE_FEATURE_SCRIPTING
296 OUString aLibName
= rLibName
.isEmpty() ? getDefaultProjectName( pShell
) : rLibName
;
297 OUString aModuleName
= rModuleName
;
298 if (hasMacro(pShell
, aLibName
, aModuleName
, rMacroName
, bOnlyPublic
, sSkipModule
))
299 return aLibName
+ "." + aModuleName
+ "." + rMacroName
;
305 MacroResolvedInfo
resolveVBAMacro( SfxObjectShell
* pShell
, const OUString
& MacroName
, bool bSearchGlobalTemplates
)
307 #if !HAVE_FEATURE_SCRIPTING
310 (void) bSearchGlobalTemplates
;
312 return MacroResolvedInfo();
315 return MacroResolvedInfo();
317 // the name may be enclosed in apostrophs
318 std::u16string_view aMacroName
= trimMacroName( MacroName
);
320 // parse the macro name
321 size_t nDocSepIndex
= aMacroName
.find( '!' );
322 if( nDocSepIndex
> 0 && nDocSepIndex
!= std::u16string_view::npos
)
324 // macro specified by document name
325 // find document shell for document name and call ourselves
328 // assume for now that the document name is *this* document
329 std::u16string_view sDocUrlOrPath
= aMacroName
.substr( 0, nDocSepIndex
);
330 aMacroName
= aMacroName
.substr( nDocSepIndex
+ 1 );
331 SAL_INFO("filter.ms", "doc search, current shell is " << pShell
);
332 SfxObjectShell
* pFoundShell
= nullptr;
333 if( bSearchGlobalTemplates
)
335 SvtPathOptions aPathOpt
;
336 const OUString
& aAddinPath
= aPathOpt
.GetAddinPath();
337 if( o3tl::starts_with(sDocUrlOrPath
, aAddinPath
) )
338 pFoundShell
= pShell
;
341 pFoundShell
= findShellForUrl( OUString(sDocUrlOrPath
) );
344 "doc search, after find, found shell is " << pFoundShell
);
345 return resolveVBAMacro( pFoundShell
, OUString(aMacroName
) );
348 // macro is contained in 'this' document ( or code imported from a template
349 // where that template is a global template or perhaps the template this
350 // document is created from )
352 MacroResolvedInfo
aRes( pShell
);
354 // macro format = Container.Module.Procedure
355 OUString sContainer
, sModule
, sProcedure
;
356 parseMacro( OUString(aMacroName
), sContainer
, sModule
, sProcedure
);
359 // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
360 // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
361 uno::Reference
< container::XNameContainer
> xPrjNameCache
;
362 uno::Reference
< lang::XMultiServiceFactory
> xSF( pShell
->GetModel(), uno::UNO_QUERY
);
365 xPrjNameCache
.set( xSF
->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY
);
367 catch( const uno::Exception
& ) // createInstance may throw
372 std::vector
< OUString
> sSearchList
;
374 if ( !sContainer
.isEmpty() )
376 // service VBAProjectNameProvider not implemented
378 // get the Project associated with the Container
379 if ( xPrjNameCache
.is() )
381 if ( xPrjNameCache
->hasByName( sContainer
) )
384 xPrjNameCache
->getByName( sContainer
) >>= sProject
;
385 sContainer
= sProject
;
389 sSearchList
.push_back( sContainer
); // First Lib to search
393 // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
394 // get the name of Project/Library for 'this' document
395 OUString
sThisProject( u
"Standard"_ustr
);
398 uno::Reference
< beans::XPropertySet
> xProps( pShell
->GetModel(), uno::UNO_QUERY_THROW
);
399 uno::Reference
< script::vba::XVBACompatibility
> xVBAMode( xProps
->getPropertyValue( u
"BasicLibraries"_ustr
), uno::UNO_QUERY_THROW
);
400 sThisProject
= xVBAMode
->getProjectName();
402 catch( const uno::Exception
& /*e*/) {}
404 sSearchList
.push_back( sThisProject
); // First Lib to search
406 // service VBAProjectNameProvider not implemented
408 if ( xPrjNameCache
.is() )
410 // is this document created from a template?
411 uno::Reference
< document::XDocumentPropertiesSupplier
> const
412 xDocPropSupp(pShell
->GetModel(), uno::UNO_QUERY_THROW
);
413 uno::Reference
< document::XDocumentProperties
> xDocProps( xDocPropSupp
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
415 OUString sCreatedFrom
= xDocProps
->getTemplateURL();
416 if ( !sCreatedFrom
.isEmpty() )
419 aObj
.SetURL( sCreatedFrom
);
420 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
426 osl::FileBase::getFileURLFromSystemPath( sCreatedFrom
, aURL
);
429 sCreatedFrom
= aObj
.GetLastName();
432 sal_Int32 nIndex
= sCreatedFrom
.lastIndexOf( '.' );
434 sCreatedFrom
= sCreatedFrom
.copy( 0, nIndex
);
437 if ( !sCreatedFrom
.isEmpty() && xPrjNameCache
->hasByName( sCreatedFrom
) )
439 xPrjNameCache
->getByName( sCreatedFrom
) >>= sPrj
;
440 // Make sure we don't double up with this project
441 if ( !sPrj
.equals( sThisProject
) )
442 sSearchList
.push_back( sPrj
);
445 // get list of global template Names
446 uno::Sequence
< OUString
> sTemplateNames
= xPrjNameCache
->getElementNames();
447 sal_Int32 nLen
= sTemplateNames
.getLength();
448 for ( sal_Int32 index
= 0; ( bSearchGlobalTemplates
&& index
< nLen
); ++index
)
451 if ( !sCreatedFrom
.equals( sTemplateNames
[ index
] ) )
453 if ( xPrjNameCache
->hasByName( sTemplateNames
[ index
] ) )
455 xPrjNameCache
->getByName( sTemplateNames
[ index
] ) >>= sPrj
;
456 // Make sure we don't double up with this project
457 if ( !sPrj
.equals( sThisProject
) )
458 sSearchList
.push_back( sPrj
);
467 for (auto const& search
: sSearchList
)
469 aRes
.mbFound
= hasMacro(pShell
, search
, sModule
, sProcedure
, /*bOnlyPublic=*/false, u
""_ustr
);
476 //aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
477 aRes
.msResolvedMacro
= sContainer
+ "." + sModule
+ "." + sProcedure
;
483 // Treat the args as possible inputs (conversion at bottom of method)
484 bool executeMacro( SfxObjectShell
* pShell
, const OUString
& sMacroName
, uno::Sequence
< uno::Any
>& aArgs
, uno::Any
& aRet
, const uno::Any
& /*aCaller*/)
486 #if !HAVE_FEATURE_SCRIPTING
497 OUString sUrl
= makeMacroURL( sMacroName
);
499 uno::Sequence
< sal_Int16
> aOutArgsIndex
;
500 uno::Sequence
< uno::Any
> aOutArgs
;
504 ErrCode nErr
= pShell
->CallXScript(sUrl
, aArgs
, aRet
, aOutArgsIndex
, aOutArgs
, false);
505 sal_Int32 nLen
= aOutArgs
.getLength();
506 // convert any out params to seem like they were inputs
509 auto pArgs
= aArgs
.getArray();
510 for (sal_Int32 index
= 0; index
< nLen
; ++index
)
512 sal_Int32 nOutIndex
= aOutArgsIndex
[index
];
513 pArgs
[nOutIndex
] = aOutArgs
[index
];
516 bRes
= ( nErr
== ERRCODE_NONE
);
518 catch ( const uno::Exception
& )
528 VBAMacroResolver::VBAMacroResolver() :
529 mpObjShell( nullptr )
533 VBAMacroResolver::~VBAMacroResolver()
537 // com.sun.star.lang.XServiceInfo interface -----------------------------------
539 OUString SAL_CALL
VBAMacroResolver::getImplementationName()
541 return u
"com.sun.star.comp.vba.VBAMacroResolver"_ustr
;
544 sal_Bool SAL_CALL
VBAMacroResolver::supportsService( const OUString
& rService
)
546 return cppu::supportsService(this, rService
);
549 uno::Sequence
< OUString
> SAL_CALL
VBAMacroResolver::getSupportedServiceNames()
551 return { u
"com.sun.star.script.vba.VBAMacroResolver"_ustr
};
554 // com.sun.star.lang.XInitialization interface --------------------------------
556 void SAL_CALL
VBAMacroResolver::initialize( const uno::Sequence
< uno::Any
>& rArgs
)
558 OSL_ENSURE( rArgs
.getLength() > 1, "VBAMacroResolver::initialize - missing arguments" );
559 if( rArgs
.getLength() < 2 )
560 throw uno::RuntimeException();
562 // first argument: document model
563 mxModel
.set( rArgs
[ 0 ], uno::UNO_QUERY_THROW
);
564 mpObjShell
= comphelper::getFromUnoTunnel
<SfxObjectShell
>(mxModel
);
566 throw uno::RuntimeException();
568 // second argument: VBA project name
569 if( !(rArgs
[ 1 ] >>= maProjectName
) || (maProjectName
.isEmpty()) )
570 throw uno::RuntimeException();
573 // com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
575 OUString SAL_CALL
VBAMacroResolver::resolveVBAMacroToScriptURL( const OUString
& rVBAMacroName
)
578 throw uno::RuntimeException();
580 // the name may be enclosed in apostrophs
581 OUString
aMacroName( trimMacroName( rVBAMacroName
) );
582 if( aMacroName
.isEmpty() )
583 throw lang::IllegalArgumentException();
585 // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
586 if( (aMacroName
[ 0 ] == '[') || (aMacroName
.indexOf( '!' ) >= 0) )
587 throw lang::IllegalArgumentException();
589 // check if macro name starts with project name, replace with "Standard"
590 // TODO: adjust this when custom VBA project name is supported
591 sal_Int32 nDotPos
= aMacroName
.indexOf( '.' );
592 if( (nDotPos
== 0) || (nDotPos
+ 1 == aMacroName
.getLength()) )
593 throw lang::IllegalArgumentException();
594 if( (nDotPos
> 0) && aMacroName
.matchIgnoreAsciiCase( maProjectName
) )
595 aMacroName
= aMacroName
.copy( nDotPos
+ 1 );
597 // try to find the macro
598 MacroResolvedInfo aInfo
= resolveVBAMacro( mpObjShell
, aMacroName
);
600 throw lang::IllegalArgumentException();
602 // build and return the script URL
603 return makeMacroURL( aInfo
.msResolvedMacro
);
606 OUString SAL_CALL
VBAMacroResolver::resolveScriptURLtoVBAMacro( const OUString
& /*rScriptURL*/ )
608 OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
609 throw uno::RuntimeException();
612 static bool getModifier( sal_Unicode c
, sal_uInt16
& mod
)
617 } else if ( c
== '^' ) {
620 } else if ( c
== '%' ) {
627 /// @throws uno::RuntimeException
628 static sal_uInt16
parseChar( sal_Unicode c
)
630 sal_uInt16 nVclKey
= 0;
631 // do we care about locale here for letters/digits? probably not
632 if ( rtl::isAsciiAlpha( c
) )
634 nVclKey
|= ( rtl::toAsciiUpperCase( c
) - 'A' ) + KEY_A
;
635 if ( rtl::isAsciiUpperCase( c
) )
636 nVclKey
|= KEY_SHIFT
;
638 else if ( rtl::isAsciiDigit( c
) )
639 nVclKey
|= ( c
- '0' ) + KEY_0
;
640 else if ( c
== '~' ) // special case
641 nVclKey
= KEY_RETURN
;
642 else if ( c
== ' ' ) // special case
644 else // I guess we have a problem ( but not sure if locale specific keys might come into play here )
645 throw uno::RuntimeException();
652 constexpr frozen::unordered_map
<std::u16string_view
, sal_uInt16
, 34> s_KeyCodes
654 { u
"BACKSPACE", KEY_BACKSPACE
},
655 { u
"BS", KEY_BACKSPACE
},
656 { u
"DELETE", KEY_DELETE
},
657 { u
"DEL", KEY_DELETE
},
658 { u
"DOWN", KEY_DOWN
},
660 { u
"LEFT", KEY_LEFT
},
661 { u
"RIGHT", KEY_RIGHT
},
663 { u
"ESCAPE", KEY_ESCAPE
},
664 { u
"ESC", KEY_ESCAPE
},
665 { u
"HELP", KEY_HELP
},
666 { u
"HOME", KEY_HOME
},
667 { u
"PGDN", KEY_PAGEDOWN
},
668 { u
"PGUP", KEY_PAGEUP
},
669 { u
"INSERT", KEY_INSERT
},
670 { u
"SCROLLLOCK", KEY_SCROLLLOCK
},
671 { u
"NUMLOCK", KEY_NUMLOCK
},
690 } // end anonymous namespace
692 awt::KeyEvent
parseKeyEvent( std::u16string_view Key
)
694 std::u16string_view sKeyCode
;
695 sal_uInt16 nVclKey
= 0;
697 // parse the modifier if any
698 for ( size_t i
=0; i
<Key
.size(); ++i
)
700 if ( ! getModifier( Key
[ i
], nVclKey
) )
702 sKeyCode
= Key
.substr( i
);
707 // check if keycode is surrounded by '{}', if so scoop out the contents
708 // else it should be just one char of ( 'a-z,A-Z,0-9' )
709 if ( sKeyCode
.size() == 1 ) // ( a single char )
711 nVclKey
|= parseChar( sKeyCode
[ 0 ] );
713 else // key should be enclosed in '{}'
715 if ( sKeyCode
.size() < 3 || sKeyCode
[0] != '{' || sKeyCode
[sKeyCode
.size() - 1 ] != '}' )
716 throw uno::RuntimeException();
718 sKeyCode
= sKeyCode
.substr(1, sKeyCode
.size() - 2 );
720 if ( sKeyCode
.size() == 1 )
721 nVclKey
|= parseChar( sKeyCode
[ 0 ] );
724 auto it
= s_KeyCodes
.find(sKeyCode
);
725 if ( it
== s_KeyCodes
.end() ) // unknown or unsupported
726 throw uno::RuntimeException();
727 nVclKey
|= it
->second
;
731 awt::KeyEvent aKeyEvent
= svt::AcceleratorExecute::st_VCLKey2AWTKey( vcl::KeyCode( nVclKey
) );
735 void applyShortCutKeyBinding ( const uno::Reference
< frame::XModel
>& rxModel
, const awt::KeyEvent
& rKeyEvent
, const OUString
& rMacroName
)
737 OUString
MacroName( rMacroName
);
738 if ( !MacroName
.isEmpty() )
740 OUString aMacroName
= MacroName
.trim();
741 if( aMacroName
.startsWith("!") )
742 aMacroName
= o3tl::trim(aMacroName
.subView(1));
743 SfxObjectShell
* pShell
= nullptr;
746 pShell
= comphelper::getFromUnoTunnel
<SfxObjectShell
>(rxModel
);
748 throw uno::RuntimeException();
750 MacroResolvedInfo aMacroInfo
= resolveVBAMacro( pShell
, aMacroName
);
751 if( !aMacroInfo
.mbFound
)
752 throw uno::RuntimeException( u
"The procedure doesn't exist"_ustr
);
753 MacroName
= aMacroInfo
.msResolvedMacro
;
755 uno::Reference
< ui::XUIConfigurationManagerSupplier
> xCfgSupplier(rxModel
, uno::UNO_QUERY_THROW
);
756 uno::Reference
< ui::XUIConfigurationManager
> xCfgMgr
= xCfgSupplier
->getUIConfigurationManager();
758 uno::Reference
< ui::XAcceleratorConfiguration
> xAcc( xCfgMgr
->getShortCutManager(), uno::UNO_SET_THROW
);
759 if ( MacroName
.isEmpty() )
760 // I believe this should really restore the [application] default. Since
761 // afaik we don't actually setup application default bindings on import
762 // we don't even know what the 'default' would be for this key
763 xAcc
->removeKeyEvent( rKeyEvent
);
765 xAcc
->setKeyEvent( rKeyEvent
, ooo::vba::makeMacroURL( MacroName
) );
772 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
773 filter_VBAMacroResolver_get_implementation(
774 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
776 return cppu::acquire(new ooo::vba::VBAMacroResolver());
779 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */