20#include <config_features.h>
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>
36#include <osl/file.hxx>
39#include <rtl/character.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>
53constexpr OUStringLiteral
sUrlPart0( u
"vnd.sun.star.script:" );
54constexpr OUStringLiteral
sUrlPart1( u
"?language=Basic&location=document" );
65 return OUString(rMacroUrl.substr(
sUrlPart0.getLength(),
71static std::u16string_view
trimMacroName( std::u16string_view rMacroName )
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
83static SfxObjectShell* findShellForUrl(
const OUString& sMacroURLOrPath )
88 aObj.
SetURL( sMacroURLOrPath );
89 bool bIsURL = aObj.
GetProtocol() != INetProtocol::NotValid;
92 aURL = sMacroURLOrPath;
95 osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL );
109 "shell " << pShell <<
" has model with url " <<
xModel->getURL()
110 <<
" and we look for " << aURL);
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;
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;
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;
176static 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())
199 pBasic = pBasicMgr->
GetLib(sLibrary);
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))
244#if HAVE_FEATURE_SCRIPTING
251 aPrjName = pBasicMgr->
GetName();
252 if( aPrjName.isEmpty() )
253 aPrjName =
"Standard";
258static 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 );
282 const OUString& rModuleName,
const OUString& rMacroName,
283 bool bOnlyPublic,
const OUString& sSkipModule)
285#if !HAVE_FEATURE_SCRIPTING
296 OUString aModuleName = rModuleName;
297 if (hasMacro(pShell, aLibName, aModuleName, rMacroName, bOnlyPublic, sSkipModule))
298 return aLibName +
"." + aModuleName +
"." + rMacroName;
306#if !HAVE_FEATURE_SCRIPTING
309 (void) bSearchGlobalTemplates;
320 size_t nDocSepIndex = aMacroName.find(
'!' );
321 if( nDocSepIndex > 0 && nDocSepIndex != std::u16string_view::npos )
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);
332 if( bSearchGlobalTemplates )
337 pFoundShell = pShell;
340 pFoundShell = findShellForUrl( OUString(sDocUrlOrPath) );
343 "doc search, after find, found shell is " << pFoundShell);
354 OUString sContainer, sModule, sProcedure;
355 parseMacro( OUString(aMacroName), sContainer, sModule, sProcedure );
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& )
371 std::vector< OUString > sSearchList;
373 if ( !sContainer.isEmpty() )
378 if ( xPrjNameCache.is() )
380 if ( xPrjNameCache->hasByName( sContainer ) )
383 xPrjNameCache->getByName( sContainer ) >>= sProject;
384 sContainer = sProject;
388 sSearchList.push_back( sContainer );
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& ) {}
403 sSearchList.push_back( sThisProject );
407 if ( xPrjNameCache.is() )
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 );
431 sal_Int32
nIndex = sCreatedFrom.lastIndexOf(
'.' );
433 sCreatedFrom = sCreatedFrom.copy( 0,
nIndex );
436 if ( !sCreatedFrom.isEmpty() && xPrjNameCache->hasByName( sCreatedFrom ) )
438 xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
440 if ( !sPrj.equals( sThisProject ) )
441 sSearchList.push_back( sPrj );
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;
456 if ( !sPrj.equals( sThisProject ) )
457 sSearchList.push_back( sPrj );
466 for (
auto const& search : sSearchList)
468 aRes.
mbFound = hasMacro(pShell, search, sModule, sProcedure,
false,
"");
485#if !HAVE_FEATURE_SCRIPTING
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();
508 auto pArgs = aArgs.getArray();
511 sal_Int32 nOutIndex = aOutArgsIndex[
index];
512 pArgs[nOutIndex] = aOutArgs[
index];
517 catch (
const uno::Exception& )
528 mpObjShell( nullptr )
540 return "com.sun.star.comp.vba.VBAMacroResolver";
550 return {
"com.sun.star.script.vba.VBAMacroResolver" };
557 OSL_ENSURE( rArgs.getLength() > 1,
"VBAMacroResolver::initialize - missing arguments" );
558 if( rArgs.getLength() < 2 )
559 throw uno::RuntimeException();
562 mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW );
565 throw uno::RuntimeException();
569 throw uno::RuntimeException();
577 throw uno::RuntimeException();
581 if( aMacroName.isEmpty() )
582 throw lang::IllegalArgumentException();
585 if( (aMacroName[ 0 ] ==
'[') || (aMacroName.indexOf(
'!' ) >= 0) )
586 throw lang::IllegalArgumentException();
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 );
599 throw lang::IllegalArgumentException();
607 OSL_ENSURE(
false,
"VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
608 throw uno::RuntimeException();
616 }
else if ( c ==
'^' ) {
619 }
else if ( c ==
'%' ) {
629 sal_uInt16 nVclKey = 0;
631 if ( rtl::isAsciiAlpha( c ) )
633 nVclKey |= ( rtl::toAsciiUpperCase( c ) -
'A' ) +
KEY_A;
634 if ( rtl::isAsciiUpperCase( c ) )
637 else if ( rtl::isAsciiDigit( c ) )
638 nVclKey |= ( c -
'0' ) +
KEY_0;
644 throw uno::RuntimeException();
651constexpr frozen::unordered_map<std::u16string_view, sal_uInt16, 34> s_KeyCodes
693 std::u16string_view sKeyCode;
694 sal_uInt16 nVclKey = 0;
697 for (
size_t i=0;
i<
Key.size(); ++
i )
701 sKeyCode =
Key.substr(
i );
708 if ( sKeyCode.size() == 1 )
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 )
723 auto it = s_KeyCodes.find(sKeyCode);
724 if ( it == s_KeyCodes.end() )
725 throw uno::RuntimeException();
726 nVclKey |= it->second;
734void applyShortCutKeyBinding (
const uno::Reference< frame::XModel >& rxModel,
const awt::KeyEvent& rKeyEvent,
const OUString& rMacroName )
740 if( aMacroName.startsWith(
"!") )
741 aMacroName =
o3tl::trim(aMacroName.subView(1));
745 pShell = comphelper::getFromUnoTunnel<SfxObjectShell>(rxModel);
747 throw uno::RuntimeException();
751 throw uno::RuntimeException(
"The procedure doesn't exist" );
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 );
762 xAcc->removeKeyEvent( rKeyEvent );
771extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
773 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any>
const&)
StarBASIC * GetLib(sal_uInt16 nLib) const
const OUString & GetName() const
bool LoadLib(sal_uInt16 nLib)
sal_uInt16 GetLibId(std::u16string_view rName) const
OUString GetLastName(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
INetProtocol GetProtocol() const
bool SetURL(std::u16string_view rTheAbsURIRef, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
SbMethod * FindMethod(const OUString &, SbxClassType)
bool IsSet(SbxFlagBits n) const
const OUString & GetName(SbxNameType=SbxNameType::NONE) const
BasicManager * GetBasicManager() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetNext(const SfxObjectShell &rPrev, const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
ErrCode CallXScript(const OUString &rScriptURL, const css::uno::Sequence< css::uno::Any > &aParams, css::uno::Any &aRet, css::uno::Sequence< sal_Int16 > &aOutParamIndex, css::uno::Sequence< css::uno::Any > &aOutParam, bool bRaiseError=true, const css::uno::Any *aCaller=nullptr)
css::uno::Reference< css::frame::XModel3 > GetModel() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetFirst(const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
SbModule * FindModule(std::u16string_view)
const OUString & GetAddinPath() const
virtual OUString SAL_CALL resolveVBAMacroToScriptURL(const OUString &rVBAMacroName) override
SfxObjectShell * mpObjShell
virtual OUString SAL_CALL getImplementationName() override
css::uno::Reference< css::frame::XModel > mxModel
virtual OUString SAL_CALL resolveScriptURLtoVBAMacro(const OUString &rScriptURL) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual ~VBAMacroResolver() override
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &rArgs) override
virtual sal_Bool SAL_CALL supportsService(const OUString &rService) override
static css::awt::KeyEvent st_VCLKey2AWTKey(const vcl::KeyCode &aKey)
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_0
constexpr sal_uInt16 KEY_F2
constexpr sal_uInt16 KEY_F3
constexpr sal_uInt16 KEY_MOD2
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_HOME
constexpr sal_uInt16 KEY_SCROLLLOCK
constexpr sal_uInt16 KEY_F15
constexpr sal_uInt16 KEY_LEFT
constexpr sal_uInt16 KEY_F4
constexpr sal_uInt16 KEY_NUMLOCK
constexpr sal_uInt16 KEY_F5
constexpr sal_uInt16 KEY_PAGEDOWN
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_F6
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_F10
constexpr sal_uInt16 KEY_F9
constexpr sal_uInt16 KEY_F7
constexpr sal_uInt16 KEY_F1
constexpr sal_uInt16 KEY_A
constexpr sal_uInt16 KEY_RIGHT
constexpr sal_uInt16 KEY_F13
constexpr sal_uInt16 KEY_DELETE
constexpr sal_uInt16 KEY_F8
constexpr sal_uInt16 KEY_F12
constexpr sal_uInt16 KEY_DOWN
constexpr sal_uInt16 KEY_SPACE
constexpr sal_uInt16 KEY_PAGEUP
constexpr sal_uInt16 KEY_F11
constexpr sal_uInt16 KEY_HELP
constexpr sal_uInt16 KEY_SHIFT
constexpr sal_uInt16 KEY_F14
constexpr sal_uInt16 KEY_INSERT
constexpr sal_uInt16 KEY_BACKSPACE
constexpr sal_uInt16 KEY_END
#define SAL_INFO(area, stream)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * filter_VBAMacroResolver_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Shape IDs per cluster in DGG atom.
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
constexpr bool ends_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
static bool getModifier(sal_Unicode c, sal_uInt16 &mod)
awt::KeyEvent parseKeyEvent(std::u16string_view Key)
OUString makeMacroURL(std::u16string_view sMacroName)
static std::u16string_view trimMacroName(std::u16string_view rMacroName)
bool executeMacro(SfxObjectShell *pShell, const OUString &sMacroName, uno::Sequence< uno::Any > &aArgs, uno::Any &aRet, const uno::Any &)
MSFILTER_DLLPUBLIC OUString getDefaultProjectName(SfxObjectShell const *pShell)
OUString extractMacroName(std::u16string_view rMacroUrl)
constexpr OUStringLiteral sUrlPart0(u"vnd.sun.star.script:")
OUString resolveVBAMacro(SfxObjectShell const *pShell, const OUString &rLibName, const OUString &rModuleName, const OUString &rMacroName, bool bOnlyPublic, const OUString &sSkipModule)
constexpr OUStringLiteral sUrlPart1(u"?language=Basic&location=document")
static sal_uInt16 parseChar(sal_Unicode c)
void applyShortCutKeyBinding(const uno::Reference< frame::XModel > &rxModel, const awt::KeyEvent &rKeyEvent, const OUString &rMacroName)
Reference< XFrame > xFrame
Reference< XModel > xModel
constexpr OUStringLiteral sLibrary
constexpr OUStringLiteral sMacroName