LCOV - code coverage report
Current view: top level - oox/source/ole - vbacontrol.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 373 0.3 %
Date: 2012-08-25 Functions: 2 42 4.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 902 0.2 %

           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: */

Generated by: LCOV version 1.10