Branch data 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 "oox/ole/vbamodule.hxx"
21 : : #include <boost/unordered_map.hpp>
22 : : #include <com/sun/star/container/XNameContainer.hpp>
23 : : #include <com/sun/star/container/XIndexContainer.hpp>
24 : : #include <com/sun/star/script/ModuleInfo.hpp>
25 : : #include <com/sun/star/script/ModuleType.hpp>
26 : : #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
27 : : #include <com/sun/star/awt/KeyEvent.hpp>
28 : : #include <cppuhelper/implbase1.hxx>
29 : : #include <filter/msfilter/msvbahelper.hxx>
30 : : #include "oox/helper/binaryinputstream.hxx"
31 : : #include "oox/helper/storagebase.hxx"
32 : : #include "oox/helper/textinputstream.hxx"
33 : : #include "oox/ole/vbahelper.hxx"
34 : : #include "oox/ole/vbainputstream.hxx"
35 : :
36 : : namespace oox {
37 : : namespace ole {
38 : :
39 : : // ============================================================================
40 : :
41 : : using namespace ::com::sun::star::lang;
42 : : using namespace ::com::sun::star::script::vba;
43 : : using namespace ::com::sun::star::uno;
44 : : using namespace ::com::sun::star;
45 : :
46 : : using ::rtl::OUString;
47 : : using ::rtl::OUStringBuffer;
48 : : using ::com::sun::star::awt::KeyEvent;
49 : : // ============================================================================
50 : : typedef ::cppu::WeakImplHelper1< container::XIndexContainer > OleIdToNameContainer_BASE;
51 : : typedef boost::unordered_map< sal_Int32, rtl::OUString > ObjIdToName;
52 : :
53 [ + - ][ + - ]: 10 : class OleIdToNameContainer : public OleIdToNameContainer_BASE
[ - + ]
54 : : {
55 : : ObjIdToName ObjIdToNameHash;
56 : : ::osl::Mutex m_aMutex;
57 : 33 : bool hasByIndex( ::sal_Int32 Index )
58 : : {
59 [ + - ]: 33 : ::osl::MutexGuard aGuard( m_aMutex );
60 [ + - ][ + - ]: 33 : return ( ObjIdToNameHash.find( Index ) != ObjIdToNameHash.end() );
[ + - ]
61 : : }
62 : : public:
63 [ + - ][ + - ]: 5 : OleIdToNameContainer() {}
64 : : // XIndexContainer Methods
65 : 11 : virtual void SAL_CALL insertByIndex( ::sal_Int32 Index, const Any& Element ) throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
66 : : {
67 [ + - ]: 11 : ::osl::MutexGuard aGuard( m_aMutex );
68 : 11 : rtl::OUString sOleName;
69 [ - + ]: 11 : if ( !( Element >>= sOleName ) )
70 [ # # ]: 0 : throw IllegalArgumentException();
71 [ + - ][ + - ]: 11 : ObjIdToNameHash[ Index ] = sOleName;
72 : 11 : }
73 : 0 : virtual void SAL_CALL removeByIndex( ::sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
74 : : {
75 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
76 [ # # ][ # # ]: 0 : if ( !hasByIndex( Index ) )
77 [ # # ]: 0 : throw IndexOutOfBoundsException();
78 [ # # ][ # # ]: 0 : ObjIdToNameHash.erase( ObjIdToNameHash.find( Index ) );
[ # # ]
79 : 0 : }
80 : : // XIndexReplace Methods
81 : 0 : virtual void SAL_CALL replaceByIndex( ::sal_Int32 Index, const Any& Element ) throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
82 : : {
83 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
84 [ # # ][ # # ]: 0 : if ( !hasByIndex( Index ) )
85 [ # # ]: 0 : throw IndexOutOfBoundsException();
86 : 0 : rtl::OUString sOleName;
87 [ # # ]: 0 : if ( !( Element >>= sOleName ) )
88 [ # # ]: 0 : throw IllegalArgumentException();
89 [ # # ][ # # ]: 0 : ObjIdToNameHash[ Index ] = sOleName;
90 : 0 : }
91 : : // XIndexAccess Methods
92 : 0 : virtual ::sal_Int32 SAL_CALL getCount( ) throw (RuntimeException)
93 : : {
94 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
95 [ # # ]: 0 : return ObjIdToNameHash.size();
96 : : }
97 : 33 : virtual Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
98 : : {
99 [ + - ]: 33 : ::osl::MutexGuard aGuard( m_aMutex );
100 [ + - ][ - + ]: 33 : if ( !hasByIndex( Index ) )
101 [ # # ]: 0 : throw IndexOutOfBoundsException();
102 [ + - ][ + - ]: 33 : return makeAny( ObjIdToNameHash[ Index ] );
[ + - ]
103 : : }
104 : : // XElementAccess Methods
105 : 0 : virtual Type SAL_CALL getElementType( ) throw (RuntimeException)
106 : : {
107 : 0 : return ::getCppuType( static_cast< const ::rtl::OUString* >( 0 ) );
108 : : }
109 : 0 : virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException)
110 : : {
111 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
112 [ # # ][ # # ]: 0 : return ( getCount() > 0 );
113 : : }
114 : : };
115 : :
116 : : // ============================================================================
117 : :
118 : 65 : VbaModule::VbaModule( const Reference< XComponentContext >& rxContext,
119 : : const Reference< frame::XModel >& rxDocModel,
120 : : const OUString& rName, rtl_TextEncoding eTextEnc, bool bExecutable ) :
121 : : mxContext( rxContext ),
122 : : mxDocModel( rxDocModel ),
123 : : maName( rName ),
124 : : meTextEnc( eTextEnc ),
125 : : mnType( script::ModuleType::UNKNOWN ),
126 : : mnOffset( SAL_MAX_UINT32 ),
127 : : mbReadOnly( false ),
128 : : mbPrivate( false ),
129 : 65 : mbExecutable( bExecutable )
130 : : {
131 : 65 : }
132 : :
133 : 65 : void VbaModule::importDirRecords( BinaryInputStream& rDirStrm )
134 : : {
135 : 65 : sal_uInt16 nRecId = 0;
136 [ + - ]: 65 : StreamDataSequence aRecData;
137 [ + - ][ + - ]: 620 : while( VbaHelper::readDirRecord( nRecId, aRecData, rDirStrm ) && (nRecId != VBA_ID_MODULEEND) )
[ + + ][ + + ]
138 : : {
139 [ + - ]: 555 : SequenceInputStream aRecStrm( aRecData );
140 : 555 : sal_Int32 nRecSize = aRecData.getLength();
141 [ - + + + : 555 : switch( nRecId )
+ + + + +
+ + - -
- ]
142 : : {
143 : : #define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaModule::importDirRecords - invalid record size" )
144 : : case VBA_ID_MODULENAME:
145 : : OSL_FAIL( "VbaModule::importDirRecords - unexpected MODULENAME record" );
146 [ # # ]: 0 : maName = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
147 : 0 : break;
148 : : case VBA_ID_MODULENAMEUNICODE:
149 : 35 : break;
150 : : case VBA_ID_MODULESTREAMNAME:
151 [ + - ]: 65 : maStreamName = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
152 : : // Actually the stream name seems the best name to use
153 : : // the VBA_ID_MODULENAME name can sometimes be the wrong case
154 : 65 : maName = maStreamName;
155 : 65 : break;
156 : : case VBA_ID_MODULESTREAMNAMEUNICODE:
157 : 65 : break;
158 : : case VBA_ID_MODULEDOCSTRING:
159 [ + - ]: 65 : maDocString = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
160 : 65 : break;
161 : : case VBA_ID_MODULEDOCSTRINGUNICODE:
162 : 65 : break;
163 : : case VBA_ID_MODULEOFFSET:
164 : : OOX_ENSURE_RECORDSIZE( nRecSize == 4 );
165 [ + - ]: 65 : aRecStrm >> mnOffset;
166 : 65 : break;
167 : : case VBA_ID_MODULEHELPCONTEXT:
168 : : OOX_ENSURE_RECORDSIZE( nRecSize == 4 );
169 : 65 : break;
170 : : case VBA_ID_MODULECOOKIE:
171 : : OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
172 : 65 : break;
173 : : case VBA_ID_MODULETYPEPROCEDURAL:
174 : : OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
175 : : OSL_ENSURE( mnType == script::ModuleType::UNKNOWN, "VbaModule::importDirRecords - multiple module type records" );
176 : 10 : mnType = script::ModuleType::NORMAL;
177 : 10 : break;
178 : : case VBA_ID_MODULETYPEDOCUMENT:
179 : : OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
180 : : OSL_ENSURE( mnType == script::ModuleType::UNKNOWN, "VbaModule::importDirRecords - multiple module type records" );
181 : 55 : mnType = script::ModuleType::DOCUMENT;
182 : 55 : break;
183 : : case VBA_ID_MODULEREADONLY:
184 : : OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
185 : 0 : mbReadOnly = true;
186 : 0 : break;
187 : : case VBA_ID_MODULEPRIVATE:
188 : : OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
189 : 0 : mbPrivate = true;
190 : 0 : break;
191 : : default:
192 : : OSL_FAIL( "VbaModule::importDirRecords - unknown module record" );
193 : : #undef OOX_ENSURE_RECORDSIZE
194 : : }
195 [ + - ]: 555 : }
196 : : OSL_ENSURE( !maName.isEmpty(), "VbaModule::importDirRecords - missing module name" );
197 : : OSL_ENSURE( !maStreamName.isEmpty(), "VbaModule::importDirRecords - missing module stream name" );
198 : : OSL_ENSURE( mnType != script::ModuleType::UNKNOWN, "VbaModule::importDirRecords - missing module type" );
199 [ + - ]: 65 : OSL_ENSURE( mnOffset < SAL_MAX_UINT32, "VbaModule::importDirRecords - missing module stream offset" );
200 : 65 : }
201 : :
202 : 65 : void VbaModule::createAndImportModule( StorageBase& rVbaStrg,
203 : : const Reference< container::XNameContainer >& rxBasicLib,
204 : : const Reference< container::XNameAccess >& rxDocObjectNA,
205 : : const Reference< container::XNameContainer >& rxOleNameOverrides ) const
206 : : {
207 [ + - ]: 65 : OUString aVBASourceCode = readSourceCode( rVbaStrg, rxOleNameOverrides );
208 [ + - ]: 65 : createModule( aVBASourceCode, rxBasicLib, rxDocObjectNA );
209 : 65 : }
210 : :
211 : 0 : void VbaModule::createEmptyModule( const Reference< container::XNameContainer >& rxBasicLib,
212 : : const Reference< container::XNameAccess >& rxDocObjectNA ) const
213 : : {
214 [ # # ]: 0 : createModule( OUString(), rxBasicLib, rxDocObjectNA );
215 : 0 : }
216 : :
217 : 65 : OUString VbaModule::readSourceCode( StorageBase& rVbaStrg, const Reference< container::XNameContainer >& rxOleNameOverrides ) const
218 : : {
219 : 65 : OUStringBuffer aSourceCode;
220 [ + - ][ + - ]: 65 : const static rtl::OUString sUnmatchedRemovedTag( RTL_CONSTASCII_USTRINGPARAM( "Rem removed unmatched Sub/End: " ) );
[ # # ][ + + ]
221 [ + - ][ + - ]: 65 : if( !maStreamName.isEmpty() && (mnOffset != SAL_MAX_UINT32) )
[ + - ]
222 : : {
223 [ + - ][ + - ]: 65 : BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true );
224 : : OSL_ENSURE( !aInStrm.isEof(), "VbaModule::readSourceCode - cannot open module stream" );
225 : : // skip the 'performance cache' stored before the actual source code
226 [ + - ]: 65 : aInStrm.seek( mnOffset );
227 : : // if stream is still valid, load the source code
228 [ + - ]: 65 : if( !aInStrm.isEof() )
229 : : {
230 : : // decompression starts at current stream position of aInStrm
231 [ + - ]: 65 : VbaInputStream aVbaStrm( aInStrm );
232 : : // load the source code line-by-line, with some more processing
233 [ + - ]: 65 : TextInputStream aVbaTextStrm( mxContext, aVbaStrm, meTextEnc );
234 : :
235 : : struct ProcedurePair
236 : : {
237 : : bool bInProcedure;
238 : : sal_uInt32 nPos;
239 : 65 : ProcedurePair() : bInProcedure( false ), nPos( 0 ) {};
240 : 65 : } procInfo;
241 : :
242 [ + - ][ + + ]: 1857 : while( !aVbaTextStrm.isEof() )
243 : : {
244 [ + - ]: 1792 : OUString aCodeLine = aVbaTextStrm.readLine();
245 [ + + ]: 1792 : if( aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) )
246 : : {
247 : : // attribute
248 : 434 : int index = aCodeLine.indexOf( ".VB_ProcData.VB_Invoke_Func = " );
249 [ - + ]: 434 : if ( index != -1 )
250 : : {
251 : : // format is
252 : : // 'Attribute Procedure.VB_ProcData.VB_Invoke_Func = "*\n14"'
253 : : // where 'Procedure' is the procedure name and '*' is the shortcut key
254 : : // note: his is only relevant for Excel, seems that
255 : : // word doesn't store the shortcut in the module
256 : : // attributes
257 : 0 : int nSpaceIndex = aCodeLine.indexOf(' ');
258 : 0 : rtl::OUString sProc = aCodeLine.copy( nSpaceIndex + 1, index - nSpaceIndex - 1);
259 : : // for Excel short cut key seems limited to cntrl+'a-z, A-Z'
260 : 0 : rtl::OUString sKey = aCodeLine.copy( aCodeLine.lastIndexOf("= ") + 3, 1 );
261 : : // only alpha key valid for key shortcut, however the api will accept other keys
262 [ # # ]: 0 : if ( !isalpha( (char)sKey[ 0 ] ) )
263 : : {
264 : : // cntrl modifier is explicit ( but could be cntrl+shift ), parseKeyEvent
265 : : // will handle and uppercase letter appropriately
266 : 0 : rtl::OUString sApiKey = "^";
267 : 0 : sApiKey += sKey;
268 : : try
269 : : {
270 [ # # ]: 0 : KeyEvent aKeyEvent = ooo::vba::parseKeyEvent( sApiKey );
271 [ # # ][ # # ]: 0 : ooo::vba::applyShortCutKeyBinding( mxDocModel, aKeyEvent, sProc );
[ # # ]
272 : : }
273 [ # # ]: 0 : catch (const Exception&)
274 : : {
275 : 0 : }
276 : 0 : }
277 : : }
278 : : else
279 [ + - ]: 434 : extractOleOverrideFromAttr( aCodeLine, rxOleNameOverrides );
280 : : }
281 : : else
282 : : {
283 : : // Hack here to weed out any unmatched End Sub / Sub Foo statements.
284 : : // The behaviour of the vba ide practically guarantees the case and
285 : : // spacing of Sub statement(s). However, indentation can be arbitrary hence
286 : : // the trim.
287 : 1358 : rtl::OUString trimLine( aCodeLine.trim() );
288 [ + + ][ + - : 6725 : if ( mbExecutable && (
+ + + - +
+ - + ]
289 : 1358 : trimLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("Sub ") ) ||
290 : 1344 : trimLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("Public Sub ") ) ||
291 : 1344 : trimLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("Private Sub ") ) ||
292 : 1321 : trimLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("Static Sub ") ) ) )
293 : : {
294 : : // this should never happen, basic doesn't support nested procedures
295 : : // first Sub Foo must be bogus
296 [ - + ]: 37 : if ( procInfo.bInProcedure )
297 : : {
298 : : // comment out the line
299 [ # # ]: 0 : aSourceCode.insert( procInfo.nPos, sUnmatchedRemovedTag );
300 : : // mark location of this Sub
301 : 0 : procInfo.nPos = aSourceCode.getLength();
302 : : }
303 : : else
304 : : {
305 : 37 : procInfo.bInProcedure = true;
306 : 37 : procInfo.nPos = aSourceCode.getLength();
307 : : }
308 : : }
309 [ + - ][ + + ]: 1321 : else if ( mbExecutable && aCodeLine.trim().matchAsciiL( RTL_CONSTASCII_STRINGPARAM("End Sub")) )
[ + - ][ + + ]
310 : : {
311 : : // un-matched End Sub
312 [ - + ]: 37 : if ( !procInfo.bInProcedure )
313 : : {
314 [ # # ]: 0 : aSourceCode.append( sUnmatchedRemovedTag );
315 : : }
316 : : else
317 : : {
318 : 37 : procInfo.bInProcedure = false;
319 : 37 : procInfo.nPos = 0;
320 : : }
321 : : }
322 : : // normal source code line
323 [ - + ]: 1358 : if( !mbExecutable )
324 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) );
325 [ + - ][ + - ]: 1358 : aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) );
326 : : }
327 [ + - ][ + - ]: 1857 : }
328 [ + - ]: 65 : }
329 : : }
330 [ + - ]: 65 : return aSourceCode.makeStringAndClear();
331 : : }
332 : :
333 : 434 : void VbaModule::extractOleOverrideFromAttr( const OUString& rAttribute,
334 : : const Reference< container::XNameContainer >& rxOleNameOverrides ) const
335 : : {
336 : : // format of the attribute we are interested in is
337 : : // Attribute VB_Control = "ControlName", intString, MSForms, ControlTypeAsString
338 : : // e.g.
339 : : // Attribute VB_Control = "CommandButton1, 201, 19, MSForms, CommandButton"
340 [ + - ]: 434 : OUString sControlAttribute = CREATE_OUSTRING( "Attribute VB_Control = \"" );
341 [ + - ][ + + ]: 434 : if ( rxOleNameOverrides.is() && rAttribute.indexOf( sControlAttribute ) != -1 )
[ + + ]
342 : : {
343 : 11 : OUString sRest = rAttribute.copy( sControlAttribute.getLength() );
344 : 11 : sal_Int32 nPos = sRest.indexOf( ',' );
345 : 11 : OUString sCntrlName = sRest.copy( 0, nPos );
346 : :
347 : 11 : sal_Int32 nCntrlId = sRest.copy( nPos + 1 ).copy( 0, sRest.indexOf( ',', nPos + 1) ).toInt32();
348 : : OSL_TRACE("In module %s, assiging %d controlname %s",
349 : : rtl::OUStringToOString( maName, RTL_TEXTENCODING_UTF8 ).getStr(), nCntrlId,
350 : : rtl::OUStringToOString( sCntrlName, RTL_TEXTENCODING_UTF8 ).getStr() );
351 [ + - ][ + + ]: 11 : if ( !rxOleNameOverrides->hasByName( maName ) )
[ + - ]
352 [ + - ][ + - ]: 5 : rxOleNameOverrides->insertByName( maName, Any( Reference< container::XIndexContainer> ( new OleIdToNameContainer ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
353 : 11 : Reference< container::XIndexContainer > xIdToOleName;
354 [ + - ][ + - ]: 11 : if ( rxOleNameOverrides->getByName( maName ) >>= xIdToOleName )
[ + - ][ + - ]
355 [ + - ][ + - ]: 11 : xIdToOleName->insertByIndex( nCntrlId, makeAny( sCntrlName ) );
[ + - ]
356 : 434 : }
357 : 434 : }
358 : :
359 : 65 : void VbaModule::createModule( const OUString& rVBASourceCode,
360 : : const Reference< container::XNameContainer >& rxBasicLib,
361 : : const Reference< container::XNameAccess >& rxDocObjectNA ) const
362 : : {
363 [ + - ]: 65 : if( maName.isEmpty() )
364 : 65 : return;
365 : :
366 : : // prepare the Basic module
367 [ + - ]: 65 : script::ModuleInfo aModuleInfo;
368 : 65 : aModuleInfo.ModuleType = mnType;
369 : 65 : OUStringBuffer aSourceCode;
370 [ + - ]: 65 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem Attribute VBA_ModuleType=" ) );
371 [ + - - + : 65 : switch( mnType )
- ]
372 : : {
373 : : case script::ModuleType::NORMAL:
374 [ + - ]: 10 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAModule" ) );
375 : 10 : break;
376 : : case script::ModuleType::CLASS:
377 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAClassModule" ) );
378 : 0 : break;
379 : : case script::ModuleType::FORM:
380 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAFormModule" ) );
381 : : // hack from old filter, document Basic should know the XModel, but it doesn't
382 [ # # ]: 0 : aModuleInfo.ModuleObject.set( mxDocModel, UNO_QUERY );
383 : 0 : break;
384 : : case script::ModuleType::DOCUMENT:
385 [ + - ]: 55 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBADocumentModule" ) );
386 : : // get the VBA implementation object associated to the document module
387 [ + + ]: 55 : if( rxDocObjectNA.is() ) try
388 : : {
389 [ + - ][ + - ]: 16 : aModuleInfo.ModuleObject.set( rxDocObjectNA->getByName( maName ), UNO_QUERY );
[ + - ][ # # ]
390 : : }
391 [ # # ]: 0 : catch (const Exception&)
392 : : {
393 : : }
394 : 55 : break;
395 : : default:
396 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAUnknown" ) );
397 : : }
398 [ + - ]: 65 : aSourceCode.append( sal_Unicode( '\n' ) );
399 [ + - ]: 65 : if( mbExecutable )
400 : : {
401 [ + - ]: 65 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Option VBASupport 1\n" ) );
402 [ - + ]: 65 : if( mnType == script::ModuleType::CLASS )
403 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Option ClassModule\n" ) );
404 : : }
405 : : else
406 : : {
407 : : // add a subroutine named after the module itself
408 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Sub " ) ).
409 [ # # ][ # # ]: 0 : append( maName.replace( ' ', '_' ) ).append( sal_Unicode( '\n' ) );
410 : : }
411 : :
412 : : // append passed VBA source code
413 [ + - ]: 65 : aSourceCode.append( rVBASourceCode );
414 : :
415 : : // close the subroutine named after the module
416 [ - + ]: 65 : if( !mbExecutable )
417 [ # # ]: 0 : aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "End Sub\n" ) );
418 : :
419 : : // insert extended module info
420 : : try
421 : : {
422 [ + - ]: 65 : Reference< XVBAModuleInfo > xVBAModuleInfo( rxBasicLib, UNO_QUERY_THROW );
423 [ + - ][ + - ]: 65 : xVBAModuleInfo->insertModuleInfo( maName, aModuleInfo );
[ # # ]
424 : : }
425 [ # # ]: 0 : catch (const Exception&)
426 : : {
427 : : }
428 : :
429 : : // insert the module into the passed Basic library
430 : : try
431 : : {
432 [ + - ][ + - ]: 65 : rxBasicLib->insertByName( maName, Any( aSourceCode.makeStringAndClear() ) );
[ + - ][ + - ]
[ # # ]
433 : : }
434 [ # # ]: 0 : catch (const Exception&)
435 : : {
436 : : OSL_FAIL( "VbaModule::createModule - cannot insert module into library" );
437 [ + - ]: 65 : }
438 : : }
439 : :
440 : : // ============================================================================
441 : :
442 : : } // namespace ole
443 [ + - ][ + - ]: 285 : } // namespace oox
444 : :
445 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|