LCOV - code coverage report
Current view: top level - libreoffice/filter/source/msfilter - msvbahelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 3 295 1.0 %
Date: 2012-12-27 Functions: 2 28 7.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <filter/msfilter/msvbahelper.hxx>
      21             : #include <basic/sbx.hxx>
      22             : #include <basic/sbstar.hxx>
      23             : #include <basic/basmgr.hxx>
      24             : #include <basic/sbmod.hxx>
      25             : #include <basic/sbmeth.hxx>
      26             : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
      27             : #include <com/sun/star/document/XDocumentProperties.hpp>
      28             : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
      29             : #include <com/sun/star/lang/XUnoTunnel.hpp>
      30             : #include <com/sun/star/script/ModuleType.hpp>
      31             : #include <tools/urlobj.hxx>
      32             : #include <osl/file.hxx>
      33             : #include <unotools/pathoptions.hxx>
      34             : 
      35             : #include <com/sun/star/awt/KeyModifier.hpp>
      36             : #include <svtools/acceleratorexecute.hxx>
      37             : #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
      38             : #include <com/sun/star/ui/XUIConfigurationManager.hpp>
      39             : #include <map>
      40             : 
      41             : using namespace ::com::sun::star;
      42             : 
      43             : namespace ooo {
      44             : namespace vba {
      45             : 
      46          20 : const OUString sUrlPart0( "vnd.sun.star.script:" );
      47          20 : const OUString sUrlPart1( "?language=Basic&location=document" );
      48             : 
      49           0 : OUString makeMacroURL( const OUString& sMacroName )
      50             : {
      51             :     return OUStringBuffer().
      52           0 :         append( sUrlPart0 ).
      53           0 :         append( sMacroName ).
      54           0 :         append( sUrlPart1 ).
      55           0 :         makeStringAndClear();
      56             : }
      57             : 
      58           0 : OUString extractMacroName( const OUString& rMacroUrl )
      59             : {
      60           0 :     if( (rMacroUrl.getLength() > sUrlPart0.getLength() + sUrlPart1.getLength()) &&
      61           0 :         rMacroUrl.match( sUrlPart0 ) &&
      62           0 :         rMacroUrl.match( sUrlPart1, rMacroUrl.getLength() - sUrlPart1.getLength() ) )
      63             :     {
      64             :         return rMacroUrl.copy( sUrlPart0.getLength(),
      65           0 :             rMacroUrl.getLength() - sUrlPart0.getLength() - sUrlPart1.getLength() );
      66             :     }
      67           0 :     return OUString();
      68             : }
      69             : 
      70           0 : OUString trimMacroName( const OUString& rMacroName )
      71             : {
      72             :     // the name may contain whitespaces and may be enclosed in apostrophs
      73           0 :     OUString aMacroName = rMacroName.trim();
      74           0 :     sal_Int32 nMacroLen = aMacroName.getLength();
      75           0 :     if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') )
      76           0 :         aMacroName = aMacroName.copy( 1, nMacroLen - 2 ).trim();
      77           0 :     return aMacroName;
      78             : }
      79             : 
      80           0 : SfxObjectShell* findShellForUrl( const OUString& sMacroURLOrPath )
      81             : {
      82           0 :     SfxObjectShell* pFoundShell=NULL;
      83           0 :     SfxObjectShell* pShell = SfxObjectShell::GetFirst();
      84           0 :     INetURLObject aObj;
      85           0 :     aObj.SetURL( sMacroURLOrPath );
      86           0 :     bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
      87           0 :     OUString aURL;
      88           0 :     if ( bIsURL )
      89           0 :         aURL = sMacroURLOrPath;
      90             :     else
      91             :     {
      92           0 :         osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL );
      93           0 :         aObj.SetURL( aURL );
      94             :     }
      95             :     OSL_TRACE("Trying to find shell for url %s", OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() );
      96           0 :     while ( pShell )
      97             :     {
      98             : 
      99           0 :         uno::Reference< frame::XModel > xModel = pShell->GetModel();
     100             :         // are we searching for a template? if so we have to cater for the
     101             :         // fact that in openoffice a document opened from a template is always
     102             :         // a new document :/
     103           0 :         if ( xModel.is() )
     104             :         {
     105             :             OSL_TRACE("shell 0x%x has model with url %s and we look for %s", pShell
     106             :                 , OUStringToOString( xModel->getURL(), RTL_TEXTENCODING_UTF8 ).getStr()
     107             :                 , OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr()
     108             :             );
     109           0 :             OUString aName = xModel->getURL() ;
     110           0 :             if (aName.isEmpty())
     111             :                 {
     112             : 
     113           0 :                     const static OUString sTitle( "Title" );
     114           0 :                     uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW );
     115           0 :                     uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW );
     116           0 :                     xProps->getPropertyValue(sTitle) >>= aName;
     117           0 :                     sal_Int32 pos = 0;
     118           0 :                     aName = aName.getToken(0,'-',pos);
     119           0 :                     aName = aName.trim();
     120           0 :                     if( sMacroURLOrPath.lastIndexOf( aName ) >= 0 )
     121             :                     {
     122           0 :                         pFoundShell = pShell;
     123             :                         break;
     124           0 :                     }
     125             :                 }
     126             : 
     127           0 :             if ( sMacroURLOrPath.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) )
     128             :             {
     129             :                 uno::Reference<document::XDocumentPropertiesSupplier> const
     130           0 :                     xDocPropSupp(xModel, uno::UNO_QUERY);
     131           0 :                 if (xDocPropSupp.is())
     132             :                 {
     133             :                     uno::Reference< document::XDocumentProperties > const
     134           0 :                         xDocProps(xDocPropSupp->getDocumentProperties(),
     135           0 :                                     uno::UNO_QUERY_THROW);
     136           0 :                     OUString sCurrName = xDocProps->getTemplateName();
     137           0 :                     if( sMacroURLOrPath.lastIndexOf( sCurrName ) >= 0 )
     138             :                     {
     139           0 :                         pFoundShell = pShell;
     140             :                         break;
     141           0 :                     }
     142           0 :                 }
     143             :             }
     144             :             else
     145             :             {
     146             :                 // sometimes just the name of the document ( without the path
     147             :                 // is used
     148           0 :                 bool bDocNameNoPathMatch = false;
     149           0 :                 if ( !aURL.isEmpty() && aURL.indexOf( '/' ) == -1 )
     150             :                 {
     151           0 :                     sal_Int32 lastSlashIndex = xModel->getURL().lastIndexOf( '/' );
     152           0 :                     if ( lastSlashIndex > -1 )
     153             :                     {
     154           0 :                         bDocNameNoPathMatch = xModel->getURL().copy( lastSlashIndex + 1 ).equals( aURL );
     155           0 :                         if ( !bDocNameNoPathMatch )
     156             :                         {
     157           0 :                             OUString aTmpName = "'" + xModel->getURL().copy( lastSlashIndex + 1 ) + "'";
     158           0 :                             bDocNameNoPathMatch = aTmpName.equals( aURL );
     159             :                         }
     160             :                     }
     161             :                 }
     162             : 
     163           0 :                 if ( aURL.equals( xModel->getURL() ) || bDocNameNoPathMatch )
     164             :                 {
     165           0 :                     pFoundShell = pShell;
     166             :                     break;
     167             :                 }
     168           0 :             }
     169             :         }
     170           0 :         pShell = SfxObjectShell::GetNext( *pShell );
     171           0 :     }
     172           0 :     return pFoundShell;
     173             : }
     174             : 
     175             : // sMod can be empty ( but we really need the library to search in )
     176             : // if sMod is empty and a macro is found then sMod is updated
     177             : // if sMod is empty, only standard modules will be searched (no class, document, form modules)
     178           0 : bool hasMacro( SfxObjectShell* pShell, const OUString& sLibrary, OUString& sMod, const OUString& sMacro )
     179             : {
     180           0 :     bool bFound = false;
     181             : 
     182             : #ifdef DISABLE_SCRIPTING
     183             :     (void) pShell;
     184             :     (void) sLibrary;
     185             :     (void) sMod;
     186             :     (void) sMacro;
     187             : #else
     188           0 :     if ( !sLibrary.isEmpty() && !sMacro.isEmpty() )
     189             :     {
     190             :         OSL_TRACE("** Searching for %s.%s in library %s"
     191             :             ,OUStringToOString( sMod, RTL_TEXTENCODING_UTF8 ).getStr()
     192             :             ,OUStringToOString( sMacro, RTL_TEXTENCODING_UTF8 ).getStr()
     193             :             ,OUStringToOString( sLibrary, RTL_TEXTENCODING_UTF8 ).getStr() );
     194           0 :         BasicManager* pBasicMgr = pShell-> GetBasicManager();
     195           0 :         if ( pBasicMgr )
     196             :         {
     197           0 :             StarBASIC* pBasic = pBasicMgr->GetLib( sLibrary );
     198           0 :             if ( !pBasic )
     199             :             {
     200           0 :                 sal_uInt16 nId = pBasicMgr->GetLibId( sLibrary );
     201           0 :                 pBasicMgr->LoadLib( nId );
     202           0 :                 pBasic = pBasicMgr->GetLib( sLibrary );
     203             :             }
     204           0 :             if ( pBasic )
     205             :             {
     206           0 :                 if ( !sMod.isEmpty() ) // we wish to find the macro is a specific module
     207             :                 {
     208           0 :                     SbModule* pModule = pBasic->FindModule( sMod );
     209           0 :                     if ( pModule )
     210             :                     {
     211           0 :                         SbxArray* pMethods = pModule->GetMethods();
     212           0 :                         if ( pMethods )
     213             :                         {
     214           0 :                             SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( sMacro, SbxCLASS_METHOD ) );
     215           0 :                             if ( pMethod )
     216           0 :                               bFound = true;
     217             :                         }
     218             :                     }
     219             :                 }
     220           0 :                 else if( SbMethod* pMethod = dynamic_cast< SbMethod* >( pBasic->Find( sMacro, SbxCLASS_METHOD ) ) )
     221             :                 {
     222           0 :                     if( SbModule* pModule = pMethod->GetModule() )
     223             :                     {
     224             :                         // when searching for a macro without module name, do not search in class/document/form modules
     225           0 :                         if( pModule->GetModuleType() == script::ModuleType::NORMAL )
     226             :                         {
     227           0 :                             sMod = pModule->GetName();
     228           0 :                             bFound = true;
     229             :                         }
     230             :                     }
     231             :                 }
     232             :             }
     233             :         }
     234             :     }
     235             : #endif
     236           0 :     return bFound;
     237             : }
     238             : 
     239           0 : OUString getDefaultProjectName( SfxObjectShell* pShell )
     240             : {
     241           0 :     OUString aPrjName;
     242           0 :     if( BasicManager* pBasicMgr = pShell ? pShell->GetBasicManager() : 0 )
     243             :     {
     244           0 :         aPrjName = pBasicMgr->GetName();
     245           0 :         if( aPrjName.isEmpty() )
     246           0 :             aPrjName = "Standard";
     247             :     }
     248           0 :     return aPrjName;
     249             : }
     250             : 
     251           0 : void parseMacro( const OUString& sMacro, OUString& sContainer, OUString& sModule, OUString& sProcedure )
     252             : {
     253           0 :     sal_Int32 nMacroDot = sMacro.lastIndexOf( '.' );
     254             : 
     255           0 :     if ( nMacroDot != -1 )
     256             :     {
     257           0 :         sProcedure = sMacro.copy( nMacroDot + 1 );
     258             : 
     259           0 :         sal_Int32 nContainerDot = sMacro.lastIndexOf( '.',  nMacroDot - 1 );
     260           0 :         if ( nContainerDot != -1 )
     261             :         {
     262           0 :             sModule = sMacro.copy( nContainerDot + 1, nMacroDot - nContainerDot - 1 );
     263           0 :             sContainer = sMacro.copy( 0, nContainerDot );
     264             :         }
     265             :         else
     266           0 :             sModule = sMacro.copy( 0, nMacroDot );
     267             :     }
     268             :     else
     269           0 :        sProcedure = sMacro;
     270           0 : }
     271             : 
     272           0 : OUString resolveVBAMacro( SfxObjectShell* pShell, const OUString& rLibName, const OUString& rModuleName, const OUString& rMacroName )
     273             : {
     274             : #ifdef DISABLE_SCRIPTING
     275             :     (void) pShell;
     276             :     (void) rLibName;
     277             :     (void) rModuleName;
     278             :     (void) rMacroName;
     279             : #else
     280           0 :     if( pShell )
     281             :     {
     282           0 :         OUString aLibName = rLibName.isEmpty() ?  getDefaultProjectName( pShell ) : rLibName ;
     283           0 :         OUString aModuleName = rModuleName;
     284           0 :         if( hasMacro( pShell, aLibName, aModuleName, rMacroName ) )
     285           0 :             return OUStringBuffer( aLibName ).append( sal_Unicode( '.' ) ).append( aModuleName ).append( sal_Unicode( '.' ) ).append( rMacroName ).makeStringAndClear();
     286             :     }
     287             : #endif
     288           0 :     return OUString();
     289             : }
     290             : 
     291           0 : MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const OUString& MacroName, bool bSearchGlobalTemplates )
     292             : {
     293             : #ifdef DISABLE_SCRIPTING
     294             :     (void) pShell;
     295             :     (void) MacroName;
     296             :     (void) bSearchGlobalTemplates;
     297             : 
     298             :     return MacroResolvedInfo();
     299             : #else
     300           0 :     if( !pShell )
     301           0 :         return MacroResolvedInfo();
     302             : 
     303             :     // the name may be enclosed in apostrophs
     304           0 :     OUString aMacroName = trimMacroName( MacroName );
     305             : 
     306             :     // parse the macro name
     307           0 :     sal_Int32 nDocSepIndex = aMacroName.indexOf( '!' );
     308           0 :     if( nDocSepIndex > 0 )
     309             :     {
     310             :         // macro specified by document name
     311             :         // find document shell for document name and call ourselves
     312             :         // recursively
     313             : 
     314             :         // assume for now that the document name is *this* document
     315           0 :         OUString sDocUrlOrPath = aMacroName.copy( 0, nDocSepIndex );
     316           0 :         aMacroName = aMacroName.copy( nDocSepIndex + 1 );
     317             :         OSL_TRACE("doc search, current shell is 0x%x", pShell );
     318           0 :         SfxObjectShell* pFoundShell = 0;
     319           0 :         if( bSearchGlobalTemplates )
     320             :         {
     321           0 :             SvtPathOptions aPathOpt;
     322           0 :             OUString aAddinPath = aPathOpt.GetAddinPath();
     323           0 :             if( OUString( sDocUrlOrPath ).indexOf( aAddinPath ) == 0 )
     324           0 :                 pFoundShell = pShell;
     325             :         }
     326           0 :         if( !pFoundShell )
     327           0 :             pFoundShell = findShellForUrl( sDocUrlOrPath );
     328             :         OSL_TRACE("doc search, after find, found shell is 0x%x", pFoundShell );
     329           0 :         return resolveVBAMacro( pFoundShell, aMacroName );
     330             :     }
     331             : 
     332             :     // macro is contained in 'this' document ( or code imported from a template
     333             :     // where that template is a global template or perhaps the template this
     334             :     // document is created from )
     335             : 
     336           0 :     MacroResolvedInfo aRes( pShell );
     337             : 
     338             :     // macro format = Container.Module.Procedure
     339           0 :     OUString sContainer, sModule, sProcedure;
     340           0 :     parseMacro( aMacroName, sContainer, sModule, sProcedure );
     341             : 
     342             : #if 0
     343             :     // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
     344             :     // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
     345             :     uno::Reference< container::XNameContainer > xPrjNameCache;
     346             :     uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
     347             :     if ( xSF.is() ) try
     348             :     {
     349             :         xPrjNameCache.set( xSF->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY );
     350             :     }
     351             :     catch( const uno::Exception& )    // createInstance may throw
     352             :     {
     353             :     }
     354             : #endif
     355             : 
     356           0 :     std::vector< OUString > sSearchList;
     357             : 
     358           0 :     if ( !sContainer.isEmpty() )
     359             :     {
     360             : // service VBAProjectNameProvider not implemented
     361             : #if 0
     362             :         // get the Project associated with the Container
     363             :         if ( xPrjNameCache.is() )
     364             :         {
     365             :             if ( xPrjNameCache->hasByName( sContainer ) )
     366             :             {
     367             :                 OUString sProject;
     368             :                 xPrjNameCache->getByName( sContainer ) >>= sProject;
     369             :                 sContainer = sProject;
     370             :             }
     371             :         }
     372             : #endif
     373           0 :         sSearchList.push_back( sContainer ); // First Lib to search
     374             :     }
     375             :     else
     376             :     {
     377             :         // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
     378             :         // get the name of Project/Library for 'this' document
     379           0 :             OUString sThisProject( "Standard" );
     380             :             try
     381             :             {
     382           0 :                 uno::Reference< beans::XPropertySet > xProps( pShell->GetModel(), uno::UNO_QUERY_THROW );
     383           0 :                 uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProps->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW );
     384           0 :                 sThisProject = xVBAMode->getProjectName();
     385             :             }
     386           0 :             catch( const uno::Exception& /*e*/) {}
     387             : 
     388           0 :         sSearchList.push_back( sThisProject ); // First Lib to search
     389             : 
     390             : // service VBAProjectNameProvider not implemented
     391             : #if 0
     392             :         if ( xPrjNameCache.is() )
     393             :         {
     394             :             // is this document created from a template?
     395             :             uno::Reference< document::XDocumentPropertiesSupplier > const
     396             :                 xDocPropSupp(pShell->GetModel(), uno::UNO_QUERY_THROW);
     397             :             uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
     398             : 
     399             :             OUString sCreatedFrom = xDocProps->getTemplateURL();
     400             :             if ( !sCreatedFrom.isEmpty() )
     401             :             {
     402             :                 INetURLObject aObj;
     403             :                 aObj.SetURL( sCreatedFrom );
     404             :                 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
     405             :                 OUString aURL;
     406             :                 if ( bIsURL )
     407             :                     aURL = sCreatedFrom;
     408             :                 else
     409             :                 {
     410             :                     osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL );
     411             :                     aObj.SetURL( aURL );
     412             :                 }
     413             :                 sCreatedFrom =  aObj.GetLastName();
     414             :             }
     415             : 
     416             :             sal_Int32 nIndex =  sCreatedFrom.lastIndexOf( '.' );
     417             :             if ( nIndex != -1 )
     418             :                 sCreatedFrom = sCreatedFrom.copy( 0, nIndex );
     419             : 
     420             :             OUString sPrj;
     421             :             if ( !sCreatedFrom.isEmpty() && xPrjNameCache->hasByName( sCreatedFrom ) )
     422             :             {
     423             :                 xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
     424             :                 // Make sure we don't double up with this project
     425             :                 if ( !sPrj.equals( sThisProject ) )
     426             :                     sSearchList.push_back( sPrj );
     427             :             }
     428             : 
     429             :             // get list of global template Names
     430             :             uno::Sequence< OUString > sTemplateNames = xPrjNameCache->getElementNames();
     431             :             sal_Int32 nLen = sTemplateNames.getLength();
     432             :             for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index )
     433             :             {
     434             : 
     435             :                 if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) )
     436             :                 {
     437             :                     if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) )
     438             :                     {
     439             :                         xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj;
     440             :                         // Make sure we don't double up with this project
     441             :                         if ( !sPrj.equals( sThisProject ) )
     442             :                             sSearchList.push_back( sPrj );
     443             :                     }
     444             :                 }
     445             : 
     446             :             }
     447             :         }
     448             : #endif
     449             :     }
     450             : 
     451           0 :     std::vector< OUString >::iterator it_end = sSearchList.end();
     452           0 :     for ( std::vector< OUString >::iterator it = sSearchList.begin(); !aRes.mbFound && (it != it_end); ++it )
     453             :     {
     454           0 :         aRes.mbFound = hasMacro( pShell, *it, sModule, sProcedure );
     455           0 :         if ( aRes.mbFound )
     456           0 :             sContainer = *it;
     457             :     }
     458             :     //aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
     459           0 :     aRes.msResolvedMacro = sContainer + "." + sModule + "." + sProcedure;
     460             : 
     461           0 :     return aRes;
     462             : #endif
     463             : }
     464             : 
     465             : // Treat the args as possible inouts ( convertion at bottom of method )
     466           0 : sal_Bool executeMacro( SfxObjectShell* pShell, const OUString& sMacroName, uno::Sequence< uno::Any >& aArgs, uno::Any& aRet, const uno::Any& /*aCaller*/)
     467             : {
     468             : #ifdef DISABLE_SCRIPTING
     469             :     (void) pShell;
     470             :     (void) sMacroName;
     471             :     (void) aArgs;
     472             :     (void) aRet;
     473             : 
     474             :     return sal_False;
     475             : #else
     476           0 :     sal_Bool bRes = sal_False;
     477           0 :     if ( !pShell )
     478           0 :         return bRes;
     479           0 :     OUString sUrl = makeMacroURL( sMacroName );
     480             : 
     481           0 :     uno::Sequence< sal_Int16 > aOutArgsIndex;
     482           0 :     uno::Sequence< uno::Any > aOutArgs;
     483             : 
     484             :     try
     485           0 :     {   ErrCode nErr( ERRCODE_BASIC_INTERNAL_ERROR );
     486           0 :         if ( pShell )
     487             :         {
     488             :             nErr = pShell->CallXScript( sUrl,
     489           0 :                                aArgs, aRet, aOutArgsIndex, aOutArgs, false );
     490           0 :             sal_Int32 nLen = aOutArgs.getLength();
     491             :             // convert any out params to seem like they were inouts
     492           0 :             if ( nLen )
     493             :             {
     494           0 :                 for ( sal_Int32 index=0; index < nLen; ++index )
     495             :                 {
     496           0 :                     sal_Int32 nOutIndex = aOutArgsIndex[ index ];
     497           0 :                     aArgs[ nOutIndex ] = aOutArgs[ index ];
     498             :                 }
     499             :             }
     500             :         }
     501           0 :         bRes = ( nErr == ERRCODE_NONE );
     502             :     }
     503           0 :     catch ( const uno::Exception& )
     504             :     {
     505           0 :        bRes = sal_False;
     506             :     }
     507           0 :     return bRes;
     508             : #endif
     509             : }
     510             : 
     511             : // ============================================================================
     512             : 
     513           0 : uno::Sequence< OUString > VBAMacroResolver_getSupportedServiceNames()
     514             : {
     515           0 :     uno::Sequence< OUString > aServiceNames( 1 );
     516           0 :     aServiceNames[ 0 ] = "com.sun.star.script.vba.VBAMacroResolver";
     517           0 :     return aServiceNames;
     518             : }
     519             : 
     520           0 : OUString VBAMacroResolver_getImplementationName()
     521             : {
     522           0 :     return OUString( "com.sun.star.comp.vba.VBAMacroResolver" );
     523             : }
     524             : 
     525           0 : uno::Reference< uno::XInterface > SAL_CALL VBAMacroResolver_createInstance( const uno::Reference< uno::XComponentContext >& ) throw (uno::Exception)
     526             : {
     527           0 :     return static_cast< ::cppu::OWeakObject* >( new VBAMacroResolver );
     528             : }
     529             : 
     530             : // ============================================================================
     531             : 
     532           0 : VBAMacroResolver::VBAMacroResolver() :
     533           0 :     mpObjShell( 0 )
     534             : {
     535           0 : }
     536             : 
     537           0 : VBAMacroResolver::~VBAMacroResolver()
     538             : {
     539           0 : }
     540             : 
     541             : // com.sun.star.lang.XServiceInfo interface -----------------------------------
     542             : 
     543           0 : OUString SAL_CALL VBAMacroResolver::getImplementationName() throw (uno::RuntimeException)
     544             : {
     545           0 :     return VBAMacroResolver_getImplementationName();
     546             : }
     547             : 
     548           0 : sal_Bool SAL_CALL VBAMacroResolver::supportsService( const OUString& rService ) throw (uno::RuntimeException)
     549             : {
     550           0 :     uno::Sequence< OUString > aServices = VBAMacroResolver_getSupportedServiceNames();
     551           0 :     const OUString* pArray = aServices.getConstArray();
     552           0 :     const OUString* pArrayEnd = pArray + aServices.getLength();
     553           0 :     return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd;
     554             : }
     555             : 
     556           0 : uno::Sequence< OUString > SAL_CALL VBAMacroResolver::getSupportedServiceNames() throw (uno::RuntimeException)
     557             : {
     558           0 :     return VBAMacroResolver_getSupportedServiceNames();
     559             : }
     560             : 
     561             : // com.sun.star.lang.XInitialization interface --------------------------------
     562             : 
     563           0 : void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rArgs ) throw (uno::Exception, uno::RuntimeException)
     564             : {
     565             :     OSL_ENSURE( rArgs.getLength() < 2, "VBAMacroResolver::initialize - missing arguments" );
     566           0 :     if( rArgs.getLength() < 2 )
     567           0 :         throw uno::RuntimeException();
     568             : 
     569             :     // first argument: document model
     570           0 :     mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW );
     571           0 :     uno::Reference< lang::XUnoTunnel > xUnoTunnel( mxModel, uno::UNO_QUERY_THROW );
     572           0 :     mpObjShell = reinterpret_cast< SfxObjectShell* >( xUnoTunnel->getSomething( SfxObjectShell::getUnoTunnelId() ) );
     573           0 :     if( !mpObjShell )
     574           0 :         throw uno::RuntimeException();
     575             : 
     576             :     // second argument: VBA project name
     577           0 :     if( !(rArgs[ 1 ] >>= maProjectName) || (maProjectName.isEmpty()) )
     578           0 :         throw uno::RuntimeException();
     579           0 : }
     580             : 
     581             : // com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
     582             : 
     583           0 : OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const OUString& rVBAMacroName ) throw (lang::IllegalArgumentException, uno::RuntimeException)
     584             : {
     585           0 :     if( !mpObjShell )
     586           0 :         throw uno::RuntimeException();
     587             : 
     588             :     // the name may be enclosed in apostrophs
     589           0 :     OUString aMacroName = trimMacroName( rVBAMacroName );
     590           0 :     if( aMacroName.isEmpty() )
     591           0 :         throw lang::IllegalArgumentException();
     592             : 
     593             :     // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
     594           0 :     if( (aMacroName[ 0 ] == '[') || (aMacroName.indexOf( '!' ) >= 0) )
     595           0 :         throw lang::IllegalArgumentException();
     596             : 
     597             :     // check if macro name starts with project name, replace with "Standard"
     598             :     // TODO: adjust this when custom VBA project name is supported
     599           0 :     sal_Int32 nDotPos = aMacroName.indexOf( '.' );
     600           0 :     if( (nDotPos == 0) || (nDotPos + 1 == aMacroName.getLength()) )
     601           0 :         throw lang::IllegalArgumentException();
     602           0 :     if( (nDotPos > 0) && aMacroName.matchIgnoreAsciiCase( maProjectName ) )
     603           0 :         aMacroName = aMacroName.copy( nDotPos + 1 );
     604             : 
     605             :     // try to find the macro
     606           0 :     MacroResolvedInfo aInfo = resolveVBAMacro( mpObjShell, aMacroName, false );
     607           0 :     if( !aInfo.mbFound )
     608           0 :         throw lang::IllegalArgumentException();
     609             : 
     610             :     // build and return the script URL
     611           0 :     return makeMacroURL( aInfo.msResolvedMacro );
     612             : }
     613             : 
     614           0 : OUString SAL_CALL VBAMacroResolver::resolveScriptURLtoVBAMacro( const OUString& /*rScriptURL*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
     615             : {
     616             :     OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
     617           0 :     throw uno::RuntimeException();
     618             : }
     619             : 
     620           0 : bool getModifier( char c, sal_uInt16& mod )
     621             : {
     622             :     static const char modifiers[] = "+^%";
     623             :     static const sal_uInt16 KEY_MODS[] = {KEY_SHIFT, KEY_MOD1, KEY_MOD2};
     624             : 
     625           0 :     for ( unsigned int i=0; i<SAL_N_ELEMENTS(modifiers); ++i )
     626             :     {
     627           0 :         if ( c == modifiers[i] )
     628             :         {
     629           0 :             mod = mod | KEY_MODS[ i ];
     630           0 :             return true;
     631             :         }
     632             :     }
     633           0 :     return false;
     634             : }
     635             : 
     636             : typedef std::map< OUString, sal_uInt16 > MSKeyCodeMap;
     637             : 
     638           0 : sal_uInt16 parseChar( char c ) throw ( uno::RuntimeException )
     639             : {
     640           0 :     sal_uInt16 nVclKey = 0;
     641             :     // do we care about locale here for isupper etc. ? probably not
     642           0 :     if ( isalpha( c ) )
     643             :     {
     644           0 :         nVclKey |= ( toupper( c ) - 'A' ) + KEY_A;
     645           0 :         if ( isupper( c ) )
     646           0 :             nVclKey |= KEY_SHIFT;
     647             :     }
     648           0 :     else if ( isdigit( c ) )
     649           0 :         nVclKey |= ( c  - '0' ) + KEY_0;
     650           0 :     else if ( c == '~' ) // special case
     651           0 :         nVclKey = KEY_RETURN;
     652           0 :     else if ( c == ' ' ) // special case
     653           0 :         nVclKey = KEY_SPACE;
     654             :     else // I guess we have a problem ( but not sure if locale specific keys might come into play here )
     655           0 :         throw uno::RuntimeException();
     656           0 :     return nVclKey;
     657             : }
     658             : 
     659             : struct KeyCodeEntry
     660             : {
     661             :    const char* sName;
     662             :    sal_uInt16 nCode;
     663             : };
     664             : 
     665             : KeyCodeEntry aMSKeyCodesData[] = {
     666             :     { "BACKSPACE", KEY_BACKSPACE },
     667             :     { "BS", KEY_BACKSPACE },
     668             :     { "DELETE", KEY_DELETE },
     669             :     { "DEL", KEY_DELETE },
     670             :     { "DOWN", KEY_DOWN },
     671             :     { "UP", KEY_UP },
     672             :     { "LEFT", KEY_LEFT },
     673             :     { "RIGHT", KEY_RIGHT },
     674             :     { "END", KEY_END },
     675             :     { "ESCAPE", KEY_ESCAPE },
     676             :     { "ESC", KEY_ESCAPE },
     677             :     { "HELP", KEY_HELP },
     678             :     { "HOME", KEY_HOME },
     679             :     { "PGDN", KEY_PAGEDOWN },
     680             :     { "PGUP", KEY_PAGEUP },
     681             :     { "INSERT", KEY_INSERT },
     682             :     { "SCROLLLOCK", KEY_SCROLLLOCK },
     683             :     { "NUMLOCK", KEY_NUMLOCK },
     684             :     { "TAB", KEY_TAB },
     685             :     { "F1", KEY_F1 },
     686             :     { "F2", KEY_F2 },
     687             :     { "F3", KEY_F3 },
     688             :     { "F4", KEY_F4 },
     689             :     { "F5", KEY_F5 },
     690             :     { "F6", KEY_F6 },
     691             :     { "F7", KEY_F7 },
     692             :     { "F8", KEY_F8 },
     693             :     { "F9", KEY_F1 },
     694             :     { "F10", KEY_F10 },
     695             :     { "F11", KEY_F11 },
     696             :     { "F12", KEY_F12 },
     697             :     { "F13", KEY_F13 },
     698             :     { "F14", KEY_F14 },
     699             :     { "F15", KEY_F15 },
     700             : };
     701             : 
     702           0 : awt::KeyEvent parseKeyEvent( const OUString& Key ) throw ( uno::RuntimeException )
     703             : {
     704           0 :     static MSKeyCodeMap msKeyCodes;
     705           0 :     if ( msKeyCodes.empty() )
     706             :     {
     707           0 :         for ( unsigned int i = 0; i < SAL_N_ELEMENTS( aMSKeyCodesData ); ++i )
     708             :         {
     709           0 :             msKeyCodes[ OUString::createFromAscii( aMSKeyCodesData[ i ].sName ) ] = aMSKeyCodesData[ i ].nCode;
     710             :         }
     711             :     }
     712           0 :     OUString sKeyCode;
     713           0 :     sal_uInt16 nVclKey = 0;
     714             : 
     715             :     // parse the modifier if any
     716           0 :     for ( int i=0; i<Key.getLength(); ++i )
     717             :     {
     718           0 :         if ( ! getModifier( Key[ i ], nVclKey ) )
     719             :         {
     720           0 :             sKeyCode = Key.copy( i );
     721           0 :             break;
     722             :         }
     723             :     }
     724             : 
     725             :     // check if keycode is surrounded by '{}', if so scoop out the contents
     726             :     // else it should be just one char of ( 'a-z,A-Z,0-9' )
     727           0 :     if ( sKeyCode.getLength() == 1 ) // ( a single char )
     728             :     {
     729           0 :         char c = (char)( sKeyCode[ 0 ] );
     730           0 :         nVclKey |= parseChar( c );
     731             :     }
     732             :     else // key should be enclosed in '{}'
     733             :     {
     734           0 :         if ( sKeyCode.getLength() < 3 ||  !( sKeyCode[0] == '{' && sKeyCode[sKeyCode.getLength() - 1 ] == '}' ) )
     735           0 :             throw uno::RuntimeException();
     736             : 
     737           0 :         sKeyCode = sKeyCode.copy(1, sKeyCode.getLength() - 2 );
     738             : 
     739           0 :         if ( sKeyCode.getLength() == 1 )
     740           0 :             nVclKey |= parseChar( (char)( sKeyCode[ 0 ] ) );
     741             :         else
     742             :         {
     743           0 :             MSKeyCodeMap::iterator it = msKeyCodes.find( sKeyCode );
     744           0 :             if ( it == msKeyCodes.end() ) // unknown or unsupported
     745           0 :                 throw uno::RuntimeException();
     746           0 :             nVclKey |= it->second;
     747             :         }
     748             :     }
     749             : 
     750           0 :     awt::KeyEvent aKeyEvent = svt::AcceleratorExecute::st_VCLKey2AWTKey( KeyCode( nVclKey ) );
     751           0 :     return aKeyEvent;
     752             : }
     753             : 
     754           0 : void applyShortCutKeyBinding ( const uno::Reference< frame::XModel >& rxModel, const awt::KeyEvent& rKeyEvent, const OUString& rMacroName ) throw (uno::RuntimeException)
     755             : {
     756           0 :     OUString MacroName( rMacroName );
     757           0 :     if ( !MacroName.isEmpty() )
     758             :     {
     759           0 :         OUString aMacroName = MacroName.trim();
     760           0 :         if (0 == aMacroName.indexOf('!'))
     761           0 :             MacroName = aMacroName.copy(1).trim();
     762           0 :         SfxObjectShell* pShell = NULL;
     763           0 :         if ( rxModel.is() )
     764             :         {
     765           0 :             uno::Reference< lang::XUnoTunnel >  xObjShellTunnel( rxModel, uno::UNO_QUERY_THROW );
     766           0 :             pShell = reinterpret_cast<SfxObjectShell*>( xObjShellTunnel->getSomething(SfxObjectShell::getUnoTunnelId()));
     767           0 :             if ( !pShell )
     768           0 :                 throw uno::RuntimeException();
     769             :         }
     770           0 :         MacroResolvedInfo aMacroInfo = resolveVBAMacro( pShell, aMacroName );
     771           0 :         if( !aMacroInfo.mbFound )
     772           0 :             throw uno::RuntimeException( "The procedure doesn't exist", uno::Reference< uno::XInterface >() );
     773           0 :        MacroName = aMacroInfo.msResolvedMacro;
     774             :     }
     775           0 :     uno::Reference< ui::XUIConfigurationManagerSupplier > xCfgSupplier(rxModel, uno::UNO_QUERY_THROW);
     776           0 :     uno::Reference< ui::XUIConfigurationManager > xCfgMgr = xCfgSupplier->getUIConfigurationManager();
     777             : 
     778           0 :     uno::Reference< ui::XAcceleratorConfiguration > xAcc( xCfgMgr->getShortCutManager(), uno::UNO_QUERY_THROW );
     779           0 :     if ( MacroName.isEmpty() )
     780             :         // I believe this should really restore the [application] default. Since
     781             :         // afaik we don't actually setup application default bindings on import
     782             :         // we don't even know what the 'default' would be for this key
     783           0 :         xAcc->removeKeyEvent( rKeyEvent );
     784             :     else
     785           0 :         xAcc->setKeyEvent( rKeyEvent, ooo::vba::makeMacroURL( MacroName ) );
     786             : 
     787           0 : }
     788             : // ============================================================================
     789             : 
     790             : } // namespace vba
     791          60 : } // namespace ooo
     792             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
     793             : 

Generated by: LCOV version 1.10