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