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

Generated by: LCOV version 1.11