1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23 // MARKER(update_precomp.py): autogen include statement, do not remove
24 #include "precompiled_filter.hxx"
25
26 #include <filter/msfilter/msvbahelper.hxx>
27 #include <basic/sbx.hxx>
28 #include <basic/sbstar.hxx>
29 #include <basic/basmgr.hxx>
30 #include <basic/sbmod.hxx>
31 #include <basic/sbmeth.hxx>
32 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
33 #include <com/sun/star/document/XDocumentProperties.hpp>
34 #include <com/sun/star/document/XDocumentInfoSupplier.hpp>
35 #include <com/sun/star/lang/XUnoTunnel.hpp>
36 #include <com/sun/star/script/ModuleType.hpp>
37 #include <tools/urlobj.hxx>
38 #include <osl/file.hxx>
39 #include <unotools/pathoptions.hxx>
40
41 using namespace ::com::sun::star;
42
43 namespace ooo {
44 namespace vba {
45
46 const static rtl::OUString sUrlPart0 = rtl::OUString::createFromAscii( "vnd.sun.star.script:");
47 const static rtl::OUString sUrlPart1 = rtl::OUString::createFromAscii( "?language=Basic&location=document");
48
makeMacroURL(const String & sMacroName)49 String makeMacroURL( const String& sMacroName )
50 {
51 return sUrlPart0.concat( sMacroName ).concat( sUrlPart1 ) ;
52 }
53
extractMacroName(const::rtl::OUString & rMacroUrl)54 ::rtl::OUString extractMacroName( const ::rtl::OUString& rMacroUrl )
55 {
56 if( (rMacroUrl.getLength() > sUrlPart0.getLength() + sUrlPart1.getLength()) &&
57 rMacroUrl.match( sUrlPart0 ) &&
58 rMacroUrl.match( sUrlPart1, rMacroUrl.getLength() - sUrlPart1.getLength() ) )
59 {
60 return rMacroUrl.copy( sUrlPart0.getLength(), rMacroUrl.getLength() - sUrlPart0.getLength() - sUrlPart1.getLength() );
61 }
62 return ::rtl::OUString();
63 }
64
trimMacroName(const::rtl::OUString & rMacroName)65 ::rtl::OUString trimMacroName( const ::rtl::OUString& rMacroName )
66 {
67 // the name may contain whitespaces and may be enclosed in apostrophs
68 ::rtl::OUString aMacroName = rMacroName.trim();
69 sal_Int32 nMacroLen = aMacroName.getLength();
70 if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') )
71 aMacroName = aMacroName.copy( 1, nMacroLen - 2 ).trim();
72 return aMacroName;
73 }
74
findShellForUrl(const rtl::OUString & sMacroURLOrPath)75 SfxObjectShell* findShellForUrl( const rtl::OUString& sMacroURLOrPath )
76 {
77 SfxObjectShell* pFoundShell=NULL;
78 SfxObjectShell* pShell = SfxObjectShell::GetFirst();
79 INetURLObject aObj;
80 aObj.SetURL( sMacroURLOrPath );
81 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
82 rtl::OUString aURL;
83 if ( bIsURL )
84 aURL = sMacroURLOrPath;
85 else
86 {
87 osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL );
88 aObj.SetURL( aURL );
89 }
90 OSL_TRACE("Trying to find shell for url %s", rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() );
91 while ( pShell )
92 {
93
94 uno::Reference< frame::XModel > xModel = pShell->GetModel();
95 // are we searching for a template? if so we have to cater for the
96 // fact that in openoffice a document opened from a template is always
97 // a new document :/
98 if ( xModel.is() )
99 {
100 OSL_TRACE("shell 0x%x has model with url %s and we look for %s", pShell
101 , rtl::OUStringToOString( xModel->getURL(), RTL_TEXTENCODING_UTF8 ).getStr()
102 , rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr()
103 );
104 ::rtl::OUString aName = xModel->getURL() ;
105 if (0 == aName.getLength())
106 {
107
108 const static rtl::OUString sTitle( RTL_CONSTASCII_USTRINGPARAM("Title" ) );
109 uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW );
110 uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW );
111 xProps->getPropertyValue(sTitle) >>= aName;
112 sal_Int32 pos = 0;
113 aName = aName.getToken(0,'-',pos);
114 aName = aName.trim();
115 if( sMacroURLOrPath.lastIndexOf( aName ) >= 0 )
116 {
117 pFoundShell = pShell;
118 break;
119 }
120 }
121
122 if ( sMacroURLOrPath.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) )
123 {
124 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( xModel, uno::UNO_QUERY );
125 if( xDocInfoSupp.is() )
126 {
127 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
128 uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
129 rtl::OUString sCurrName = xDocProps->getTemplateName();
130 if( sMacroURLOrPath.lastIndexOf( sCurrName ) >= 0 )
131 {
132 pFoundShell = pShell;
133 break;
134 }
135 }
136 }
137 else
138 {
139 // sometimes just the name of the document ( without the path
140 // is used
141 bool bDocNameNoPathMatch = false;
142 if ( aURL.getLength() && aURL.indexOf( '/' ) == -1 )
143 {
144 sal_Int32 lastSlashIndex = xModel->getURL().lastIndexOf( '/' );
145 if ( lastSlashIndex > -1 )
146 {
147 bDocNameNoPathMatch = xModel->getURL().copy( lastSlashIndex + 1 ).equals( aURL );
148 if ( !bDocNameNoPathMatch )
149 {
150 rtl::OUString aTmpName = rtl::OUString::createFromAscii("'") + xModel->getURL().copy( lastSlashIndex + 1 ) + rtl::OUString::createFromAscii("'");
151 bDocNameNoPathMatch = aTmpName.equals( aURL );
152 }
153 }
154 }
155
156 if ( aURL.equals( xModel->getURL() ) || bDocNameNoPathMatch )
157 {
158 pFoundShell = pShell;
159 break;
160 }
161 }
162 }
163 pShell = SfxObjectShell::GetNext( *pShell );
164 }
165 return pFoundShell;
166 }
167
168 // sMod can be empty ( but we really need the library to search in )
169 // if sMod is empty and a macro is found then sMod is updated
170 // if sMod is empty, only standard modules will be searched (no class, document, form modules)
hasMacro(SfxObjectShell * pShell,const String & sLibrary,String & sMod,const String & sMacro)171 bool hasMacro( SfxObjectShell* pShell, const String& sLibrary, String& sMod, const String& sMacro )
172 {
173 bool bFound = false;
174 if ( sLibrary.Len() && sMacro.Len() )
175 {
176 OSL_TRACE("** Searching for %s.%s in library %s"
177 ,rtl::OUStringToOString( sMod, RTL_TEXTENCODING_UTF8 ).getStr()
178 ,rtl::OUStringToOString( sMacro, RTL_TEXTENCODING_UTF8 ).getStr()
179 ,rtl::OUStringToOString( sLibrary, RTL_TEXTENCODING_UTF8 ).getStr() );
180 BasicManager* pBasicMgr = pShell-> GetBasicManager();
181 if ( pBasicMgr )
182 {
183 StarBASIC* pBasic = pBasicMgr->GetLib( sLibrary );
184 if ( !pBasic )
185 {
186 sal_uInt16 nId = pBasicMgr->GetLibId( sLibrary );
187 pBasicMgr->LoadLib( nId );
188 pBasic = pBasicMgr->GetLib( sLibrary );
189 }
190 if ( pBasic )
191 {
192 if ( sMod.Len() ) // we wish to find the macro is a specific module
193 {
194 SbModule* pModule = pBasic->FindModule( sMod );
195 if ( pModule )
196 {
197 SbxArray* pMethods = pModule->GetMethods();
198 if ( pMethods )
199 {
200 SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( sMacro, SbxCLASS_METHOD ) );
201 if ( pMethod )
202 bFound = true;
203 }
204 }
205 }
206 else if( SbMethod* pMethod = dynamic_cast< SbMethod* >( pBasic->Find( sMacro, SbxCLASS_METHOD ) ) )
207 {
208 if( SbModule* pModule = pMethod->GetModule() )
209 {
210 // when searching for a macro without module name, do not search in class/document/form modules
211 if( pModule->GetModuleType() == script::ModuleType::NORMAL )
212 {
213 sMod = pModule->GetName();
214 bFound = true;
215 }
216 }
217 }
218 }
219 }
220 }
221 return bFound;
222 }
223
getDefaultProjectName(SfxObjectShell * pShell)224 ::rtl::OUString getDefaultProjectName( SfxObjectShell* pShell )
225 {
226 ::rtl::OUString aPrjName;
227 if( BasicManager* pBasicMgr = pShell ? pShell->GetBasicManager() : 0 )
228 {
229 aPrjName = pBasicMgr->GetName();
230 if( aPrjName.getLength() == 0 )
231 aPrjName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
232 }
233 return aPrjName;
234 }
235
parseMacro(const rtl::OUString & sMacro,String & sContainer,String & sModule,String & sProcedure)236 void parseMacro( const rtl::OUString& sMacro, String& sContainer, String& sModule, String& sProcedure )
237 {
238 sal_Int32 nMacroDot = sMacro.lastIndexOf( '.' );
239
240 if ( nMacroDot != -1 )
241 {
242 sProcedure = sMacro.copy( nMacroDot + 1 );
243
244 sal_Int32 nContainerDot = sMacro.lastIndexOf( '.', nMacroDot - 1 );
245 if ( nContainerDot != -1 )
246 {
247 sModule = sMacro.copy( nContainerDot + 1, nMacroDot - nContainerDot - 1 );
248 sContainer = sMacro.copy( 0, nContainerDot );
249 }
250 else
251 sModule = sMacro.copy( 0, nMacroDot );
252 }
253 else
254 sProcedure = sMacro;
255 }
256
resolveVBAMacro(SfxObjectShell * pShell,const::rtl::OUString & rLibName,const::rtl::OUString & rModuleName,const::rtl::OUString & rMacroName)257 ::rtl::OUString resolveVBAMacro( SfxObjectShell* pShell, const ::rtl::OUString& rLibName, const ::rtl::OUString& rModuleName, const ::rtl::OUString& rMacroName )
258 {
259 if( pShell )
260 {
261 ::rtl::OUString aLibName = (rLibName.getLength() > 0) ? rLibName : getDefaultProjectName( pShell );
262 String aModuleName = rModuleName;
263 if( hasMacro( pShell, aLibName, aModuleName, rMacroName ) )
264 return ::rtl::OUStringBuffer( aLibName ).append( sal_Unicode( '.' ) ).append( aModuleName ).append( sal_Unicode( '.' ) ).append( rMacroName ).makeStringAndClear();
265 }
266 return ::rtl::OUString();
267 }
268
resolveVBAMacro(SfxObjectShell * pShell,const rtl::OUString & MacroName,bool bSearchGlobalTemplates)269 MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUString& MacroName, bool bSearchGlobalTemplates )
270 {
271 if( !pShell )
272 return MacroResolvedInfo();
273
274 // the name may be enclosed in apostrophs
275 ::rtl::OUString aMacroName = trimMacroName( MacroName );
276
277 // parse the macro name
278 sal_Int32 nDocSepIndex = aMacroName.indexOf( '!' );
279 if( nDocSepIndex > 0 )
280 {
281 // macro specified by document name
282 // find document shell for document name and call ourselves
283 // recursively
284
285 // assume for now that the document name is *this* document
286 String sDocUrlOrPath = aMacroName.copy( 0, nDocSepIndex );
287 aMacroName = aMacroName.copy( nDocSepIndex + 1 );
288 OSL_TRACE("doc search, current shell is 0x%x", pShell );
289 SfxObjectShell* pFoundShell = 0;
290 if( bSearchGlobalTemplates )
291 {
292 SvtPathOptions aPathOpt;
293 String aAddinPath = aPathOpt.GetAddinPath();
294 if( rtl::OUString( sDocUrlOrPath ).indexOf( aAddinPath ) == 0 )
295 pFoundShell = pShell;
296 }
297 if( !pFoundShell )
298 pFoundShell = findShellForUrl( sDocUrlOrPath );
299 OSL_TRACE("doc search, after find, found shell is 0x%x", pFoundShell );
300 return resolveVBAMacro( pFoundShell, aMacroName );
301 }
302
303 // macro is contained in 'this' document ( or code imported from a template
304 // where that template is a global template or perhaps the template this
305 // document is created from )
306
307 MacroResolvedInfo aRes( pShell );
308
309 // macro format = Container.Module.Procedure
310 String sContainer, sModule, sProcedure;
311 parseMacro( aMacroName, sContainer, sModule, sProcedure );
312
313 #if 0
314 // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
315 // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
316 uno::Reference< container::XNameContainer > xPrjNameCache;
317 uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
318 if ( xSF.is() ) try
319 {
320 xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
321 }
322 catch( uno::Exception& ) // createInstance may throw
323 {
324 }
325 #endif
326
327 std::vector< rtl::OUString > sSearchList;
328
329 if ( sContainer.Len() > 0 )
330 {
331 // service VBAProjectNameProvider not implemented
332 #if 0
333 // get the Project associated with the Container
334 if ( xPrjNameCache.is() )
335 {
336 if ( xPrjNameCache->hasByName( sContainer ) )
337 {
338 rtl::OUString sProject;
339 xPrjNameCache->getByName( sContainer ) >>= sProject;
340 sContainer = sProject;
341 }
342 }
343 #endif
344 sSearchList.push_back( sContainer ); // First Lib to search
345 }
346 else
347 {
348 // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
349 // get the name of Project/Library for 'this' document
350 rtl::OUString sThisProject = getDefaultProjectName( pShell );
351 sSearchList.push_back( sThisProject ); // First Lib to search
352
353 // service VBAProjectNameProvider not implemented
354 #if 0
355 if ( xPrjNameCache.is() )
356 {
357 // is this document created from a template?
358 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( pShell->GetModel(), uno::UNO_QUERY_THROW );
359 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
360 uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
361
362 rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
363 if ( sCreatedFrom.getLength() )
364 {
365 INetURLObject aObj;
366 aObj.SetURL( sCreatedFrom );
367 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
368 rtl::OUString aURL;
369 if ( bIsURL )
370 aURL = sCreatedFrom;
371 else
372 {
373 osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL );
374 aObj.SetURL( aURL );
375 }
376 sCreatedFrom = aObj.GetLastName();
377 }
378
379 sal_Int32 nIndex = sCreatedFrom.lastIndexOf( '.' );
380 if ( nIndex != -1 )
381 sCreatedFrom = sCreatedFrom.copy( 0, nIndex );
382
383 rtl::OUString sPrj;
384 if ( sCreatedFrom.getLength() && xPrjNameCache->hasByName( sCreatedFrom ) )
385 {
386 xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
387 // Make sure we don't double up with this project
388 if ( !sPrj.equals( sThisProject ) )
389 sSearchList.push_back( sPrj );
390 }
391
392 // get list of global template Names
393 uno::Sequence< rtl::OUString > sTemplateNames = xPrjNameCache->getElementNames();
394 sal_Int32 nLen = sTemplateNames.getLength();
395 for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index )
396 {
397
398 if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) )
399 {
400 if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) )
401 {
402 xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj;
403 // Make sure we don't double up with this project
404 if ( !sPrj.equals( sThisProject ) )
405 sSearchList.push_back( sPrj );
406 }
407 }
408
409 }
410 }
411 #endif
412 }
413
414 std::vector< rtl::OUString >::iterator it_end = sSearchList.end();
415 for ( std::vector< rtl::OUString >::iterator it = sSearchList.begin(); !aRes.mbFound && (it != it_end); ++it )
416 {
417 aRes.mbFound = hasMacro( pShell, *it, sModule, sProcedure );
418 if ( aRes.mbFound )
419 sContainer = *it;
420 }
421 aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
422
423 return aRes;
424 }
425
426 // Treat the args as possible inouts ( conversion at bottom of method )
executeMacro(SfxObjectShell * pShell,const String & sMacroName,uno::Sequence<uno::Any> & aArgs,uno::Any & aRet,const uno::Any &)427 sal_Bool executeMacro( SfxObjectShell* pShell, const String& sMacroName, uno::Sequence< uno::Any >& aArgs, uno::Any& aRet, const uno::Any& /*aCaller*/)
428 {
429 sal_Bool bRes = sal_False;
430 if ( !pShell )
431 return bRes;
432 rtl::OUString sUrl = makeMacroURL( sMacroName );
433
434 uno::Sequence< sal_Int16 > aOutArgsIndex;
435 uno::Sequence< uno::Any > aOutArgs;
436
437 try
438 { ErrCode nErr( ERRCODE_BASIC_INTERNAL_ERROR );
439 if ( pShell )
440 {
441 nErr = pShell->CallXScript( sUrl,
442 aArgs, aRet, aOutArgsIndex, aOutArgs, ::rtl::OUString(), false );
443 sal_Int32 nLen = aOutArgs.getLength();
444 // convert any out params to seem like they were inouts
445 if ( nLen )
446 {
447 for ( sal_Int32 index=0; index < nLen; ++index )
448 {
449 sal_Int32 nOutIndex = aOutArgsIndex[ index ];
450 aArgs[ nOutIndex ] = aOutArgs[ index ];
451 }
452 }
453 }
454 bRes = ( nErr == ERRCODE_NONE );
455 }
456 catch ( uno::Exception& )
457 {
458 bRes = sal_False;
459 }
460 return bRes;
461 }
462
463 // ============================================================================
464
VBAMacroResolver_getSupportedServiceNames()465 uno::Sequence< ::rtl::OUString > VBAMacroResolver_getSupportedServiceNames()
466 {
467 uno::Sequence< ::rtl::OUString > aServiceNames( 1 );
468 aServiceNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.vba.VBAMacroResolver" ) );
469 return aServiceNames;
470 }
471
VBAMacroResolver_getImplementationName()472 ::rtl::OUString VBAMacroResolver_getImplementationName()
473 {
474 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.vba.VBAMacroResolver" ) );
475 }
476
VBAMacroResolver_createInstance(const uno::Reference<uno::XComponentContext> &)477 uno::Reference< uno::XInterface > SAL_CALL VBAMacroResolver_createInstance( const uno::Reference< uno::XComponentContext >& ) throw (uno::Exception)
478 {
479 return static_cast< ::cppu::OWeakObject* >( new VBAMacroResolver );
480 }
481
482 // ============================================================================
483
VBAMacroResolver()484 VBAMacroResolver::VBAMacroResolver() :
485 mpObjShell( 0 )
486 {
487 }
488
~VBAMacroResolver()489 VBAMacroResolver::~VBAMacroResolver()
490 {
491 }
492
493 // com.sun.star.lang.XServiceInfo interface -----------------------------------
494
getImplementationName()495 ::rtl::OUString SAL_CALL VBAMacroResolver::getImplementationName() throw (uno::RuntimeException)
496 {
497 return VBAMacroResolver_getImplementationName();
498 }
499
supportsService(const::rtl::OUString & rService)500 sal_Bool SAL_CALL VBAMacroResolver::supportsService( const ::rtl::OUString& rService ) throw (uno::RuntimeException)
501 {
502 uno::Sequence< ::rtl::OUString > aServices = VBAMacroResolver_getSupportedServiceNames();
503 const ::rtl::OUString* pArray = aServices.getConstArray();
504 const ::rtl::OUString* pArrayEnd = pArray + aServices.getLength();
505 return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd;
506 }
507
getSupportedServiceNames()508 uno::Sequence< ::rtl::OUString > SAL_CALL VBAMacroResolver::getSupportedServiceNames() throw (uno::RuntimeException)
509 {
510 return VBAMacroResolver_getSupportedServiceNames();
511 }
512
513 // com.sun.star.lang.XInitialization interface --------------------------------
514
initialize(const uno::Sequence<uno::Any> & rArgs)515 void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rArgs ) throw (uno::Exception, uno::RuntimeException)
516 {
517 OSL_ENSURE( rArgs.getLength() < 2, "VBAMacroResolver::initialize - missing arguments" );
518 if( rArgs.getLength() < 2 )
519 throw uno::RuntimeException();
520
521 // first argument: document model
522 mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW );
523 uno::Reference< lang::XUnoTunnel > xUnoTunnel( mxModel, uno::UNO_QUERY_THROW );
524 mpObjShell = reinterpret_cast< SfxObjectShell* >( xUnoTunnel->getSomething( SfxObjectShell::getUnoTunnelId() ) );
525 if( !mpObjShell )
526 throw uno::RuntimeException();
527
528 // second argument: VBA project name
529 if( !(rArgs[ 1 ] >>= maProjectName) || (maProjectName.getLength() == 0) )
530 throw uno::RuntimeException();
531 }
532
533 // com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
534
resolveVBAMacroToScriptURL(const::rtl::OUString & rVBAMacroName)535 ::rtl::OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const ::rtl::OUString& rVBAMacroName ) throw (lang::IllegalArgumentException, uno::RuntimeException)
536 {
537 if( !mpObjShell )
538 throw uno::RuntimeException();
539
540 // the name may be enclosed in apostrophs
541 ::rtl::OUString aMacroName = trimMacroName( rVBAMacroName );
542 if( aMacroName.getLength() == 0 )
543 throw lang::IllegalArgumentException();
544
545 // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
546 if( (aMacroName[ 0 ] == '[') || (aMacroName.indexOf( '!' ) >= 0) )
547 throw lang::IllegalArgumentException();
548
549 // check if macro name starts with project name, replace with "Standard"
550 // TODO: adjust this when custom VBA project name is supported
551 sal_Int32 nDotPos = aMacroName.indexOf( '.' );
552 if( (nDotPos == 0) || (nDotPos + 1 == aMacroName.getLength()) )
553 throw lang::IllegalArgumentException();
554 if( (nDotPos > 0) && aMacroName.matchIgnoreAsciiCase( maProjectName ) )
555 aMacroName = aMacroName.copy( nDotPos + 1 );
556
557 // try to find the macro
558 MacroResolvedInfo aInfo = resolveVBAMacro( mpObjShell, aMacroName, false );
559 if( !aInfo.mbFound )
560 throw lang::IllegalArgumentException();
561
562 // build and return the script URL
563 return makeMacroURL( aInfo.msResolvedMacro );
564 }
565
resolveScriptURLtoVBAMacro(const::rtl::OUString &)566 ::rtl::OUString SAL_CALL VBAMacroResolver::resolveScriptURLtoVBAMacro( const ::rtl::OUString& /*rScriptURL*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
567 {
568 OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
569 throw uno::RuntimeException();
570 }
571
572 // ============================================================================
573
574 } // namespace vba
575 } // namespace ooo
576