summaryrefslogtreecommitdiff
path: root/filter/source/msfilter/msvbahelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/msfilter/msvbahelper.cxx')
-rw-r--r--filter/source/msfilter/msvbahelper.cxx346
1 files changed, 228 insertions, 118 deletions
diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx
index e40c3c2c61c2..3bbcf7b4727d 100644
--- a/filter/source/msfilter/msvbahelper.cxx
+++ b/filter/source/msfilter/msvbahelper.cxx
@@ -36,13 +36,15 @@
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <tools/urlobj.hxx>
#include <osl/file.hxx>
#include <unotools/pathoptions.hxx>
using namespace ::com::sun::star;
-namespace ooo { namespace vba {
+namespace ooo {
+namespace vba {
const static rtl::OUString sUrlPart0 = rtl::OUString::createFromAscii( "vnd.sun.star.script:");
const static rtl::OUString sUrlPart1 = rtl::OUString::createFromAscii( "?language=Basic&location=document");
@@ -63,6 +65,16 @@ String makeMacroURL( const String& sMacroName )
return ::rtl::OUString();
}
+::rtl::OUString trimMacroName( const ::rtl::OUString& rMacroName )
+{
+ // the name may contain whitespaces and may be enclosed in apostrophs
+ ::rtl::OUString aMacroName = rMacroName.trim();
+ sal_Int32 nMacroLen = aMacroName.getLength();
+ if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') )
+ aMacroName = aMacroName.copy( 1, nMacroLen - 2 ).trim();
+ return aMacroName;
+}
+
SfxObjectShell* findShellForUrl( const rtl::OUString& sMacroURLOrPath )
{
SfxObjectShell* pFoundShell=NULL;
@@ -227,26 +239,16 @@ void parseMacro( const rtl::OUString& sMacro, String& sContainer, String& sModul
sProcedure = sMacro;
}
-VBAMacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUString& MacroName, bool bSearchGlobalTemplates )
+MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUString& MacroName, bool bSearchGlobalTemplates )
{
- VBAMacroResolvedInfo aRes;
- if ( !pShell )
- return aRes;
- aRes.SetMacroDocContext( pShell );
+ if( !pShell )
+ return MacroResolvedInfo();
// the name may be enclosed in apostrophs
- ::rtl::OUString sMacroUrl = MacroName;
- sal_Int32 nMacroLen = MacroName.getLength();
- if( (nMacroLen >= 2) && (MacroName[0] == '\'') && (MacroName[nMacroLen-1] == '\'') )
- sMacroUrl = MacroName.copy( 1, nMacroLen - 2 );
+ ::rtl::OUString aMacroName = trimMacroName( MacroName );
// parse the macro name
- sal_Int32 nDocSepIndex = sMacroUrl.indexOf( '!' );
-
- String sContainer;
- String sModule;
- String sProcedure;
-
+ sal_Int32 nDocSepIndex = aMacroName.indexOf( '!' );
if( nDocSepIndex > 0 )
{
// macro specified by document name
@@ -254,10 +256,10 @@ VBAMacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUStrin
// recursively
// assume for now that the document name is *this* document
- String sDocUrlOrPath = sMacroUrl.copy( 0, nDocSepIndex );
- sMacroUrl = sMacroUrl.copy( nDocSepIndex + 1 );
+ String sDocUrlOrPath = aMacroName.copy( 0, nDocSepIndex );
+ aMacroName = aMacroName.copy( nDocSepIndex + 1 );
OSL_TRACE("doc search, current shell is 0x%x", pShell );
- SfxObjectShell* pFoundShell = NULL;
+ SfxObjectShell* pFoundShell = 0;
if( bSearchGlobalTemplates )
{
SvtPathOptions aPathOpt;
@@ -265,129 +267,124 @@ VBAMacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUStrin
if( rtl::OUString( sDocUrlOrPath ).indexOf( aAddinPath ) == 0 )
pFoundShell = pShell;
}
- if( pFoundShell == NULL )
+ if( !pFoundShell )
pFoundShell = findShellForUrl( sDocUrlOrPath );
OSL_TRACE("doc search, after find, found shell is 0x%x", pFoundShell );
- aRes = resolveVBAMacro( pFoundShell, sMacroUrl, bSearchGlobalTemplates );
- return aRes;
+ return resolveVBAMacro( pFoundShell, aMacroName );
}
- else
- {
- // macro is contained in 'this' document ( or code imported from a template
- // where that template is a global template or perhaps the template this
- // document is created from )
- // macro format = Container.Module.Procedure
- parseMacro( sMacroUrl, sContainer, sModule, sProcedure );
- uno::Reference< container::XNameContainer > xPrjNameCache;
+ // macro is contained in 'this' document ( or code imported from a template
+ // where that template is a global template or perhaps the template this
+ // document is created from )
+
+ MacroResolvedInfo aRes( pShell );
- // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
- // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
- //uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
- //if ( xSF.is() )
- // xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
+ // macro format = Container.Module.Procedure
+ String sContainer, sModule, sProcedure;
+ parseMacro( aMacroName, sContainer, sModule, sProcedure );
+ uno::Reference< container::XNameContainer > xPrjNameCache;
- std::vector< rtl::OUString > sSearchList;
+ // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
+ // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
+ //uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
+ //if ( xSF.is() )
+ // xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
- if ( sContainer.Len() > 0 )
+ std::vector< rtl::OUString > sSearchList;
+
+ if ( sContainer.Len() > 0 )
+ {
+ // get the Project associated with the Container
+ if ( xPrjNameCache.is() )
{
- // get the Project associated with the Container
- if ( xPrjNameCache.is() )
+ if ( xPrjNameCache->hasByName( sContainer ) )
{
- if ( xPrjNameCache->hasByName( sContainer ) )
- {
- rtl::OUString sProject;
- xPrjNameCache->getByName( sContainer ) >>= sProject;
- sContainer = sProject;
- }
+ rtl::OUString sProject;
+ xPrjNameCache->getByName( sContainer ) >>= sProject;
+ sContainer = sProject;
}
- sSearchList.push_back( sContainer ); // First Lib to search
}
- else
+ sSearchList.push_back( sContainer ); // First Lib to search
+ }
+ else
+ {
+ // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
+ // get the name of Project/Library for 'this' document
+ rtl::OUString sThisProject;
+ BasicManager* pBasicMgr = pShell-> GetBasicManager();
+ if ( pBasicMgr )
{
- // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
- // get the name of Project/Library for 'this' document
- rtl::OUString sThisProject;
- BasicManager* pBasicMgr = pShell-> GetBasicManager();
- if ( pBasicMgr )
- {
- if ( pBasicMgr->GetName().Len() )
- sThisProject = pBasicMgr->GetName();
- else // cater for the case where VBA is not enabled
- sThisProject = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") );
- }
- sSearchList.push_back( sThisProject ); // First Lib to search
- if ( xPrjNameCache.is() )
- {
- // is this document created from a template?
- uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( pShell->GetModel(), uno::UNO_QUERY_THROW );
- uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
- uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
+ if ( pBasicMgr->GetName().Len() )
+ sThisProject = pBasicMgr->GetName();
+ else // cater for the case where VBA is not enabled
+ sThisProject = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") );
+ }
+ sSearchList.push_back( sThisProject ); // First Lib to search
+ if ( xPrjNameCache.is() )
+ {
+ // is this document created from a template?
+ uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( pShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
+ uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
- rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
- if ( sCreatedFrom.getLength() )
+ rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
+ if ( sCreatedFrom.getLength() )
+ {
+ INetURLObject aObj;
+ aObj.SetURL( sCreatedFrom );
+ bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
+ rtl::OUString aURL;
+ if ( bIsURL )
+ aURL = sCreatedFrom;
+ else
{
- INetURLObject aObj;
- aObj.SetURL( sCreatedFrom );
- bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
- rtl::OUString aURL;
- if ( bIsURL )
- aURL = sCreatedFrom;
- else
- {
- osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL );
- aObj.SetURL( aURL );
- }
- sCreatedFrom = aObj.GetLastName();
+ osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL );
+ aObj.SetURL( aURL );
}
+ sCreatedFrom = aObj.GetLastName();
+ }
- sal_Int32 nIndex = sCreatedFrom.lastIndexOf( '.' );
- if ( nIndex != -1 )
- sCreatedFrom = sCreatedFrom.copy( 0, nIndex );
+ sal_Int32 nIndex = sCreatedFrom.lastIndexOf( '.' );
+ if ( nIndex != -1 )
+ sCreatedFrom = sCreatedFrom.copy( 0, nIndex );
- rtl::OUString sPrj;
- if ( sCreatedFrom.getLength() && xPrjNameCache->hasByName( sCreatedFrom ) )
- {
- xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
- // Make sure we don't double up with this project
- if ( !sPrj.equals( sThisProject ) )
- sSearchList.push_back( sPrj );
- }
+ rtl::OUString sPrj;
+ if ( sCreatedFrom.getLength() && xPrjNameCache->hasByName( sCreatedFrom ) )
+ {
+ xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
+ // Make sure we don't double up with this project
+ if ( !sPrj.equals( sThisProject ) )
+ sSearchList.push_back( sPrj );
+ }
- // get list of global template Names
- uno::Sequence< rtl::OUString > sTemplateNames = xPrjNameCache->getElementNames();
- sal_Int32 nLen = sTemplateNames.getLength();
- for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index )
- {
+ // get list of global template Names
+ uno::Sequence< rtl::OUString > sTemplateNames = xPrjNameCache->getElementNames();
+ sal_Int32 nLen = sTemplateNames.getLength();
+ for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index )
+ {
- if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) )
+ if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) )
+ {
+ if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) )
{
- if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) )
- {
- xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj;
- // Make sure we don't double up with this project
- if ( !sPrj.equals( sThisProject ) )
- sSearchList.push_back( sPrj );
- }
+ xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj;
+ // Make sure we don't double up with this project
+ if ( !sPrj.equals( sThisProject ) )
+ sSearchList.push_back( sPrj );
}
-
}
+
}
}
- std::vector< rtl::OUString >::iterator it_end = sSearchList.end();
- for ( std::vector< rtl::OUString >::iterator it = sSearchList.begin(); it != it_end; ++it )
- {
- bool bRes = hasMacro( pShell, *it, sModule, sProcedure );
- if ( bRes )
- {
- aRes.SetResolved( true );
- aRes.SetMacroDocContext( pShell );
- sContainer = *it;
- break;
- }
- }
- aRes.SetResolvedMacro( sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 ) );
}
+ std::vector< rtl::OUString >::iterator it_end = sSearchList.end();
+ for ( std::vector< rtl::OUString >::iterator it = sSearchList.begin(); !aRes.mbFound && (it != it_end); ++it )
+ {
+ aRes.mbFound = hasMacro( pShell, *it, sModule, sProcedure );
+ if ( aRes.mbFound )
+ sContainer = *it;
+ }
+ aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
return aRes;
}
@@ -428,4 +425,117 @@ sal_Bool executeMacro( SfxObjectShell* pShell, const String& sMacroName, uno::Se
}
return bRes;
}
-} } // vba // ooo
+
+// ============================================================================
+
+uno::Sequence< ::rtl::OUString > VBAMacroResolver_getSupportedServiceNames()
+{
+ uno::Sequence< ::rtl::OUString > aServiceNames( 1 );
+ aServiceNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.vba.VBAMacroResolver" ) );
+ return aServiceNames;
+}
+
+::rtl::OUString VBAMacroResolver_getImplementationName()
+{
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.vba.VBAMacroResolver" ) );
+}
+
+uno::Reference< uno::XInterface > SAL_CALL VBAMacroResolver_createInstance( const uno::Reference< uno::XComponentContext >& ) throw (uno::Exception)
+{
+ return static_cast< ::cppu::OWeakObject* >( new VBAMacroResolver );
+}
+
+// ============================================================================
+
+VBAMacroResolver::VBAMacroResolver() :
+ mpObjShell( 0 )
+{
+}
+
+VBAMacroResolver::~VBAMacroResolver()
+{
+}
+
+// com.sun.star.lang.XServiceInfo interface -----------------------------------
+
+::rtl::OUString SAL_CALL VBAMacroResolver::getImplementationName() throw (uno::RuntimeException)
+{
+ return VBAMacroResolver_getImplementationName();
+}
+
+sal_Bool SAL_CALL VBAMacroResolver::supportsService( const ::rtl::OUString& rService ) throw (uno::RuntimeException)
+{
+ uno::Sequence< ::rtl::OUString > aServices = VBAMacroResolver_getSupportedServiceNames();
+ const ::rtl::OUString* pArray = aServices.getConstArray();
+ const ::rtl::OUString* pArrayEnd = pArray + aServices.getLength();
+ return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd;
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL VBAMacroResolver::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return VBAMacroResolver_getSupportedServiceNames();
+}
+
+// com.sun.star.lang.XInitialization interface --------------------------------
+
+void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rArgs ) throw (uno::Exception, uno::RuntimeException)
+{
+ OSL_ENSURE( rArgs.getLength() < 2, "VBAMacroResolver::initialize - missing arguments" );
+ if( rArgs.getLength() < 2 )
+ throw uno::RuntimeException();
+
+ // first argument: document model
+ mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW );
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( mxModel, uno::UNO_QUERY_THROW );
+ mpObjShell = reinterpret_cast< SfxObjectShell* >( xUnoTunnel->getSomething( SfxObjectShell::getUnoTunnelId() ) );
+ if( !mpObjShell )
+ throw uno::RuntimeException();
+
+ // second argument: VBA project name
+ if( !(rArgs[ 1 ] >>= maProjectName) || (maProjectName.getLength() == 0) )
+ throw uno::RuntimeException();
+}
+
+// com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
+
+::rtl::OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const ::rtl::OUString& rVBAMacroName ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ if( !mpObjShell )
+ throw uno::RuntimeException();
+
+ // the name may be enclosed in apostrophs
+ ::rtl::OUString aMacroName = trimMacroName( rVBAMacroName );
+ if( aMacroName.getLength() == 0 )
+ throw lang::IllegalArgumentException();
+
+ // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
+ if( (aMacroName[ 0 ] == '[') || (aMacroName.indexOf( '!' ) >= 0) )
+ throw lang::IllegalArgumentException();
+
+ // check if macro name starts with project name, replace with "Standard"
+ // TODO: adjust this when custom VBA project name is supported
+ sal_Int32 nDotPos = aMacroName.indexOf( '.' );
+ if( (nDotPos == 0) || (nDotPos + 1 == aMacroName.getLength()) )
+ throw lang::IllegalArgumentException();
+ if( (nDotPos > 0) && aMacroName.matchIgnoreAsciiCase( maProjectName ) )
+ aMacroName = aMacroName.copy( nDotPos + 1 );
+
+ // try to find the macro
+ MacroResolvedInfo aInfo = resolveVBAMacro( mpObjShell, aMacroName, false );
+ if( !aInfo.mbFound )
+ throw lang::IllegalArgumentException();
+
+ // build and return the script URL
+ return makeMacroURL( aInfo.msResolvedMacro );
+}
+
+::rtl::OUString SAL_CALL VBAMacroResolver::resolveScriptURLtoVBAMacro( const ::rtl::OUString& /*rScriptURL*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
+ throw uno::RuntimeException();
+}
+
+// ============================================================================
+
+} // namespace vba
+} // namespace ooo