some fixes after resync
This commit is contained in:
parent
82f5d55a7f
commit
7e4d3b6cce
1 changed files with 384 additions and 0 deletions
384
filter/source/msfilter/msvbahelper.cxx
Normal file
384
filter/source/msfilter/msvbahelper.cxx
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* Copyright 2008 by Sun Microsystems, Inc.
|
||||
*
|
||||
* OpenOffice.org - a multi-platform office productivity suite
|
||||
*
|
||||
* $RCSfile:
|
||||
* $Revision:
|
||||
*
|
||||
* This file is part of OpenOffice.org.
|
||||
*
|
||||
* OpenOffice.org is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 3
|
||||
* only, as published by the Free Software Foundation.
|
||||
*
|
||||
* OpenOffice.org is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License version 3 for more details
|
||||
* (a copy is included in the LICENSE file that accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* version 3 along with OpenOffice.org. If not, see
|
||||
* <http://www.openoffice.org/license.html>
|
||||
* for a copy of the LGPLv3 License.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#include "precompiled_filter.hxx"
|
||||
#include <svx/msvbahelper.hxx>
|
||||
#include <basic/sbx.hxx>
|
||||
#include <basic/sbstar.hxx>
|
||||
#include <basic/basmgr.hxx>
|
||||
#include <basic/sbmod.hxx>
|
||||
#include <basic/sbmeth.hxx>
|
||||
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
|
||||
#include <com/sun/star/document/XDocumentProperties.hpp>
|
||||
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <osl/file.hxx>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
const static rtl::OUString sUrlPart0 = rtl::OUString::createFromAscii( "vnd.sun.star.script:");
|
||||
const static rtl::OUString sUrlPart1 = rtl::OUString::createFromAscii( "?language=Basic&location=document");
|
||||
|
||||
namespace ooo { namespace vba {
|
||||
|
||||
String makeMacroURL( const String& sMacroName )
|
||||
{
|
||||
return sUrlPart0.concat( sMacroName ).concat( sUrlPart1 ) ;
|
||||
}
|
||||
|
||||
SfxObjectShell* findShellForUrl( const rtl::OUString& sMacroURLOrPath )
|
||||
{
|
||||
SfxObjectShell* pFoundShell=NULL;
|
||||
SfxObjectShell* pShell = SfxObjectShell::GetFirst();
|
||||
INetURLObject aObj;
|
||||
aObj.SetURL( sMacroURLOrPath );
|
||||
bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
|
||||
rtl::OUString aURL;
|
||||
if ( bIsURL )
|
||||
aURL = sMacroURLOrPath;
|
||||
else
|
||||
{
|
||||
osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL );
|
||||
aObj.SetURL( aURL );
|
||||
}
|
||||
OSL_TRACE("Trying to find shell for url %s", rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() );
|
||||
while ( pShell )
|
||||
{
|
||||
|
||||
uno::Reference< frame::XModel > xModel = pShell->GetModel();
|
||||
// are we searching for a template? if so we have to cater for the
|
||||
// fact that in openoffice a document opened from a template is always
|
||||
// a new document :/
|
||||
if ( xModel.is() )
|
||||
{
|
||||
OSL_TRACE("shell 0x%x has model with url %s and we look for %s", pShell
|
||||
, rtl::OUStringToOString( xModel->getURL(), RTL_TEXTENCODING_UTF8 ).getStr()
|
||||
, rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr()
|
||||
);
|
||||
if ( sMacroURLOrPath.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) )
|
||||
{
|
||||
uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( xModel, uno::UNO_QUERY );
|
||||
if( xDocInfoSupp.is() )
|
||||
{
|
||||
uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
|
||||
uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
|
||||
rtl::OUString sCurrName = xDocProps->getTemplateName();
|
||||
if( sMacroURLOrPath.lastIndexOf( sCurrName ) >= 0 )
|
||||
{
|
||||
pFoundShell = pShell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( aURL.equals( xModel->getURL() ) )
|
||||
{
|
||||
pFoundShell = pShell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pShell = SfxObjectShell::GetNext( *pShell );
|
||||
}
|
||||
return pFoundShell;
|
||||
}
|
||||
|
||||
// sMod can be empty ( but we really need the library to search in )
|
||||
// if sMod is empty and a macro is found then sMod is updated
|
||||
bool hasMacro( SfxObjectShell* pShell, const String& sLibrary, String& sMod, const String& sMacro )
|
||||
{
|
||||
bool bFound = false;
|
||||
if ( sLibrary.Len() && sMacro.Len() )
|
||||
{
|
||||
OSL_TRACE("** Searching for %s.%s in library %s"
|
||||
,rtl::OUStringToOString( sMod, RTL_TEXTENCODING_UTF8 ).getStr()
|
||||
,rtl::OUStringToOString( sMacro, RTL_TEXTENCODING_UTF8 ).getStr()
|
||||
,rtl::OUStringToOString( sLibrary, RTL_TEXTENCODING_UTF8 ).getStr() );
|
||||
BasicManager* pBasicMgr = pShell-> GetBasicManager();
|
||||
if ( pBasicMgr )
|
||||
{
|
||||
StarBASIC* pBasic = pBasicMgr->GetLib( sLibrary );
|
||||
if ( !pBasic )
|
||||
{
|
||||
USHORT nId = pBasicMgr->GetLibId( sLibrary );
|
||||
pBasicMgr->LoadLib( nId );
|
||||
pBasic = pBasicMgr->GetLib( sLibrary );
|
||||
}
|
||||
if ( pBasic )
|
||||
{
|
||||
if ( sMod.Len() ) // we wish to find the macro is a specific module
|
||||
{
|
||||
SbModule* pModule = pBasic->FindModule( sMod );
|
||||
if ( pModule )
|
||||
{
|
||||
SbxArray* pMethods = pModule->GetMethods();
|
||||
if ( pMethods )
|
||||
{
|
||||
SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( sMacro, SbxCLASS_METHOD ) );
|
||||
if ( pMethod )
|
||||
bFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( SbMethod* pMethod = dynamic_cast< SbMethod* >( pBasic->Find( sMacro, SbxCLASS_METHOD ) ) )
|
||||
{
|
||||
if( SbModule* pModule = pMethod->GetModule() )
|
||||
{
|
||||
sMod = pModule->GetName();
|
||||
bFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bFound;
|
||||
}
|
||||
void parseMacro( const rtl::OUString& sMacro, String& sContainer, String& sModule, String& sProcedure )
|
||||
{
|
||||
sal_Int32 nMacroDot = sMacro.lastIndexOf( '.' );
|
||||
|
||||
if ( nMacroDot != -1 )
|
||||
{
|
||||
sProcedure = sMacro.copy( nMacroDot + 1 );
|
||||
|
||||
sal_Int32 nContainerDot = sMacro.lastIndexOf( '.', nMacroDot - 1 );
|
||||
if ( nContainerDot != -1 )
|
||||
{
|
||||
sModule = sMacro.copy( nContainerDot + 1, nMacroDot - nContainerDot - 1 );
|
||||
sContainer = sMacro.copy( 0, nContainerDot );
|
||||
}
|
||||
else
|
||||
sModule = sMacro.copy( 0, nMacroDot );
|
||||
}
|
||||
else
|
||||
sProcedure = sMacro;
|
||||
}
|
||||
|
||||
VBAMacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUString& MacroName, bool bSearchGlobalTemplates )
|
||||
{
|
||||
VBAMacroResolvedInfo aRes;
|
||||
if ( !pShell )
|
||||
return aRes;
|
||||
aRes.SetMacroDocContext( pShell );
|
||||
// parse the macro name
|
||||
sal_Int32 nDocSepIndex = MacroName.indexOfAsciiL( "!", 1 );
|
||||
String sMacroUrl = MacroName;
|
||||
|
||||
String sContainer;
|
||||
String sModule;
|
||||
String sProcedure;
|
||||
|
||||
if( nDocSepIndex > 0 )
|
||||
{
|
||||
// macro specified by document name
|
||||
// find document shell for document name and call ourselves
|
||||
// recursively
|
||||
|
||||
// assume for now that the document name is *this* document
|
||||
String sDocUrlOrPath = MacroName.copy( 0, nDocSepIndex );
|
||||
sMacroUrl = MacroName.copy( nDocSepIndex + 1 );
|
||||
OSL_TRACE("doc search, current shell is 0x%x", pShell );
|
||||
SfxObjectShell* pFoundShell = findShellForUrl( sDocUrlOrPath );
|
||||
OSL_TRACE("doc search, after find, found shell is 0x%x", pFoundShell );
|
||||
aRes = resolveVBAMacro( pFoundShell, sMacroUrl );
|
||||
}
|
||||
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( MacroName, sContainer, sModule, sProcedure );
|
||||
uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
|
||||
uno::Reference< container::XNameContainer > xPrjNameCache;
|
||||
if ( xSF.is() )
|
||||
xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
|
||||
|
||||
std::vector< rtl::OUString > sSearchList;
|
||||
|
||||
if ( sContainer.Len() > 0 )
|
||||
{
|
||||
// get the Project associated with the Container
|
||||
if ( xPrjNameCache.is() )
|
||||
{
|
||||
if ( xPrjNameCache->hasByName( sContainer ) )
|
||||
{
|
||||
rtl::OUString sProject;
|
||||
xPrjNameCache->getByName( sContainer ) >>= sProject;
|
||||
sContainer = sProject;
|
||||
}
|
||||
}
|
||||
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 )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
// 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 ( 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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ) );
|
||||
|
||||
return aRes;
|
||||
}
|
||||
|
||||
// Treat the args as possible inouts ( convertion at bottom of method )
|
||||
sal_Bool executeMacro( SfxObjectShell* pShell, const String& sMacroName, uno::Sequence< uno::Any >& aArgs, uno::Any& /*aRet*/, const uno::Any& aCaller )
|
||||
{
|
||||
sal_Bool bRes = sal_False;
|
||||
if ( !pShell )
|
||||
return bRes;
|
||||
rtl::OUString sUrl = makeMacroURL( sMacroName );
|
||||
|
||||
uno::Sequence< sal_Int16 > aOutArgsIndex;
|
||||
uno::Sequence< uno::Any > aOutArgs;
|
||||
|
||||
try
|
||||
{
|
||||
uno::Reference< script::provider::XScriptProvider > xScriptProvider;
|
||||
uno::Reference< script::provider::XScriptProviderSupplier > xSPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
|
||||
|
||||
xScriptProvider.set( xSPS->getScriptProvider(), uno::UNO_QUERY_THROW );
|
||||
|
||||
uno::Reference< script::provider::XScript > xScript( xScriptProvider->getScript( sUrl ), uno::UNO_QUERY_THROW );
|
||||
|
||||
if ( aCaller.hasValue() )
|
||||
{
|
||||
uno::Reference< beans::XPropertySet > xProps( xScript, uno::UNO_QUERY );
|
||||
if ( xProps.is() )
|
||||
{
|
||||
uno::Sequence< uno::Any > aCallerHack(1);
|
||||
aCallerHack[ 0 ] = aCaller;
|
||||
xProps->setPropertyValue( rtl::OUString::createFromAscii( "Caller" ), uno::makeAny( aCallerHack ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xScript->invoke( aArgs, aOutArgsIndex, aOutArgs );
|
||||
|
||||
sal_Int32 nLen = aOutArgs.getLength();
|
||||
// convert any out params to seem like they were inouts
|
||||
if ( nLen )
|
||||
{
|
||||
for ( sal_Int32 index=0; index < nLen; ++index )
|
||||
{
|
||||
sal_Int32 nOutIndex = aOutArgsIndex[ index ];
|
||||
aArgs[ nOutIndex ] = aOutArgs[ index ];
|
||||
}
|
||||
}
|
||||
|
||||
bRes = sal_True;
|
||||
}
|
||||
catch ( uno::Exception& e )
|
||||
{
|
||||
bRes = sal_False;
|
||||
}
|
||||
return bRes;
|
||||
}
|
||||
} } // vba // ooo
|
Loading…
Reference in a new issue