LCOV - code coverage report
Current view: top level - forms/source/component - FormComponent.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1021 1292 79.0 %
Date: 2015-06-13 12:38:46 Functions: 159 176 90.3 %
Legend: Lines: hit not hit

          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             : #include "componenttools.hxx"
      20             : #include "FormComponent.hxx"
      21             : #include "frm_resource.hrc"
      22             : #include "frm_resource.hxx"
      23             : #include "property.hrc"
      24             : #include "services.hxx"
      25             : 
      26             : #include <com/sun/star/awt/XTextComponent.hpp>
      27             : #include <com/sun/star/awt/XVclWindowPeer.hpp>
      28             : #include <com/sun/star/awt/XWindow.hpp>
      29             : #include <com/sun/star/form/XForm.hpp>
      30             : #include <com/sun/star/form/XLoadable.hpp>
      31             : #include <com/sun/star/io/XMarkableStream.hpp>
      32             : #include <com/sun/star/lang/DisposedException.hpp>
      33             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      34             : #include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
      35             : #include <com/sun/star/sdb/XRowSetSupplier.hpp>
      36             : #include <com/sun/star/sdbc/ColumnValue.hpp>
      37             : #include <com/sun/star/sdbc/DataType.hpp>
      38             : #include <com/sun/star/util/XModifyBroadcaster.hpp>
      39             : 
      40             : #include <comphelper/basicio.hxx>
      41             : #include <comphelper/guarding.hxx>
      42             : #include <comphelper/listenernotification.hxx>
      43             : #include <comphelper/property.hxx>
      44             : #include <connectivity/dbtools.hxx>
      45             : #include <cppuhelper/exc_hlp.hxx>
      46             : #include <cppuhelper/queryinterface.hxx>
      47             : #include <cppuhelper/supportsservice.hxx>
      48             : #include <toolkit/helper/emptyfontdescriptor.hxx>
      49             : #include <tools/debug.hxx>
      50             : #include <tools/diagnose_ex.h>
      51             : 
      52             : #include <functional>
      53             : #include <algorithm>
      54             : 
      55             : namespace frm
      56             : {
      57             : using namespace ::com::sun::star::uno;
      58             : using namespace ::com::sun::star::sdb;
      59             : using namespace ::com::sun::star::sdbc;
      60             : using namespace ::com::sun::star::sdbcx;
      61             : using namespace ::com::sun::star::beans;
      62             : using namespace ::com::sun::star::container;
      63             : using namespace ::com::sun::star::form;
      64             : using namespace ::com::sun::star::awt;
      65             : using namespace ::com::sun::star::io;
      66             : using namespace ::com::sun::star::lang;
      67             : using namespace ::com::sun::star::util;
      68             : using namespace ::com::sun::star::form::binding;
      69             : using namespace ::com::sun::star::form::validation;
      70             : using namespace ::dbtools;
      71             : using namespace ::comphelper;
      72             : 
      73             : // FieldChangeNotifier
      74        1409 : void ControlModelLock::impl_notifyAll_nothrow()
      75             : {
      76        1409 :     m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() );
      77        1409 : }
      78             : 
      79          31 : void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
      80             : {
      81          31 :     sal_Int32 nOldLength = m_aHandles.getLength();
      82          62 :     if  (   ( nOldLength != m_aOldValues.getLength() )
      83          31 :         ||  ( nOldLength != m_aNewValues.getLength() )
      84             :         )
      85           0 :         throw RuntimeException( OUString(), m_rModel );
      86             : 
      87          31 :     m_aHandles.realloc( nOldLength + 1 );
      88          31 :     m_aHandles[ nOldLength ] = _nHandle;
      89          31 :     m_aOldValues.realloc( nOldLength + 1 );
      90          31 :     m_aOldValues[ nOldLength ] = _rOldValue;
      91          31 :     m_aNewValues.realloc( nOldLength + 1 );
      92          31 :     m_aNewValues[ nOldLength ] = _rNewValue;
      93          31 : }
      94             : 
      95             : class FieldChangeNotifier
      96             : {
      97             : public:
      98         781 :     FieldChangeNotifier( ControlModelLock& _rLock )
      99             :         :m_rLock( _rLock )
     100         781 :         ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
     101             :     {
     102         781 :         m_xOldField = m_rModel.getField();
     103         781 :     }
     104             : 
     105         781 :     ~FieldChangeNotifier()
     106         781 :     {
     107         781 :         Reference< XPropertySet > xNewField( m_rModel.getField() );
     108         781 :         if ( m_xOldField != xNewField )
     109          31 :             m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) );
     110         781 :     }
     111             : 
     112             : private:
     113             :     ControlModelLock&           m_rLock;
     114             :     OBoundControlModel&         m_rModel;
     115             :     Reference< XPropertySet >   m_xOldField;
     116             : };
     117             : 
     118             : // base class for form layer controls
     119         341 : OControl::OControl( const Reference< XComponentContext >& _rxContext, const OUString& _rAggregateService, const bool _bSetDelegator )
     120             :             :OComponentHelper(m_aMutex)
     121         341 :             ,m_xContext( _rxContext )
     122             : {
     123             :     // Aggregate VCL Control
     124             :     // Increment the RefCount for aggregates, because the aggregate by itself increments the RefCount in the setDelegator
     125         341 :     osl_atomic_increment( &m_refCount );
     126             :     {
     127         341 :         m_xAggregate.set(_rxContext->getServiceManager()->createInstanceWithContext(_rAggregateService, _rxContext), css::uno::UNO_QUERY);
     128         341 :         m_xControl.set(m_xAggregate, css::uno::UNO_QUERY);
     129             :     }
     130         341 :     osl_atomic_decrement( &m_refCount );
     131             : 
     132         341 :     if ( _bSetDelegator )
     133         307 :         doSetDelegator();
     134         341 : }
     135             : 
     136         604 : OControl::~OControl()
     137             : {
     138         302 :     doResetDelegator();
     139         302 : }
     140             : 
     141         324 : void OControl::doResetDelegator()
     142             : {
     143         324 :     if ( m_xAggregate.is() )
     144         324 :         m_xAggregate->setDelegator( NULL );
     145         324 : }
     146             : 
     147         341 : void OControl::doSetDelegator()
     148             : {
     149         341 :     osl_atomic_increment( &m_refCount );
     150         341 :     if ( m_xAggregate.is() )
     151             :     {   // those brackets are important for some compilers, don't remove!
     152             :         // (they ensure that the temporary object created in the line below
     153             :         // is destroyed *before* the refcount-decrement)
     154         341 :         m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
     155             :     }
     156         341 :     osl_atomic_decrement( &m_refCount );
     157         341 : }
     158             : 
     159             : // UNO Binding
     160       16975 : Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException, std::exception)
     161             : {
     162             :     // ask the base class
     163       16975 :     Any aReturn( OComponentHelper::queryAggregation(_rType) );
     164             :     // ask our own interfaces
     165       16975 :     if (!aReturn.hasValue())
     166             :     {
     167       16145 :         aReturn = OControl_BASE::queryInterface(_rType);
     168             :         // ask our aggregate
     169       16145 :         if (!aReturn.hasValue() && m_xAggregate.is())
     170       10900 :             aReturn = m_xAggregate->queryAggregation(_rType);
     171             :     }
     172             : 
     173       16975 :     return aReturn;
     174             : }
     175             : 
     176           0 : Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException, std::exception)
     177             : {
     178           0 :     return css::uno::Sequence<sal_Int8>();
     179             : }
     180             : 
     181         132 : Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException, std::exception)
     182             : {
     183         132 :     TypeBag aTypes( _getTypes() );
     184             : 
     185         264 :     Reference< XTypeProvider > xProv;
     186         132 :     if ( query_aggregation( m_xAggregate, xProv ) )
     187         132 :         aTypes.addTypes( xProv->getTypes() );
     188             : 
     189         264 :     return aTypes.getTypes();
     190             : }
     191             : 
     192          74 : Sequence<Type> OControl::_getTypes()
     193             : {
     194          74 :     return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
     195             : }
     196             : 
     197             : // OComponentHelper
     198         305 : void OControl::disposing()
     199             : {
     200         305 :     OComponentHelper::disposing();
     201             : 
     202         305 :     m_aWindowStateGuard.attach( NULL, NULL );
     203             : 
     204         305 :     Reference< XComponent > xComp;
     205         305 :     if (query_aggregation(m_xAggregate, xComp))
     206         305 :         xComp->dispose();
     207         305 : }
     208             : 
     209             : // XServiceInfo
     210           0 : sal_Bool SAL_CALL OControl::supportsService(const OUString& _rsServiceName) throw ( RuntimeException, std::exception)
     211             : {
     212           0 :     return cppu::supportsService(this, _rsServiceName);
     213             : }
     214             : 
     215          15 : Sequence< OUString > OControl::getAggregateServiceNames()
     216             : {
     217          15 :     Sequence< OUString > aAggServices;
     218          30 :     Reference< XServiceInfo > xInfo;
     219          15 :     if ( query_aggregation( m_xAggregate, xInfo ) )
     220          15 :         aAggServices = xInfo->getSupportedServiceNames();
     221             : 
     222          30 :     return aAggServices;
     223             : }
     224             : 
     225          15 : Sequence<OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException, std::exception)
     226             : {
     227             :     return ::comphelper::concatSequences(
     228             :         getAggregateServiceNames(),
     229             :         getSupportedServiceNames_Static()
     230          15 :    );
     231             : }
     232             : 
     233          15 : Sequence< OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException )
     234             : {
     235             :     // no own supported service names
     236          15 :     return Sequence< OUString >();
     237             : }
     238             : 
     239             : // XEventListener
     240         841 : void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException, std::exception)
     241             : {
     242         841 :     Reference< XInterface > xAggAsIface;
     243         841 :     query_aggregation(m_xAggregate, xAggAsIface);
     244             : 
     245             :     // does the disposing come from the aggregate?
     246         841 :     if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
     247             :     {   // no -> forward it
     248         582 :         Reference<com::sun::star::lang::XEventListener> xListener;
     249         582 :         if (query_aggregation(m_xAggregate, xListener))
     250         582 :             xListener->disposing(_rEvent);
     251         841 :     }
     252         841 : }
     253             : 
     254             : // XControl
     255         383 : void SAL_CALL OControl::setContext(const Reference< XInterface >& Context) throw (RuntimeException, std::exception)
     256             : {
     257         383 :     if (m_xControl.is())
     258         383 :         m_xControl->setContext(Context);
     259         383 : }
     260             : 
     261          13 : Reference< XInterface > SAL_CALL OControl::getContext() throw (RuntimeException, std::exception)
     262             : {
     263          13 :     return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >();
     264             : }
     265             : 
     266         629 : void OControl::impl_resetStateGuard_nothrow()
     267             : {
     268         629 :     Reference< XWindow2 > xWindow;
     269        1258 :     Reference< XControlModel > xModel;
     270             :     try
     271             :     {
     272         629 :         xWindow.set( getPeer(), UNO_QUERY );
     273         629 :         xModel.set( getModel(), UNO_QUERY );
     274             :     }
     275           0 :     catch( const Exception& )
     276             :     {
     277             :         DBG_UNHANDLED_EXCEPTION();
     278             :     }
     279        1258 :     m_aWindowStateGuard.attach( xWindow, xModel );
     280         629 : }
     281             : 
     282         338 : void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException, std::exception)
     283             : {
     284         338 :     if ( m_xControl.is() )
     285             :     {
     286         338 :         m_xControl->createPeer( _rxToolkit, _rxParent );
     287         338 :         impl_resetStateGuard_nothrow();
     288             :     }
     289         338 : }
     290             : 
     291        5166 : Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException, std::exception)
     292             : {
     293        5166 :     return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
     294             : }
     295             : 
     296         291 : sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException, std::exception)
     297             : {
     298         291 :     if ( !m_xControl.is() )
     299           0 :         return sal_False;
     300             : 
     301         291 :     bool bSuccess = m_xControl->setModel( Model );
     302         291 :     impl_resetStateGuard_nothrow();
     303         291 :     return bSuccess;
     304             : }
     305             : 
     306        2040 : Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException, std::exception)
     307             : {
     308        2040 :     return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
     309             : }
     310             : 
     311          13 : Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException, std::exception)
     312             : {
     313          13 :     return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
     314             : }
     315             : 
     316         210 : void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException, std::exception)
     317             : {
     318         210 :     if (m_xControl.is())
     319         210 :         m_xControl->setDesignMode(bOn);
     320         210 : }
     321             : 
     322       13927 : sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException, std::exception)
     323             : {
     324       13927 :     return m_xControl.is() ? m_xControl->isDesignMode() : sal_True;
     325             : }
     326             : 
     327          13 : sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException, std::exception)
     328             : {
     329          13 :     return m_xControl.is() ? m_xControl->isTransparent() : sal_True;
     330             : }
     331             : 
     332         199 : OBoundControl::OBoundControl( const Reference< XComponentContext >& _rxContext,
     333             :             const OUString& _rAggregateService, const bool _bSetDelegator )
     334             :     :OControl( _rxContext, _rAggregateService, _bSetDelegator )
     335             :     ,m_bLocked(false)
     336             :     ,m_aOriginalFont( EmptyFontDescriptor() )
     337         199 :     ,m_nOriginalTextLineColor( 0 )
     338             : {
     339         199 : }
     340             : 
     341         168 : OBoundControl::~OBoundControl()
     342             : {
     343         168 : }
     344             : 
     345          70 : Sequence< Type> OBoundControl::_getTypes()
     346             : {
     347          70 :     return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes();
     348             : }
     349             : 
     350       14828 : Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException, std::exception)
     351             : {
     352       14828 :     Any aReturn;
     353             : 
     354             :     // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
     355       14828 :     if ( _rType.equals( cppu::UnoType<XTypeProvider>::get() ) )
     356          35 :         aReturn = OControl::queryAggregation( _rType );
     357             : 
     358             :     // ask our own interfaces
     359             :     // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
     360       14828 :     if ( !aReturn.hasValue() )
     361       14793 :         aReturn = OBoundControl_BASE::queryInterface( _rType );
     362             : 
     363             :     // ask the base class
     364       14828 :     if ( !aReturn.hasValue() )
     365       13344 :         aReturn = OControl::queryAggregation( _rType );
     366             : 
     367       14828 :     return aReturn;
     368             : }
     369             : 
     370          22 : sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException, std::exception)
     371             : {
     372          22 :     return m_bLocked;
     373             : }
     374             : 
     375          22 : void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException, std::exception)
     376             : {
     377          22 :     if (m_bLocked == bool(_bLock))
     378          22 :         return;
     379             : 
     380          22 :     osl::MutexGuard aGuard(m_aMutex);
     381          22 :     _setLock(_bLock);
     382          22 :     m_bLocked = _bLock;
     383             : }
     384             : 
     385          22 : void OBoundControl::_setLock(bool _bLock)
     386             : {
     387             :     // try to set the text component to readonly
     388          22 :     Reference< XWindowPeer > xPeer = getPeer();
     389          44 :     Reference< XTextComponent > xText( xPeer, UNO_QUERY );
     390             : 
     391          22 :     if ( xText.is() )
     392          16 :         xText->setEditable( !_bLock );
     393             :     else
     394             :     {
     395             :         // disable the window
     396           6 :         Reference< XWindow > xComp( xPeer, UNO_QUERY );
     397           6 :         if ( xComp.is() )
     398           6 :             xComp->setEnable( !_bLock );
     399          22 :     }
     400          22 : }
     401             : 
     402         155 : sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException, std::exception)
     403             : {
     404         155 :     return OControl::setModel( _rxModel );
     405             : }
     406             : 
     407         398 : void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException, std::exception)
     408             : {
     409             :     // just disambiguate
     410         398 :     OControl::disposing(Source);
     411         398 : }
     412             : 
     413         171 : void OBoundControl::disposing()
     414             : {
     415         171 :     OControl::disposing();
     416         171 : }
     417             : 
     418             : // OControlModel
     419          30 : Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException, std::exception)
     420             : {
     421          30 :     return css::uno::Sequence<sal_Int8>();
     422             : }
     423             : 
     424          86 : Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException, std::exception)
     425             : {
     426          86 :     TypeBag aTypes( _getTypes() );
     427             : 
     428         172 :     Reference< XTypeProvider > xProv;
     429             : 
     430          86 :     if ( query_aggregation( m_xAggregate, xProv ) )
     431          86 :         aTypes.addTypes( xProv->getTypes() );
     432             : 
     433         172 :     return aTypes.getTypes();
     434             : }
     435             : 
     436          86 : Sequence<Type> OControlModel::_getTypes()
     437             : {
     438             :     return TypeBag( OComponentHelper::getTypes(),
     439             :         OPropertySetAggregationHelper::getTypes(),
     440             :         OControlModel_BASE::getTypes()
     441          86 :     ).getTypes();
     442             : }
     443             : 
     444      108557 : Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
     445             : {
     446             :     // base class 1
     447      108557 :     Any aReturn(OComponentHelper::queryAggregation(_rType));
     448             : 
     449             :     // base class 2
     450      108557 :     if (!aReturn.hasValue())
     451             :     {
     452       82010 :         aReturn = OControlModel_BASE::queryInterface(_rType);
     453             : 
     454             :         // our own interfaces
     455       82010 :         if (!aReturn.hasValue())
     456             :         {
     457       76673 :             aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
     458             :             // our aggregate
     459       76673 :             if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(cppu::UnoType<XCloneable>::get()))
     460       44650 :                 aReturn = m_xAggregate->queryAggregation(_rType);
     461             :         }
     462             :     }
     463      108557 :     return aReturn;
     464             : }
     465             : 
     466          17 : void OControlModel::readHelpTextCompatibly(const css::uno::Reference< css::io::XObjectInputStream >& _rxInStream)
     467             : {
     468          17 :     OUString sHelpText;
     469          17 :     ::comphelper::operator>>( _rxInStream, sHelpText);
     470             :     try
     471             :     {
     472          17 :         if (m_xAggregateSet.is())
     473          17 :             m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText));
     474             :     }
     475           0 :     catch(const Exception&)
     476             :     {
     477             :         SAL_WARN("forms.component", "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
     478             :         DBG_UNHANDLED_EXCEPTION();
     479          17 :     }
     480          17 : }
     481             : 
     482          17 : void OControlModel::writeHelpTextCompatibly(const css::uno::Reference< css::io::XObjectOutputStream >& _rxOutStream)
     483             : {
     484          17 :     OUString sHelpText;
     485             :     try
     486             :     {
     487          17 :         if (m_xAggregateSet.is())
     488          17 :             m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
     489             :     }
     490           0 :     catch(const Exception&)
     491             :     {
     492             :         SAL_WARN("forms.component", "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
     493             :         DBG_UNHANDLED_EXCEPTION();
     494             :     }
     495          17 :     ::comphelper::operator<<( _rxOutStream, sHelpText);
     496          17 : }
     497             : 
     498         594 : OControlModel::OControlModel(
     499             :             const Reference<XComponentContext>& _rxContext,
     500             :             const OUString& _rUnoControlModelTypeName,
     501             :             const OUString& rDefault, const bool _bSetDelegator)
     502             :     :OComponentHelper(m_aMutex)
     503             :     ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
     504             :     ,m_xContext( _rxContext )
     505             :     ,m_lockCount( 0 )
     506             :     ,m_aPropertyBagHelper( *this )
     507             :     ,m_nTabIndex(FRM_DEFAULT_TABINDEX)
     508             :     ,m_nClassId(FormComponentType::CONTROL)
     509             :     ,m_bNativeLook( false )
     510             :     ,m_bGenerateVbEvents( false )
     511             :     ,m_nControlTypeinMSO(0) // 0 : default value is create from AOO
     512         594 :     ,m_nObjIDinMSO(INVALID_OBJ_ID_IN_MSO)
     513             :     // form controls are usually embedded into documents, not dialogs, and in documents
     514             :     // the native look is ugly...
     515             :     // #i37342#
     516             : {
     517         594 :     if (!_rUnoControlModelTypeName.isEmpty())  // the is a model we have to aggregate
     518             :     {
     519         455 :         osl_atomic_increment(&m_refCount);
     520             :         {
     521         455 :             m_xAggregate = Reference<XAggregation>(m_xContext->getServiceManager()->createInstanceWithContext(_rUnoControlModelTypeName, m_xContext), UNO_QUERY);
     522         455 :             setAggregation(m_xAggregate);
     523             : 
     524         455 :             if ( m_xAggregateSet.is() )
     525             :             {
     526             :                 try
     527             :                 {
     528         455 :                     if ( !rDefault.isEmpty() )
     529         390 :                         m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) );
     530             :                 }
     531           0 :                 catch( const Exception& )
     532             :                 {
     533             :                     SAL_WARN("forms.component",  "OControlModel::OControlModel: caught an exception!");
     534             :                     DBG_UNHANDLED_EXCEPTION();
     535             :                 }
     536             :             }
     537             :         }
     538         455 :         if (_bSetDelegator)
     539         142 :             doSetDelegator();
     540             : 
     541             :         // Refcount is at NULL again
     542         455 :         osl_atomic_decrement(&m_refCount);
     543             :     }
     544         594 : }
     545             : 
     546          21 : OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory, const bool _bCloneAggregate, const bool _bSetDelegator )
     547             :     :OComponentHelper( m_aMutex )
     548             :     ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
     549             :     ,m_xContext( _rxFactory )
     550             :     ,m_lockCount( 0 )
     551             :     ,m_aPropertyBagHelper( *this )
     552             :     ,m_nTabIndex( FRM_DEFAULT_TABINDEX )
     553          21 :     ,m_nClassId( FormComponentType::CONTROL )
     554             : {
     555             :     DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
     556             : 
     557             :     // copy members
     558          21 :     m_aName = _pOriginal->m_aName;
     559          21 :     m_aTag = _pOriginal->m_aTag;
     560          21 :     m_nTabIndex = _pOriginal->m_nTabIndex;
     561          21 :     m_nClassId = _pOriginal->m_nClassId;
     562          21 :     m_bNativeLook = _pOriginal->m_bNativeLook;
     563          21 :     m_bGenerateVbEvents = _pOriginal->m_bGenerateVbEvents;
     564          21 :     m_nControlTypeinMSO = _pOriginal->m_nControlTypeinMSO;
     565          21 :     m_nObjIDinMSO = _pOriginal->m_nObjIDinMSO;
     566             : 
     567          21 :     if ( _bCloneAggregate )
     568             :     {
     569             :         // temporarily increment refcount because of temporary references to ourself in the following
     570          19 :         osl_atomic_increment( &m_refCount );
     571             :         {
     572             :             // transfer the (only, at the very moment!) ref count
     573          19 :             m_xAggregate = createAggregateClone( _pOriginal );
     574             : 
     575             :             // set aggregation (retrieve other direct interfaces of the aggregate)
     576          19 :             setAggregation( m_xAggregate );
     577             :         }
     578             : 
     579             :         // set the delegator, if allowed by our derived class
     580          19 :         if ( _bSetDelegator )
     581           4 :             doSetDelegator();
     582             : 
     583             :         // decrement ref count
     584          19 :         osl_atomic_decrement( &m_refCount );
     585             :     }
     586          21 : }
     587             : 
     588        1164 : OControlModel::~OControlModel()
     589             : {
     590             :     // release the aggregate
     591         582 :     doResetDelegator( );
     592         582 : }
     593             : 
     594           6 : void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
     595             : {
     596             :     // nothing to do in this base class
     597           6 : }
     598             : 
     599         893 : void OControlModel::doResetDelegator()
     600             : {
     601         893 :     if (m_xAggregate.is())
     602         861 :         m_xAggregate->setDelegator(NULL);
     603         893 : }
     604             : 
     605         583 : void OControlModel::doSetDelegator()
     606             : {
     607         583 :     osl_atomic_increment(&m_refCount);
     608         583 :     if (m_xAggregate.is())
     609             :     {
     610         581 :         m_xAggregate->setDelegator(static_cast<XWeak*>(this));
     611             :     }
     612         583 :     osl_atomic_decrement(&m_refCount);
     613         583 : }
     614             : 
     615             : // XChild
     616        4953 : Reference< XInterface > SAL_CALL OControlModel::getParent() throw(RuntimeException, std::exception)
     617             : {
     618        4953 :     return m_xParent;
     619             : }
     620             : 
     621         937 : void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException, std::exception)
     622             : {
     623         937 :     osl::MutexGuard aGuard(m_aMutex);
     624             : 
     625        1874 :     Reference<XComponent> xComp(m_xParent, UNO_QUERY);
     626         937 :     if (xComp.is())
     627         287 :         xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
     628             : 
     629         937 :     m_xParent = _rxParent;
     630         937 :     xComp.set(m_xParent, css::uno::UNO_QUERY);
     631             : 
     632         937 :     if ( xComp.is() )
     633        1337 :         xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
     634         937 : }
     635             : 
     636             : // XNamed
     637         185 : OUString SAL_CALL OControlModel::getName() throw(RuntimeException, std::exception)
     638             : {
     639         185 :     OUString aReturn;
     640             :     try
     641             :     {
     642         185 :         OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn;
     643             :     }
     644           0 :     catch (const css::beans::UnknownPropertyException&)
     645             :     {
     646           0 :         css::uno::Any a(cppu::getCaughtException());
     647             :         throw WrappedTargetRuntimeException(
     648             :             "OControlModel::getName",
     649             :             *this,
     650             :             a
     651           0 :         );
     652             :     }
     653         185 :     return aReturn;
     654             : }
     655             : 
     656          36 : void SAL_CALL OControlModel::setName(const OUString& _rName) throw(RuntimeException, std::exception)
     657             : {
     658             :     try
     659             :     {
     660          36 :         setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName));
     661             :     }
     662           0 :     catch (const css::beans::UnknownPropertyException&)
     663             :     {
     664           0 :         css::uno::Any a(cppu::getCaughtException());
     665             :         throw WrappedTargetRuntimeException(
     666             :             "OControlModel::setName",
     667             :             *this,
     668             :             a
     669           0 :         );
     670             :     }
     671          36 : }
     672             : 
     673             : // XServiceInfo
     674         304 : sal_Bool SAL_CALL OControlModel::supportsService(const OUString& _rServiceName) throw ( RuntimeException, std::exception)
     675             : {
     676         304 :     return cppu::supportsService(this, _rServiceName);
     677             : }
     678             : 
     679         365 : Sequence< OUString > OControlModel::getAggregateServiceNames()
     680             : {
     681         365 :     Sequence< OUString > aAggServices;
     682         730 :     Reference< XServiceInfo > xInfo;
     683         365 :     if ( query_aggregation( m_xAggregate, xInfo ) )
     684         359 :         aAggServices = xInfo->getSupportedServiceNames();
     685         730 :     return aAggServices;
     686             : }
     687             : 
     688          20 : Sequence<OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException, std::exception)
     689             : {
     690             :     return ::comphelper::concatSequences(
     691             :         getAggregateServiceNames(),
     692             :         getSupportedServiceNames_Static()
     693          20 :     );
     694             : }
     695             : 
     696         371 : Sequence< OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
     697             : {
     698         371 :     Sequence< OUString > aServiceNames( 2 );
     699         371 :     aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT;
     700         371 :     aServiceNames[ 1 ] = "com.sun.star.form.FormControlModel";
     701         371 :     return aServiceNames;
     702             : }
     703             : 
     704             : // XEventListener
     705         266 : void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException, std::exception)
     706             : {
     707             :     // release the parent
     708         266 :     if (_rSource.Source == m_xParent)
     709             :     {
     710         109 :         osl::MutexGuard aGuard(m_aMutex);
     711         109 :         m_xParent = NULL;
     712             :     }
     713             :     else
     714             :     {
     715         157 :         Reference<com::sun::star::lang::XEventListener> xEvtLst;
     716         157 :         if (query_aggregation(m_xAggregate, xEvtLst))
     717             :         {
     718          46 :             osl::MutexGuard aGuard(m_aMutex);
     719          46 :             xEvtLst->disposing(_rSource);
     720         157 :         }
     721             :     }
     722         266 : }
     723             : 
     724             : // OComponentHelper
     725         583 : void OControlModel::disposing()
     726             : {
     727         583 :     OPropertySetAggregationHelper::disposing();
     728             : 
     729         583 :     Reference<com::sun::star::lang::XComponent> xComp;
     730         583 :     if (query_aggregation(m_xAggregate, xComp))
     731         450 :         xComp->dispose();
     732             : 
     733         583 :     setParent(Reference<XFormComponent>());
     734             : 
     735         583 :     m_aPropertyBagHelper.dispose();
     736         583 : }
     737             : 
     738          18 : void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
     739             : {
     740          18 :     Reference< XPersistObject > xPersist;
     741          18 :     if ( query_aggregation( m_xAggregate, xPersist ) )
     742          15 :         xPersist->write( _rxOutStream );
     743          18 : }
     744             : 
     745          15 : void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
     746             : {
     747          15 :     Reference< XPersistObject > xPersist;
     748          15 :     if ( query_aggregation( m_xAggregate, xPersist ) )
     749          15 :         xPersist->read( _rxInStream );
     750          15 : }
     751             : 
     752          20 : void SAL_CALL OControlModel::write(const Reference<css::io::XObjectOutputStream>& _rxOutStream)
     753             :                         throw(css::io::IOException, RuntimeException, std::exception)
     754             : {
     755          20 :     osl::MutexGuard aGuard(m_aMutex);
     756             : 
     757             :     // 1. writing the UnoControls
     758          40 :     Reference<css::io::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
     759          20 :     if ( !xMark.is() )
     760             :     {
     761             :         throw IOException(
     762             :             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
     763             :             static_cast< ::cppu::OWeakObject* >( this )
     764           0 :         );
     765             :     }
     766             : 
     767          20 :     sal_Int32 nMark = xMark->createMark();
     768          20 :     sal_Int32 nLen = 0;
     769             : 
     770          20 :     _rxOutStream->writeLong(nLen);
     771             : 
     772          20 :     writeAggregate( _rxOutStream );
     773             : 
     774             :     // determining the length
     775          20 :     nLen = xMark->offsetToMark(nMark) - 4;
     776          20 :     xMark->jumpToMark(nMark);
     777          20 :     _rxOutStream->writeLong(nLen);
     778          20 :     xMark->jumpToFurthest();
     779          20 :     xMark->deleteMark(nMark);
     780             : 
     781             :     // 2. writing a version number
     782          20 :     _rxOutStream->writeShort(0x0003);
     783             : 
     784             :     // 3. writing the general properties
     785          20 :     ::comphelper::operator<<( _rxOutStream, m_aName);
     786          20 :     _rxOutStream->writeShort(m_nTabIndex);
     787          40 :     ::comphelper::operator<<( _rxOutStream, m_aTag); // 3rd version
     788             : 
     789             :     // IMPORTANT NOTE!
     790             :     // don't write any new members here: this wouldn't be compatible with older versions, as OControlModel
     791             :     // is a base class which is called in derived classes "read" method. So if you increment the version
     792             :     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
     793             :     // in anything from data loss to crash.
     794             :     // EOIN!
     795          20 : }
     796             : 
     797          20 : void OControlModel::read(const Reference<css::io::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException, std::exception)
     798             : {
     799          20 :     osl::MutexGuard aGuard(m_aMutex);
     800             : 
     801          40 :     Reference<css::io::XMarkableStream> xMark(InStream, UNO_QUERY);
     802          20 :     if ( !xMark.is() )
     803             :     {
     804             :         throw IOException(
     805             :             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
     806             :             static_cast< ::cppu::OWeakObject* >( this )
     807           0 :         );
     808             :     }
     809             : 
     810             :     // 1. reading the UnoControls
     811          20 :     sal_Int32 nLen = InStream->readLong();
     812          20 :     if (nLen)
     813             :     {
     814          17 :         sal_Int32 nMark = xMark->createMark();
     815             : 
     816             :         try
     817             :         {
     818          17 :             readAggregate( InStream );
     819             :         }
     820             : 
     821           0 :         catch( const Exception& )
     822             :         {
     823             :             DBG_UNHANDLED_EXCEPTION();
     824             :         }
     825             : 
     826          17 :         xMark->jumpToMark(nMark);
     827          17 :         InStream->skipBytes(nLen);
     828          17 :         xMark->deleteMark(nMark);
     829             :     }
     830             : 
     831             :     // 2. reading the version number
     832          20 :     sal_uInt16 nVersion = InStream->readShort();
     833             : 
     834             :     // 3. reading the general properties
     835          20 :     ::comphelper::operator>>( InStream, m_aName);
     836          20 :     m_nTabIndex  = InStream->readShort();
     837             : 
     838          20 :     if (nVersion > 0x0002)
     839          20 :         ::comphelper::operator>>( InStream, m_aTag);
     840             : 
     841             :     // we had a version where we wrote the help text
     842          20 :     if (nVersion == 0x0004)
     843           0 :         readHelpTextCompatibly(InStream);
     844             : 
     845          20 :     DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
     846             :     // 4 was the version where we wrote the help text
     847             :     // later versions shouldn't exist (see write for a detailed comment)
     848          20 : }
     849             : 
     850          16 : PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
     851             : {
     852             :     // simply compare the current and the default value
     853          16 :     Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
     854          32 :     Any aDefaultValue;  getFastPropertyValue( aDefaultValue, _nHandle );
     855             : 
     856             :     bool bEqual = uno_type_equalData(
     857          32 :             const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
     858          32 :             const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
     859             :             reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
     860             :             reinterpret_cast< uno_ReleaseFunc >(cpp_release)
     861          48 :         );
     862          32 :     return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
     863             : }
     864             : 
     865           3 : void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle)
     866             : {
     867           3 :     Any aDefault = getPropertyDefaultByHandle( _nHandle );
     868             : 
     869           6 :     Any aConvertedValue, aOldValue;
     870           3 :     if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
     871             :     {
     872           0 :         setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
     873             :         // TODO: fire the property change
     874           3 :     }
     875           3 : }
     876             : 
     877           4 : Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
     878             : {
     879           4 :     Any aReturn;
     880           4 :     switch ( _nHandle )
     881             :     {
     882             :         case PROPERTY_ID_NAME:
     883             :         case PROPERTY_ID_TAG:
     884           0 :             aReturn <<= OUString();
     885           0 :             break;
     886             :         case PROPERTY_ID_CLASSID:
     887           0 :             aReturn <<= (sal_Int16)FormComponentType::CONTROL;
     888           0 :             break;
     889             :         case PROPERTY_ID_TABINDEX:
     890           0 :             aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX;
     891           0 :             break;
     892             :         case PROPERTY_ID_NATIVE_LOOK:
     893           0 :             aReturn <<= true;
     894           0 :             break;
     895             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     896           0 :             aReturn <<= false;
     897           0 :             break;
     898             :         // added for exporting OCX control
     899             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     900           2 :             aReturn <<= (sal_Int16)0;
     901           2 :             break;
     902             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     903           2 :             aReturn <<= (sal_uInt16)INVALID_OBJ_ID_IN_MSO;
     904           2 :             break;
     905             :         default:
     906           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     907           0 :                 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn );
     908             :             else
     909             :                 SAL_WARN("forms.component",  "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
     910             :     }
     911           4 :     return aReturn;
     912             : }
     913             : 
     914       57175 : void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
     915             : {
     916       57175 :     switch ( _nHandle )
     917             :     {
     918             :         case PROPERTY_ID_NAME:
     919        4764 :             _rValue <<= m_aName;
     920        4764 :             break;
     921             :         case PROPERTY_ID_TAG:
     922        1371 :             _rValue <<= m_aTag;
     923        1371 :             break;
     924             :         case PROPERTY_ID_CLASSID:
     925        1899 :             _rValue <<= m_nClassId;
     926        1899 :             break;
     927             :         case PROPERTY_ID_TABINDEX:
     928        2625 :             _rValue <<= m_nTabIndex;
     929        2625 :             break;
     930             :         case PROPERTY_ID_NATIVE_LOOK:
     931        1237 :             _rValue <<= m_bNativeLook;
     932        1237 :             break;
     933             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     934         915 :             _rValue <<= m_bGenerateVbEvents;
     935             :         // added for exporting OCX control
     936             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     937        2151 :             _rValue <<= (sal_Int16)m_nControlTypeinMSO;
     938        2151 :             break;
     939             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     940        1239 :             _rValue <<= (sal_uInt16)m_nObjIDinMSO;
     941        1239 :             break;
     942             :         default:
     943       41889 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     944           0 :                 m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue );
     945             :             else
     946       41889 :                 OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
     947       41889 :             break;
     948             :     }
     949       57175 : }
     950             : 
     951        4976 : sal_Bool OControlModel::convertFastPropertyValue(
     952             :                         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
     953             :                         throw (com::sun::star::lang::IllegalArgumentException)
     954             : {
     955        4976 :     bool bModified(false);
     956        4976 :     switch (_nHandle)
     957             :     {
     958             :         case PROPERTY_ID_NAME:
     959        1247 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
     960        1246 :             break;
     961             :         case PROPERTY_ID_TAG:
     962         754 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
     963         754 :             break;
     964             :         case PROPERTY_ID_TABINDEX:
     965         752 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
     966         752 :             break;
     967             :         case PROPERTY_ID_NATIVE_LOOK:
     968         690 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
     969         690 :             break;
     970             :         case PROPERTY_ID_GENERATEVBAEVENTS:
     971          91 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bGenerateVbEvents);
     972          91 :             break;
     973             :         // added for exporting OCX control
     974             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
     975         723 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nControlTypeinMSO);
     976         723 :             break;
     977             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
     978         719 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nObjIDinMSO);
     979         719 :             break;
     980             :         default:
     981           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
     982           0 :                 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
     983             :             else
     984             :                 SAL_WARN("forms.component",  "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
     985           0 :             break;
     986             :     }
     987        4975 :     return bModified;
     988             : }
     989             : 
     990        1532 : void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
     991             :                         throw (Exception, std::exception)
     992             : {
     993        1532 :     switch (_nHandle)
     994             :     {
     995             :         case PROPERTY_ID_NAME:
     996             :             DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<OUString>::get(),
     997             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
     998         641 :             _rValue >>= m_aName;
     999         641 :             break;
    1000             :         case PROPERTY_ID_TAG:
    1001             :             DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<OUString>::get(),
    1002             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
    1003         181 :             _rValue >>= m_aTag;
    1004         181 :             break;
    1005             :         case PROPERTY_ID_TABINDEX:
    1006             :             DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<sal_Int16>::get(),
    1007             :                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
    1008         177 :             _rValue >>= m_nTabIndex;
    1009         177 :             break;
    1010             :         case PROPERTY_ID_NATIVE_LOOK:
    1011         135 :             OSL_VERIFY( _rValue >>= m_bNativeLook );
    1012         135 :             break;
    1013             :         case PROPERTY_ID_GENERATEVBAEVENTS:
    1014          66 :             OSL_VERIFY( _rValue >>= m_bGenerateVbEvents );
    1015          66 :             break;
    1016             :         // added for exporting OCX control
    1017             :         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
    1018         168 :             OSL_VERIFY( _rValue >>= m_nControlTypeinMSO );
    1019         168 :             break;
    1020             :         case PROPERTY_ID_OBJ_ID_IN_MSO:
    1021         164 :             OSL_VERIFY( _rValue >>= m_nObjIDinMSO );
    1022         164 :             break;
    1023             :         default:
    1024           0 :             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
    1025           0 :                 m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue );
    1026             :             else
    1027             :                 SAL_WARN("forms.component",  "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle " << _nHandle );
    1028           0 :             break;
    1029             :     }
    1030        1532 : }
    1031             : 
    1032         597 : void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
    1033             : {
    1034         597 :     BEGIN_DESCRIBE_BASE_PROPERTIES( 7 )
    1035         597 :         DECL_PROP2      (CLASSID,     sal_Int16,        READONLY, TRANSIENT);
    1036         597 :         DECL_PROP1      (NAME,        OUString,  BOUND);
    1037         597 :         DECL_BOOL_PROP2 (NATIVE_LOOK,                   BOUND, TRANSIENT);
    1038         597 :         DECL_PROP1      (TAG,         OUString,  BOUND);
    1039         597 :         DECL_PROP1      (GENERATEVBAEVENTS,         sal_Bool,  TRANSIENT);
    1040         597 :         DECL_PROP1      (CONTROL_TYPE_IN_MSO,sal_Int16,     BOUND);
    1041         597 :         DECL_PROP1      (OBJ_ID_IN_MSO,cppu::UnoUnsignedShortType,      BOUND);
    1042             :     END_DESCRIBE_PROPERTIES()
    1043         597 : }
    1044             : 
    1045         618 : void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
    1046             : {
    1047         618 :     if ( m_xAggregateSet.is() )
    1048             :     {
    1049         585 :         Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
    1050         585 :         if ( xPSI.is() )
    1051         585 :             _rAggregateProps = xPSI->getProperties();
    1052             :     }
    1053         618 : }
    1054             : 
    1055         816 : ::osl::Mutex& OControlModel::getMutex()
    1056             : {
    1057         816 :     return m_aMutex;
    1058             : }
    1059             : 
    1060         618 : void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
    1061             : {
    1062         618 :     describeFixedProperties( _out_rFixedProperties );
    1063         618 :     describeAggregateProperties( _out_rAggregateProperties );
    1064         618 : }
    1065             : 
    1066         144 : Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
    1067             : {
    1068         144 :     return Reference< XMultiPropertySet >( *this, UNO_QUERY );
    1069             : }
    1070             : 
    1071       21039 : Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException, std::exception)
    1072             : {
    1073       21039 :     return createPropertySetInfo( getInfoHelper() );
    1074             : }
    1075             : 
    1076      174395 : ::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper()
    1077             : {
    1078      174395 :     return m_aPropertyBagHelper.getInfoHelper();
    1079             : }
    1080             : 
    1081          72 : void SAL_CALL OControlModel::addProperty( const OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
    1082             : {
    1083          72 :     m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
    1084          18 : }
    1085             : 
    1086          54 : void SAL_CALL OControlModel::removeProperty( const OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException, std::exception)
    1087             : {
    1088          54 :     m_aPropertyBagHelper.removeProperty( _rName );
    1089          18 : }
    1090             : 
    1091          18 : Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException, std::exception)
    1092             : {
    1093          18 :     return m_aPropertyBagHelper.getPropertyValues();
    1094             : }
    1095             : 
    1096          54 : void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
    1097             : {
    1098          54 :     m_aPropertyBagHelper.setPropertyValues( _rProps );
    1099          18 : }
    1100             : 
    1101        1436 : void OControlModel::lockInstance( LockAccess )
    1102             : {
    1103        1436 :     m_aMutex.acquire();
    1104        1436 :     osl_atomic_increment( &m_lockCount );
    1105        1436 : }
    1106             : 
    1107        1436 : oslInterlockedCount OControlModel::unlockInstance( LockAccess )
    1108             : {
    1109             :     OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
    1110        1436 :     oslInterlockedCount lockCount = osl_atomic_decrement( &m_lockCount );
    1111        1436 :     m_aMutex.release();
    1112        1436 :     return lockCount;
    1113             : }
    1114             : 
    1115        1409 : void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues,
    1116             :                                         const Sequence< Any >& _rNewValues, LockAccess )
    1117             : {
    1118             :     OPropertySetHelper::fire(
    1119             :         const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(),
    1120             :         _rNewValues.getConstArray(),
    1121             :         _rOldValues.getConstArray(),
    1122             :         _rHandles.getLength(),
    1123             :         sal_False
    1124        1409 :     );
    1125        1409 : }
    1126             : 
    1127             : // OBoundControlModel
    1128       84077 : Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException, std::exception)
    1129             : {
    1130       84077 :     Any aReturn( OControlModel::queryAggregation(_rType) );
    1131       84077 :     if (!aReturn.hasValue())
    1132             :     {
    1133        3179 :         aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
    1134             : 
    1135        3179 :         if ( !aReturn.hasValue() && m_bCommitable )
    1136        2497 :             aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
    1137             : 
    1138        3179 :         if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
    1139        2710 :             aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
    1140             : 
    1141        3179 :         if ( !aReturn.hasValue() && m_bSupportsValidation )
    1142        2577 :             aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
    1143             :     }
    1144       84077 :     return aReturn;
    1145             : }
    1146             : 
    1147         313 : OBoundControlModel::OBoundControlModel(
    1148             :         const Reference< XComponentContext>& _rxFactory,
    1149             :         const OUString& _rUnoControlModelTypeName, const OUString& _rDefault,
    1150             :         const bool _bCommitable, const bool _bSupportExternalBinding, const bool _bSupportsValidation )
    1151             :     :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, false )
    1152             :     ,OPropertyChangeListener( m_aMutex )
    1153             :     ,m_xField()
    1154             :     ,m_xAmbientForm()
    1155             :     ,m_nValuePropertyAggregateHandle( -1 )
    1156             :     ,m_nFieldType( DataType::OTHER )
    1157             :     ,m_bValuePropertyMayBeVoid( false )
    1158             :     ,m_aResetHelper( *this, m_aMutex )
    1159             :     ,m_aUpdateListeners(m_aMutex)
    1160             :     ,m_aFormComponentListeners( m_aMutex )
    1161             :     ,m_bInputRequired( true )
    1162             :     ,m_pAggPropMultiplexer( NULL )
    1163             :     ,m_bFormListening( false )
    1164             :     ,m_bLoaded(false)
    1165             :     ,m_bRequired(false)
    1166             :     ,m_bCommitable(_bCommitable)
    1167             :     ,m_bSupportsExternalBinding( _bSupportExternalBinding )
    1168             :     ,m_bSupportsValidation( _bSupportsValidation )
    1169             :     ,m_bForwardValueChanges(true)
    1170             :     ,m_bTransferingValue( false )
    1171             :     ,m_bIsCurrentValueValid( true )
    1172             :     ,m_bBindingControlsRO( false )
    1173             :     ,m_bBindingControlsEnable( false )
    1174             :     ,m_eControlValueChangeInstigator( eOther )
    1175         313 :     ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
    1176             : {
    1177             :     // start property listening at the aggregate
    1178         313 :     implInitAggMultiplexer( );
    1179         313 : }
    1180             : 
    1181          15 : OBoundControlModel::OBoundControlModel(
    1182             :         const OBoundControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory )
    1183             :     :OControlModel( _pOriginal, _rxFactory, true, false )
    1184             :     ,OPropertyChangeListener( m_aMutex )
    1185             :     ,m_xField()
    1186             :     ,m_xAmbientForm()
    1187             :     ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
    1188             :     ,m_nFieldType( DataType::OTHER )
    1189             :     ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
    1190             :     ,m_aResetHelper( *this, m_aMutex )
    1191             :     ,m_aUpdateListeners( m_aMutex )
    1192             :     ,m_aFormComponentListeners( m_aMutex )
    1193             :     ,m_xValidator( _pOriginal->m_xValidator )
    1194             :     ,m_bInputRequired( true )
    1195             :     ,m_pAggPropMultiplexer( NULL )
    1196             :     ,m_bFormListening( false )
    1197             :     ,m_bLoaded( false )
    1198             :     ,m_bRequired( false )
    1199             :     ,m_bCommitable( _pOriginal->m_bCommitable )
    1200             :     ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
    1201             :     ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
    1202             :     ,m_bForwardValueChanges( true )
    1203             :     ,m_bTransferingValue( false )
    1204             :     ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
    1205             :     ,m_bBindingControlsRO( false )
    1206             :     ,m_bBindingControlsEnable( false )
    1207          15 :     ,m_eControlValueChangeInstigator( eOther )
    1208             : {
    1209             :     // start property listening at the aggregate
    1210          15 :     implInitAggMultiplexer( );
    1211          15 :     m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
    1212          15 :     m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
    1213          15 :     m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
    1214          15 :     m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
    1215          15 :     m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
    1216          15 :     m_aControlSource = _pOriginal->m_aControlSource;
    1217          15 :     m_bInputRequired = _pOriginal->m_bInputRequired;
    1218             :     // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transferred.
    1219             :     // (the former should be clear - a clone of the object we're only referencing does not make sense)
    1220             :     // (the second would violate the restriction for label controls that they're part of the
    1221             :     // same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
    1222             :     // start listening for changes at the value property
    1223          15 :     implInitValuePropertyListening( );
    1224          15 : }
    1225             : 
    1226         622 : OBoundControlModel::~OBoundControlModel()
    1227             : {
    1228         311 :     if ( !OComponentHelper::rBHelper.bDisposed )
    1229             :     {
    1230           0 :         acquire();
    1231           0 :         dispose();
    1232             :     }
    1233             : 
    1234         311 :     doResetDelegator( );
    1235             :     OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
    1236         311 :     if ( m_pAggPropMultiplexer )
    1237             :     {
    1238         311 :         m_pAggPropMultiplexer->dispose();
    1239         311 :         m_pAggPropMultiplexer->release();
    1240         311 :         m_pAggPropMultiplexer = NULL;
    1241             :     }
    1242         311 : }
    1243             : 
    1244          15 : void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal )
    1245             : {
    1246          15 :     const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
    1247             :     // the value binding can be handled as if somebody called setValueBinding here
    1248             :     // By definition, bindings can be share between bindables
    1249          15 :     if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() )
    1250             :     {
    1251             :         try
    1252             :         {
    1253           0 :             setValueBinding( pBoundOriginal->m_xExternalBinding );
    1254             :         }
    1255             : 
    1256           0 :         catch( const Exception& )
    1257             :         {
    1258             :             DBG_UNHANDLED_EXCEPTION();
    1259             :         }
    1260             : 
    1261             :     }
    1262          15 : }
    1263             : 
    1264         328 : void OBoundControlModel::implInitAggMultiplexer( )
    1265             : {
    1266         328 :     osl_atomic_increment( &m_refCount );
    1267         328 :     if ( m_xAggregateSet.is() )
    1268             :     {
    1269         328 :         m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, false );
    1270         328 :         m_pAggPropMultiplexer->acquire();
    1271             :     }
    1272             : 
    1273         328 :     osl_atomic_decrement( &m_refCount );
    1274         328 :     doSetDelegator();
    1275         328 : }
    1276             : 
    1277         318 : void OBoundControlModel::implInitValuePropertyListening( ) const
    1278             : {
    1279             :     // start listening for changes at the value property
    1280             :     // There are three pre-requisites for this to be done:
    1281             :     // 1. We support external value bindings. In this case, the changes in the control value need to
    1282             :     //    be propagated to the external binding immediately when they happen
    1283             :     // 2. We support external validation. In this case, we need to listen for changes in the value
    1284             :     //    property, since we need to revalidate then.
    1285             :     // 3. We are not committable. In this case, changes in the control value need to be propagated
    1286             :     //    to the database column immediately when they happen.
    1287         318 :     if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
    1288             :     {
    1289             :         OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
    1290         307 :         if ( m_pAggPropMultiplexer && !m_sValuePropertyName.isEmpty() )
    1291         307 :             m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
    1292             :     }
    1293         318 : }
    1294             : 
    1295          10 : void OBoundControlModel::initOwnValueProperty( const OUString& i_rValuePropertyName )
    1296             : {
    1297             :     OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
    1298             :         "OBoundControlModel::initOwnValueProperty: value property is already initialized!" );
    1299             :     OSL_ENSURE( !i_rValuePropertyName.isEmpty(), "OBoundControlModel::initOwnValueProperty: invalid property name!" );
    1300          10 :     m_sValuePropertyName = i_rValuePropertyName;
    1301          10 : }
    1302             : 
    1303         303 : void OBoundControlModel::initValueProperty( const OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
    1304             : {
    1305             :     OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
    1306             :         "OBoundControlModel::initValueProperty: value property is already initialized!" );
    1307             :     OSL_ENSURE( !_rValuePropertyName.isEmpty(), "OBoundControlModel::initValueProperty: invalid property name!" );
    1308             :     OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
    1309             : 
    1310         303 :     m_sValuePropertyName = _rValuePropertyName;
    1311         303 :     m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
    1312             :     OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
    1313             : 
    1314         303 :     if ( m_nValuePropertyAggregateHandle != -1 )
    1315             :     {
    1316         303 :         Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
    1317         606 :         Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
    1318         303 :         m_aValuePropertyType = aValuePropDesc.Type;
    1319         606 :         m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
    1320             :     }
    1321             : 
    1322             :     // start listening for changes at the value property
    1323         303 :     implInitValuePropertyListening( );
    1324         303 : }
    1325             : 
    1326          27 : void OBoundControlModel::suspendValueListening( )
    1327             : {
    1328             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
    1329             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
    1330             : 
    1331          27 : if ( m_pAggPropMultiplexer )
    1332          27 :         m_pAggPropMultiplexer->lock();
    1333          27 : }
    1334             : 
    1335          27 : void OBoundControlModel::resumeValueListening( )
    1336             : {
    1337             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
    1338             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
    1339             :     OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
    1340          27 :     if ( m_pAggPropMultiplexer )
    1341          27 :         m_pAggPropMultiplexer->unlock();
    1342          27 : }
    1343             : 
    1344          64 : Sequence< Type > OBoundControlModel::_getTypes()
    1345             : {
    1346             :     TypeBag aTypes(
    1347             :         OControlModel::_getTypes(),
    1348             :         OBoundControlModel_BASE1::getTypes()
    1349          64 :     );
    1350             : 
    1351          64 :     if ( m_bCommitable )
    1352          44 :         aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() );
    1353             : 
    1354          64 :     if ( m_bSupportsExternalBinding )
    1355          64 :         aTypes.addTypes( OBoundControlModel_BINDING::getTypes() );
    1356             : 
    1357          64 :     if ( m_bSupportsValidation )
    1358          64 :         aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() );
    1359          64 :     return aTypes.getTypes();
    1360             : }
    1361             : 
    1362             : // OComponentHelper
    1363         312 : void OBoundControlModel::disposing()
    1364             : {
    1365         312 :     OControlModel::disposing();
    1366             : 
    1367         312 :     ::osl::ClearableMutexGuard aGuard(m_aMutex);
    1368             : 
    1369         312 :     if ( m_pAggPropMultiplexer )
    1370         312 :         m_pAggPropMultiplexer->dispose();
    1371             : 
    1372             :     // notify all our listeners
    1373         624 :     com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
    1374         312 :     m_aUpdateListeners.disposeAndClear( aEvt );
    1375         312 :     m_aResetHelper.disposing();
    1376             : 
    1377             :     // disconnect from our database column
    1378             :     // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
    1379             :     // The only more thing which it does is calling onDisconnectedDbColumn - could this
    1380             :     // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
    1381         312 :     if ( hasField() )
    1382             :     {
    1383           0 :         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
    1384           0 :         resetField();
    1385             :     }
    1386             : 
    1387         312 :     m_xCursor = NULL;
    1388         624 :     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1389         312 :     if ( xComp.is() )
    1390           0 :         xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
    1391             :     // disconnect from our external value binding
    1392         312 :     if ( hasExternalValueBinding() )
    1393           9 :         disconnectExternalValueBinding();
    1394             :     // dito for the validator
    1395         312 :     if ( hasValidator() )
    1396         330 :         disconnectValidator( );
    1397         312 : }
    1398             : 
    1399         341 : void OBoundControlModel::onValuePropertyChange( ControlModelLock& i_rControLock )
    1400             : {
    1401         341 :     if ( hasExternalValueBinding() )
    1402             :     {
    1403             :         // the control value changed, while we have an external value binding
    1404             :         // -> forward the value to it
    1405           4 :         if ( m_eControlValueChangeInstigator != eExternalBinding )
    1406           0 :             transferControlValueToExternal( i_rControLock );
    1407             :     }
    1408             : 
    1409         337 :     else if ( !m_bCommitable && m_xColumnUpdate.is() )
    1410             :     {
    1411             :         // the control value changed, while we are  bound to a database column,
    1412             :         // but not committable (which means changes in the control have to be reflected to
    1413             :         // the underlying database column immediately)
    1414             :         // -> forward the value to the database column
    1415           0 :         if ( m_eControlValueChangeInstigator != eDbColumnBinding )
    1416           0 :             commitControlValueToDbColumn( false );
    1417             :     }
    1418             : 
    1419             :     // validate the new value
    1420         341 :     if ( m_bSupportsValidation )
    1421         314 :         recheckValidity( true );
    1422         341 : }
    1423             : 
    1424         336 : void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException )
    1425             : {
    1426         336 :     ControlModelLock aLock( *this );
    1427             :     OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
    1428             :         "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
    1429             :     OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
    1430             :         "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
    1431         336 :     if ( _rEvt.PropertyName == m_sValuePropertyName )
    1432             :     {
    1433         336 :         onValuePropertyChange( aLock );
    1434         336 :     }
    1435         336 : }
    1436             : 
    1437          75 : void OBoundControlModel::startAggregatePropertyListening( const OUString& _rPropertyName )
    1438             : {
    1439             :     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
    1440             :     OSL_ENSURE( !_rPropertyName.isEmpty(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
    1441          75 :     if ( m_pAggPropMultiplexer && !_rPropertyName.isEmpty() )
    1442             :     {
    1443          75 :         m_pAggPropMultiplexer->addProperty( _rPropertyName );
    1444             :     }
    1445          75 : }
    1446             : 
    1447         619 : void OBoundControlModel::doFormListening( const bool _bStart )
    1448             : {
    1449             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
    1450         619 :     if ( isFormListening() == _bStart )
    1451         619 :         return;
    1452         619 :     if ( m_xAmbientForm.is() )
    1453         435 :         _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
    1454         619 :     Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
    1455         619 :     if ( getParent().is() && !xParentLoadable.is() )
    1456             :     {
    1457             :         // if our parent does not directly support the XLoadable interface, then it might support the
    1458             :         // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
    1459             :         // broadcasted by the latter.
    1460          81 :         Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
    1461          81 :         if ( xRowSetBroadcaster.is() )
    1462          81 :             _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
    1463             :     }
    1464             : 
    1465         619 :     m_bFormListening = _bStart && m_xAmbientForm.is();
    1466             : }
    1467             : 
    1468             : // XChild
    1469         723 : void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException, std::exception)
    1470             : {
    1471         723 :     ControlModelLock aLock( *this );
    1472        1134 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    1473         723 :     if ( getParent() == _rxParent )
    1474        1035 :         return;
    1475             :     // disconnect from database column (which is controlled by parent, directly or indirectly)
    1476         411 :     if ( hasField() )
    1477           0 :         impl_disconnectDatabaseColumn_noNotify();
    1478             :     // log off old listeners
    1479         411 :     if ( isFormListening() )
    1480         162 :         doFormListening( false );
    1481             :     // actually set the new parent
    1482         411 :     OControlModel::setParent( _rxParent );
    1483             :     // a new parent means a new ambient form
    1484         411 :     impl_determineAmbientForm_nothrow();
    1485         411 :     if ( !hasExternalValueBinding() )
    1486             :     {
    1487             :         // log on new listeners
    1488         403 :         doFormListening( true );
    1489             :         // re-connect to database column of the new parent
    1490         403 :         if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    1491          31 :             impl_connectDatabaseColumn_noNotify( false );
    1492         411 :     }
    1493             : }
    1494             : 
    1495             : // XEventListener
    1496         195 : void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException, std::exception)
    1497             : {
    1498         195 :     ControlModelLock aLock( *this );
    1499         195 :     if ( _rEvent.Source == getField() )
    1500             :     {
    1501          31 :         resetField();
    1502             :     }
    1503             : 
    1504         164 :     else if ( _rEvent.Source == m_xLabelControl )
    1505             :     {
    1506           0 :         Reference<XPropertySet> xOldValue = m_xLabelControl;
    1507           0 :         m_xLabelControl = NULL;
    1508             :         // fire a propertyChanged (when we leave aLock's scope)
    1509           0 :         aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) );
    1510             :     }
    1511             : 
    1512         164 :     else if ( _rEvent.Source == m_xExternalBinding )
    1513             :     {   // *first* check for the external binding
    1514           0 :         disconnectExternalValueBinding( );
    1515             :     }
    1516             : 
    1517         164 :     else if ( _rEvent.Source == m_xValidator )
    1518             :     {   // *then* check for the validator. Reason is that bindings may also act as validator at the same
    1519             :         // time, in this case, the validator is automatically revoked when the binding is revoked
    1520           0 :         disconnectValidator( );
    1521             :     }
    1522             : 
    1523             :     else
    1524         164 :         OControlModel::disposing(_rEvent);
    1525         195 : }
    1526             : 
    1527             : // XServiceInfo
    1528         278 : StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException, std::exception)
    1529             : {
    1530             :     return ::comphelper::combineSequences(
    1531             :         getAggregateServiceNames(),
    1532             :         getSupportedServiceNames_Static()
    1533         278 :     );
    1534             : }
    1535             : 
    1536         278 : Sequence< OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
    1537             : {
    1538         278 :     Sequence< OUString > aOwnServiceNames( 1 );
    1539         278 :     aOwnServiceNames[ 0 ] = "com.sun.star.form.DataAwareControlModel";
    1540             :     return ::comphelper::concatSequences(
    1541             :         OControlModel::getSupportedServiceNames_Static(),
    1542             :         aOwnServiceNames
    1543         278 :     );
    1544             : }
    1545             : 
    1546             : // XPersist
    1547          15 : void SAL_CALL OBoundControlModel::write( const Reference<css::io::XObjectOutputStream>& _rxOutStream ) throw(css::io::IOException, RuntimeException, std::exception)
    1548             : {
    1549          15 :     OControlModel::write(_rxOutStream);
    1550          15 :     osl::MutexGuard aGuard(m_aMutex);
    1551             :     // Version
    1552          15 :     _rxOutStream->writeShort(0x0002);
    1553             :     // Controlsource
    1554          15 :     ::comphelper::operator<<( _rxOutStream, m_aControlSource);
    1555             :     // !!! IMPORTANT NOTE !!!
    1556             :     // don't write any new members here: this wouldn't be compatible with older versions, as OBoundControlModel
    1557             :     // is a base class which is called in derived classes "read" method. So if you increment the version
    1558             :     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
    1559             :     // in anything from data loss to crash.
    1560             :     // (use writeCommonProperties instead, this is called in derived classes write-method)
    1561             :     // !!! EOIN !!!
    1562          15 : }
    1563             : 
    1564           0 : void OBoundControlModel::defaultCommonProperties()
    1565             : {
    1566           0 :     Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
    1567           0 :     if (xComp.is())
    1568           0 :         xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1569           0 :     m_xLabelControl = NULL;
    1570           0 : }
    1571             : 
    1572          13 : void OBoundControlModel::readCommonProperties(const Reference<css::io::XObjectInputStream>& _rxInStream)
    1573             : {
    1574          13 :     sal_Int32 nLen = _rxInStream->readLong();
    1575          13 :     Reference<css::io::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
    1576             :     DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
    1577          13 :     sal_Int32 nMark = xMark->createMark();
    1578             :     // read the reference to the label control
    1579          26 :     Reference<css::io::XPersistObject> xPersist;
    1580             :     sal_Int32 nUsedFlag;
    1581          13 :     nUsedFlag = _rxInStream->readLong();
    1582          13 :     if (nUsedFlag)
    1583           0 :         xPersist = _rxInStream->readObject();
    1584          13 :     m_xLabelControl.set(xPersist, css::uno::UNO_QUERY);
    1585          26 :     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1586          13 :     if (xComp.is())
    1587           0 :         xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1588             :     // read any other new common properties here
    1589             :     // skip the remaining bytes
    1590          13 :     xMark->jumpToMark(nMark);
    1591          13 :     _rxInStream->skipBytes(nLen);
    1592          26 :     xMark->deleteMark(nMark);
    1593          13 : }
    1594             : 
    1595          13 : void OBoundControlModel::writeCommonProperties(const Reference<css::io::XObjectOutputStream>& _rxOutStream)
    1596             : {
    1597          13 :     Reference<css::io::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
    1598             :     DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
    1599          13 :     sal_Int32 nMark = xMark->createMark();
    1600             :     // a placeholder where we will write the overall length (later in this method)
    1601          13 :     sal_Int32 nLen = 0;
    1602          13 :     _rxOutStream->writeLong(nLen);
    1603             :     // write the reference to the label control
    1604          26 :     Reference<css::io::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
    1605          13 :     sal_Int32 nUsedFlag = 0;
    1606          13 :     if (xPersist.is())
    1607           0 :         nUsedFlag = 1;
    1608          13 :     _rxOutStream->writeLong(nUsedFlag);
    1609          13 :     if (xPersist.is())
    1610           0 :         _rxOutStream->writeObject(xPersist);
    1611             :     // write any other new common properties here
    1612             :     // write the correct length at the beginning of the block
    1613          13 :     nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
    1614          13 :     xMark->jumpToMark(nMark);
    1615          13 :     _rxOutStream->writeLong(nLen);
    1616          13 :     xMark->jumpToFurthest();
    1617          26 :     xMark->deleteMark(nMark);
    1618          13 : }
    1619             : 
    1620          15 : void SAL_CALL OBoundControlModel::read( const Reference< css::io::XObjectInputStream >& _rxInStream ) throw(css::io::IOException, RuntimeException, std::exception)
    1621             : {
    1622          15 :     OControlModel::read(_rxInStream);
    1623          15 :     osl::MutexGuard aGuard(m_aMutex);
    1624          15 :     sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
    1625          15 :     ::comphelper::operator>>( _rxInStream, m_aControlSource);
    1626          15 : }
    1627             : 
    1628       55169 : void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
    1629             : {
    1630       55169 :     switch (nHandle)
    1631             :     {
    1632             :         case PROPERTY_ID_INPUT_REQUIRED:
    1633         971 :             rValue <<= m_bInputRequired;
    1634         971 :             break;
    1635             :         case PROPERTY_ID_CONTROLSOURCEPROPERTY:
    1636        1949 :             rValue <<= m_sValuePropertyName;
    1637        1949 :             break;
    1638             :         case PROPERTY_ID_CONTROLSOURCE:
    1639        1183 :             rValue <<= m_aControlSource;
    1640        1183 :             break;
    1641             :         case PROPERTY_ID_BOUNDFIELD:
    1642         414 :             rValue <<= getField();
    1643         414 :             break;
    1644             :         case PROPERTY_ID_CONTROLLABEL:
    1645         337 :             if (!m_xLabelControl.is())
    1646         337 :                 rValue.clear();
    1647             :             else
    1648           0 :                 rValue <<= m_xLabelControl;
    1649         337 :             break;
    1650             :         default:
    1651       50315 :             OControlModel::getFastPropertyValue(rValue, nHandle);
    1652             :     }
    1653       55169 : }
    1654             : 
    1655        5426 : sal_Bool OBoundControlModel::convertFastPropertyValue(
    1656             :                                 Any& _rConvertedValue, Any& _rOldValue,
    1657             :                 sal_Int32 _nHandle,
    1658             :                                 const Any& _rValue)
    1659             :                 throw (com::sun::star::lang::IllegalArgumentException)
    1660             : {
    1661        5426 :     bool bModified(false);
    1662        5426 :     switch (_nHandle)
    1663             :     {
    1664             :         case PROPERTY_ID_INPUT_REQUIRED:
    1665         568 :             bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
    1666         568 :             break;
    1667             :         case PROPERTY_ID_CONTROLSOURCE:
    1668         659 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
    1669         659 :             break;
    1670             :         case PROPERTY_ID_BOUNDFIELD:
    1671             :             SAL_WARN("forms.component",  "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
    1672           0 :             throw com::sun::star::lang::IllegalArgumentException();
    1673             :         case PROPERTY_ID_CONTROLLABEL:
    1674           0 :             if (!_rValue.hasValue())
    1675             :             {   // property set to void
    1676           0 :                 _rConvertedValue = Any();
    1677           0 :                 getFastPropertyValue(_rOldValue, _nHandle);
    1678           0 :                 bModified = m_xLabelControl.is();
    1679             :             }
    1680             : 
    1681             :             else
    1682             :             {
    1683           0 :                 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
    1684           0 :                 if (!m_xLabelControl.is())
    1685             :                     // an empty interface is interpreted as VOID
    1686           0 :                     _rOldValue.clear();
    1687             :             }
    1688             : 
    1689           0 :             break;
    1690             :         default:
    1691        4199 :             bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
    1692             :     }
    1693        5426 :     return bModified;
    1694             : }
    1695             : 
    1696           2 : Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
    1697             : {
    1698           2 :     Any aDefault;
    1699           2 :     switch ( _nHandle )
    1700             :     {
    1701             :         case PROPERTY_ID_INPUT_REQUIRED:
    1702           0 :             aDefault <<= true;
    1703           0 :             break;
    1704             :         case PROPERTY_ID_CONTROLSOURCE:
    1705           0 :             aDefault <<= OUString();
    1706           0 :             break;
    1707             :         case PROPERTY_ID_CONTROLLABEL:
    1708           0 :             aDefault <<= Reference< XPropertySet >();
    1709           0 :             break;
    1710             :     }
    1711           2 :     return aDefault;
    1712             : }
    1713             : 
    1714        1379 : void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception, std::exception)
    1715             : {
    1716        1379 :     switch (nHandle)
    1717             :     {
    1718             :         case PROPERTY_ID_INPUT_REQUIRED:
    1719          98 :             OSL_VERIFY( rValue >>= m_bInputRequired );
    1720          98 :             break;
    1721             :         case PROPERTY_ID_CONTROLSOURCE:
    1722         188 :             OSL_VERIFY( rValue >>= m_aControlSource );
    1723         188 :             break;
    1724             :         case PROPERTY_ID_BOUNDFIELD:
    1725             :             SAL_WARN("forms.component", "OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
    1726           0 :             throw com::sun::star::lang::IllegalArgumentException();
    1727             :         case PROPERTY_ID_CONTROLLABEL:
    1728             :         {
    1729           0 :             if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) )
    1730           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1731           0 :             Reference< XInterface > xNewValue( rValue, UNO_QUERY );
    1732           0 :             if ( !xNewValue.is() )
    1733             :             {   // set property to "void"
    1734           0 :                 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
    1735           0 :                 if ( xComp.is() )
    1736           0 :                     xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
    1737           0 :                 m_xLabelControl = NULL;
    1738           0 :                 break;
    1739             :             }
    1740             : 
    1741           0 :             Reference< XControlModel >  xAsModel        ( xNewValue,        UNO_QUERY );
    1742           0 :             Reference< XServiceInfo >   xAsServiceInfo  ( xAsModel,         UNO_QUERY );
    1743           0 :             Reference< XPropertySet >   xAsPropSet      ( xAsServiceInfo,   UNO_QUERY );
    1744           0 :             Reference< XChild >         xAsChild        ( xAsPropSet,       UNO_QUERY );
    1745           0 :             if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) )
    1746             :             {
    1747           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1748             :             }
    1749             : 
    1750             :             // Check if we and the given model have a common ancestor (up to the forms collection)
    1751             :             Reference<XChild> xCont(
    1752           0 :                 static_cast<XWeak*>(this), css::uno::UNO_QUERY);
    1753           0 :             Reference< XInterface > xMyTopLevel = xCont->getParent();
    1754           0 :             while (xMyTopLevel.is())
    1755             :             {
    1756           0 :                 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
    1757           0 :                 if (!xAsForm.is())
    1758             :                     // found my root
    1759           0 :                     break;
    1760           0 :                 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
    1761           0 :                 xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
    1762           0 :             }
    1763             : 
    1764           0 :             Reference< XInterface > xNewTopLevel = xAsChild->getParent();
    1765           0 :             while (xNewTopLevel.is())
    1766             :             {
    1767           0 :                 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
    1768           0 :                 if (!xAsForm.is())
    1769           0 :                     break;
    1770           0 :                 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
    1771           0 :                 xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
    1772           0 :             }
    1773             : 
    1774           0 :             if (xNewTopLevel != xMyTopLevel)
    1775             :             {
    1776             :                 // the both objects don't belong to the same forms collection -> not acceptable
    1777           0 :                 throw com::sun::star::lang::IllegalArgumentException();
    1778             :             }
    1779             : 
    1780           0 :             m_xLabelControl = xAsPropSet;
    1781           0 :             Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
    1782           0 :             if (xComp.is())
    1783           0 :                 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
    1784             :         }
    1785             : 
    1786           0 :         break;
    1787             :         default:
    1788        1093 :             OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue );
    1789             :     }
    1790        1379 : }
    1791             : 
    1792             : // XPropertyChangeListener
    1793           0 : void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException, std::exception)
    1794             : {
    1795             :     // if the DBColumn value changed, transfer it to the control
    1796           0 :     if ( evt.PropertyName == PROPERTY_VALUE )
    1797             :     {
    1798             :         OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database column?" );
    1799           0 :         osl::MutexGuard aGuard(m_aMutex);
    1800           0 :         if ( m_bForwardValueChanges && m_xColumn.is() )
    1801           0 :             transferDbValueToControl();
    1802             :     }
    1803             : 
    1804             :     else
    1805             :     {
    1806             :         OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
    1807             :         // our binding has properties which can control properties of ourself
    1808           0 :         OUString sBindingControlledProperty;
    1809           0 :         bool bForwardToLabelControl = false;
    1810           0 :         if ( evt.PropertyName == PROPERTY_READONLY )
    1811             :         {
    1812           0 :             sBindingControlledProperty = PROPERTY_READONLY;
    1813             :         }
    1814             : 
    1815           0 :         else if ( evt.PropertyName == PROPERTY_RELEVANT )
    1816             :         {
    1817           0 :             sBindingControlledProperty = PROPERTY_ENABLED;
    1818           0 :             bForwardToLabelControl = true;
    1819             :         }
    1820             : 
    1821             :         else
    1822           0 :             return;
    1823             :         try
    1824             :         {
    1825           0 :             setPropertyValue( sBindingControlledProperty, evt.NewValue );
    1826           0 :             if ( bForwardToLabelControl && m_xLabelControl.is() )
    1827           0 :                 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
    1828             :         }
    1829             : 
    1830           0 :         catch( const Exception& )
    1831             :         {
    1832             :             SAL_WARN("forms.component",  "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!");
    1833             :             DBG_UNHANDLED_EXCEPTION();
    1834           0 :         }
    1835             : 
    1836             :     }
    1837             : }
    1838             : 
    1839          10 : void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException, std::exception)
    1840             : {
    1841          10 :     ControlModelLock aLock( *this );
    1842          20 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    1843             :     // disconnect from database column (which is controlled by parent, directly or indirectly)
    1844          10 :     if ( hasField() )
    1845           0 :         impl_disconnectDatabaseColumn_noNotify();
    1846             :     // log off old listeners
    1847          10 :     if ( isFormListening() )
    1848          10 :         doFormListening( false );
    1849             :     // determine the new ambient form
    1850          10 :     impl_determineAmbientForm_nothrow();
    1851             :     // log on new listeners
    1852          10 :     doFormListening( true );
    1853             :     // re-connect to database column if needed and possible
    1854          10 :     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    1855          10 :         impl_connectDatabaseColumn_noNotify( false );
    1856          10 : }
    1857             : 
    1858             : // XBoundComponent
    1859           0 : void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException, std::exception)
    1860             : {
    1861           0 :     m_aUpdateListeners.addInterface(_rxListener);
    1862           0 : }
    1863             : 
    1864           0 : void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException, std::exception)
    1865             : {
    1866           0 :     m_aUpdateListeners.removeInterface(_rxListener);
    1867           0 : }
    1868             : 
    1869           8 : sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException, std::exception)
    1870             : {
    1871           8 :     ControlModelLock aLock( *this );
    1872             :     OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " );
    1873           8 :     if ( hasExternalValueBinding() )
    1874             :     {
    1875             :         // in most cases, no action is required: For most derivees, we know the value property of
    1876             :         // our control (see initValueProperty), and when an external binding is active, we
    1877             :         // instantly forward all changes in this property to the external binding.
    1878           0 :         if ( m_sValuePropertyName.isEmpty() )
    1879             :             // but for those derivees which did not use this feature, we need an
    1880             :             // explicit transfer
    1881           0 :             transferControlValueToExternal( aLock );
    1882           0 :         return sal_True;
    1883             :     }
    1884             : 
    1885             :     OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
    1886             :         // we reach this only if we're not working with an external binding
    1887           8 :     if ( !hasField() )
    1888           8 :         return sal_True;
    1889           0 :     ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners );
    1890           0 :     EventObject aEvent;
    1891           0 :     aEvent.Source = static_cast< XWeak* >( this );
    1892           0 :     bool bSuccess = true;
    1893           0 :     aLock.release();
    1894             :     // UNSAFE >
    1895           0 :     while (aIter.hasMoreElements() && bSuccess)
    1896           0 :         bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent );
    1897             :     // < UNSAFE
    1898           0 :     aLock.acquire();
    1899           0 :     if ( bSuccess )
    1900             :     {
    1901             :         try
    1902             :         {
    1903           0 :             if ( m_xColumnUpdate.is() )
    1904           0 :                 bSuccess = commitControlValueToDbColumn( false );
    1905             :         }
    1906             : 
    1907           0 :         catch(const Exception&)
    1908             :         {
    1909           0 :             bSuccess = false;
    1910             :         }
    1911             : 
    1912             :     }
    1913             : 
    1914           0 :     if ( bSuccess )
    1915             :     {
    1916           0 :         aLock.release();
    1917           0 :         m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
    1918             :     }
    1919           8 :     return bSuccess;
    1920             : }
    1921             : 
    1922          31 : void OBoundControlModel::resetField()
    1923             : {
    1924          31 :     m_xColumnUpdate.clear();
    1925          31 :     m_xColumn.clear();
    1926          31 :     m_xField.clear();
    1927          31 :     m_nFieldType = DataType::OTHER;
    1928          31 : }
    1929             : 
    1930          31 : bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
    1931             : {
    1932             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
    1933             :     // if there's a connection to the database
    1934          31 :     if (rForm.is() && getConnection(rForm).is())
    1935             :     {
    1936             :         // determine field and PropertyChangeListener
    1937          31 :         m_xCursor = rForm;
    1938          31 :         Reference<XPropertySet> xFieldCandidate;
    1939          31 :         if (m_xCursor.is())
    1940             :         {
    1941          31 :             Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
    1942             :             DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !");
    1943          31 :             if (xColumnsSupplier.is())
    1944             :             {
    1945          31 :                 Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY);
    1946          31 :                 if (xColumns.is() && xColumns->hasByName(m_aControlSource))
    1947             :                 {
    1948          31 :                     OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
    1949          31 :                 }
    1950             : 
    1951          31 :             }
    1952             : 
    1953             :         }
    1954             : 
    1955             :         try
    1956             :         {
    1957          31 :             sal_Int32 nFieldType = DataType::OTHER;
    1958          31 :             if ( xFieldCandidate.is() )
    1959             :             {
    1960          31 :                 xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
    1961          31 :                 if ( approveDbColumnType( nFieldType ) )
    1962          31 :                     impl_setField_noNotify( xFieldCandidate );
    1963             :             }
    1964             : 
    1965             :             else
    1966           0 :                 impl_setField_noNotify( NULL );
    1967          31 :             if ( m_xField.is() )
    1968             :             {
    1969          31 :                 if ( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
    1970             :                 {
    1971          31 :                     m_nFieldType = nFieldType;
    1972             :                     // listen to changing values
    1973          31 :                     m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
    1974          31 :                     m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY );
    1975          31 :                     m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY );
    1976          31 :                     sal_Int32 nNullableFlag = ColumnValue::NO_NULLS;
    1977          31 :                     m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
    1978          31 :                     m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag);
    1979             :                     // we're optimistic: in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability...
    1980             :                 }
    1981             :                 else
    1982             :                 {
    1983             :                     SAL_WARN("forms.component", "OBoundControlModel::connectToField: property " PROPERTY_VALUE " not supported!");
    1984           0 :                     impl_setField_noNotify( NULL );
    1985             :                 }
    1986             : 
    1987             :             }
    1988             : 
    1989             :         }
    1990             : 
    1991           0 :         catch( const Exception& )
    1992             :         {
    1993             :             DBG_UNHANDLED_EXCEPTION();
    1994           0 :             resetField();
    1995          31 :         }
    1996             : 
    1997             :     }
    1998          31 :     return hasField();
    1999             : }
    2000             : 
    2001          31 : void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
    2002             : {
    2003             :     // but only if the rowset if posisitioned on a valid record
    2004          31 :     if ( hasField() && _rxRowSet.is() )
    2005             :     {
    2006          31 :         if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() )
    2007          31 :             transferDbValueToControl();
    2008             :         else
    2009             :             // reset the field if the row set is empty
    2010             :             // #i30661#
    2011           0 :             resetNoBroadcast();
    2012             :     }
    2013          31 : }
    2014             : 
    2015          31 : bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType)
    2016             : {
    2017             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
    2018          31 :     if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
    2019          31 :         || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
    2020          31 :         || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
    2021          31 :         || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
    2022          31 :         || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/
    2023          31 :         || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
    2024           0 :         return false;
    2025          31 :     return true;
    2026             : }
    2027             : 
    2028         421 : void OBoundControlModel::impl_determineAmbientForm_nothrow()
    2029             : {
    2030         421 :     Reference< XInterface > xParent( getParent() );
    2031         421 :     m_xAmbientForm.set( xParent, UNO_QUERY );
    2032         421 :     if ( !m_xAmbientForm.is() )
    2033             :     {
    2034         235 :         Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
    2035         235 :         if ( xSupRowSet.is() )
    2036          63 :             m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
    2037         421 :     }
    2038         421 : }
    2039             : 
    2040          31 : void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload )
    2041             : {
    2042             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
    2043             :     // consistency checks
    2044             :     DBG_ASSERT( !( hasField() && !_bFromReload ),
    2045             :         "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
    2046             :     (void)_bFromReload;
    2047          31 :     Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
    2048             :     OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
    2049          31 :     if ( !xRowSet.is() )
    2050          31 :         return;
    2051          31 :     if ( !hasField() )
    2052             :     {
    2053             :         // connect to the column
    2054          31 :         connectToField( xRowSet );
    2055             :     }
    2056             : 
    2057             :     // now that we're connected (more or less, even if we did not find a column),
    2058             :     // we definitely want to forward any potentially occurring value changes
    2059          31 :     m_bForwardValueChanges = true;
    2060             :     // let derived classes react on this new connection
    2061          31 :     m_bLoaded = true;
    2062          31 :     onConnectedDbColumn( xRowSet );
    2063             :     // initially transfer the db column value to the control, if we successfully connected to a database column
    2064          31 :     if ( hasField() )
    2065          31 :         initFromField( xRowSet );
    2066             : }
    2067             : 
    2068          31 : void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify()
    2069             : {
    2070             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
    2071             :     // let derived classes react on this
    2072          31 :     onDisconnectedDbColumn();
    2073          31 :     if ( hasField() )
    2074             :     {
    2075           0 :         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
    2076           0 :         resetField();
    2077             :     }
    2078             : 
    2079          31 :     m_xCursor = NULL;
    2080          31 :     m_bLoaded = false;
    2081          31 : }
    2082             : 
    2083             : // XLoadListener
    2084           0 : void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException, std::exception)
    2085             : {
    2086           0 :     ControlModelLock aLock( *this );
    2087           0 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2088             :     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
    2089             :     (void)_rEvent;
    2090             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
    2091           0 :     if ( hasExternalValueBinding() )
    2092           0 :         return;
    2093           0 :     impl_connectDatabaseColumn_noNotify( false );
    2094             : }
    2095             : 
    2096          31 : void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException, std::exception)
    2097             : {
    2098             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
    2099          31 : }
    2100             : 
    2101           0 : void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException, std::exception)
    2102             : {
    2103             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
    2104           0 :     if ( hasExternalValueBinding() )
    2105           0 :         return;
    2106           0 :     osl::MutexGuard aGuard(m_aMutex);
    2107           0 :     m_bForwardValueChanges = false;
    2108             : }
    2109             : 
    2110          31 : void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException, std::exception)
    2111             : {
    2112          31 :     ControlModelLock aLock( *this );
    2113          62 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2114             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
    2115          31 :     if ( hasExternalValueBinding() )
    2116          31 :         return;
    2117          62 :     impl_disconnectDatabaseColumn_noNotify();
    2118             : }
    2119             : 
    2120           0 : void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException, std::exception)
    2121             : {
    2122           0 :     ControlModelLock aLock( *this );
    2123           0 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2124             :     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
    2125             :     (void)_rEvent;
    2126             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
    2127           0 :     if ( hasExternalValueBinding() )
    2128           0 :         return;
    2129           0 :     impl_connectDatabaseColumn_noNotify( true );
    2130             : }
    2131             : 
    2132         241 : void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
    2133             : {
    2134         241 :     m_eControlValueChangeInstigator = _eInstigator;
    2135         241 :     doSetControlValue( _rValue );
    2136         241 :     m_eControlValueChangeInstigator = eOther;
    2137         241 : }
    2138             : 
    2139         235 : void OBoundControlModel::doSetControlValue( const Any& _rValue )
    2140             : {
    2141             :     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
    2142             :         "OBoundControlModel::doSetControlValue: invalid aggregate !" );
    2143             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
    2144             :         "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
    2145             :     try
    2146             :     {
    2147             :         // release our mutex once (it's acquired in one of the calling methods), as setting aggregate properties
    2148             :         // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
    2149             :         // our own mutex locked
    2150         235 :         MutexRelease aRelease( m_aMutex );
    2151         235 :         if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
    2152             :         {
    2153         235 :             m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
    2154             :         }
    2155             : 
    2156           0 :         else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
    2157             :         {
    2158           0 :             m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
    2159         235 :         }
    2160             : 
    2161             :     }
    2162             : 
    2163           6 :     catch( const Exception& )
    2164             :     {
    2165             :         SAL_WARN("forms.component",  "OBoundControlModel::doSetControlValue: caught an exception!");
    2166             :         DBG_UNHANDLED_EXCEPTION();
    2167             :     }
    2168         235 : }
    2169             : 
    2170          18 : void OBoundControlModel::onConnectedValidator( )
    2171             : {
    2172             :     try
    2173             :     {
    2174             :         // if we have an external validator, we do not want the control to force invalid
    2175             :         // inputs to the default value. Instead, invalid inputs should be translated
    2176             :         // to NaN (not a number)
    2177          18 :         Reference< XPropertySetInfo > xAggregatePropertyInfo;
    2178          18 :         if ( m_xAggregateSet.is() )
    2179          18 :             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
    2180          18 :         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
    2181           8 :             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( false ) );
    2182             :     }
    2183             : 
    2184           0 :     catch( const Exception& )
    2185             :     {
    2186             :         SAL_WARN("forms.component",  "OBoundControlModel::onConnectedValidator: caught an exception!");
    2187             :         DBG_UNHANDLED_EXCEPTION();
    2188             :     }
    2189             : 
    2190          18 :     recheckValidity( false );
    2191          18 : }
    2192             : 
    2193          18 : void OBoundControlModel::onDisconnectedValidator( )
    2194             : {
    2195             :     try
    2196             :     {
    2197          18 :         Reference< XPropertySetInfo > xAggregatePropertyInfo;
    2198          18 :         if ( m_xAggregateSet.is() )
    2199          18 :             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
    2200          18 :         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
    2201           8 :             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( true ) );
    2202             :     }
    2203             : 
    2204           0 :     catch( const Exception& )
    2205             :     {
    2206             :         SAL_WARN("forms.component",  "OBoundControlModel::onDisconnectedValidator: caught an exception!");
    2207             :         DBG_UNHANDLED_EXCEPTION();
    2208             :     }
    2209             : 
    2210          18 :     recheckValidity( false );
    2211          18 : }
    2212             : 
    2213          17 : void OBoundControlModel::onConnectedExternalValue( )
    2214             : {
    2215          17 :     calculateExternalValueType();
    2216          17 : }
    2217             : 
    2218          14 : void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
    2219             : {
    2220             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
    2221          14 : }
    2222             : 
    2223          31 : void OBoundControlModel::onDisconnectedDbColumn()
    2224             : {
    2225             :     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
    2226          31 : }
    2227             : 
    2228             : // XReset
    2229           0 : Any OBoundControlModel::getDefaultForReset() const
    2230             : {
    2231           0 :     return Any();
    2232             : }
    2233             : 
    2234         152 : void OBoundControlModel::resetNoBroadcast()
    2235             : {
    2236         152 :     setControlValue( getDefaultForReset(), eOther );
    2237         152 : }
    2238             : 
    2239          51 : void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException, std::exception)
    2240             : {
    2241          51 :     m_aResetHelper.addResetListener( l );
    2242          51 : }
    2243             : 
    2244          38 : void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException, std::exception)
    2245             : {
    2246          38 :     m_aResetHelper.removeResetListener( l );
    2247          38 : }
    2248             : 
    2249          43 : void OBoundControlModel::reset() throw (RuntimeException, std::exception)
    2250             : {
    2251          43 :     if ( !m_aResetHelper.approveReset() )
    2252          56 :        return;
    2253          30 :     ControlModelLock aLock( *this );
    2254             :     // on a new record?
    2255          30 :     bool bIsNewRecord = false;
    2256          60 :     Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
    2257          30 :     if ( xSet.is() )
    2258             :     {
    2259             :         try
    2260             :         {
    2261           0 :             xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
    2262             :         }
    2263             : 
    2264           0 :         catch( const Exception& )
    2265             :         {
    2266             :             DBG_UNHANDLED_EXCEPTION();
    2267             :         }
    2268             : 
    2269             :     }
    2270             : 
    2271             :     // cursor on an invalid row?
    2272          30 :     bool bInvalidCursorPosition = true;
    2273             :     try
    2274             :     {
    2275          30 :         bInvalidCursorPosition =    m_xCursor.is()
    2276           0 :                                 &&  (  m_xCursor->isAfterLast()
    2277           0 :                                     || m_xCursor->isBeforeFirst()
    2278             :                                     )
    2279          30 :                                 &&  !bIsNewRecord;
    2280             :     }
    2281             : 
    2282           0 :     catch( const SQLException& )
    2283             :     {
    2284             :         SAL_WARN("forms.component",  "OBoundControlModel::reset: caught an SQL exception!" );
    2285             :         DBG_UNHANDLED_EXCEPTION();
    2286             :     }
    2287             : 
    2288             :     // #i24495# - don't count the insert row as "invalid"
    2289             :     bool bSimpleReset =
    2290          30 :                         (   !m_xColumn.is()                     // no connection to a database column
    2291           0 :                         ||  (   m_xCursor.is()                  // OR   we have an improperly positioned cursor
    2292           0 :                             &&  bInvalidCursorPosition
    2293             :                             )
    2294          30 :                         ||  hasExternalValueBinding()           // OR we have an external value binding
    2295          30 :                         );
    2296          30 :     if ( !bSimpleReset )
    2297             :     {
    2298             :         // The default values will be set if and only if the current value of the field which we're bound
    2299             :         // to is NULL.
    2300             :         // Else, the current field value should be refreshed
    2301             :         // This behaviour is not completely ... "matured": What should happen if the field as well as the
    2302             :         // control have a default value?
    2303           0 :         bool bIsNull = true;
    2304             :         // we have to access the field content at least once to get a reliable result by XColumn::wasNull
    2305             :         try
    2306             :         {
    2307             :             // normally, we'd do a getString here. However, this is extremely expensive in the case
    2308             :             // of binary fields. Unfortunately, getString is the only method which is guaranteed
    2309             :             // to *always* succeed, all other getXXX methods may fail if the column is asked for a
    2310             :             // non-convertible type
    2311           0 :             sal_Int32 nFieldType = DataType::OBJECT;
    2312           0 :             getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
    2313           0 :             if  (  ( nFieldType == DataType::BINARY        )
    2314           0 :                 || ( nFieldType == DataType::VARBINARY     )
    2315           0 :                 || ( nFieldType == DataType::LONGVARBINARY )
    2316           0 :                 || ( nFieldType == DataType::OBJECT        )
    2317             :                 /*|| ( nFieldType == DataType::CLOB          )*/
    2318             :                 )
    2319           0 :                 m_xColumn->getBinaryStream();
    2320           0 :             else if ( nFieldType == DataType::BLOB          )
    2321           0 :                 m_xColumn->getBlob();
    2322             :             else
    2323           0 :                 m_xColumn->getString();
    2324           0 :             bIsNull = m_xColumn->wasNull();
    2325             :         }
    2326             : 
    2327           0 :         catch(const Exception&)
    2328             :         {
    2329             :             SAL_WARN("forms.component", "OBoundControlModel::reset: this should have succeeded in all cases!");
    2330             :             DBG_UNHANDLED_EXCEPTION();
    2331             :         }
    2332             : 
    2333           0 :         bool bNeedValueTransfer = true;
    2334           0 :         if ( bIsNull )
    2335             :         {
    2336           0 :             if ( bIsNewRecord )
    2337             :             {
    2338             :                 // reset the control to it's default
    2339           0 :                 resetNoBroadcast();
    2340             :                 // and immediately commit the changes to the DB column, to keep consistency
    2341           0 :                 commitControlValueToDbColumn( true );
    2342           0 :                 bNeedValueTransfer = false;
    2343             :             }
    2344             : 
    2345             :         }
    2346             : 
    2347           0 :         if ( bNeedValueTransfer )
    2348           0 :             transferDbValueToControl();
    2349             :     }
    2350             : 
    2351             :     else
    2352             :     {
    2353          30 :         resetNoBroadcast();
    2354             :         // transfer to the external binding, if necessary
    2355          30 :         if ( hasExternalValueBinding() )
    2356           0 :             transferControlValueToExternal( aLock );
    2357             :     }
    2358             : 
    2359             :     // revalidate, if necessary
    2360          30 :     if ( hasValidator() )
    2361          18 :         recheckValidity( true );
    2362          30 :     aLock.release();
    2363          60 :     m_aResetHelper.notifyResetted();
    2364             : }
    2365             : 
    2366          31 : void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
    2367             : {
    2368             :     DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
    2369          31 :     m_xField = _rxField;
    2370          31 : }
    2371             : 
    2372          17 : bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
    2373             : {
    2374          17 :     if ( !_rxBinding.is() )
    2375           0 :         return false;
    2376          17 :     Sequence< Type > aTypeCandidates;
    2377             :     {
    2378             :         // SYNCHRONIZED >
    2379          17 :         ::osl::MutexGuard aGuard( m_aMutex );
    2380          17 :         aTypeCandidates = getSupportedBindingTypes();
    2381             :         // < SYNCHRONIZED
    2382             :     }
    2383             : 
    2384          34 :     for (   const Type* pType = aTypeCandidates.getConstArray();
    2385          17 :             pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
    2386             :             ++pType
    2387             :         )
    2388             :     {
    2389          17 :         if ( _rxBinding->supportsType( *pType ) )
    2390          17 :             return true;
    2391             :     }
    2392           0 :     return false;
    2393             : }
    2394             : 
    2395          17 : void OBoundControlModel::connectExternalValueBinding(
    2396             :         const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
    2397             : {
    2398             :     OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
    2399             :     OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
    2400             :     // if we're connected to a database column, suspend this
    2401          17 :     if ( hasField() )
    2402           0 :         impl_disconnectDatabaseColumn_noNotify();
    2403             :     // suspend listening for load-related events at out ambient form.
    2404             :     // This is because an external value binding overrules a possible database binding.
    2405          17 :     if ( isFormListening() )
    2406          17 :         doFormListening( false );
    2407             :     // remember this new binding
    2408          17 :     m_xExternalBinding = _rxBinding;
    2409             :     // tell the derivee
    2410          17 :     onConnectedExternalValue();
    2411             :     try
    2412             :     {
    2413             :         // add as value listener so we get notified when the value changes
    2414          17 :         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
    2415          17 :         if ( xModifiable.is() )
    2416           1 :             xModifiable->addModifyListener( this );
    2417             :         // add as property change listener for some (possibly present) properties we're
    2418             :         // interested in
    2419          34 :         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
    2420          34 :         Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
    2421          17 :         if ( xBindingPropsInfo.is() )
    2422             :         {
    2423           1 :             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
    2424             :             {
    2425           0 :                 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
    2426           0 :                 m_bBindingControlsRO = true;
    2427             :             }
    2428             : 
    2429           1 :             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
    2430             :             {
    2431           0 :                 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
    2432           0 :                 m_bBindingControlsEnable = true;
    2433             :             }
    2434             : 
    2435          17 :         }
    2436             : 
    2437             :     }
    2438             : 
    2439           0 :     catch( const Exception& )
    2440             :     {
    2441             :         DBG_UNHANDLED_EXCEPTION();
    2442             :     }
    2443             : 
    2444             :     // propagate our new value
    2445          17 :     transferExternalValueToControl( _rInstanceLock );
    2446             :     // if the binding is also a validator, use it, too. This is a constraint of the
    2447             :     // com.sun.star.form.binding.ValidatableBindableFormComponent service
    2448          17 :     if ( m_bSupportsValidation )
    2449             :     {
    2450             :         try
    2451             :         {
    2452          17 :             Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
    2453          17 :             if ( xAsValidator.is() )
    2454           0 :                 setValidator( xAsValidator );
    2455             :         }
    2456             : 
    2457           0 :         catch( const Exception& )
    2458             :         {
    2459             :             DBG_UNHANDLED_EXCEPTION();
    2460             :         }
    2461             : 
    2462             :     }
    2463          17 : }
    2464             : 
    2465          17 : void OBoundControlModel::disconnectExternalValueBinding( )
    2466             : {
    2467             :     try
    2468             :     {
    2469             :         // not listening at the binding anymore
    2470          17 :         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
    2471          17 :         if ( xModifiable.is() )
    2472           1 :             xModifiable->removeModifyListener( this );
    2473             :         // remove as property change listener
    2474          34 :         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
    2475          17 :         if ( m_bBindingControlsRO )
    2476           0 :             xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
    2477          17 :         if ( m_bBindingControlsEnable )
    2478          17 :             xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
    2479             :     }
    2480             : 
    2481           0 :     catch( const Exception& )
    2482             :     {
    2483             :         SAL_WARN("forms.component",  "OBoundControlModel::disconnectExternalValueBinding: caught an exception!");
    2484             :         DBG_UNHANDLED_EXCEPTION();
    2485             :     }
    2486             : 
    2487             :     // if the binding also acts as our validator, disconnect the validator, too
    2488          17 :     if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
    2489           0 :         disconnectValidator( );
    2490             :     // no binding anymore
    2491          17 :     m_xExternalBinding.clear();
    2492             :     // be a load listener at our form, again. This was suspended while we had
    2493             :     // an external value binding in place.
    2494          17 :     doFormListening( true );
    2495             :     // re-connect to database column of the new parent
    2496          17 :     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
    2497           0 :         impl_connectDatabaseColumn_noNotify( false );
    2498          17 : }
    2499             : 
    2500          17 : void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException, std::exception)
    2501             : {
    2502             :     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
    2503             :     // the interface for this method should not have been exposed if we do not
    2504             :     // support binding to external data
    2505             :     // allow reset
    2506          17 :     if ( _rxBinding.is() && !impl_approveValueBinding_nolock( _rxBinding ) )
    2507             :     {
    2508             :         throw IncompatibleTypesException(
    2509             :             FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
    2510             :             *this
    2511           0 :         );
    2512             :     }
    2513             : 
    2514          17 :     ControlModelLock aLock( *this );
    2515             :     // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
    2516             :     // might trigger a change in our BoundField.
    2517          34 :     FieldChangeNotifier aBoundFieldNotifier( aLock );
    2518             :     // disconnect from the old binding
    2519          17 :     if ( hasExternalValueBinding() )
    2520           8 :         disconnectExternalValueBinding( );
    2521             :     // connect to the new binding
    2522          17 :     if ( _rxBinding.is() )
    2523          34 :         connectExternalValueBinding( _rxBinding, aLock );
    2524          17 : }
    2525             : 
    2526         158 : Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding(  ) throw (RuntimeException, std::exception)
    2527             : {
    2528         158 :     ::osl::MutexGuard aGuard( m_aMutex );
    2529             :     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
    2530             :     // the interface for this method should not have been exposed if we do not
    2531             :     // support binding to external data
    2532         158 :     return m_xExternalBinding;
    2533             : }
    2534             : 
    2535           0 : void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException, std::exception )
    2536             : {
    2537           0 :     ControlModelLock aLock( *this );
    2538             :     OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
    2539           0 :     if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
    2540             :     {
    2541           0 :         transferExternalValueToControl( aLock );
    2542           0 :     }
    2543           0 : }
    2544             : 
    2545          31 : void OBoundControlModel::transferDbValueToControl( )
    2546             : {
    2547             :     try
    2548             :     {
    2549          31 :         setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
    2550             :     }
    2551             : 
    2552           0 :     catch( const Exception& )
    2553             :     {
    2554             :         DBG_UNHANDLED_EXCEPTION();
    2555             :     }
    2556          31 : }
    2557             : 
    2558          17 : void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock )
    2559             : {
    2560          17 :         Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
    2561          34 :         Type aValueExchangeType( getExternalValueType() );
    2562          17 :         _rInstanceLock.release();
    2563             :         // UNSAFE >
    2564          34 :         Any aExternalValue;
    2565             :         try
    2566             :         {
    2567          17 :             aExternalValue = xExternalBinding->getValue( aValueExchangeType );
    2568             :         }
    2569             : 
    2570           0 :         catch( const Exception& )
    2571             :         {
    2572             :             DBG_UNHANDLED_EXCEPTION();
    2573             :         }
    2574             :         // < UNSAFE
    2575          17 :         _rInstanceLock.acquire();
    2576          34 :         setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding );
    2577          17 : }
    2578             : 
    2579           0 : void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock )
    2580             : {
    2581             :     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
    2582             :         "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
    2583           0 :     if ( m_xExternalBinding.is() )
    2584             :     {
    2585           0 :         Any aExternalValue( translateControlValueToExternalValue() );
    2586           0 :         m_bTransferingValue = true;
    2587           0 :         _rInstanceLock.release();
    2588             :          // UNSAFE >
    2589             :         try
    2590             :         {
    2591           0 :             m_xExternalBinding->setValue( aExternalValue );
    2592             :         }
    2593             : 
    2594           0 :         catch( const Exception& )
    2595             :         {
    2596             :             DBG_UNHANDLED_EXCEPTION();
    2597             :         }
    2598             : 
    2599             :         // < UNSAFE
    2600           0 :         _rInstanceLock.acquire();
    2601           0 :         m_bTransferingValue = false;
    2602             :     }
    2603           0 : }
    2604             : 
    2605          12 : Sequence< Type > OBoundControlModel::getSupportedBindingTypes()
    2606             : {
    2607          12 :     return Sequence< Type >( &m_aValuePropertyType, 1 );
    2608             : }
    2609             : 
    2610          43 : void OBoundControlModel::calculateExternalValueType()
    2611             : {
    2612          43 :     m_aExternalValueType = Type();
    2613          43 :     if ( !m_xExternalBinding.is() )
    2614          69 :         return;
    2615          17 :     Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
    2616          34 :     for (   const Type* pTypeCandidate = aTypeCandidates.getConstArray();
    2617          17 :             pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
    2618             :             ++pTypeCandidate
    2619             :         )
    2620             :     {
    2621          17 :         if ( m_xExternalBinding->supportsType( *pTypeCandidate ) )
    2622             :         {
    2623          17 :             m_aExternalValueType = *pTypeCandidate;
    2624          17 :             break;
    2625             :         }
    2626          17 :     }
    2627             : }
    2628             : 
    2629           6 : Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
    2630             : {
    2631             :     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
    2632             :         "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
    2633           6 :     Any aControlValue( _rExternalValue );
    2634             :     // if the external value is VOID, and our value property is not allowed to be VOID,
    2635             :     // then default-construct a value
    2636           6 :     if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
    2637           0 :         aControlValue.setValue( NULL, m_aValuePropertyType );
    2638             :     // out of here
    2639           6 :     return aControlValue;
    2640             : }
    2641             : 
    2642           0 : Any OBoundControlModel::translateControlValueToExternalValue( ) const
    2643             : {
    2644           0 :     return getControlValue( );
    2645             : }
    2646             : 
    2647          45 : Any OBoundControlModel::translateControlValueToValidatableValue( ) const
    2648             : {
    2649             :     OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
    2650          45 :     if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
    2651           0 :         return translateControlValueToExternalValue();
    2652          45 :     return getControlValue();
    2653             : }
    2654             : 
    2655         264 : Any OBoundControlModel::getControlValue( ) const
    2656             : {
    2657             :     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
    2658             :         "OBoundControlModel::getControlValue: invalid aggregate !" );
    2659             :     OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
    2660             :         "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
    2661             :     // determine the current control value
    2662         264 :     Any aControlValue;
    2663         264 :     if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
    2664             :     {
    2665         264 :         aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
    2666             :     }
    2667             : 
    2668           0 :     else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
    2669             :     {
    2670           0 :         aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
    2671             :     }
    2672         264 :     return aControlValue;
    2673             : }
    2674             : 
    2675          18 : void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
    2676             : {
    2677             :     OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
    2678             :     OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
    2679          18 :     m_xValidator = _rxValidator;
    2680             : 
    2681             :     // add as value listener so we get notified when the value changes
    2682          18 :     if ( m_xValidator.is() )
    2683             :     {
    2684             :         try
    2685             :         {
    2686          18 :             m_xValidator->addValidityConstraintListener( this );
    2687             :         }
    2688             : 
    2689           0 :         catch( const RuntimeException& )
    2690             :         {
    2691             :         }
    2692             :     }
    2693          18 :     onConnectedValidator( );
    2694          18 : }
    2695             : 
    2696          18 : void OBoundControlModel::disconnectValidator( )
    2697             : {
    2698             :     OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
    2699             : 
    2700             :     // add as value listener so we get notified when the value changes
    2701          18 :     if ( m_xValidator.is() )
    2702             :     {
    2703             :         try
    2704             :         {
    2705          18 :             m_xValidator->removeValidityConstraintListener( this );
    2706             :         }
    2707             : 
    2708           0 :         catch( const RuntimeException& )
    2709             :         {
    2710             :         }
    2711             :     }
    2712             : 
    2713          18 :     m_xValidator.clear();
    2714             : 
    2715          18 :     onDisconnectedValidator( );
    2716          18 : }
    2717             : 
    2718          18 : void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException, std::exception)
    2719             : {
    2720          18 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    2721             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
    2722             :     // the interface for this method should not have been exposed if we do not
    2723             :     // support validation
    2724             : 
    2725             :     // early out if the validator does not change
    2726          18 :     if ( _rxValidator == m_xValidator )
    2727          18 :         return;
    2728             : 
    2729          18 :     if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
    2730             :         throw VetoException(
    2731             :             FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
    2732             :             *this
    2733           0 :         );
    2734             : 
    2735             :     // disconnect from the old validator
    2736          18 :     if ( hasValidator() )
    2737           0 :         disconnectValidator( );
    2738             : 
    2739             :     // connect to the new validator
    2740          18 :     if ( _rxValidator.is() )
    2741          18 :         connectValidator( _rxValidator );
    2742             : }
    2743             : 
    2744          40 : Reference< XValidator > SAL_CALL OBoundControlModel::getValidator(  ) throw (RuntimeException, std::exception)
    2745             : {
    2746          40 :     ::osl::MutexGuard aGuard( m_aMutex );
    2747             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
    2748             :     // the interface for this method should not have been exposed if we do not
    2749             :     // support validation
    2750             : 
    2751          40 :     return m_xValidator;
    2752             : }
    2753             : 
    2754           9 : void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
    2755             : {
    2756           9 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    2757             :     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
    2758             :     // the interface for this method should not have been exposed if we do not
    2759             :     // support validation
    2760             : 
    2761           9 :     recheckValidity( false );
    2762           9 : }
    2763             : 
    2764          50 : sal_Bool SAL_CALL OBoundControlModel::isValid(  ) throw (RuntimeException, std::exception)
    2765             : {
    2766          50 :     return m_bIsCurrentValueValid;
    2767             : }
    2768             : 
    2769           8 : ::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const
    2770             : {
    2771           8 :     if ( hasValidator() )
    2772           0 :         return translateControlValueToValidatableValue();
    2773           8 :     return getControlValue();
    2774             : }
    2775             : 
    2776           9 : Any SAL_CALL OBoundControlModel::getCurrentValue(  ) throw (RuntimeException, std::exception)
    2777             : {
    2778           9 :     ::osl::MutexGuard aGuard( m_aMutex );
    2779           9 :     return getCurrentFormComponentValue();
    2780             : }
    2781             : 
    2782          33 : void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException, std::exception)
    2783             : {
    2784          33 :     if ( Listener.is() )
    2785          33 :         m_aFormComponentListeners.addInterface( Listener );
    2786          33 : }
    2787             : 
    2788          33 : void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException, std::exception)
    2789             : {
    2790          33 :     if ( Listener.is() )
    2791          33 :         m_aFormComponentListeners.removeInterface( Listener );
    2792          33 : }
    2793             : 
    2794         377 : void OBoundControlModel::recheckValidity( bool _bForceNotification )
    2795             : {
    2796             :     try
    2797             :     {
    2798         377 :         bool bIsCurrentlyValid = true;
    2799         377 :         if ( hasValidator() )
    2800         102 :             bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
    2801             : 
    2802         377 :         if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
    2803             :         {
    2804         350 :             m_bIsCurrentValueValid = bIsCurrentlyValid;
    2805             : 
    2806             :             // release our mutex for the notifications
    2807         350 :             MutexRelease aRelease( m_aMutex );
    2808         350 :             m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
    2809             :         }
    2810             : 
    2811             :     }
    2812             : 
    2813           0 :     catch( const Exception& )
    2814             :     {
    2815             :         SAL_WARN("forms.component",  "OBoundControlModel::recheckValidity: caught an exception!");
    2816             :         DBG_UNHANDLED_EXCEPTION();
    2817             :     }
    2818         377 : }
    2819             : 
    2820         324 : void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
    2821             : {
    2822         324 :     BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel )
    2823         324 :         DECL_PROP1      ( CONTROLSOURCE,           OUString,     BOUND );
    2824         324 :         DECL_IFACE_PROP3( BOUNDFIELD,               XPropertySet,       BOUND, READONLY, TRANSIENT );
    2825         324 :         DECL_IFACE_PROP2( CONTROLLABEL,             XPropertySet,       BOUND, MAYBEVOID );
    2826         324 :         DECL_PROP2      ( CONTROLSOURCEPROPERTY,    OUString,    READONLY, TRANSIENT );
    2827         324 :         DECL_BOOL_PROP1 ( INPUT_REQUIRED,                               BOUND );
    2828             :     END_DESCRIBE_PROPERTIES()
    2829         324 : }
    2830             : }
    2831             : 
    2832             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11