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/vbacontrol.hxx"
21 : :
22 : : #include <algorithm>
23 : : #include <set>
24 : : #include <com/sun/star/awt/XControlModel.hpp>
25 : : #include <com/sun/star/container/XNameContainer.hpp>
26 : : #include <com/sun/star/io/XInputStreamProvider.hpp>
27 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 : : #include <com/sun/star/uno/XComponentContext.hpp>
29 : : #include <rtl/ustrbuf.hxx>
30 : : #include <xmlscript/xmldlg_imexp.hxx>
31 : : #include "oox/helper/attributelist.hxx"
32 : : #include "oox/helper/binaryinputstream.hxx"
33 : : #include "oox/helper/containerhelper.hxx"
34 : : #include "oox/helper/propertymap.hxx"
35 : : #include "oox/helper/propertyset.hxx"
36 : : #include "oox/helper/storagebase.hxx"
37 : : #include "oox/helper/textinputstream.hxx"
38 : : #include "oox/ole/vbahelper.hxx"
39 : :
40 : : namespace oox {
41 : : namespace ole {
42 : :
43 : : // ============================================================================
44 : :
45 : : using namespace ::com::sun::star::awt;
46 : : using namespace ::com::sun::star::container;
47 : : using namespace ::com::sun::star::frame;
48 : : using namespace ::com::sun::star::io;
49 : : using namespace ::com::sun::star::lang;
50 : : using namespace ::com::sun::star::uno;
51 : :
52 : : using ::rtl::OUString;
53 : : using ::rtl::OUStringBuffer;
54 : :
55 : : // ============================================================================
56 : :
57 : : namespace {
58 : :
59 : : const sal_uInt16 VBA_SITE_CLASSIDINDEX = 0x8000;
60 : : const sal_uInt16 VBA_SITE_INDEXMASK = 0x7FFF;
61 : : const sal_uInt16 VBA_SITE_FORM = 7;
62 : : const sal_uInt16 VBA_SITE_IMAGE = 12;
63 : : const sal_uInt16 VBA_SITE_FRAME = 14;
64 : : const sal_uInt16 VBA_SITE_SPINBUTTON = 16;
65 : : const sal_uInt16 VBA_SITE_COMMANDBUTTON = 17;
66 : : const sal_uInt16 VBA_SITE_TABSTRIP = 18;
67 : : const sal_uInt16 VBA_SITE_LABEL = 21;
68 : : const sal_uInt16 VBA_SITE_TEXTBOX = 23;
69 : : const sal_uInt16 VBA_SITE_LISTBOX = 24;
70 : : const sal_uInt16 VBA_SITE_COMBOBOX = 25;
71 : : const sal_uInt16 VBA_SITE_CHECKBOX = 26;
72 : : const sal_uInt16 VBA_SITE_OPTIONBUTTON = 27;
73 : : const sal_uInt16 VBA_SITE_TOGGLEBUTTON = 28;
74 : : const sal_uInt16 VBA_SITE_SCROLLBAR = 47;
75 : : const sal_uInt16 VBA_SITE_MULTIPAGE = 57;
76 : : const sal_uInt16 VBA_SITE_UNKNOWN = 0x7FFF;
77 : :
78 : : const sal_uInt32 VBA_SITE_TABSTOP = 0x00000001;
79 : : const sal_uInt32 VBA_SITE_VISIBLE = 0x00000002;
80 : : const sal_uInt32 VBA_SITE_DEFAULTBUTTON = 0x00000004;
81 : : const sal_uInt32 VBA_SITE_CANCELBUTTON = 0x00000008;
82 : : const sal_uInt32 VBA_SITE_OSTREAM = 0x00000010;
83 : : const sal_uInt32 VBA_SITE_DEFFLAGS = 0x00000033;
84 : :
85 : : const sal_uInt8 VBA_SITEINFO_COUNT = 0x80;
86 : : const sal_uInt8 VBA_SITEINFO_MASK = 0x7F;
87 : :
88 : : // ----------------------------------------------------------------------------
89 : :
90 : : /** Collects names of all controls in a user form or container control. Allows
91 : : to generate unused names for dummy controls separating option groups.
92 : : */
93 : 0 : class VbaControlNamesSet
94 : : {
95 : : public:
96 : : explicit VbaControlNamesSet();
97 : :
98 : : /** Inserts the name of the passed control. */
99 : : void insertName( const VbaFormControl& rControl );
100 : : /** Returns a name that is not contained in this set. */
101 : : OUString generateDummyName();
102 : :
103 : : private:
104 : : typedef ::std::set< OUString > OUStringSet;
105 : : OUStringSet maCtrlNames;
106 : : const OUString maDummyBaseName;
107 : : sal_Int32 mnIndex;
108 : : };
109 : :
110 : 0 : VbaControlNamesSet::VbaControlNamesSet() :
111 : : maDummyBaseName( CREATE_OUSTRING( "DummyGroupSep" ) ),
112 [ # # ]: 0 : mnIndex( 0 )
113 : : {
114 : 0 : }
115 : :
116 : 0 : void VbaControlNamesSet::insertName( const VbaFormControl& rControl )
117 : : {
118 [ # # ]: 0 : OUString aName = rControl.getControlName();
119 [ # # ]: 0 : if( !aName.isEmpty() )
120 [ # # ]: 0 : maCtrlNames.insert( aName );
121 : 0 : }
122 : :
123 : 0 : OUString VbaControlNamesSet::generateDummyName()
124 : : {
125 : 0 : OUString aCtrlName;
126 [ # # ]: 0 : do
127 : : {
128 [ # # ][ # # ]: 0 : aCtrlName = OUStringBuffer( maDummyBaseName ).append( ++mnIndex ).makeStringAndClear();
[ # # ]
129 : : }
130 [ # # ]: 0 : while( maCtrlNames.count( aCtrlName ) > 0 );
131 [ # # ]: 0 : maCtrlNames.insert( aCtrlName );
132 : 0 : return aCtrlName;
133 : : }
134 : :
135 : : // ----------------------------------------------------------------------------
136 : :
137 : : /** Functor that inserts the name of a control into a VbaControlNamesSet. */
138 : : struct VbaControlNameInserter
139 : : {
140 : : public:
141 : : VbaControlNamesSet& mrCtrlNames;
142 : 0 : inline explicit VbaControlNameInserter( VbaControlNamesSet& rCtrlNames ) : mrCtrlNames( rCtrlNames ) {}
143 : 0 : inline void operator()( const VbaFormControl& rControl ) { mrCtrlNames.insertName( rControl ); }
144 : : };
145 : :
146 : : // ----------------------------------------------------------------------------
147 : :
148 : : /** A dummy invisible form control (fixed label without text) that is used to
149 : : separate two groups of option buttons.
150 : : */
151 [ # # ]: 0 : class VbaDummyFormControl : public VbaFormControl
152 : : {
153 : : public:
154 : : explicit VbaDummyFormControl( const OUString& rName );
155 : : };
156 : :
157 : 0 : VbaDummyFormControl::VbaDummyFormControl( const OUString& rName )
158 : : {
159 [ # # ][ # # ]: 0 : mxSiteModel.reset( new VbaSiteModel );
[ # # ]
160 [ # # ]: 0 : mxSiteModel->importProperty( XML_Name, rName );
161 [ # # ]: 0 : mxSiteModel->importProperty( XML_VariousPropertyBits, OUString( sal_Unicode( '0' ) ) );
162 : :
163 [ # # ][ # # ]: 0 : mxCtrlModel.reset( new AxLabelModel );
[ # # ]
164 : 0 : mxCtrlModel->setAwtModelMode();
165 [ # # ][ # # ]: 0 : mxCtrlModel->importProperty( XML_Size, CREATE_OUSTRING( "10;10" ) );
166 : 0 : }
167 : :
168 : : } // namespace
169 : :
170 : : // ============================================================================
171 : :
172 : 0 : VbaSiteModel::VbaSiteModel() :
173 : : maPos( 0, 0 ),
174 : : mnId( 0 ),
175 : : mnHelpContextId( 0 ),
176 : : mnFlags( VBA_SITE_DEFFLAGS ),
177 : : mnStreamLen( 0 ),
178 : : mnTabIndex( -1 ),
179 : : mnClassIdOrCache( VBA_SITE_UNKNOWN ),
180 : 0 : mnGroupId( 0 )
181 : : {
182 : 0 : }
183 : :
184 : 0 : VbaSiteModel::~VbaSiteModel()
185 : : {
186 [ # # ]: 0 : }
187 : :
188 : 0 : void VbaSiteModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
189 : : {
190 [ # # # # ]: 0 : switch( nPropId )
191 : : {
192 : 0 : case XML_Name: maName = rValue; break;
193 : 0 : case XML_Tag: maTag = rValue; break;
194 : 0 : case XML_VariousPropertyBits: mnFlags = AttributeConversion::decodeUnsigned( rValue ); break;
195 : : }
196 : 0 : }
197 : :
198 : 0 : bool VbaSiteModel::importBinaryModel( BinaryInputStream& rInStrm )
199 : : {
200 [ # # ]: 0 : AxBinaryPropertyReader aReader( rInStrm );
201 [ # # ]: 0 : aReader.readStringProperty( maName );
202 [ # # ]: 0 : aReader.readStringProperty( maTag );
203 [ # # ]: 0 : aReader.readIntProperty< sal_Int32 >( mnId );
204 [ # # ]: 0 : aReader.readIntProperty< sal_Int32 >( mnHelpContextId );
205 [ # # ]: 0 : aReader.readIntProperty< sal_uInt32 >( mnFlags );
206 [ # # ]: 0 : aReader.readIntProperty< sal_uInt32 >( mnStreamLen );
207 [ # # ]: 0 : aReader.readIntProperty< sal_Int16 >( mnTabIndex );
208 [ # # ]: 0 : aReader.readIntProperty< sal_uInt16 >( mnClassIdOrCache );
209 [ # # ]: 0 : aReader.readPairProperty( maPos );
210 [ # # ]: 0 : aReader.readIntProperty< sal_uInt16 >( mnGroupId );
211 [ # # ]: 0 : aReader.skipUndefinedProperty();
212 [ # # ]: 0 : aReader.readStringProperty( maToolTip );
213 [ # # ]: 0 : aReader.skipStringProperty(); // license key
214 [ # # ]: 0 : aReader.readStringProperty( maControlSource );
215 [ # # ]: 0 : aReader.readStringProperty( maRowSource );
216 [ # # ][ # # ]: 0 : return aReader.finalizeImport();
217 : : }
218 : :
219 : 0 : bool VbaSiteModel::isContainer() const
220 : : {
221 : 0 : return !getFlag( mnFlags, VBA_SITE_OSTREAM );
222 : : }
223 : :
224 : 0 : sal_uInt32 VbaSiteModel::getStreamLength() const
225 : : {
226 [ # # ]: 0 : return isContainer() ? 0 : mnStreamLen;
227 : : }
228 : :
229 : 0 : OUString VbaSiteModel::getSubStorageName() const
230 : : {
231 [ # # ]: 0 : if( mnId >= 0 )
232 : : {
233 : 0 : OUStringBuffer aBuffer;
234 [ # # ]: 0 : aBuffer.append( sal_Unicode( 'i' ) );
235 [ # # ]: 0 : if( mnId < 10 )
236 [ # # ]: 0 : aBuffer.append( sal_Unicode( '0' ) );
237 [ # # ]: 0 : aBuffer.append( mnId );
238 [ # # ]: 0 : return aBuffer.makeStringAndClear();
239 : : }
240 : 0 : return OUString();
241 : : }
242 : :
243 : 0 : ControlModelRef VbaSiteModel::createControlModel( const AxClassTable& rClassTable ) const
244 : : {
245 : 0 : ControlModelRef xCtrlModel;
246 : :
247 : 0 : sal_Int32 nTypeIndex = static_cast< sal_Int32 >( mnClassIdOrCache & VBA_SITE_INDEXMASK );
248 [ # # ]: 0 : if( !getFlag( mnClassIdOrCache, VBA_SITE_CLASSIDINDEX ) )
249 : : {
250 [ # # # # : 0 : switch( nTypeIndex )
# # # # #
# # # # #
# # ]
251 : : {
252 [ # # ][ # # ]: 0 : case VBA_SITE_COMMANDBUTTON: xCtrlModel.reset( new AxCommandButtonModel ); break;
[ # # ]
253 [ # # ][ # # ]: 0 : case VBA_SITE_LABEL: xCtrlModel.reset( new AxLabelModel ); break;
[ # # ]
254 [ # # ][ # # ]: 0 : case VBA_SITE_IMAGE: xCtrlModel.reset( new AxImageModel ); break;
[ # # ]
255 [ # # ][ # # ]: 0 : case VBA_SITE_TOGGLEBUTTON: xCtrlModel.reset( new AxToggleButtonModel ); break;
[ # # ]
256 [ # # ][ # # ]: 0 : case VBA_SITE_CHECKBOX: xCtrlModel.reset( new AxCheckBoxModel ); break;
[ # # ]
257 [ # # ][ # # ]: 0 : case VBA_SITE_OPTIONBUTTON: xCtrlModel.reset( new AxOptionButtonModel ); break;
[ # # ]
258 [ # # ][ # # ]: 0 : case VBA_SITE_TEXTBOX: xCtrlModel.reset( new AxTextBoxModel ); break;
[ # # ]
259 [ # # ][ # # ]: 0 : case VBA_SITE_LISTBOX: xCtrlModel.reset( new AxListBoxModel ); break;
[ # # ]
260 [ # # ][ # # ]: 0 : case VBA_SITE_COMBOBOX: xCtrlModel.reset( new AxComboBoxModel ); break;
[ # # ]
261 [ # # ][ # # ]: 0 : case VBA_SITE_SPINBUTTON: xCtrlModel.reset( new AxSpinButtonModel ); break;
[ # # ]
262 [ # # ][ # # ]: 0 : case VBA_SITE_SCROLLBAR: xCtrlModel.reset( new AxScrollBarModel ); break;
[ # # ]
263 [ # # ][ # # ]: 0 : case VBA_SITE_TABSTRIP: xCtrlModel.reset( new AxTabStripModel ); break;
[ # # ]
264 [ # # ][ # # ]: 0 : case VBA_SITE_FRAME: xCtrlModel.reset( new AxFrameModel ); break;
[ # # ]
265 [ # # ][ # # ]: 0 : case VBA_SITE_MULTIPAGE: xCtrlModel.reset( new AxMultiPageModel ); break;
[ # # ]
266 [ # # ][ # # ]: 0 : case VBA_SITE_FORM: xCtrlModel.reset( new AxFormPageModel ); break;
[ # # ]
267 : : default: OSL_FAIL( "VbaSiteModel::createControlModel - unknown type index" );
268 : : }
269 : : }
270 : : else
271 : : {
272 [ # # ]: 0 : const OUString* pGuid = ContainerHelper::getVectorElement( rClassTable, nTypeIndex );
273 : : OSL_ENSURE( pGuid, "VbaSiteModel::createControlModel - invalid class table index" );
274 [ # # ]: 0 : if( pGuid )
275 : : {
276 [ # # ]: 0 : if( *pGuid == COMCTL_GUID_SCROLLBAR_60 )
277 [ # # ][ # # ]: 0 : xCtrlModel.reset( new ComCtlScrollBarModel( 6 ) );
[ # # ]
278 [ # # ]: 0 : else if( *pGuid == COMCTL_GUID_PROGRESSBAR_50 )
279 [ # # ][ # # ]: 0 : xCtrlModel.reset( new ComCtlProgressBarModel( 5 ) );
[ # # ]
280 [ # # ]: 0 : else if( *pGuid == COMCTL_GUID_PROGRESSBAR_60 )
281 [ # # ][ # # ]: 0 : xCtrlModel.reset( new ComCtlProgressBarModel( 6 ) );
[ # # ]
282 : : }
283 : : }
284 : :
285 [ # # ]: 0 : if( xCtrlModel.get() )
286 : : {
287 : : // user form controls are AWT models
288 : 0 : xCtrlModel->setAwtModelMode();
289 : :
290 : : // check that container model matches container flag in site data
291 [ # # ][ # # ]: 0 : bool bModelIsContainer = dynamic_cast< const AxContainerModelBase* >( xCtrlModel.get() ) != 0;
292 [ # # ]: 0 : bool bTypeMatch = bModelIsContainer == isContainer();
293 : : OSL_ENSURE( bTypeMatch, "VbaSiteModel::createControlModel - container type does not match container flag" );
294 [ # # ]: 0 : if( !bTypeMatch )
295 [ # # ]: 0 : xCtrlModel.reset();
296 : : }
297 : 0 : return xCtrlModel;
298 : : }
299 : :
300 : 0 : void VbaSiteModel::convertProperties( PropertyMap& rPropMap,
301 : : const ControlConverter& rConv, ApiControlType eCtrlType, sal_Int32 nCtrlIndex ) const
302 : : {
303 : 0 : rPropMap.setProperty( PROP_Name, maName );
304 : 0 : rPropMap.setProperty( PROP_Tag, maTag );
305 : :
306 [ # # ]: 0 : if( eCtrlType != API_CONTROL_DIALOG )
307 : : {
308 : 0 : rPropMap.setProperty( PROP_HelpText, maToolTip );
309 [ # # ]: 0 : rPropMap.setProperty( PROP_EnableVisible, getFlag( mnFlags, VBA_SITE_VISIBLE ) );
310 : : // we need to set the passed control index to make option button groups work
311 [ # # ][ # # ]: 0 : if( (0 <= nCtrlIndex) && (nCtrlIndex <= SAL_MAX_INT16) )
312 [ # # ]: 0 : rPropMap.setProperty( PROP_TabIndex, static_cast< sal_Int16 >( nCtrlIndex ) );
313 : : // progress bar and group box support TabIndex, but not Tabstop...
314 [ # # ][ # # ]: 0 : if( (eCtrlType != API_CONTROL_PROGRESSBAR) && (eCtrlType != API_CONTROL_GROUPBOX) && (eCtrlType != API_CONTROL_FRAME) && (eCtrlType != API_CONTROL_PAGE) )
[ # # ][ # # ]
315 [ # # ]: 0 : rPropMap.setProperty( PROP_Tabstop, getFlag( mnFlags, VBA_SITE_TABSTOP ) );
316 : 0 : rConv.convertPosition( rPropMap, maPos );
317 : : }
318 : 0 : }
319 : :
320 : 0 : void VbaSiteModel::bindToSources( const Reference< XControlModel >& rxCtrlModel, const ControlConverter& rConv ) const
321 : : {
322 : 0 : rConv.bindToSources( rxCtrlModel, maControlSource, maRowSource );
323 : 0 : }
324 : :
325 : : // ============================================================================
326 : :
327 [ # # ][ # # ]: 0 : VbaFormControl::VbaFormControl()
[ # # ]
328 : : {
329 : 0 : }
330 : :
331 [ # # ]: 0 : VbaFormControl::~VbaFormControl()
332 : : {
333 [ # # ]: 0 : }
334 : :
335 : 0 : void VbaFormControl::importModelOrStorage( BinaryInputStream& rInStrm, StorageBase& rStrg, const AxClassTable& rClassTable )
336 : : {
337 [ # # ]: 0 : if( mxSiteModel.get() )
338 : : {
339 [ # # ]: 0 : if( mxSiteModel->isContainer() )
340 : : {
341 [ # # ][ # # ]: 0 : StorageRef xSubStrg = rStrg.openSubStorage( mxSiteModel->getSubStorageName(), false );
342 : : OSL_ENSURE( xSubStrg.get(), "VbaFormControl::importModelOrStorage - cannot find storage for embedded control" );
343 [ # # ]: 0 : if( xSubStrg.get() )
344 [ # # ][ # # ]: 0 : importStorage( *xSubStrg, rClassTable );
345 : : }
346 [ # # ]: 0 : else if( !rInStrm.isEof() )
347 : : {
348 : 0 : sal_Int64 nNextStrmPos = rInStrm.tell() + mxSiteModel->getStreamLength();
349 : 0 : importControlModel( rInStrm, rClassTable );
350 : 0 : rInStrm.seek( nNextStrmPos );
351 : : }
352 : : }
353 : 0 : }
354 : :
355 : 0 : OUString VbaFormControl::getControlName() const
356 : : {
357 [ # # ]: 0 : return mxSiteModel.get() ? mxSiteModel->getName() : OUString();
358 : : }
359 : :
360 : 0 : sal_Int32 VbaFormControl::getControlId() const
361 : : {
362 [ # # ]: 0 : return mxSiteModel.get() ? mxSiteModel->getId() : -1;
363 : : }
364 : :
365 : 0 : void VbaFormControl::createAndConvert( sal_Int32 nCtrlIndex,
366 : : const Reference< XNameContainer >& rxParentNC, const ControlConverter& rConv ) const
367 : : {
368 [ # # ][ # # ]: 0 : if( rxParentNC.is() && mxSiteModel.get() && mxCtrlModel.get() ) try
[ # # ][ # # ]
369 : : {
370 : : // create the control model
371 [ # # ]: 0 : OUString aServiceName = mxCtrlModel->getServiceName();
372 [ # # ]: 0 : Reference< XMultiServiceFactory > xModelFactory( rxParentNC, UNO_QUERY_THROW );
373 [ # # ][ # # ]: 0 : Reference< XControlModel > xCtrlModel( xModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
[ # # ]
374 : :
375 : : // convert all properties and embedded controls
376 [ # # ][ # # ]: 0 : if( convertProperties( xCtrlModel, rConv, nCtrlIndex ) )
377 : : {
378 : : // insert into parent container
379 : 0 : const OUString& rCtrlName = mxSiteModel->getName();
380 : : OSL_ENSURE( !rxParentNC->hasByName( rCtrlName ), "VbaFormControl::createAndConvert - multiple controls with equal name" );
381 [ # # ][ # # ]: 0 : ContainerHelper::insertByName( rxParentNC, rCtrlName, Any( xCtrlModel ) );
382 [ # # ]: 0 : }
383 : : }
384 : 0 : catch(const Exception& )
385 : : {
386 : : }
387 : 0 : }
388 : :
389 : : // protected ------------------------------------------------------------------
390 : :
391 : 0 : void VbaFormControl::importControlModel( BinaryInputStream& rInStrm, const AxClassTable& rClassTable )
392 : : {
393 : 0 : createControlModel( rClassTable );
394 [ # # ]: 0 : if( mxCtrlModel.get() )
395 : 0 : mxCtrlModel->importBinaryModel( rInStrm );
396 : 0 : }
397 : :
398 : 0 : void VbaFormControl::importStorage( StorageBase& rStrg, const AxClassTable& rClassTable )
399 : : {
400 : 0 : createControlModel( rClassTable );
401 [ # # ]: 0 : AxContainerModelBase* pContainerModel = dynamic_cast< AxContainerModelBase* >( mxCtrlModel.get() );
402 : : OSL_ENSURE( pContainerModel, "VbaFormControl::importStorage - missing container control model" );
403 [ # # ]: 0 : if( pContainerModel )
404 : : {
405 : : /* Open the 'f' stream containing the model of this control and a list
406 : : of site models for all child controls. */
407 [ # # ][ # # ]: 0 : BinaryXInputStream aFStrm( rStrg.openInputStream( CREATE_OUSTRING( "f" ) ), true );
[ # # ]
408 : : OSL_ENSURE( !aFStrm.isEof(), "VbaFormControl::importStorage - missing 'f' stream" );
409 : :
410 : : /* Read the properties of this container control and the class table
411 : : (into the maClassTable vector) containing a list of GUIDs for
412 : : exotic embedded controls. */
413 [ # # ][ # # ]: 0 : if( !aFStrm.isEof() && pContainerModel->importBinaryModel( aFStrm ) && pContainerModel->importClassTable( aFStrm, maClassTable ) )
[ # # ][ # # ]
[ # # ][ # # ]
414 : : {
415 : : /* Read the site models of all embedded controls (this fills the
416 : : maControls vector). Ignore failure of importSiteModels() but
417 : : try to import as much controls as possible. */
418 [ # # ]: 0 : importEmbeddedSiteModels( aFStrm );
419 : :
420 : : /* Open the 'o' stream containing models of embedded simple
421 : : controls. Stream may be empty or missing, if this control
422 : : contains no controls or only container controls. */
423 [ # # ][ # # ]: 0 : BinaryXInputStream aOStrm( rStrg.openInputStream( CREATE_OUSTRING( "o" ) ), true );
[ # # ]
424 : :
425 : : /* Iterate over all embedded controls, import model from 'o'
426 : : stream (for embedded simple controls) or from the substorage
427 : : (for embedded container controls). */
428 : : maControls.forEachMem( &VbaFormControl::importModelOrStorage,
429 [ # # ][ # # ]: 0 : ::boost::ref( aOStrm ), ::boost::ref( rStrg ), ::boost::cref( maClassTable ) );
[ # # ][ # # ]
430 : :
431 : : /** Final processing on the control and all embedded controls,
432 : : depending on the type of this control. */
433 [ # # ][ # # ]: 0 : finalizeEmbeddedControls( rStrg );
434 [ # # ]: 0 : }
435 : : }
436 : 0 : }
437 : :
438 : 0 : bool VbaFormControl::convertProperties( const Reference< XControlModel >& rxCtrlModel,
439 : : const ControlConverter& rConv, sal_Int32 nCtrlIndex ) const
440 : : {
441 [ # # ][ # # ]: 0 : if( rxCtrlModel.is() && mxSiteModel.get() && mxCtrlModel.get() )
[ # # ][ # # ]
442 : : {
443 : 0 : const OUString& rCtrlName = mxSiteModel->getName();
444 : : OSL_ENSURE( !rCtrlName.isEmpty(), "VbaFormControl::convertProperties - control without name" );
445 [ # # ]: 0 : if( !rCtrlName.isEmpty() )
446 : : {
447 : : // convert all properties
448 [ # # ]: 0 : PropertyMap aPropMap;
449 [ # # ][ # # ]: 0 : mxSiteModel->convertProperties( aPropMap, rConv, mxCtrlModel->getControlType(), nCtrlIndex );
450 [ # # ]: 0 : mxCtrlModel->convertProperties( aPropMap, rConv );
451 [ # # ]: 0 : mxCtrlModel->convertSize( aPropMap, rConv );
452 [ # # ]: 0 : PropertySet aPropSet( rxCtrlModel );
453 [ # # ]: 0 : aPropSet.setProperties( aPropMap );
454 : :
455 : : // bind to control source and row source range
456 [ # # ]: 0 : mxSiteModel->bindToSources( rxCtrlModel, rConv );
457 : :
458 : : // create and convert all embedded controls
459 [ # # ]: 0 : if( !maControls.empty() ) try
460 : : {
461 [ # # ]: 0 : Reference< XNameContainer > xCtrlModelNC( rxCtrlModel, UNO_QUERY_THROW );
462 : : /* Call conversion for all controls. Pass vector index as new
463 : : tab order to make option button groups work correctly. */
464 : : maControls.forEachMemWithIndex( &VbaFormControl::createAndConvert,
465 [ # # ][ # # ]: 0 : ::boost::cref( xCtrlModelNC ), ::boost::cref( rConv ) );
[ # # ][ # # ]
466 : : }
467 [ # # ]: 0 : catch(const Exception& )
468 : : {
469 : : OSL_FAIL( "VbaFormControl::convertProperties - cannot get control container interface" );
470 : : }
471 : :
472 [ # # ]: 0 : return true;
473 : : }
474 : : }
475 : 0 : return false;
476 : : }
477 : :
478 : : // private --------------------------------------------------------------------
479 : :
480 : 0 : void VbaFormControl::createControlModel( const AxClassTable& rClassTable )
481 : : {
482 : : // derived classes may have created their own control model
483 [ # # ][ # # ]: 0 : if( !mxCtrlModel && mxSiteModel.get() )
[ # # ]
484 [ # # ]: 0 : mxCtrlModel = mxSiteModel->createControlModel( rClassTable );
485 : 0 : }
486 : :
487 : 0 : bool VbaFormControl::importSiteModel( BinaryInputStream& rInStrm )
488 : : {
489 [ # # ]: 0 : mxSiteModel.reset( new VbaSiteModel );
490 : 0 : return mxSiteModel->importBinaryModel( rInStrm );
491 : : }
492 : :
493 : 0 : bool VbaFormControl::importEmbeddedSiteModels( BinaryInputStream& rInStrm )
494 : : {
495 [ # # ]: 0 : sal_uInt64 nAnchorPos = rInStrm.tell();
496 : : sal_uInt32 nSiteCount, nSiteDataSize;
497 [ # # ][ # # ]: 0 : rInStrm >> nSiteCount >> nSiteDataSize;
498 [ # # ]: 0 : sal_Int64 nSiteEndPos = rInStrm.tell() + nSiteDataSize;
499 : :
500 : : // skip the site info structure
501 : 0 : sal_uInt32 nSiteIndex = 0;
502 [ # # ][ # # ]: 0 : while( !rInStrm.isEof() && (nSiteIndex < nSiteCount) )
[ # # ]
503 : : {
504 [ # # ]: 0 : rInStrm.skip( 1 ); // site depth
505 [ # # ]: 0 : sal_uInt8 nTypeCount = rInStrm.readuInt8(); // 'type-or-count' byte
506 [ # # ]: 0 : if( getFlag( nTypeCount, VBA_SITEINFO_COUNT ) )
507 : : {
508 : : /* Count flag is set: the 'type-or-count' byte contains the number
509 : : of controls in the lower bits, the type specifier follows in
510 : : the next byte. The type specifier should always be 1 according
511 : : to the specification. */
512 [ # # ]: 0 : rInStrm.skip( 1 );
513 : 0 : nSiteIndex += (nTypeCount & VBA_SITEINFO_MASK);
514 : : }
515 : : else
516 : : {
517 : : /* Count flag is not set: the 'type-or-count' byte contains the
518 : : type specifier of *one* control in the lower bits (this type
519 : : should be 1, see above). */
520 : 0 : ++nSiteIndex;
521 : : }
522 : : }
523 : : // align the stream to 32bit, relative to start of entire site info
524 [ # # ]: 0 : rInStrm.alignToBlock( 4, nAnchorPos );
525 : :
526 : : // import the site models for all embedded controls
527 : 0 : maControls.clear();
528 : 0 : bool bValid = !rInStrm.isEof();
529 [ # # ][ # # ]: 0 : for( nSiteIndex = 0; bValid && (nSiteIndex < nSiteCount); ++nSiteIndex )
[ # # ]
530 : : {
531 [ # # ][ # # ]: 0 : VbaFormControlRef xControl( new VbaFormControl );
[ # # ]
532 [ # # ]: 0 : maControls.push_back( xControl );
533 [ # # ]: 0 : bValid = xControl->importSiteModel( rInStrm );
534 [ # # ]: 0 : }
535 : :
536 [ # # ]: 0 : rInStrm.seek( nSiteEndPos );
537 : 0 : return bValid;
538 : : }
539 : :
540 : 0 : void VbaFormControl::finalizeEmbeddedControls( StorageBase& rStrg )
541 : : {
542 : : /* Store all embedded controls in a temporary vector, so "exit on error"
543 : : will leave this control empty. */
544 [ # # ]: 0 : VbaFormControlVector aControls;
545 : 0 : aControls.swap( maControls );
546 : :
547 : : /* If this is a multipage control, it stores additional data in the 'x'
548 : : stream of its storage. It contains the control identifiers of the form
549 : : page controls that contain the embedded controls of each page.
550 : : Additionally, the order of these pages is stored there (they are not
551 : : nessecarily in the order they are persisted in). */
552 [ # # ][ # # ]: 0 : if( AxMultiPageModel* pMultiPageModel = dynamic_cast< AxMultiPageModel* >( mxCtrlModel.get() ) )
553 : : {
554 : : // read additional attributes from the 'x' stream
555 [ # # ][ # # ]: 0 : BinaryXInputStream aXStrm( rStrg.openInputStream( CREATE_OUSTRING( "x" ) ), true );
[ # # ]
556 : : OSL_ENSURE( !aXStrm.isEof(), "VbaFormControl::finalizeEmbeddedControls - missing 'x' stream" );
557 [ # # ]: 0 : if( aXStrm.isEof() ) return;
558 : :
559 : : // skip the page property structures related to all controls
560 [ # # ]: 0 : for( size_t nSiteIdx = 0, nSiteCount = aControls.size(); nSiteIdx < nSiteCount; ++nSiteIdx )
561 : : {
562 [ # # ]: 0 : AxBinaryPropertyReader aReader( aXStrm );
563 [ # # ]: 0 : aReader.skipUndefinedProperty();
564 [ # # ]: 0 : aReader.skipIntProperty< sal_uInt32 >(); // transition effect
565 [ # # ]: 0 : aReader.skipIntProperty< sal_uInt32 >(); // transition period
566 [ # # ][ # # ]: 0 : if( !aReader.finalizeImport() ) return;
567 [ # # ][ # # ]: 0 : }
568 : :
569 : : // read the multipage property structure containing a list of page IDs
570 : 0 : sal_Int32 nPageCount = 0;
571 : 0 : sal_Int32 nTabStripId = 0;
572 [ # # ]: 0 : AxBinaryPropertyReader aReader( aXStrm );
573 [ # # ]: 0 : aReader.skipUndefinedProperty();
574 [ # # ]: 0 : aReader.readIntProperty< sal_Int32 >( nPageCount );
575 [ # # ]: 0 : aReader.readIntProperty< sal_Int32 >( nTabStripId );
576 [ # # ][ # # ]: 0 : if( !aReader.finalizeImport() ) return;
577 : : // read the array containing all page identifiers in current order
578 : : typedef ::std::vector< sal_Int32 > AxPageIdVector;
579 [ # # ]: 0 : AxPageIdVector aPageIds;
580 [ # # ][ # # ]: 0 : for( sal_Int32 nPage = 0; !aXStrm.isEof() && (nPage < nPageCount); ++nPage )
[ # # ]
581 [ # # ][ # # ]: 0 : aPageIds.push_back( aXStrm.readInt32() );
582 [ # # ]: 0 : if( aXStrm.isEof() ) return;
583 : :
584 : : // check the page count value
585 [ # # ][ # # ]: 0 : bool bValidPageCount = (0 < nPageCount) && (static_cast< size_t >( nPageCount + 1 ) == aControls.size());
586 : : OSL_ENSURE( bValidPageCount, "VbaFormControl::finalizeEmbeddedControls - invalid number of pages" );
587 [ # # ]: 0 : if( !bValidPageCount ) return;
588 : :
589 : : /* Check that this multipage contains the expected controls:
590 : : - a tabstrip control, specified by nTabStripId,
591 : : - form page controls (containing the embedded controls of each page). */
592 : :
593 : : // the controls may be in arbitrary order, first map them by ID
594 [ # # ]: 0 : RefMap< sal_Int32, VbaFormControl > aControlsById;
595 [ # # ][ # # ]: 0 : for( VbaFormControlVector::iterator aIt = aControls.begin(), aEnd = aControls.end(); aIt != aEnd; ++aIt )
596 : : {
597 [ # # ]: 0 : VbaFormControlRef xControl = *aIt;
598 [ # # ]: 0 : sal_Int32 nId = xControl->getControlId();
599 : : OSL_ENSURE( (nId > 0) && !aControlsById.has( nId ), "VbaFormControl::finalizeEmbeddedControls - invalid control ID" );
600 [ # # ][ # # ]: 0 : aControlsById[ nId ] = xControl;
601 [ # # ]: 0 : }
602 : : // store tabstrip in the multipage, it will care about property conversion
603 [ # # ]: 0 : AxTabStripModelRef xTabStripModel;
604 [ # # ]: 0 : VbaFormControlRef xControl = aControlsById.get( nTabStripId );
605 [ # # ]: 0 : if( xControl.get() )
606 [ # # ][ # # ]: 0 : xTabStripModel = ::boost::dynamic_pointer_cast< AxTabStripModel >( xControl->mxCtrlModel );
[ # # ]
607 : : OSL_ENSURE( xTabStripModel.get(), "VbaFormControl::finalizeEmbeddedControls - missing tabstrip control" );
608 [ # # ]: 0 : if( !xTabStripModel ) return;
609 [ # # ]: 0 : pMultiPageModel->setTabStripModel( xTabStripModel );
610 [ # # ]: 0 : aControlsById.erase( nTabStripId );
611 : : // store all pages in maControls in the correct order specified by aPageIds
612 : 0 : sal_Int32 nTabIndex = 0;
613 [ # # ][ # # ]: 0 : for( AxPageIdVector::iterator aIt = aPageIds.begin(), aEnd = aPageIds.end(); aIt != aEnd; ++aIt, ++nTabIndex )
[ # # ]
614 : : {
615 [ # # ][ # # ]: 0 : VbaFormControlRef rControl = aControlsById.get( *aIt );
616 [ # # ][ # # ]: 0 : AxFormPageModel* pFormPageModel = rControl.get() ? dynamic_cast< AxFormPageModel* >( rControl->mxCtrlModel.get() ) : 0;
617 : : OSL_ENSURE( pFormPageModel, "VbaFormControl::finalizeEmbeddedControls - missing formpage control" );
618 : : // do not exit on error but try to collect as much pages as possible
619 [ # # ]: 0 : if( pFormPageModel )
620 : : {
621 : : // get the tab caption from tabstrip control and set it at the formpage
622 [ # # ]: 0 : OUString aCaption = xTabStripModel->getCaption( nTabIndex );
623 [ # # ]: 0 : pFormPageModel->importProperty( XML_Caption, aCaption );
624 : : // store the control in maControls
625 [ # # ]: 0 : maControls.push_back( rControl );
626 [ # # ][ # # ]: 0 : aControlsById.erase( *aIt );
627 : : }
628 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
629 : : }
630 : : else
631 : : {
632 : : /* Reorder the controls appropriately (sort all option buttons of an
633 : : option group together to make grouping work), and erase all plain
634 : : tabstrip controls (currently not supported in UNO dialogs). */
635 : :
636 : : // first, sort all controls by original tab index
637 [ # # ]: 0 : ::std::sort( aControls.begin(), aControls.end(), &compareByTabIndex );
638 : :
639 : : /* Collect the programmatical names of all embedded controls (needed to be
640 : : able to set unused names to new dummy controls created below). */
641 [ # # ]: 0 : VbaControlNamesSet aControlNames;
642 : 0 : VbaControlNameInserter aInserter( aControlNames );
643 [ # # ]: 0 : aControls.forEach( aInserter );
644 : :
645 : : /* Reprocess the sorted list and collect all option button controls that
646 : : are part of the same option group (determined by group name). All
647 : : controls will be stored in a vector of vectors, that collects every
648 : : option button group in one vector element, and other controls between
649 : : these option groups (or leading or trailing controls) in other vector
650 : : elements. If an option button group follows another group, a dummy
651 : : separator control has to be inserted. */
652 : : typedef RefVector< VbaFormControlVector > VbaFormControlVectorVector;
653 [ # # ]: 0 : VbaFormControlVectorVector aControlGroups;
654 : :
655 : : typedef RefMap< OUString, VbaFormControlVector > VbaFormControlVectorMap;
656 [ # # ]: 0 : VbaFormControlVectorMap aOptionGroups;
657 : :
658 : : typedef VbaFormControlVectorMap::mapped_type VbaFormControlVectorRef;
659 : 0 : bool bLastWasOptionButton = false;
660 [ # # ][ # # ]: 0 : for( VbaFormControlVector::iterator aIt = aControls.begin(), aEnd = aControls.end(); aIt != aEnd; ++aIt )
661 : : {
662 [ # # ]: 0 : VbaFormControlRef xControl = *aIt;
663 : 0 : const ControlModelBase* pCtrlModel = xControl->mxCtrlModel.get();
664 [ # # ]: 0 : if ( !pCtrlModel ) // skip unsupported controls
665 : 0 : continue;
666 [ # # ][ # # ]: 0 : if( const AxOptionButtonModel* pOptButtonModel = dynamic_cast< const AxOptionButtonModel* >( pCtrlModel ) )
667 : : {
668 : : // check if a new option group needs to be created
669 : 0 : const OUString& rGroupName = pOptButtonModel->getGroupName();
670 [ # # ]: 0 : VbaFormControlVectorRef& rxOptionGroup = aOptionGroups[ rGroupName ];
671 [ # # ]: 0 : if( !rxOptionGroup )
672 : : {
673 : : /* If last control was an option button too, we have two
674 : : option groups following each other, so a dummy separator
675 : : control is needed. */
676 [ # # ]: 0 : if( bLastWasOptionButton )
677 : : {
678 [ # # ][ # # ]: 0 : VbaFormControlVectorRef xDummyGroup( new VbaFormControlVector );
[ # # ]
679 [ # # ]: 0 : aControlGroups.push_back( xDummyGroup );
680 [ # # ]: 0 : OUString aName = aControlNames.generateDummyName();
681 [ # # ][ # # ]: 0 : VbaFormControlRef xDummyControl( new VbaDummyFormControl( aName ) );
[ # # ]
682 [ # # ][ # # ]: 0 : xDummyGroup->push_back( xDummyControl );
[ # # ]
683 : : }
684 [ # # ][ # # ]: 0 : rxOptionGroup.reset( new VbaFormControlVector );
[ # # ]
685 [ # # ]: 0 : aControlGroups.push_back( rxOptionGroup );
686 : : }
687 : : /* Append the option button to the control group (which is now
688 : : referred by the vector aControlGroups and by the map
689 : : aOptionGroups). */
690 [ # # ]: 0 : rxOptionGroup->push_back( xControl );
691 : 0 : bLastWasOptionButton = true;
692 : : }
693 : : else
694 : : {
695 : : // skip unsupported controls (tabstrips and page controls)
696 [ # # ]: 0 : ApiControlType eCtrlType = pCtrlModel->getControlType();
697 [ # # ][ # # ]: 0 : if( (eCtrlType != API_CONTROL_TABSTRIP) && (eCtrlType != API_CONTROL_PAGE) )
698 : : {
699 : : // open a new control group, if the last group is an option group
700 [ # # ][ # # ]: 0 : if( bLastWasOptionButton || aControlGroups.empty() )
[ # # ]
701 : : {
702 [ # # ][ # # ]: 0 : VbaFormControlVectorRef xControlGroup( new VbaFormControlVector );
[ # # ]
703 [ # # ][ # # ]: 0 : aControlGroups.push_back( xControlGroup );
704 : : }
705 : : // append the control to the last control group
706 [ # # ]: 0 : VbaFormControlVector& rLastGroup = *aControlGroups.back();
707 [ # # ]: 0 : rLastGroup.push_back( xControl );
708 : 0 : bLastWasOptionButton = false;
709 : : }
710 : : }
711 [ # # ][ # # ]: 0 : }
712 : :
713 : : // flatten the vector of vectors of form controls to a single vector
714 [ # # ][ # # ]: 0 : for( VbaFormControlVectorVector::iterator aIt = aControlGroups.begin(), aEnd = aControlGroups.end(); aIt != aEnd; ++aIt )
715 [ # # ]: 0 : maControls.insert( maControls.end(), (*aIt)->begin(), (*aIt)->end() );
716 [ # # ]: 0 : }
717 : : }
718 : :
719 : 0 : /*static*/ bool VbaFormControl::compareByTabIndex( const VbaFormControlRef& rxLeft, const VbaFormControlRef& rxRight )
720 : : {
721 : : // sort controls without model to the end
722 [ # # ]: 0 : sal_Int32 nLeftTabIndex = rxLeft->mxSiteModel.get() ? rxLeft->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
723 [ # # ]: 0 : sal_Int32 nRightTabIndex = rxRight->mxSiteModel.get() ? rxRight->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
724 : 0 : return nLeftTabIndex < nRightTabIndex;
725 : : }
726 : :
727 : : // ============================================================================
728 : :
729 : : namespace {
730 : :
731 : 0 : OUString lclGetQuotedString( const OUString& rCodeLine )
732 : : {
733 : 0 : OUStringBuffer aBuffer;
734 : 0 : sal_Int32 nLen = rCodeLine.getLength();
735 [ # # ][ # # ]: 0 : if( (nLen > 0) && (rCodeLine[ 0 ] == '"') )
[ # # ]
736 : : {
737 : 0 : bool bExitLoop = false;
738 [ # # ][ # # ]: 0 : for( sal_Int32 nIndex = 1; !bExitLoop && (nIndex < nLen); ++nIndex )
[ # # ]
739 : : {
740 : 0 : sal_Unicode cChar = rCodeLine[ nIndex ];
741 : : // exit on closing quote char (but check on double quote chars)
742 [ # # ][ # # ]: 0 : bExitLoop = (cChar == '"') && ((nIndex + 1 == nLen) || (rCodeLine[ nIndex + 1 ] != '"'));
[ # # ]
743 [ # # ]: 0 : if( !bExitLoop )
744 : : {
745 [ # # ]: 0 : aBuffer.append( cChar );
746 : : // skip second quote char
747 [ # # ]: 0 : if( cChar == '"' )
748 : 0 : ++nIndex;
749 : : }
750 : : }
751 : : }
752 [ # # ]: 0 : return aBuffer.makeStringAndClear();
753 : : }
754 : :
755 : 0 : bool lclEatWhitespace( OUString& rCodeLine )
756 : : {
757 : 0 : sal_Int32 nIndex = 0;
758 [ # # ][ # # ]: 0 : while( (nIndex < rCodeLine.getLength()) && ((rCodeLine[ nIndex ] == ' ') || (rCodeLine[ nIndex ] == '\t')) )
[ # # ][ # # ]
759 : 0 : ++nIndex;
760 [ # # ]: 0 : if( nIndex > 0 )
761 : : {
762 : 0 : rCodeLine = rCodeLine.copy( nIndex );
763 : 0 : return true;
764 : : }
765 : 0 : return false;
766 : : }
767 : :
768 : 0 : bool lclEatKeyword( OUString& rCodeLine, const OUString& rKeyword )
769 : : {
770 [ # # ]: 0 : if( rCodeLine.matchIgnoreAsciiCase( rKeyword ) )
771 : : {
772 : 0 : rCodeLine = rCodeLine.copy( rKeyword.getLength() );
773 : : // success, if code line ends after keyword, or if whitespace follows
774 [ # # ][ # # ]: 0 : return rCodeLine.isEmpty() || lclEatWhitespace( rCodeLine );
775 : : }
776 : 0 : return false;
777 : : }
778 : :
779 : : } // namespace
780 : :
781 : : // ----------------------------------------------------------------------------
782 : :
783 : 0 : VbaUserForm::VbaUserForm( const Reference< XComponentContext >& rxContext,
784 : : const Reference< XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) :
785 : : mxContext( rxContext ),
786 : : mxDocModel( rxDocModel ),
787 [ # # ]: 0 : maConverter( rxDocModel, rGraphicHelper, bDefaultColorBgr )
788 : : {
789 : : OSL_ENSURE( mxContext.is(), "VbaUserForm::VbaUserForm - missing component context" );
790 : : OSL_ENSURE( mxDocModel.is(), "VbaUserForm::VbaUserForm - missing document model" );
791 : 0 : }
792 : :
793 : 0 : void VbaUserForm::importForm(
794 : : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel,
795 : : const Reference< XNameContainer >& rxDialogLib,
796 : : StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc )
797 : : {
798 : : OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" );
799 [ # # ][ # # ]: 0 : if( !mxContext.is() || !mxDocModel.is() || !rxDialogLib.is() )
[ # # ][ # # ]
800 : : return;
801 : :
802 : : // check that the '03VBFrame' stream exists, this is required for forms
803 [ # # ][ # # ]: 0 : BinaryXInputStream aInStrm( rVbaFormStrg.openInputStream( CREATE_OUSTRING( "\003VBFrame" ) ), true );
[ # # ]
804 : : OSL_ENSURE( !aInStrm.isEof(), "VbaUserForm::importForm - missing \\003VBFrame stream" );
805 [ # # ]: 0 : if( aInStrm.isEof() )
806 : : return;
807 : :
808 : : // scan for the line 'Begin {GUID} <FormName>'
809 [ # # ]: 0 : TextInputStream aFrameTextStrm( mxContext, aInStrm, eTextEnc );
810 [ # # ]: 0 : const OUString aBegin = CREATE_OUSTRING( "Begin" );
811 : 0 : OUString aLine;
812 : 0 : bool bBeginFound = false;
813 [ # # ][ # # ]: 0 : while( !bBeginFound && !aFrameTextStrm.isEof() )
[ # # ][ # # ]
814 : : {
815 [ # # ]: 0 : aLine = aFrameTextStrm.readLine().trim();
816 : 0 : bBeginFound = lclEatKeyword( aLine, aBegin );
817 : : }
818 : : // check for the specific GUID that represents VBA forms
819 [ # # ][ # # ]: 0 : if( !bBeginFound || !lclEatKeyword( aLine, CREATE_OUSTRING( "{C62A69F0-16DC-11CE-9E98-00AA00574A4F}" ) ) )
[ # # ][ # # ]
[ # # ][ # # ]
820 : : return;
821 : :
822 : : // remaining line is the form name
823 : 0 : OUString aFormName = aLine.trim();
824 : : OSL_ENSURE( !aFormName.isEmpty(), "VbaUserForm::importForm - missing form name" );
825 : : OSL_ENSURE( rModuleName.equalsIgnoreAsciiCase( aFormName ), "VbaUserForm::importFrameStream - form and module name mismatch" );
826 [ # # ]: 0 : if( aFormName.isEmpty() )
827 : 0 : aFormName = rModuleName;
828 [ # # ]: 0 : if( aFormName.isEmpty() )
829 : : return;
830 [ # # ][ # # ]: 0 : mxSiteModel.reset( new VbaSiteModel );
[ # # ]
831 [ # # ]: 0 : mxSiteModel->importProperty( XML_Name, aFormName );
832 : :
833 : : // read the form properties (caption is contained in this '03VBFrame' stream, not in the 'f' stream)
834 [ # # ][ # # ]: 0 : mxCtrlModel.reset( new AxUserFormModel );
[ # # ]
835 : 0 : OUString aKey, aValue;
836 : 0 : bool bExitLoop = false;
837 [ # # ][ # # ]: 0 : while( !bExitLoop && !aFrameTextStrm.isEof() )
[ # # ][ # # ]
838 : : {
839 [ # # ]: 0 : aLine = aFrameTextStrm.readLine().trim();
840 : 0 : bExitLoop = aLine.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "End" ) );
841 [ # # ][ # # ]: 0 : if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
[ # # ][ # # ]
842 : : {
843 [ # # ]: 0 : if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Caption" ) ) )
844 [ # # ][ # # ]: 0 : mxCtrlModel->importProperty( XML_Caption, lclGetQuotedString( aValue ) );
845 [ # # ]: 0 : else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Tag" ) ) )
846 [ # # ][ # # ]: 0 : mxSiteModel->importProperty( XML_Tag, lclGetQuotedString( aValue ) );
847 : : }
848 : : }
849 : :
850 : : // use generic container control functionality to import the embedded controls
851 [ # # ][ # # ]: 0 : importStorage( rVbaFormStrg, AxClassTable() );
852 : :
853 : : try
854 : : {
855 : : // create the dialog model
856 [ # # ]: 0 : OUString aServiceName = mxCtrlModel->getServiceName();
857 [ # # ][ # # ]: 0 : Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
[ # # ]
858 [ # # ][ # # ]: 0 : Reference< XControlModel > xDialogModel( xFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
[ # # ]
859 [ # # ]: 0 : Reference< XNameContainer > xDialogNC( xDialogModel, UNO_QUERY_THROW );
860 : :
861 : : // convert properties and embedded controls
862 [ # # ][ # # ]: 0 : if( convertProperties( xDialogModel, maConverter, 0 ) )
863 : : {
864 : : // export the dialog to XML and insert it into the dialog library
865 [ # # ][ # # ]: 0 : Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, mxContext, rxDocModel ), UNO_SET_THROW );
866 : : OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" );
867 [ # # ][ # # ]: 0 : ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) );
868 [ # # ]: 0 : }
869 : : }
870 [ # # ]: 0 : catch(const Exception& )
871 : : {
872 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
873 : : }
874 : :
875 : : // ============================================================================
876 : :
877 : : } // namespace ole
878 [ + - ][ + - ]: 285 : } // namespace oox
879 : :
880 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|