LibreOffice Module oox (master) 1
vbacontrol.cxx
Go to the documentation of this file.
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
21
22#include <algorithm>
23#include <set>
24#include <com/sun/star/awt/XControlModel.hpp>
25#include <com/sun/star/beans/XPropertySet.hpp>
26#include <com/sun/star/container/XNameContainer.hpp>
27#include <com/sun/star/io/XInputStreamProvider.hpp>
28#include <com/sun/star/lang/XMultiServiceFactory.hpp>
29#include <com/sun/star/uno/XComponentContext.hpp>
30#include <osl/diagnose.h>
31#include <rtl/ustrbuf.hxx>
32#include <sal/log.hxx>
42#include <oox/ole/vbahelper.hxx>
43#include <oox/token/properties.hxx>
44#include <oox/token/tokens.hxx>
45#include <unordered_map>
46
47namespace oox::ole {
48
49using namespace ::com::sun::star::awt;
50using namespace ::com::sun::star::container;
51using namespace ::com::sun::star::frame;
52using namespace ::com::sun::star::io;
53using namespace ::com::sun::star::lang;
54using namespace ::com::sun::star::uno;
55
56namespace {
57
58const sal_uInt16 VBA_SITE_CLASSIDINDEX = 0x8000;
59const sal_uInt16 VBA_SITE_INDEXMASK = 0x7FFF;
60const sal_uInt16 VBA_SITE_FORM = 7;
61const sal_uInt16 VBA_SITE_IMAGE = 12;
62const sal_uInt16 VBA_SITE_FRAME = 14;
63const sal_uInt16 VBA_SITE_SPINBUTTON = 16;
64const sal_uInt16 VBA_SITE_COMMANDBUTTON = 17;
65const sal_uInt16 VBA_SITE_TABSTRIP = 18;
66const sal_uInt16 VBA_SITE_LABEL = 21;
67const sal_uInt16 VBA_SITE_TEXTBOX = 23;
68const sal_uInt16 VBA_SITE_LISTBOX = 24;
69const sal_uInt16 VBA_SITE_COMBOBOX = 25;
70const sal_uInt16 VBA_SITE_CHECKBOX = 26;
71const sal_uInt16 VBA_SITE_OPTIONBUTTON = 27;
72const sal_uInt16 VBA_SITE_TOGGLEBUTTON = 28;
73const sal_uInt16 VBA_SITE_SCROLLBAR = 47;
74const sal_uInt16 VBA_SITE_MULTIPAGE = 57;
75const sal_uInt16 VBA_SITE_UNKNOWN = 0x7FFF;
76
77const sal_uInt32 VBA_SITE_TABSTOP = 0x00000001;
78const sal_uInt32 VBA_SITE_VISIBLE = 0x00000002;
79const sal_uInt32 VBA_SITE_OSTREAM = 0x00000010;
80const sal_uInt32 VBA_SITE_DEFFLAGS = 0x00000033;
81
82const sal_uInt8 VBA_SITEINFO_COUNT = 0x80;
83const sal_uInt8 VBA_SITEINFO_MASK = 0x7F;
84
88class VbaControlNamesSet
89{
90public:
91 explicit VbaControlNamesSet();
92
94 void insertName( const VbaFormControl& rControl );
96 OUString generateDummyName();
97
98private:
99 ::std::set< OUString >
101 sal_Int32 mnIndex;
102};
103
104constexpr OUStringLiteral gaDummyBaseName( u"DummyGroupSep" );
105
106VbaControlNamesSet::VbaControlNamesSet() :
107 mnIndex( 0 )
108{
109}
110
111void VbaControlNamesSet::insertName( const VbaFormControl& rControl )
112{
113 OUString aName = rControl.getControlName();
114 if( !aName.isEmpty() )
115 maCtrlNames.insert( aName );
116}
117
118OUString VbaControlNamesSet::generateDummyName()
119{
120 OUString aCtrlName;
121 do
122 {
123 aCtrlName = gaDummyBaseName + OUString::number( ++mnIndex );
124 }
125 while( maCtrlNames.count( aCtrlName ) > 0 );
126 maCtrlNames.insert( aCtrlName );
127 return aCtrlName;
128}
129
131struct VbaControlNameInserter
132{
133public:
134 VbaControlNamesSet& mrCtrlNames;
135 explicit VbaControlNameInserter( VbaControlNamesSet& rCtrlNames ) : mrCtrlNames( rCtrlNames ) {}
136 void operator()( const VbaFormControl& rControl ) { mrCtrlNames.insertName( rControl ); }
137};
138
142class VbaDummyFormControl : public VbaFormControl
143{
144public:
145 explicit VbaDummyFormControl( const OUString& rName );
146};
147
148VbaDummyFormControl::VbaDummyFormControl( const OUString& rName )
149{
150 mxSiteModel = std::make_shared<VbaSiteModel>();
151 mxSiteModel->importProperty( XML_Name, rName );
152 mxSiteModel->importProperty( XML_VariousPropertyBits, OUString( '0' ) );
153
154 mxCtrlModel = std::make_shared<AxLabelModel>();
155 mxCtrlModel->setAwtModelMode();
156 mxCtrlModel->importProperty( XML_Size, "10;10" );
157}
158
159} // namespace
160
161VbaSiteModel::VbaSiteModel() :
162 maPos( 0, 0 ),
163 mnId( 0 ),
164 mnHelpContextId( 0 ),
165 mnFlags( VBA_SITE_DEFFLAGS ),
166 mnStreamLen( 0 ),
167 mnTabIndex( -1 ),
168 mnClassIdOrCache( VBA_SITE_UNKNOWN ),
169 mnGroupId( 0 )
170{
171}
172
174{
175}
176
177void VbaSiteModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
178{
179 switch( nPropId )
180 {
181 case XML_Name: maName = rValue; break;
182 case XML_Tag: maTag = rValue; break;
183 case XML_VariousPropertyBits: mnFlags = AttributeConversion::decodeUnsigned( rValue ); break;
184 }
185}
186
188{
189 AxBinaryPropertyReader aReader( rInStrm );
190 aReader.readStringProperty( maName );
191 aReader.readStringProperty( maTag );
192 aReader.readIntProperty< sal_Int32 >( mnId );
193 aReader.readIntProperty< sal_Int32 >( mnHelpContextId );
194 aReader.readIntProperty< sal_uInt32 >( mnFlags );
195 aReader.readIntProperty< sal_uInt32 >( mnStreamLen );
196 aReader.readIntProperty< sal_Int16 >( mnTabIndex );
197 aReader.readIntProperty< sal_uInt16 >( mnClassIdOrCache );
198 aReader.readPairProperty( maPos );
199 aReader.readIntProperty< sal_uInt16 >( mnGroupId );
200 aReader.skipUndefinedProperty();
201 aReader.readStringProperty( maToolTip );
202 aReader.skipStringProperty(); // license key
205 return aReader.finalizeImport();
206}
207
209{
210 maPos.first += rDistance.first;
211 maPos.second += rDistance.second;
212}
213
215{
216 return !getFlag( mnFlags, VBA_SITE_OSTREAM );
217}
218
220{
221 return isContainer() ? 0 : mnStreamLen;
222}
223
225{
226 if( mnId >= 0 )
227 {
228 OUStringBuffer aBuffer( "i" );
229 if( mnId < 10 )
230 aBuffer.append( '0' );
231 aBuffer.append( mnId );
232 return aBuffer.makeStringAndClear();
233 }
234 return OUString();
235}
236
238{
239 ControlModelRef xCtrlModel;
240
241 sal_Int32 nTypeIndex = static_cast< sal_Int32 >( mnClassIdOrCache & VBA_SITE_INDEXMASK );
242 if( !getFlag( mnClassIdOrCache, VBA_SITE_CLASSIDINDEX ) )
243 {
244 switch( nTypeIndex )
245 {
246 case VBA_SITE_COMMANDBUTTON: xCtrlModel= std::make_shared<AxCommandButtonModel>(); break;
247 case VBA_SITE_LABEL: xCtrlModel= std::make_shared<AxLabelModel>(); break;
248 case VBA_SITE_IMAGE: xCtrlModel= std::make_shared<AxImageModel>(); break;
249 case VBA_SITE_TOGGLEBUTTON: xCtrlModel= std::make_shared<AxToggleButtonModel>(); break;
250 case VBA_SITE_CHECKBOX: xCtrlModel= std::make_shared<AxCheckBoxModel>(); break;
251 case VBA_SITE_OPTIONBUTTON: xCtrlModel= std::make_shared<AxOptionButtonModel>(); break;
252 case VBA_SITE_TEXTBOX: xCtrlModel= std::make_shared<AxTextBoxModel>(); break;
253 case VBA_SITE_LISTBOX: xCtrlModel= std::make_shared<AxListBoxModel>(); break;
254 case VBA_SITE_COMBOBOX: xCtrlModel= std::make_shared<AxComboBoxModel>(); break;
255 case VBA_SITE_SPINBUTTON: xCtrlModel= std::make_shared<AxSpinButtonModel>(); break;
256 case VBA_SITE_SCROLLBAR: xCtrlModel= std::make_shared<AxScrollBarModel>(); break;
257 case VBA_SITE_TABSTRIP: xCtrlModel= std::make_shared<AxTabStripModel>();
258 break;
259 case VBA_SITE_FRAME: xCtrlModel= std::make_shared<AxFrameModel>(); break;
260 case VBA_SITE_MULTIPAGE: xCtrlModel= std::make_shared<AxMultiPageModel>();
261 break;
262 case VBA_SITE_FORM: xCtrlModel= std::make_shared<AxPageModel>();
263 break;
264 default: OSL_FAIL( "VbaSiteModel::createControlModel - unknown type index" );
265 }
266 }
267 else
268 {
269 const OUString* pGuid = ContainerHelper::getVectorElement( rClassTable, nTypeIndex );
270 OSL_ENSURE( pGuid, "VbaSiteModel::createControlModel - invalid class table index" );
271 if( pGuid )
272 {
273 if( *pGuid == COMCTL_GUID_SCROLLBAR_60 )
274 xCtrlModel = std::make_shared<ComCtlScrollBarModel>( 6 );
275 else if( *pGuid == COMCTL_GUID_PROGRESSBAR_50 )
276 xCtrlModel = std::make_shared<ComCtlProgressBarModel>( 5 );
277 else if( *pGuid == COMCTL_GUID_PROGRESSBAR_60 )
278 xCtrlModel = std::make_shared<ComCtlProgressBarModel>( 6 );
279 }
280 }
281
282 if( xCtrlModel )
283 {
284 // user form controls are AWT models
285 xCtrlModel->setAwtModelMode();
286
287 // check that container model matches container flag in site data
288 bool bModelIsContainer = dynamic_cast< const AxContainerModelBase* >( xCtrlModel.get() ) != nullptr;
289 bool bTypeMatch = bModelIsContainer == isContainer();
290 OSL_ENSURE( bTypeMatch, "VbaSiteModel::createControlModel - container type does not match container flag" );
291 if( !bTypeMatch )
292 xCtrlModel.reset();
293 }
294 return xCtrlModel;
295}
296
298 const ControlConverter& rConv, ApiControlType eCtrlType, sal_Int32 nCtrlIndex ) const
299{
300 rPropMap.setProperty( PROP_Name, maName );
301 rPropMap.setProperty( PROP_Tag, maTag );
302
303 if( eCtrlType != API_CONTROL_DIALOG )
304 {
305 rPropMap.setProperty( PROP_HelpText, maToolTip );
306 rPropMap.setProperty( PROP_EnableVisible, getFlag( mnFlags, VBA_SITE_VISIBLE ) );
307 // we need to set the passed control index to make option button groups work
308 if( (0 <= nCtrlIndex) && (nCtrlIndex <= SAL_MAX_INT16) )
309 rPropMap.setProperty( PROP_TabIndex, static_cast< sal_Int16 >( nCtrlIndex ) );
310 // progress bar and group box support TabIndex, but not Tabstop...
311 if( (eCtrlType != API_CONTROL_PROGRESSBAR) && (eCtrlType != API_CONTROL_GROUPBOX) && (eCtrlType != API_CONTROL_FRAME) && (eCtrlType != API_CONTROL_PAGE) )
312 rPropMap.setProperty( PROP_Tabstop, getFlag( mnFlags, VBA_SITE_TABSTOP ) );
313 rConv.convertPosition( rPropMap, maPos );
314 }
315}
316
318{
319}
320
322{
323}
324
326{
327 if( !mxSiteModel )
328 return;
329
330 if( mxSiteModel->isContainer() )
331 {
332 StorageRef xSubStrg = rStrg.openSubStorage( mxSiteModel->getSubStorageName(), false );
333 OSL_ENSURE( xSubStrg, "VbaFormControl::importModelOrStorage - cannot find storage for embedded control" );
334 if( xSubStrg )
335 importStorage( *xSubStrg, rClassTable );
336 }
337 else if( !rInStrm.isEof() )
338 {
339 sal_Int64 nNextStrmPos = rInStrm.tell() + mxSiteModel->getStreamLength();
340 importControlModel( rInStrm, rClassTable );
341 rInStrm.seek( nNextStrmPos );
342 }
343}
344
346{
347 return mxSiteModel ? mxSiteModel->getName() : OUString();
348}
349
350void VbaFormControl::createAndConvert( sal_Int32 nCtrlIndex,
351 const Reference< XNameContainer >& rxParentNC, const ControlConverter& rConv ) const
352{
353 if( !(rxParentNC.is() && mxSiteModel && mxCtrlModel) )
354 return;
355
356 try
357 {
358 // create the control model
359 OUString aServiceName = mxCtrlModel->getServiceName();
360 Reference< XMultiServiceFactory > xModelFactory( rxParentNC, UNO_QUERY_THROW );
361 Reference< XControlModel > xCtrlModel( xModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
362
363 // convert all properties and embedded controls
364 if( convertProperties( xCtrlModel, rConv, nCtrlIndex ) )
365 {
366 // insert into parent container
367 const OUString& rCtrlName = mxSiteModel->getName();
368 OSL_ENSURE( !rxParentNC->hasByName( rCtrlName ), "VbaFormControl::createAndConvert - multiple controls with equal name" );
369 ContainerHelper::insertByName( rxParentNC, rCtrlName, Any( xCtrlModel ) );
370 }
371 }
372 catch(const Exception& )
373 {
374 }
375}
376
377// protected ------------------------------------------------------------------
378
380{
381 createControlModel( rClassTable );
382 if( mxCtrlModel )
383 mxCtrlModel->importBinaryModel( rInStrm );
384}
385
387{
388 createControlModel( rClassTable );
389 AxContainerModelBase* pContainerModel = dynamic_cast< AxContainerModelBase* >( mxCtrlModel.get() );
390 OSL_ENSURE( pContainerModel, "VbaFormControl::importStorage - missing container control model" );
391 if( !pContainerModel )
392 return;
393
394 /* Open the 'f' stream containing the model of this control and a list
395 of site models for all child controls. */
396 BinaryXInputStream aFStrm( rStrg.openInputStream( "f" ), true );
397 OSL_ENSURE( !aFStrm.isEof(), "VbaFormControl::importStorage - missing 'f' stream" );
398
399 /* Read the properties of this container control and the class table
400 (into the maClassTable vector) containing a list of GUIDs for
401 exotic embedded controls. */
402 if( !(!aFStrm.isEof() && pContainerModel->importBinaryModel( aFStrm ) && pContainerModel->importClassTable( aFStrm, maClassTable )) )
403 return;
404
405 /* Read the site models of all embedded controls (this fills the
406 maControls vector). Ignore failure of importSiteModels() but
407 try to import as much controls as possible. */
408 importEmbeddedSiteModels( aFStrm );
409 /* Open the 'o' stream containing models of embedded simple
410 controls. Stream may be empty or missing, if this control
411 contains no controls or only container controls. */
412 BinaryXInputStream aOStrm( rStrg.openInputStream( "o" ), true );
413
414 /* Iterate over all embedded controls, import model from 'o'
415 stream (for embedded simple controls) or from the substorage
416 (for embedded container controls). */
418 ::std::ref( aOStrm ), ::std::ref( rStrg ), ::std::cref( maClassTable ) );
419
420 // Special handling for multi-page which has non-standard
421 // containment and additionally needs to re-order Page children
422 if ( pContainerModel->getControlType() == API_CONTROL_MULTIPAGE )
423 {
424 AxMultiPageModel* pMultiPage = dynamic_cast< AxMultiPageModel* >( pContainerModel );
425 assert(pMultiPage);
426 {
427 BinaryXInputStream aXStrm( rStrg.openInputStream( "x" ), true );
428 pMultiPage->importPageAndMultiPageProperties( aXStrm, maControls.size() );
429 }
430 typedef std::unordered_map< sal_uInt32, std::shared_ptr< VbaFormControl > > IdToPageMap;
431 IdToPageMap idToPage;
432 AxArrayString sCaptions;
433
434 for (auto const& control : maControls)
435 {
436 auto& elem = control->mxCtrlModel;
437 if (!elem)
438 {
439 SAL_WARN("oox", "empty control model");
440 continue;
441 }
442 if (elem->getControlType() == API_CONTROL_PAGE)
443 {
444 VbaSiteModelRef xPageSiteRef = control->mxSiteModel;
445 if ( xPageSiteRef )
446 idToPage[ xPageSiteRef->getId() ] = control;
447 }
448 else if (elem->getControlType() == API_CONTROL_TABSTRIP)
449 {
450 AxTabStripModel* pTabStrip = static_cast<AxTabStripModel*>(elem.get());
451 sCaptions = pTabStrip->maItems;
452 pMultiPage->mnActiveTab = pTabStrip->mnListIndex;
453 pMultiPage->mnTabStyle = pTabStrip->mnTabStyle;
454 }
455 else
456 {
457 SAL_WARN("oox", "unexpected control type " << elem->getControlType());
458 }
459 }
460 // apply caption/titles to pages
461
462 maControls.clear();
463 // need to sort the controls according to the order of the ids
464 if ( sCaptions.size() == idToPage.size() )
465 {
466 AxArrayString::iterator itCaption = sCaptions.begin();
467 for ( const auto& rCtrlId : pMultiPage->mnIDs )
468 {
469 IdToPageMap::iterator iter = idToPage.find( rCtrlId );
470 if ( iter != idToPage.end() )
471 {
472 AxPageModel* pPage = static_cast<AxPageModel*> ( iter->second->mxCtrlModel.get() );
473
474 pPage->importProperty( XML_Caption, *itCaption );
475 maControls.push_back( iter->second );
476 }
477 ++itCaption;
478 }
479 }
480 }
481 /* Reorder the controls (sorts all option buttons of an option
482 group together), and move all children of all embedded frames
483 (group boxes) to this control (UNO group boxes cannot contain
484 other controls). */
486}
487
488bool VbaFormControl::convertProperties( const Reference< XControlModel >& rxCtrlModel,
489 const ControlConverter& rConv, sal_Int32 nCtrlIndex ) const
490{
491 if( rxCtrlModel.is() && mxSiteModel && mxCtrlModel )
492 {
493 const OUString& rCtrlName = mxSiteModel->getName();
494 OSL_ENSURE( !rCtrlName.isEmpty(), "VbaFormControl::convertProperties - control without name" );
495 if( !rCtrlName.isEmpty() )
496 {
497 // convert all properties
498 PropertyMap aPropMap;
499 mxSiteModel->convertProperties( aPropMap, rConv, mxCtrlModel->getControlType(), nCtrlIndex );
500 rConv.bindToSources( rxCtrlModel, mxSiteModel->getControlSource(), mxSiteModel->getRowSource() );
501 mxCtrlModel->convertProperties( aPropMap, rConv );
502 mxCtrlModel->convertSize( aPropMap, rConv );
503 PropertySet aPropSet( rxCtrlModel );
504 aPropSet.setProperties( aPropMap );
505
506 // create and convert all embedded controls
507 if( !maControls.empty() ) try
508 {
509 Reference< XNameContainer > xCtrlModelNC( rxCtrlModel, UNO_QUERY_THROW );
510 /* Call conversion for all controls. Pass vector index as new
511 tab order to make option button groups work correctly. */
513 ::std::cref( xCtrlModelNC ), ::std::cref( rConv ) );
514 }
515 catch(const Exception& )
516 {
517 OSL_FAIL( "VbaFormControl::convertProperties - cannot get control container interface" );
518 }
519
520 return true;
521 }
522 }
523 return false;
524}
525
526// private --------------------------------------------------------------------
527
529{
530 // derived classes may have created their own control model
531 if( !mxCtrlModel && mxSiteModel )
532 mxCtrlModel = mxSiteModel->createControlModel( rClassTable );
533}
534
536{
537 mxSiteModel = std::make_shared<VbaSiteModel>();
538 return mxSiteModel->importBinaryModel( rInStrm );
539}
540
542{
543 sal_uInt64 nAnchorPos = rInStrm.tell();
544 sal_uInt32 nSiteCount, nSiteDataSize;
545 nSiteCount = rInStrm.readuInt32();
546 nSiteDataSize = rInStrm.readuInt32();
547 sal_Int64 nSiteEndPos = rInStrm.tell() + nSiteDataSize;
548
549 // skip the site info structure
550 sal_uInt32 nSiteIndex = 0;
551 while( !rInStrm.isEof() && (nSiteIndex < nSiteCount) )
552 {
553 rInStrm.skip( 1 ); // site depth
554 sal_uInt8 nTypeCount = rInStrm.readuInt8(); // 'type-or-count' byte
555 if( getFlag( nTypeCount, VBA_SITEINFO_COUNT ) )
556 {
557 /* Count flag is set: the 'type-or-count' byte contains the number
558 of controls in the lower bits, the type specifier follows in
559 the next byte. The type specifier should always be 1 according
560 to the specification. */
561 rInStrm.skip( 1 );
562 nSiteIndex += (nTypeCount & VBA_SITEINFO_MASK);
563 }
564 else
565 {
566 /* Count flag is not set: the 'type-or-count' byte contains the
567 type specifier of *one* control in the lower bits (this type
568 should be 1, see above). */
569 ++nSiteIndex;
570 }
571 }
572 // align the stream to 32bit, relative to start of entire site info
573 rInStrm.alignToBlock( 4, nAnchorPos );
574
575 // import the site models for all embedded controls
576 maControls.clear();
577 bool bValid = !rInStrm.isEof();
578 for( nSiteIndex = 0; bValid && (nSiteIndex < nSiteCount); ++nSiteIndex )
579 {
580 VbaFormControlRef xControl = std::make_shared<VbaFormControl>();
581 maControls.push_back( xControl );
582 bValid = xControl->importSiteModel( rInStrm );
583 }
584
585 rInStrm.seek( nSiteEndPos );
586}
587
589{
590 /* This function performs two tasks:
591
592 1) Reorder the controls appropriately (sort all option buttons of an
593 option group together to make grouping work).
594 2) Move all children of all embedded frames (group boxes) to this
595 control (UNO group boxes cannot contain other controls).
596 */
597
598 // first, sort all controls by original tab index
599 ::std::sort( maControls.begin(), maControls.end(), &compareByTabIndex );
600
601 /* Collect the programmatical names of all embedded controls (needed to be
602 able to set unused names to new dummy controls created below). Also
603 collect the names of all children of embedded frames (group boxes).
604 Luckily, names of controls must be unique in the entire form, not just
605 in the current container. */
606 VbaControlNamesSet aControlNames;
607 VbaControlNameInserter aInserter( aControlNames );
608 maControls.forEach( aInserter );
609 for (auto const& control : maControls)
610 if( control->mxCtrlModel && (control->mxCtrlModel->getControlType() == API_CONTROL_GROUPBOX) )
611 control->maControls.forEach( aInserter );
612
613 /* Reprocess the sorted list and collect all option button controls that
614 are part of the same option group (determined by group name). All
615 controls will be stored in a vector of vectors, that collects every
616 option button group in one vector element, and other controls between
617 these option groups (or leading or trailing controls) in other vector
618 elements. If an option button group follows another group, a dummy
619 separator control has to be inserted. */
620 typedef RefVector< VbaFormControlVector > VbaFormControlVectorVector;
621 VbaFormControlVectorVector aControlGroups;
622
623 typedef RefMap< OUString, VbaFormControlVector > VbaFormControlVectorMap;
624 VbaFormControlVectorMap aOptionGroups;
625
626 typedef VbaFormControlVectorMap::mapped_type VbaFormControlVectorRef;
627 bool bLastWasOptionButton = false;
628 for (auto const& control : maControls)
629 {
630 const ControlModelBase* pCtrlModel = control->mxCtrlModel.get();
631
632 if( const AxOptionButtonModel* pOptButtonModel = dynamic_cast< const AxOptionButtonModel* >( pCtrlModel ) )
633 {
634 // check if a new option group needs to be created
635 const OUString& rGroupName = pOptButtonModel->getGroupName();
636 VbaFormControlVectorRef& rxOptionGroup = aOptionGroups[ rGroupName ];
637 if( !rxOptionGroup )
638 {
639 /* If last control was an option button too, we have two
640 option groups following each other, so a dummy separator
641 control is needed. */
642 if( bLastWasOptionButton )
643 {
644 VbaFormControlVectorRef xDummyGroup = std::make_shared<VbaFormControlVector>();
645 aControlGroups.push_back( xDummyGroup );
646 OUString aName = aControlNames.generateDummyName();
647 VbaFormControlRef xDummyControl = std::make_shared<VbaDummyFormControl>( aName );
648 xDummyGroup->push_back( xDummyControl );
649 }
650 rxOptionGroup = std::make_shared<VbaFormControlVector>();
651 aControlGroups.push_back( rxOptionGroup );
652 }
653 /* Append the option button to the control group (which is now
654 referred by the vector aControlGroups and by the map
655 aOptionGroups). */
656 rxOptionGroup->push_back(control);
657 bLastWasOptionButton = true;
658 }
659 else
660 {
661 // open a new control group, if the last group is an option group
662 if( bLastWasOptionButton || aControlGroups.empty() )
663 {
664 VbaFormControlVectorRef xControlGroup = std::make_shared<VbaFormControlVector>();
665 aControlGroups.push_back( xControlGroup );
666 }
667 // append the control to the last control group
668 VbaFormControlVector& rLastGroup = *aControlGroups.back();
669 rLastGroup.push_back(control);
670 bLastWasOptionButton = false;
671
672 // if control is a group box, move all its children to this control
673 if( pCtrlModel && (pCtrlModel->getControlType() == API_CONTROL_GROUPBOX) )
674 {
675 /* Move all embedded controls of the group box relative to the
676 position of the group box. */
677 control->moveEmbeddedToAbsoluteParent();
678 /* Insert all children of the group box into the last control
679 group (following the group box). */
680 rLastGroup.insert( rLastGroup.end(), control->maControls.begin(), control->maControls.end() );
681 control->maControls.clear();
682 // check if last control of the group box is an option button
683 bLastWasOptionButton = dynamic_cast< const AxOptionButtonModel* >( rLastGroup.back()->mxCtrlModel.get() ) != nullptr;
684 }
685 }
686 }
687
688 // flatten the vector of vectors of form controls to a single vector
689 maControls.clear();
690 for (auto const& controlGroup : aControlGroups)
691 maControls.insert( maControls.end(), controlGroup->begin(), controlGroup->end() );
692}
693
695{
696 if( mxSiteModel )
697 mxSiteModel->moveRelative( rDistance );
698}
699
701{
702 if( !mxSiteModel || maControls.empty() )
703 return;
704
705 // distance to move is equal to position of this control in its parent
706 AxPairData aDistance = mxSiteModel->getPosition();
707
708 /* For group boxes: add half of the font height to Y position (VBA
709 positions relative to frame border line, not to 'top' of frame). */
710 const AxFontDataModel* pFontModel = dynamic_cast< const AxFontDataModel* >( mxCtrlModel.get() );
711 if( pFontModel && (pFontModel->getControlType() == API_CONTROL_GROUPBOX) )
712 {
713 sal_Int32 nFontHeight = convertPointToMm100(pFontModel->getFontHeight());
714 aDistance.second += nFontHeight / 2;
715 }
716
717 // move the embedded controls
719}
720
722{
723 // sort controls without model to the end
724 sal_Int32 nLeftTabIndex = rxLeft->mxSiteModel ? rxLeft->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
725 sal_Int32 nRightTabIndex = rxRight->mxSiteModel ? rxRight->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
726 return nLeftTabIndex < nRightTabIndex;
727}
728
729namespace {
730
731OUString lclGetQuotedString( std::u16string_view rCodeLine )
732{
733 OUStringBuffer aBuffer;
734 size_t nLen = rCodeLine.size();
735 if( (nLen > 0) && (rCodeLine[ 0 ] == '"') )
736 {
737 bool bExitLoop = false;
738 for( size_t nIndex = 1; !bExitLoop && (nIndex < nLen); ++nIndex )
739 {
740 sal_Unicode cChar = rCodeLine[ nIndex ];
741 // exit on closing quote char (but check on double quote chars)
742 bExitLoop = (cChar == '"') && ((nIndex + 1 == nLen) || (rCodeLine[ nIndex + 1 ] != '"'));
743 if( !bExitLoop )
744 {
745 aBuffer.append( cChar );
746 // skip second quote char
747 if( cChar == '"' )
748 ++nIndex;
749 }
750 }
751 }
752 return aBuffer.makeStringAndClear();
753}
754
755bool lclEatWhitespace( OUString& rCodeLine )
756{
757 sal_Int32 nIndex = 0;
758 while( (nIndex < rCodeLine.getLength()) && ((rCodeLine[ nIndex ] == ' ') || (rCodeLine[ nIndex ] == '\t')) )
759 ++nIndex;
760 if( nIndex > 0 )
761 {
762 rCodeLine = rCodeLine.copy( nIndex );
763 return true;
764 }
765 return false;
766}
767
768bool lclEatKeyword( OUString& rCodeLine, std::u16string_view rKeyword )
769{
770 if( rCodeLine.matchIgnoreAsciiCase( rKeyword ) )
771 {
772 rCodeLine = rCodeLine.copy( rKeyword.size() );
773 // success, if code line ends after keyword, or if whitespace follows
774 return rCodeLine.isEmpty() || lclEatWhitespace( rCodeLine );
775 }
776 return false;
777}
778
779} // namespace
780
781VbaUserForm::VbaUserForm( const Reference< XComponentContext >& rxContext,
782 const Reference< XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) :
783 mxContext( rxContext ),
784 mxDocModel( rxDocModel ),
785 maConverter( rxDocModel, rGraphicHelper, bDefaultColorBgr )
786{
787 OSL_ENSURE( mxContext.is(), "VbaUserForm::VbaUserForm - missing component context" );
788 OSL_ENSURE( mxDocModel.is(), "VbaUserForm::VbaUserForm - missing document model" );
789}
790
791void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib,
792 StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc )
793{
794 OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" );
795 if( !mxContext.is() || !mxDocModel.is() || !rxDialogLib.is() )
796 return;
797
798 // check that the '03VBFrame' stream exists, this is required for forms
799 BinaryXInputStream aInStrm( rVbaFormStrg.openInputStream( "\003VBFrame" ), true );
800 OSL_ENSURE( !aInStrm.isEof(), "VbaUserForm::importForm - missing \\003VBFrame stream" );
801 if( aInStrm.isEof() )
802 return;
803
804 // scan for the line 'Begin {GUID} <FormName>'
805 TextInputStream aFrameTextStrm( mxContext, aInStrm, eTextEnc );
806 static constexpr OUStringLiteral aBegin = u"Begin";
807 OUString aLine;
808 bool bBeginFound = false;
809 while( !bBeginFound && !aFrameTextStrm.isEof() )
810 {
811 aLine = aFrameTextStrm.readLine().trim();
812 bBeginFound = lclEatKeyword( aLine, aBegin );
813 }
814 // check for the specific GUID that represents VBA forms
815 if( !bBeginFound || !lclEatKeyword( aLine, u"{C62A69F0-16DC-11CE-9E98-00AA00574A4F}" ) )
816 return;
817
818 // remaining line is the form name
819 OUString aFormName = aLine.trim();
820 OSL_ENSURE( !aFormName.isEmpty(), "VbaUserForm::importForm - missing form name" );
821 OSL_ENSURE( rModuleName.equalsIgnoreAsciiCase( aFormName ), "VbaUserForm::importFrameStream - form and module name mismatch" );
822 if( aFormName.isEmpty() )
823 aFormName = rModuleName;
824 if( aFormName.isEmpty() )
825 return;
826 mxSiteModel = std::make_shared<VbaSiteModel>();
827 mxSiteModel->importProperty( XML_Name, aFormName );
828
829 // read the form properties (caption is contained in this '03VBFrame' stream, not in the 'f' stream)
830 mxCtrlModel = std::make_shared<AxUserFormModel>();
831 OUString aKey, aValue;
832 bool bExitLoop = false;
833 while( !bExitLoop && !aFrameTextStrm.isEof() )
834 {
835 aLine = aFrameTextStrm.readLine().trim();
836 bExitLoop = aLine.equalsIgnoreAsciiCase( "End" );
837 if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
838 {
839 if( aKey.equalsIgnoreAsciiCase( "Caption" ) )
840 mxCtrlModel->importProperty( XML_Caption, lclGetQuotedString( aValue ) );
841 else if( aKey.equalsIgnoreAsciiCase( "Tag" ) )
842 mxSiteModel->importProperty( XML_Tag, lclGetQuotedString( aValue ) );
843 }
844 }
845
846 // use generic container control functionality to import the embedded controls
847 importStorage( rVbaFormStrg, AxClassTable() );
848
849 try
850 {
851 // create the dialog model
852 OUString aServiceName = mxCtrlModel->getServiceName();
853 Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
854 Reference< XControlModel > xDialogModel( xFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
855 Reference< XNameContainer > xDialogNC( xDialogModel, UNO_QUERY_THROW );
856
857 // convert properties and embedded controls
858 if( convertProperties( xDialogModel, maConverter, 0 ) )
859 {
860 // export the dialog to XML and insert it into the dialog library
861 Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, mxContext, mxDocModel ), UNO_SET_THROW );
862 OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" );
863 ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) );
864 }
865 }
866 catch(const Exception& )
867 {
868 }
869}
870
871} // namespace oox
872
873/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr auto convertPointToMm100(N n)
#define COMCTL_GUID_PROGRESSBAR_50
Definition: axcontrol.hxx:57
#define COMCTL_GUID_PROGRESSBAR_60
Definition: axcontrol.hxx:58
#define COMCTL_GUID_SCROLLBAR_60
Definition: axcontrol.hxx:56
static sal_uInt32 decodeUnsigned(std::u16string_view rValue)
Returns the 32-bit unsigned integer value from the passed string (decimal).
Interface for binary input stream classes.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement seeking the stream forward by the passed number of bytes.
void alignToBlock(sal_Int32 nBlockSize, sal_Int64 nAnchorPos)
Seeks the stream forward to a position that is a multiple of the passed block size,...
bool isEof() const
Returns true, if the stream position is invalid (EOF).
virtual sal_Int64 tell() const =0
Implementations return the current stream position, if possible.
virtual void seek(sal_Int64 nPos)=0
Implementations seek the stream to the passed position, if the stream is seekable.
Wraps a UNO input stream and provides convenient access functions.
static bool insertByName(const css::uno::Reference< css::container::XNameContainer > &rxNameContainer, const OUString &rName, const css::uno::Any &rObject)
Inserts an object into a name container.
static const VectorType::value_type * getVectorElement(const VectorType &rVector, sal_Int32 nIndex)
Returns the pointer to an existing element of the passed vector, or a null pointer,...
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
A helper that maps property identifiers to property values.
Definition: propertymap.hxx:52
bool setProperty(sal_Int32 nPropId, Type &&rValue)
Sets the specified property to the passed value.
Definition: propertymap.hxx:72
A wrapper for a UNO property set.
Definition: propertyset.hxx:58
void setProperties(const css::uno::Sequence< OUString > &rPropNames, const css::uno::Sequence< css::uno::Any > &rValues)
Puts the passed properties into the property set.
Template for a map of ref-counted objects with additional accessor functions.
Definition: refmap.hxx:41
Template for a vector of ref-counted objects with additional accessor functions.
Definition: refvector.hxx:43
value_type get(sal_Int32 nIndex) const
Returns a reference to the object with the passed index, or 0 on error.
Definition: refvector.hxx:52
void forEach(FunctorType aFunctor) const
Calls the passed functor for every contained object, automatically skips all elements that are empty ...
Definition: refvector.hxx:61
void forEachMemWithIndex(FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2) const
Calls the passed member function of ObjType on every contained object.
Definition: refvector.hxx:109
void forEachMem(FuncType pFunc) const
Calls the passed member function of ObjType on every contained object, automatically skips all elemen...
Definition: refvector.hxx:69
Base class for storage access implementations.
Definition: storagebase.hxx:52
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
StorageRef openSubStorage(const OUString &rStorageName, bool bCreateMissing)
Opens and returns the specified sub storage from the storage.
bool isEof() const
Returns true, if no more text is available in the stream.
OUString readLine()
Reads a text line from the stream.
Import helper to read simple and complex ActiveX form control properties from a binary input stream.
void readIntProperty(DataType &ornValue)
Reads the next integer property value from the stream, if the respective flag in the property mask is...
bool finalizeImport()
Final processing, reads contents of all complex properties.
void readStringProperty(OUString &orValue)
Reads the next string property from the stream, if the respective flag in the property mask is set.
void readPairProperty(AxPairData &orPairData)
Reads the next pair property from the stream, if the respective flag in the property mask is set.
void skipUndefinedProperty()
Has to be called for undefined properties.
void skipStringProperty()
Skips the next string property in the stream, if the respective flag in the property mask is set.
Base class for ActiveX container controls.
Definition: axcontrol.hxx:798
virtual bool importBinaryModel(BinaryInputStream &rInStrm) override
Reads the leading structure in the 'f' stream containing the model for this control.
Definition: axcontrol.cxx:2389
bool importClassTable(BinaryInputStream &rInStrm, AxClassTable &orClassTable)
Reads the class table structure for embedded controls following the own model from the 'f' stream.
Definition: axcontrol.cxx:2432
virtual void importProperty(sal_Int32 nPropId, const OUString &rValue) override
Allows to set single properties specified by XML token identifier.
Definition: axcontrol.cxx:2383
Base class for Forms 2.0 controls supporting text formatting.
Definition: axcontrol.hxx:483
sal_Int16 getFontHeight() const
Returns the font height in points.
Definition: axcontrol.hxx:494
std::vector< sal_uInt32 > mnIDs
Definition: axcontrol.hxx:861
void importPageAndMultiPageProperties(BinaryInputStream &rInStrm, sal_Int32 nPages)
Definition: axcontrol.cxx:2509
Model for a Forms 2.0 option button.
Definition: axcontrol.hxx:670
std::vector< OUString > maItems
Definition: axcontrol.hxx:600
A base class with useful helper functions for something that is able to convert ActiveX and ComCtl fo...
Definition: axcontrol.hxx:194
void bindToSources(const css::uno::Reference< css::awt::XControlModel > &rxCtrlModel, const OUString &rCtrlSource, const OUString &rRowSource, sal_Int32 nRefSheet=0) const
Binds the passed control model to the passed data sources.
Definition: axcontrol.cxx:329
void convertPosition(PropertyMap &rPropMap, const AxPairData &rPos) const
Converts the passed position in 1/100 mm to UNO properties.
Definition: axcontrol.cxx:240
Base class for all models of form controls.
Definition: axcontrol.hxx:347
virtual ApiControlType getControlType() const =0
Derived classes return the UNO control type enum value.
void moveRelative(const AxPairData &rDistance)
Moves the control relative to its current position by the passed distance.
Definition: vbacontrol.cxx:694
OUString getControlName() const
Returns the programmatical name of the control.
Definition: vbacontrol.cxx:345
VbaSiteModelRef mxSiteModel
Common control properties.
Definition: vbacontrol.hxx:177
VbaFormControlVector::value_type VbaFormControlRef
Definition: vbacontrol.hxx:155
void importModelOrStorage(BinaryInputStream &rInStrm, StorageBase &rStrg, const AxClassTable &rClassTable)
Imports the model from the passed stream or storage, depending on the control's type.
Definition: vbacontrol.cxx:325
ControlModelRef mxCtrlModel
Specific control properties.
Definition: vbacontrol.hxx:178
void importStorage(StorageBase &rStrg, const AxClassTable &rClassTable)
Creates and imports the control model, and imports all embedded controls from the passed substorage.
Definition: vbacontrol.cxx:386
void importControlModel(BinaryInputStream &rInStrm, const AxClassTable &rClassTable)
Creates and imports the control model containing properties of the control.
Definition: vbacontrol.cxx:379
VbaFormControlVector maControls
All embedded form controls.
Definition: vbacontrol.hxx:181
void createControlModel(const AxClassTable &rClassTable)
Creates the control model according to the current site model.
Definition: vbacontrol.cxx:528
bool convertProperties(const css::uno::Reference< css::awt::XControlModel > &rxCtrlModel, const ControlConverter &rConv, sal_Int32 nCtrlIndex) const
Converts all control properties, and inserts and converts embedded controls.
Definition: vbacontrol.cxx:488
bool importSiteModel(BinaryInputStream &rInStrm)
Imports the site model data containing common properties of the control.
Definition: vbacontrol.cxx:535
void importEmbeddedSiteModels(BinaryInputStream &rInStrm)
Imports the site models of all embedded controls from the 'f' stream.
Definition: vbacontrol.cxx:541
AxClassTable maClassTable
Class identifiers for exotic embedded controls.
Definition: vbacontrol.hxx:182
void createAndConvert(sal_Int32 nCtrlIndex, const css::uno::Reference< css::container::XNameContainer > &rxParentNC, const ControlConverter &rConv) const
Creates the UNO control model, inserts it into the passed container, and converts all control propert...
Definition: vbacontrol.cxx:350
static bool compareByTabIndex(const VbaFormControlRef &rxLeft, const VbaFormControlRef &rxRight)
Functor for comparing controls by their tab index.
Definition: vbacontrol.cxx:721
void moveEmbeddedToAbsoluteParent()
Moves all embedded controls from their relative position in this control to an absolute position in t...
Definition: vbacontrol.cxx:700
sal_uInt32 mnStreamLen
Size of control stream data.
Definition: vbacontrol.hxx:101
AxPairData maPos
Position in parent container.
Definition: vbacontrol.hxx:97
void importProperty(sal_Int32 nPropId, const OUString &rValue)
Allows to set single properties specified by XML token identifier.
Definition: vbacontrol.cxx:177
sal_uInt32 mnFlags
Various flags.
Definition: vbacontrol.hxx:100
sal_uInt16 mnGroupId
Group identifier for grouped controls.
Definition: vbacontrol.hxx:104
sal_Int32 mnId
Control identifier.
Definition: vbacontrol.hxx:98
OUString maToolTip
Tool tip for the control.
Definition: vbacontrol.hxx:93
ControlModelRef createControlModel(const AxClassTable &rClassTable) const
Tries to create the control model according to the site model.
Definition: vbacontrol.cxx:237
sal_Int32 mnHelpContextId
Help context identifier.
Definition: vbacontrol.hxx:99
OUString maRowSource
Source data for the control in a spreadsheet.
Definition: vbacontrol.hxx:95
sal_uInt32 getStreamLength() const
Returns the length of the stream data for stream based controls.
Definition: vbacontrol.cxx:219
OUString maTag
User defined tag.
Definition: vbacontrol.hxx:92
sal_uInt16 mnClassIdOrCache
Class name identifier or GUID cache index.
Definition: vbacontrol.hxx:103
bool isContainer() const
Returns true, if this control is a container control.
Definition: vbacontrol.cxx:214
void convertProperties(PropertyMap &rPropMap, const ControlConverter &rConv, ApiControlType eCtrlType, sal_Int32 nCtrlIndex) const
Converts all form site properties.
Definition: vbacontrol.cxx:297
void moveRelative(const AxPairData &rDistance)
Moves the control relative to its current position by the passed distance.
Definition: vbacontrol.cxx:208
OUString getSubStorageName() const
Returns the name of the substorage for the container control data.
Definition: vbacontrol.cxx:224
bool importBinaryModel(BinaryInputStream &rInStrm)
Imports the site model data from the passed input stream.
Definition: vbacontrol.cxx:187
OUString maControlSource
Linked cell for the control value in a spreadsheet.
Definition: vbacontrol.hxx:94
sal_Int16 mnTabIndex
Tab order index.
Definition: vbacontrol.hxx:102
OUString maName
Name of the control.
Definition: vbacontrol.hxx:91
VbaUserForm(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XModel > &rxDocModel, const GraphicHelper &rGraphicHelper, bool bDefaultColorBgr)
Definition: vbacontrol.cxx:781
css::uno::Reference< css::frame::XModel > mxDocModel
Definition: vbacontrol.hxx:205
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: vbacontrol.hxx:204
ControlConverter maConverter
Definition: vbacontrol.hxx:206
void importForm(const css::uno::Reference< css::container::XNameContainer > &rxDialogLib, StorageBase &rVbaFormStrg, const OUString &rModuleName, rtl_TextEncoding eTextEnc)
Imports the form and its embedded controls, and inserts the form with all its controls into the passe...
Definition: vbacontrol.cxx:791
sal_uInt16 mnId
Definition: dffdumper.cxx:163
uno::Reference< uno::XComponentContext > mxContext
float u
Reference< XSingleServiceFactory > xFactory
FuncFlags mnFlags
sal_Int32 nIndex
OUString aName
#define SAL_WARN(area, stream)
@ Exception
bool extractKeyValue(OUString &rKey, OUString &rValue, std::u16string_view rKeyValue)
Extracts a key/value pair from a string separated by an equality sign.
Definition: vbahelper.cxx:45
::std::pair< sal_Int32, sal_Int32 > AxPairData
A pair of integer values as a property.
ApiControlType
Enumerates all UNO API control types supported by these filters.
Definition: axcontrol.hxx:152
@ API_CONTROL_PAGE
Definition: axcontrol.hxx:168
@ API_CONTROL_TABSTRIP
Definition: axcontrol.hxx:164
@ API_CONTROL_FRAME
Definition: axcontrol.hxx:167
@ API_CONTROL_MULTIPAGE
Definition: axcontrol.hxx:169
@ API_CONTROL_DIALOG
Definition: axcontrol.hxx:170
@ API_CONTROL_GROUPBOX
Definition: axcontrol.hxx:166
@ API_CONTROL_PROGRESSBAR
Definition: axcontrol.hxx:165
std::shared_ptr< VbaSiteModel > VbaSiteModelRef
Definition: vbacontrol.hxx:107
std::shared_ptr< ControlModelBase > ControlModelRef
Definition: axcontrol.hxx:388
::std::vector< OUString > AxClassTable
Definition: axcontrol.hxx:794
::std::vector< OUString > AxArrayString
An array of string values as a property.
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
bool getFlag(Type nBitField, Type nMask)
Returns true, if at least one of the bits set in nMask is set in nBitField.
Definition: helper.hxx:137
o3tl::enumarray< SvxBoxItemLine, sal_uInt16 > aDistance
unsigned char sal_uInt8
#define SAL_MAX_INT32
#define SAL_MAX_INT16
sal_uInt16 sal_Unicode
::std::set< OUString > maCtrlNames
Definition: vbacontrol.cxx:100
VbaControlNamesSet & mrCtrlNames
Definition: vbacontrol.cxx:134
sal_Int32 mnIndex
Definition: vbacontrol.cxx:101
std::unique_ptr< char[]> aBuffer