summaryrefslogtreecommitdiff
path: root/cppuhelper/source/propshlp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cppuhelper/source/propshlp.cxx')
-rw-r--r--cppuhelper/source/propshlp.cxx1106
1 files changed, 1106 insertions, 0 deletions
diff --git a/cppuhelper/source/propshlp.cxx b/cppuhelper/source/propshlp.cxx
new file mode 100644
index 000000000000..1783d853908e
--- /dev/null
+++ b/cppuhelper/source/propshlp.cxx
@@ -0,0 +1,1106 @@
+/*************************************************************************
+ *
+ * $RCSfile: propshlp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 15:26:10 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#ifndef _CPPUHELPER_IMPLBASE1_HXX
+#include <cppuhelper/implbase1.hxx>
+#endif
+
+#include <osl/diagnose.h>
+
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+using namespace rtl;
+using namespace cppu;
+
+namespace cppu {
+
+IPropertyArrayHelper::~IPropertyArrayHelper()
+{
+}
+
+inline const ::com::sun::star::uno::Type & getPropertyTypeIdentifier( )
+{
+ return ::getCppuType( (Reference< XPropertyChangeListener > *)0 );
+}
+inline const ::com::sun::star::uno::Type & getPropertiesTypeIdentifier()
+{
+ return ::getCppuType( (Reference< XPropertiesChangeListener > *)0 );
+}
+inline const ::com::sun::star::uno::Type & getVetoableTypeIdentifier()
+{
+ return ::getCppuType( (Reference< XVetoableChangeListener > *)0 );
+}
+
+int SAL_CALL compare_OUString_Property_Impl( const void *arg1, const void *arg2 )
+{
+ return ((OUString *)arg1)->compareTo( ((Property *)arg2)->Name );
+}
+
+/**
+ * The class which implements the PropertySetInfo interface.
+ */
+class OPropertySetHelperInfo_Impl
+ : public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo >
+{
+ Sequence < Property > aInfos;
+
+public:
+ OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ );
+
+ // XPropertySetInfo-Methoden
+ virtual Sequence< Property > SAL_CALL getProperties(void);
+ virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName);
+ virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName);
+};
+
+
+/**
+ * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
+ */
+OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ )
+ :aInfos( rHelper_.getProperties() )
+{
+}
+
+/**
+ * Return the sequence of properties, which are provided throug the constructor.
+ */
+Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void)
+{
+ return aInfos;
+}
+
+/**
+ * Return the sequence of properties, which are provided throug the constructor.
+ */
+Property OPropertySetHelperInfo_Impl::getPropertyByName( const OUString & PropertyName )
+{
+ Property * pR;
+ pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl );
+ if( !pR ) {
+ throw UnknownPropertyException();
+ }
+
+ return *pR;
+}
+
+/**
+ * Return the sequence of properties, which are provided throug the constructor.
+ */
+sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString & PropertyName )
+{
+ Property * pR;
+ pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl );
+ return pR != NULL;
+}
+
+// ----------------------------------------------------
+// class PropertySetHelper
+// ----------------------------------------------------
+OPropertySetHelper::OPropertySetHelper(
+ OBroadcastHelper & rBHelper_ )
+ : rBHelper( rBHelper_ )
+ , aBoundLC( rBHelper_.rMutex )
+ , aVetoableLC( rBHelper_.rMutex )
+{
+}
+
+/**
+ * You must call disposing before.
+ */
+OPropertySetHelper::~OPropertySetHelper()
+{
+}
+
+/**
+ * These method is called from queryInterface, if no delegator is set.
+ * Otherwise this method is called from the delegator.
+ */
+// XAggregation
+Any OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type & rType )
+{
+ return ::cppu::queryInterface( rType,
+ static_cast< XPropertySet * >( this ),
+ static_cast< XMultiPropertySet * >( this ),
+ static_cast< XFastPropertySet * >( this ) );
+}
+
+// ComponentHelper
+void OPropertySetHelper::disposing()
+{
+ // Create an event with this as sender
+ Reference < XPropertySet > rSource( SAL_STATIC_CAST( XPropertySet * , this ) , UNO_QUERY );
+ EventObject aEvt;
+ aEvt.Source = rSource;
+
+ // inform all listeners to reelease this object
+ // The listener container are automaticly cleared
+ aBoundLC.disposeAndClear( aEvt );
+ aVetoableLC.disposeAndClear( aEvt );
+}
+
+Reference < XPropertySetInfo > OPropertySetHelper::createPropertySetInfo( IPropertyArrayHelper & rProperties )
+{
+ return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) );
+}
+
+// XPropertySet
+void OPropertySetHelper::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
+{
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ // call the method of the XFastPropertySet interface
+ setFastPropertyValue( nHandle, rValue );
+}
+
+// XPropertySet
+Any OPropertySetHelper::getPropertyValue( const OUString& rPropertyName )
+{
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ // call the method of the XFastPropertySet interface
+ return getFastPropertyValue( nHandle );
+}
+
+// XPropertySet
+void OPropertySetHelper::addPropertyChangeListener(const OUString& rPropertyName,
+ const Reference < XPropertyChangeListener > & rxListener)
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ // only add listeners if you are not disposed
+ // a listener with no name means all properties
+ if( rPropertyName.len() )
+ {
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ if( nHandle == -1 ) {
+ // property not known throw exception
+ throw UnknownPropertyException() ;
+ }
+
+ sal_Int16 nAttributes;
+ rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
+ if( !(nAttributes & ::com::sun::star::beans::PropertyAttribute::BOUND) )
+ {
+ OSL_ENSHURE( sal_False, "add listener to an unbound property" );
+ // silent ignore this
+ return;
+ }
+ // add the change listener to the helper container
+
+ aBoundLC.addInterface( (sal_Int32)nHandle, rxListener );
+ }
+ else
+ // add the change listener to the helper container
+ rBHelper.aLC.addInterface(
+ getPropertyTypeIdentifier( ),
+ rxListener
+ );
+ }
+}
+
+
+// XPropertySet
+void OPropertySetHelper::removePropertyChangeListener(const OUString& rPropertyName,
+ const Reference < XPropertyChangeListener >& rxListener)
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automaticly released in a dispose call
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ if( rPropertyName.len() )
+ {
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ if( nHandle == -1 )
+ // property not known throw exception
+ throw UnknownPropertyException();
+ aBoundLC.removeInterface( (sal_Int32)nHandle, rxListener );
+ }
+ else {
+ // remove the change listener to the helper container
+ rBHelper.aLC.removeInterface(
+ getPropertyTypeIdentifier( ),
+ rxListener
+ );
+ }
+ }
+}
+
+// XPropertySet
+void OPropertySetHelper::addVetoableChangeListener
+(
+ const OUString& rPropertyName,
+ const Reference< XVetoableChangeListener > & rxListener
+)
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bInDispose, "do not addVetoableChangeListener in the dispose call" );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ // only add listeners if you are not disposed
+ // a listener with no name means all properties
+ if( rPropertyName.len() )
+ {
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ if( nHandle == -1 ) {
+ // property not known throw exception
+ throw UnknownPropertyException();
+ }
+
+ sal_Int16 nAttributes;
+ rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
+ if( !(nAttributes & PropertyAttribute::CONSTRAINED) )
+ {
+ OSL_ENSHURE( sal_False, "addVetoableChangeListener, and property is not constrained" );
+ // silent ignore this
+ return;
+ }
+ // add the vetoable listener to the helper container
+ aVetoableLC.addInterface( (sal_Int32)nHandle, rxListener );
+ }
+ else
+ // add the vetoable listener to the helper container
+ rBHelper.aLC.addInterface(
+ getVetoableTypeIdentifier( ),
+ rxListener
+ );
+ }
+}
+
+// XPropertySet
+void OPropertySetHelper::removeVetoableChangeListener
+(
+ const OUString& rPropertyName,
+ const Reference < XVetoableChangeListener > & rxListener
+)
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automaticly released in a dispose call
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ if( rPropertyName.len() )
+ {
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // map the name to the handle
+ sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
+ if( nHandle == -1 ) {
+ // property not known throw exception
+ throw UnknownPropertyException();
+ }
+ // remove the vetoable listener to the helper container
+ aVetoableLC.removeInterface( (sal_Int32)nHandle, rxListener );
+ }
+ else
+ // add the vetoable listener to the helper container
+ rBHelper.aLC.removeInterface(
+ getVetoableTypeIdentifier( ),
+ rxListener
+ );
+ }
+}
+
+// XFastPropertySet
+void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::beans::PropertyVetoException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ OSL_ENSHURE( !rBHelper.bInDispose, "do not setFastPropertyValue in the dispose call" );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+
+ IPropertyArrayHelper & rInfo = getInfoHelper();
+ sal_Int16 nAttributes;
+ if( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ) ) {
+ // unknown property
+ throw UnknownPropertyException();
+ }
+ if( nAttributes & PropertyAttribute::READONLY )
+ throw PropertyVetoException();
+
+ Any aConvertedVal;
+ Any aOldVal;
+
+ // Will the property change?
+ sal_Bool bChanged;
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue );
+ // release guard to fire events
+ }
+ if( bChanged )
+ {
+ // Is it a constrained property?
+ if( nAttributes & PropertyAttribute::CONSTRAINED )
+ {
+ // In aValue is the converted rValue
+ // fire a constarined event
+ // second parameter NULL means constrained
+ fire( &nHandle, &rValue, &aOldVal, 1, sal_True );
+ }
+
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ // set the property to the new value
+ setFastPropertyValue_NoBroadcast( nHandle, aConvertedVal );
+ // release guard to fire events
+ }
+ // file a change event, if the value changed
+ fire( &nHandle, &rValue, &aOldVal, 1, sal_False );
+ }
+}
+
+// XFastPropertySet
+Any OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle )
+ throw(::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+
+{
+ IPropertyArrayHelper & rInfo = getInfoHelper();
+ if( !rInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) )
+ // unknown property
+ throw UnknownPropertyException();
+
+ Any aRet;
+ MutexGuard aGuard( rBHelper.rMutex );
+ getFastPropertyValue( aRet, nHandle );
+ return aRet;
+}
+
+//--------------------------------------------------------------------------
+void OPropertySetHelper::fire
+(
+ sal_Int32 * pnHandles,
+ const Any * pNewValues,
+ const Any * pOldValues,
+ sal_Int32 nHandles, // These is the Count of the array
+ sal_Bool bVetoable
+)
+{
+ // Only fire, if one or more properties changed
+ if( nHandles )
+ {
+ // create the event sequence of all changed properties
+ Sequence< PropertyChangeEvent > aEvts( nHandles );
+ PropertyChangeEvent * pEvts = aEvts.getArray();
+ Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
+ sal_Int32 i;
+ sal_Int32 nChangesLen = 0;
+ // Loop over all changed properties to fill the event struct
+ for( i = 0; i < nHandles; i++ )
+ {
+ // Vetoable fire and constrained attribute set or
+ // Change fire and Changed and bound attribute set
+ IPropertyArrayHelper & rInfo = getInfoHelper();
+ sal_Int16 nAttributes;
+ OUString aPropName;
+ rInfo.fillPropertyMembersByHandle( &aPropName, &nAttributes, pnHandles[i] );
+
+ if( bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)
+ || !bVetoable && (nAttributes & PropertyAttribute::BOUND) )
+ {
+ pEvts[nChangesLen].Source = xSource;
+ pEvts[nChangesLen].PropertyName = aPropName;
+ pEvts[nChangesLen].PropertyHandle = pnHandles[i];
+ pEvts[nChangesLen].OldValue = pOldValues[i];
+ pEvts[nChangesLen].NewValue = pNewValues[i];
+ nChangesLen++;
+ }
+ }
+
+ // fire the events for all changed properties
+ for( i = 0; i < nChangesLen; i++ )
+ {
+ // get the listener container for the property name
+ OInterfaceContainerHelper * pLC;
+ if( bVetoable ) // fire change Events?
+ pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle );
+ else
+ pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle );
+ if( pLC )
+ {
+ // Ueber alle Listener iterieren und Events senden
+ OInterfaceIteratorHelper aIt( *pLC);
+ while( aIt.hasMoreElements() )
+ {
+ XInterface * pL = aIt.next();
+ if( bVetoable ) // fire change Events?
+ ((XVetoableChangeListener *)pL)->vetoableChange( pEvts[i] );
+ else
+ ((XPropertyChangeListener *)pL)->propertyChange( pEvts[i] );
+ }
+ }
+ // broadcast to all listeners with "" property name
+ if( bVetoable ){
+ // fire change Events?
+ pLC = rBHelper.aLC.getContainer(
+ getVetoableTypeIdentifier()
+ );
+ }
+ else {
+ pLC = rBHelper.aLC.getContainer(
+ getPropertyTypeIdentifier( )
+ );
+ }
+ if( pLC )
+ {
+ // Ueber alle Listener iterieren und Events senden
+ OInterfaceIteratorHelper aIt( *pLC);
+ while( aIt.hasMoreElements() )
+ {
+ XInterface * pL = aIt.next();
+ if( bVetoable ) // fire change Events?
+ ((XVetoableChangeListener *)pL)->vetoableChange( pEvts[i] );
+ else
+ ((XPropertyChangeListener *)pL)->propertyChange( pEvts[i] );
+ }
+ }
+ }
+
+ // reduce array to changed properties
+ aEvts.realloc( nChangesLen );
+
+ if( !bVetoable )
+ {
+ OInterfaceContainerHelper * pCont = 0;
+ pCont = rBHelper.aLC.getContainer(
+ getPropertiesTypeIdentifier( )
+ );
+ if( pCont )
+ {
+ // Here is a Bug, unbound properties are also fired
+ OInterfaceIteratorHelper aIt( *pCont );
+ while( aIt.hasMoreElements() )
+ {
+ XPropertiesChangeListener * pL = (XPropertiesChangeListener *)aIt.next();
+ // fire the hole event sequence to the XPropertiesChangeListener's
+ pL->propertiesChange( aEvts );
+ }
+ }
+ }
+ }
+}
+
+// OPropertySetHelper
+void OPropertySetHelper::setFastPropertyValues
+(
+ sal_Int32 nSeqLen,
+ sal_Int32 * pHandles,
+ const Any * pValues,
+ sal_Int32 nHitCount
+)
+throw (Exception)
+{
+ OSL_ENSHURE( !rBHelper.bInDispose, "do not getFastPropertyValue in the dispose call" );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+
+ Any * pConvertedValues = NULL;
+ Any * pOldValues = NULL;
+
+ try
+ {
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+
+ pConvertedValues = new Any[ nHitCount ];
+ pOldValues = new Any[ nHitCount ];
+ sal_Int32 nHitCount = 0;
+ sal_Int32 i;
+
+ {
+ // must lock the mutex outside the loop. So all values are consistent.
+ MutexGuard aGuard( rBHelper.rMutex );
+ for( i = 0; i < nSeqLen; i++ )
+ {
+ if( pHandles[i] != -1 )
+ {
+ sal_Int16 nAttributes;
+ rPH.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] );
+ if( nAttributes & PropertyAttribute::READONLY ) {
+ throw PropertyVetoException();
+ }
+ // Will the property change?
+ if( convertFastPropertyValue( pConvertedValues[ nHitCount ], pOldValues[nHitCount],
+ pHandles[i], pValues[i] ) )
+ {
+ // only increment if the property really change
+ pHandles[nHitCount] = pHandles[i];
+ nHitCount++;
+ }
+ }
+ }
+ // release guard to fire events
+ }
+
+ // fire vetoable events
+ fire( pHandles, pConvertedValues, pOldValues, nHitCount, sal_True );
+
+ {
+ // must lock the mutex outside the loop.
+ MutexGuard aGuard( rBHelper.rMutex );
+ // Loop over all changed properties
+ for( i = 0; i < nHitCount; i++ )
+ {
+ // Will the property change?
+ setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
+ }
+ // release guard to fire events
+ }
+
+ // fire change events
+ fire( pHandles, pConvertedValues, pOldValues, nHitCount, sal_False );
+ }
+ catch( ... )
+ {
+ delete [] pOldValues;
+ delete [] pConvertedValues;
+ throw;
+ }
+ delete [] pOldValues;
+ delete [] pConvertedValues;
+}
+
+// XMultiPropertySet
+/**
+ * The sequence may be conatain not known properties. The implementation
+ * must ignore these properties.
+ */
+void OPropertySetHelper::setPropertyValues
+(
+ const Sequence<OUString>& rPropertyNames,
+ const Sequence<Any>& rValues
+)
+{
+ sal_Int32 * pHandles = NULL;
+ try
+ {
+ sal_Int32 nSeqLen = rPropertyNames.getLength();
+ pHandles = new sal_Int32[ nSeqLen ];
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // fill the handle array
+ sal_Int32 nHitCount = rPH.fillHandles( pHandles, rPropertyNames );
+ if( nHitCount != 0 )
+ setFastPropertyValues( nSeqLen, pHandles, rValues.getConstArray(), nHitCount );
+ }
+ catch( ... )
+ {
+ delete [] pHandles;
+ throw;
+ }
+ delete [] pHandles;
+}
+
+// XMultiPropertySet
+Sequence<Any> OPropertySetHelper::getPropertyValues( const Sequence<OUString>& rPropertyNames )
+{
+ sal_Int32 nSeqLen = rPropertyNames.getLength();
+ sal_Int32 * pHandles = new sal_Int32[ nSeqLen ];
+ Sequence< Any > aValues( nSeqLen );
+
+ // get the map table
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ // fill the handle array
+ rPH.fillHandles( pHandles, rPropertyNames );
+
+ Any * pValues = aValues.getArray();
+ const OUString * pNames = rPropertyNames.getConstArray();
+
+ MutexGuard aGuard( rBHelper.rMutex );
+ // fill the sequence with the values
+ for( sal_Int32 i = 0; i < nSeqLen; i++ )
+ getFastPropertyValue( pValues[i], pHandles[i] );
+
+ delete [] pHandles;
+ return aValues;
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::addPropertiesChangeListener (
+ const Sequence<OUString> & ,
+ const Reference < XPropertiesChangeListener > & rListener
+ )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automaticly released in a dispose call
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ // Listener wird zu allen Properties angemeldet, besser ist
+ // sie ueber die Namen anzumelden
+ rBHelper.aLC.addInterface(
+ getPropertiesTypeIdentifier( ),
+ rListener
+ );
+ }
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::removePropertiesChangeListener
+ ( const Reference < XPropertiesChangeListener > & rxListener )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSHURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automaticly released in a dispose call
+ if( !rBHelper.bInDispose && !rBHelper.bDisposed )
+ {
+ rBHelper.aLC.removeInterface(
+ getPropertiesTypeIdentifier( ),
+ rxListener
+ );
+ }
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::firePropertiesChangeEvent
+(
+ const Sequence<OUString>& rPropertyNames,
+ const Reference < XPropertiesChangeListener >& rListener
+)
+{
+ sal_Int32 nLen = rPropertyNames.getLength();
+ sal_Int32 * pHandles = new sal_Int32[nLen];
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ rPH.fillHandles( pHandles, rPropertyNames );
+ const OUString* pNames = rPropertyNames.getConstArray();
+
+ // get the count of matching properties
+ sal_Int32 nFireLen = 0;
+ sal_Int32 i;
+ for( i = 0; i < nLen; i++ )
+ if( pHandles[i] != -1 )
+ nFireLen++;
+
+ Sequence<PropertyChangeEvent> aChanges( nFireLen );
+ PropertyChangeEvent* pChanges = aChanges.getArray();
+
+ sal_Int32 nFirePos = 0;
+ {
+ // must lock the mutex outside the loop. So all values are consistent.
+ MutexGuard aGuard( rBHelper.rMutex );
+ Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
+ for( i = 0; i < nLen; i++ )
+ {
+ if( pHandles[i] != -1 )
+ {
+ pChanges[nFirePos].Source = xSource;
+ pChanges[nFirePos].PropertyName = pNames[i];
+ pChanges[nFirePos].PropertyHandle = pHandles[i];
+ getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] );
+ pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
+ nFirePos++;
+ }
+ }
+ // release guard to fire events
+ }
+ if( nFireLen )
+ rListener->propertiesChange( aChanges );
+
+ delete [] pHandles;
+}
+
+#ifdef xdvnsdfln
+// XPropertyState
+PropertyState OPropertySetHelper::getPropertyState( const OUString& PropertyName )
+{
+ PropertyState aState;
+ return aState;
+}
+
+// XPropertyState
+Sequence< PropertyState > OPropertySetHelper::getPropertyStates( const Sequence< OUString >& PropertyNames )
+{
+ ULONG nNames = PropertyNames.getLength();
+ const OUString* pNames = PropertyNames.getConstArray();
+
+ Sequence< PropertyState > aStates( nNames );
+ return aStates;
+
+}
+
+void OPropertySetHelper::setPropertyToDefault( const OUString& aPropertyName )
+{
+ setPropertyValue( aPropertyName, Any() );
+}
+
+Any OPropertySetHelper::getPropertyDefault( const OUString& aPropertyName ) const
+{
+ return Any();
+}
+
+void OPropertySetHelper::addPropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
+{
+}
+
+void OPropertySetHelper::removePropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
+{
+}
+#endif
+
+//========================================================================
+//== OPropertyArrayHelper ================================================
+//========================================================================
+
+//========================================================================
+
+// static OUString makeOUString( sal_Char *p )
+// {
+// sal_Int32 nLen = strlen(p);
+// sal_Unicode *pw = new sal_Unicode[nLen];
+
+// for( int i = 0 ; i < nLen ; i ++ ) {
+
+// // Only ascii strings allowed with this helper !
+// OSL_ASSERT( p[i] < 127 );
+// pw[i] = p[i];
+// }
+// OUString ow( pw , nLen );
+// delete pw;
+// return ow;
+// }
+
+int SAL_CALL compare_Property_Impl( const void *arg1, const void *arg2 )
+{
+ return ((Property *)arg1)->Name.compareTo( ((Property *)arg2)->Name );
+}
+
+void OPropertyArrayHelper::init( sal_Bool bSorted )
+{
+ sal_Int32 i, nElements = aInfos.getLength();
+ const Property* pProperties = aInfos.getConstArray();
+
+ for( i = 1; i < nElements; i++ )
+ {
+ if( pProperties[i-1].Name >= pProperties[i].Name )
+ {
+ OSL_ENSHURE( !bSorted, "Property array is not sorted" );
+ // not sorted
+ qsort( aInfos.getArray(), nElements, sizeof( Property ),
+ compare_Property_Impl );
+ break;
+ }
+ }
+ // may be that the array is resorted
+ pProperties = aInfos.getConstArray();
+ for( i = 0; i < nElements; i++ )
+ if( pProperties[i].Handle != i )
+ return;
+ // The handle is the index
+ bRightOrdered = sal_True;
+}
+
+OPropertyArrayHelper::OPropertyArrayHelper
+(
+ Property * pProps,
+ sal_Int32 nEle,
+ sal_Bool bSorted
+)
+ : aInfos(pProps, nEle)
+ , bRightOrdered( sal_False )
+{
+ init( bSorted );
+}
+
+OPropertyArrayHelper::OPropertyArrayHelper
+(
+ const Sequence< Property > & aProps,
+ sal_Bool bSorted
+)
+ : aInfos(aProps)
+ , bRightOrdered( sal_False )
+{
+ init( bSorted );
+}
+
+//========================================================================
+sal_Int32 OPropertyArrayHelper::getCount() const
+{
+ return aInfos.getLength();
+}
+
+//========================================================================
+sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle
+(
+ OUString * pPropName,
+ sal_Int16 * pAttributes,
+ sal_Int32 nHandle
+)
+{
+ const Property* pProperties = aInfos.getConstArray();
+ sal_Int32 nElements = aInfos.getLength();
+
+ if( bRightOrdered )
+ {
+ if( nHandle < 0 || nHandle >= nElements )
+ return sal_False;
+ if( pPropName )
+ *pPropName = pProperties[ nHandle ].Name;
+ if( pAttributes )
+ *pAttributes = pProperties[ nHandle ].Attributes;
+ return sal_True;
+ }
+ else
+ {
+ // normally the array is sorted
+ for( sal_Int32 i = 0; i < nElements; i++ )
+ {
+ if( pProperties[i].Handle == nHandle )
+ {
+ if( pPropName )
+ *pPropName = pProperties[ i ].Name;
+ if( pAttributes )
+ *pAttributes = pProperties[ i ].Attributes;
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+//========================================================================
+Sequence< Property > OPropertyArrayHelper::getProperties(void)
+{
+ /*if( aInfos.getLength() != nElements )
+ {
+ ((OPropertyArrayHelper *)this)->aInfos.realloc( nElements );
+ Property * pProps = ((OPropertyArrayHelper *)this)->aInfos.getArray();
+ for( sal_Int32 i = 0; i < nElements; i++ )
+ {
+ pProps[i].Name = pProperties[i].Name;
+ pProps[i].Handle = pProperties[i].Handle;
+ pProps[i].Type = pProperties[i].Type;
+ pProps[i].Attributes = pProperties[i].Attributes;
+ }
+ }*/
+ return aInfos;
+}
+
+//========================================================================
+Property OPropertyArrayHelper::getPropertyByName(const OUString& aPropertyName)
+ throw (UnknownPropertyException)
+{
+ Property * pR;
+ pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl );
+ if( !pR ) {
+ throw UnknownPropertyException();
+ }
+
+ /*Property aProp;
+ aProp.Name = pR->Name;
+ aProp.Handle = pR->Handle;
+ aProp.Type = pR->Type;
+ aProp.Attributes = pR->Attributes;
+ return aProp;*/
+ return *pR;
+}
+
+//========================================================================
+sal_Bool OPropertyArrayHelper::hasPropertyByName(const OUString& aPropertyName)
+{
+ Property * pR;
+ pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl );
+ return pR != NULL;
+}
+
+//========================================================================
+sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName )
+{
+ Property * pR;
+ pR = (Property *)bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl );
+ return pR ? pR->Handle : -1;
+}
+
+//========================================================================
+sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames )
+{
+ sal_Int32 nHitCount = 0;
+ const OUString * pReqProps = rPropNames.getConstArray();
+ sal_Int32 nReqLen = rPropNames.getLength();
+ const Property * pCur = aInfos.getConstArray();
+ const Property * pEnd = pCur + aInfos.getLength();
+
+ for( sal_Int32 i = 0; i < nReqLen; i++ )
+ {
+ // Logarithmus ermitteln
+ sal_Int32 n = (sal_Int32)(pEnd - pCur);
+ sal_Int32 nLog = 0;
+ while( n )
+ {
+ nLog += 1;
+ n = n >> 1;
+ }
+
+ // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
+ // zu dursuchenden Properties.
+ if( (nReqLen - i) * nLog >= pEnd - pCur )
+ {
+ // linear search is better
+ while( pCur < pEnd && pReqProps[i] > pCur->Name )
+ {
+ pCur++;
+ }
+ if( pCur < pEnd && pReqProps[i] == pCur->Name )
+ {
+ pHandles[i] = pCur->Handle;
+ nHitCount++;
+ }
+ else
+ pHandles[i] = -1;
+ }
+ else
+ {
+ // binary search is better
+ sal_Int32 nCompVal = 1;
+ const Property * pOldEnd = pEnd--;
+ const Property * pMid = pCur;
+
+ while( nCompVal != 0 && pCur <= pEnd )
+ {
+ pMid = (pEnd - pCur) / 2 + pCur;
+
+ nCompVal = pReqProps[i].compareTo( pMid->Name );
+
+ if( nCompVal > 0 )
+ pCur = pMid + 1;
+ else
+ pEnd = pMid - 1;
+ }
+
+ if( nCompVal == 0 )
+ {
+ pHandles[i] = pMid->Handle;
+ nHitCount++;
+ pCur = pMid +1;
+ }
+ else if( nCompVal > 0 )
+ {
+ pHandles[i] = -1;
+ pCur = pMid +1;
+ }
+ else
+ {
+ pHandles[i] = -1;
+ pCur = pMid;
+ }
+ pEnd = pOldEnd;
+ }
+ }
+ return nHitCount;
+}
+
+} // end namespace cppu
+
+
+