xref: /trunk/main/cppuhelper/source/propshlp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppuhelper.hxx"
30 
31 #include "osl/diagnose.h"
32 #include "cppuhelper/implbase1.hxx"
33 #include "cppuhelper/weak.hxx"
34 #include "cppuhelper/propshlp.hxx"
35 #include "cppuhelper/exc_hlp.hxx"
36 #include "com/sun/star/beans/PropertyAttribute.hpp"
37 #include "com/sun/star/lang/DisposedException.hpp"
38 
39 
40 using namespace osl;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::beans;
43 using namespace com::sun::star::lang;
44 using namespace rtl;
45 using namespace cppu;
46 
47 namespace cppu {
48 
49 IPropertyArrayHelper::~IPropertyArrayHelper()
50 {
51 }
52 
53 inline const ::com::sun::star::uno::Type & getPropertyTypeIdentifier( ) SAL_THROW( () )
54 {
55 	return ::getCppuType( (Reference< XPropertyChangeListener > *)0 );
56 }
57 inline const ::com::sun::star::uno::Type & getPropertiesTypeIdentifier() SAL_THROW( () )
58 {
59 	return ::getCppuType( (Reference< XPropertiesChangeListener > *)0 );
60 }
61 inline const ::com::sun::star::uno::Type & getVetoableTypeIdentifier() SAL_THROW( () )
62 {
63 	return ::getCppuType( (Reference< XVetoableChangeListener > *)0 );
64 }
65 
66 extern "C" {
67 
68 static int compare_OUString_Property_Impl( const void *arg1, const void *arg2 )
69     SAL_THROW_EXTERN_C()
70 {
71    return ((OUString *)arg1)->compareTo( ((Property *)arg2)->Name );
72 }
73 
74 }
75 
76 /**
77  * The class which implements the PropertySetInfo interface.
78  */
79 
80 class OPropertySetHelperInfo_Impl
81 	: public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo >
82 {
83 	Sequence < Property > aInfos;
84 
85 public:
86 	OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ ) SAL_THROW( () );
87 
88 	// XPropertySetInfo-Methoden
89     virtual Sequence< Property > SAL_CALL getProperties(void) throw(::com::sun::star::uno::RuntimeException);
90     virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
91     virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) throw(::com::sun::star::uno::RuntimeException);
92 };
93 
94 
95 /**
96  * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
97  */
98 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
99 	IPropertyArrayHelper & rHelper_ )
100 	SAL_THROW( () )
101 	:aInfos( rHelper_.getProperties() )
102 {
103 }
104 
105 /**
106  * Return the sequence of properties, which are provided throug the constructor.
107  */
108 Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException)
109 
110 {
111 	return aInfos;
112 }
113 
114 /**
115  * Return the sequence of properties, which are provided throug the constructor.
116  */
117 Property OPropertySetHelperInfo_Impl::getPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
118 {
119 	Property * pR;
120 	pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
121                               sizeof( Property ),
122 							  compare_OUString_Property_Impl );
123 	if( !pR ) {
124 		throw UnknownPropertyException();
125 	}
126 
127 	return *pR;
128 }
129 
130 /**
131  * Return the sequence of properties, which are provided throug the constructor.
132  */
133 sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException)
134 {
135 	Property * pR;
136 	pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
137                               sizeof( Property ),
138 							  compare_OUString_Property_Impl );
139 	return pR != NULL;
140 }
141 
142 //	----------------------------------------------------
143 //	class PropertySetHelper_Impl
144 //	----------------------------------------------------
145 class OPropertySetHelper::Impl {
146 
147 public:
148     Impl(   bool i_bIgnoreRuntimeExceptionsWhileFiring,
149             IEventNotificationHook *i_pFireEvents
150         )
151         :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring )
152         ,m_pFireEvents( i_pFireEvents )
153     {
154     }
155 
156     bool m_bIgnoreRuntimeExceptionsWhileFiring;
157     class IEventNotificationHook * const m_pFireEvents;
158 
159     ::std::vector< sal_Int32 >  m_handles;
160     ::std::vector< Any >        m_newValues;
161     ::std::vector< Any >        m_oldValues;
162 };
163 
164 
165 //	----------------------------------------------------
166 //	class PropertySetHelper
167 //	----------------------------------------------------
168 OPropertySetHelper::OPropertySetHelper(
169     OBroadcastHelper  & rBHelper_ ) SAL_THROW( () )
170 	: rBHelper( rBHelper_ ),
171       aBoundLC( rBHelper_.rMutex ),
172       aVetoableLC( rBHelper_.rMutex ),
173       m_pReserved( new Impl(false, 0) )
174 {
175 }
176 
177 OPropertySetHelper::OPropertySetHelper(
178 	OBroadcastHelper  & rBHelper_, bool bIgnoreRuntimeExceptionsWhileFiring )
179 	: rBHelper( rBHelper_ ),
180       aBoundLC( rBHelper_.rMutex ),
181       aVetoableLC( rBHelper_.rMutex ),
182       m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring, 0 ) )
183 {
184 }
185 
186 OPropertySetHelper::OPropertySetHelper(
187 	OBroadcastHelper  & rBHelper_, IEventNotificationHook * i_pFireEvents,
188     bool bIgnoreRuntimeExceptionsWhileFiring)
189 	: rBHelper( rBHelper_ ),
190       aBoundLC( rBHelper_.rMutex ),
191       aVetoableLC( rBHelper_.rMutex ),
192       m_pReserved(
193         new Impl( bIgnoreRuntimeExceptionsWhileFiring, i_pFireEvents) )
194 {
195 }
196 
197 /**
198  * You must call disposing before.
199  */
200 OPropertySetHelper::~OPropertySetHelper() SAL_THROW( () )
201 {
202 }
203 
204 /**
205  * These method is called from queryInterface, if no delegator is set.
206  * Otherwise this method is called from the delegator.
207  */
208 // XAggregation
209 Any OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type & rType )
210 	throw (RuntimeException)
211 {
212 	return ::cppu::queryInterface(
213 		rType,
214 		static_cast< XPropertySet * >( this ),
215 		static_cast< XMultiPropertySet * >( this ),
216 		static_cast< XFastPropertySet * >( this ) );
217 }
218 
219 /**
220  * called from the derivee's XTypeProvider::getTypes implementation
221  */
222 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > OPropertySetHelper::getTypes()
223     throw (RuntimeException)
224 {
225     Sequence< ::com::sun::star::uno::Type > aTypes( 3 );
226     aTypes[ 0 ] = XPropertySet::static_type();
227     aTypes[ 1 ] = XMultiPropertySet::static_type();
228     aTypes[ 2 ] = XFastPropertySet::static_type();
229     return aTypes;
230 }
231 
232 // ComponentHelper
233 void OPropertySetHelper::disposing() SAL_THROW( () )
234 {
235 	// Create an event with this as sender
236 	Reference < XPropertySet  > rSource( SAL_STATIC_CAST( XPropertySet * , this ) , UNO_QUERY );
237 	EventObject aEvt;
238 	aEvt.Source = rSource;
239 
240 	// inform all listeners to reelease this object
241 	// The listener container are automaticly cleared
242 	aBoundLC.disposeAndClear( aEvt );
243 	aVetoableLC.disposeAndClear( aEvt );
244 }
245 
246 Reference < XPropertySetInfo > OPropertySetHelper::createPropertySetInfo(
247 	IPropertyArrayHelper & rProperties ) SAL_THROW( () )
248 {
249 	return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) );
250 }
251 
252 // XPropertySet
253 void OPropertySetHelper::setPropertyValue(
254 	const OUString& rPropertyName, const Any& rValue )
255 	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)
256 {
257 	// get the map table
258 	IPropertyArrayHelper & rPH = getInfoHelper();
259 	// map the name to the handle
260 	sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
261 	// call the method of the XFastPropertySet interface
262 	setFastPropertyValue( nHandle, rValue );
263 }
264 
265 // XPropertySet
266 Any OPropertySetHelper::getPropertyValue(
267 	const OUString& rPropertyName )
268 	throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
269 {
270 	// get the map table
271 	IPropertyArrayHelper & rPH = getInfoHelper();
272 	// map the name to the handle
273 	sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
274 	// call the method of the XFastPropertySet interface
275 	return getFastPropertyValue( nHandle );
276 }
277 
278 // XPropertySet
279 void OPropertySetHelper::addPropertyChangeListener(
280 	const OUString& rPropertyName,
281 	const Reference < XPropertyChangeListener > & rxListener )
282      throw(::com::sun::star::beans::UnknownPropertyException,
283 		   ::com::sun::star::lang::WrappedTargetException,
284 		   ::com::sun::star::uno::RuntimeException)
285 {
286 	MutexGuard aGuard( rBHelper.rMutex );
287 	OSL_ENSURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" );
288 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
289 	if( !rBHelper.bInDispose && !rBHelper.bDisposed )
290 	{
291 		// only add listeners if you are not disposed
292 		// a listener with no name means all properties
293 		if( rPropertyName.getLength() )
294 		{
295 			// get the map table
296 			IPropertyArrayHelper & rPH = getInfoHelper();
297 			// map the name to the handle
298 			sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
299 			if( nHandle == -1 ) {
300 				// property not known throw exception
301 				throw  UnknownPropertyException() ;
302 			}
303 
304 			sal_Int16 nAttributes;
305 			rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
306 			if( !(nAttributes & ::com::sun::star::beans::PropertyAttribute::BOUND) )
307 			{
308 				OSL_ENSURE( sal_False, "add listener to an unbound property" );
309 				// silent ignore this
310 				return;
311 			}
312 			// add the change listener to the helper container
313 
314 			aBoundLC.addInterface( (sal_Int32)nHandle, rxListener );
315 		}
316 		else
317 			// add the change listener to the helper container
318 			rBHelper.aLC.addInterface(
319 							getPropertyTypeIdentifier(  ),
320 							rxListener
321 									 );
322 	}
323 }
324 
325 
326 // XPropertySet
327 void OPropertySetHelper::removePropertyChangeListener(
328 	const OUString& rPropertyName,
329 	const Reference < XPropertyChangeListener >& rxListener )
330 	throw(::com::sun::star::beans::UnknownPropertyException,
331 		  ::com::sun::star::lang::WrappedTargetException,
332 		  ::com::sun::star::uno::RuntimeException)
333 {
334 	MutexGuard aGuard( rBHelper.rMutex );
335 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
336 	// all listeners are automaticly released in a dispose call
337 	if( !rBHelper.bInDispose && !rBHelper.bDisposed )
338 	{
339 		if( rPropertyName.getLength() )
340 		{
341 			// get the map table
342 			IPropertyArrayHelper & rPH = getInfoHelper();
343 			// map the name to the handle
344 			sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
345 			if( nHandle == -1 )
346 				// property not known throw exception
347 				throw UnknownPropertyException();
348 			aBoundLC.removeInterface( (sal_Int32)nHandle, rxListener );
349 		}
350 		else {
351 			// remove the change listener to the helper container
352 			rBHelper.aLC.removeInterface(
353 							getPropertyTypeIdentifier(  ),
354 							rxListener
355 										);
356 		}
357 	}
358 }
359 
360 // XPropertySet
361 void OPropertySetHelper::addVetoableChangeListener(
362 	const OUString& rPropertyName,
363 	const Reference< XVetoableChangeListener > & rxListener )
364 	throw(::com::sun::star::beans::UnknownPropertyException,
365 		  ::com::sun::star::lang::WrappedTargetException,
366 		  ::com::sun::star::uno::RuntimeException)
367 {
368 	MutexGuard aGuard( rBHelper.rMutex );
369 	OSL_ENSURE( !rBHelper.bInDispose, "do not addVetoableChangeListener in the dispose call" );
370 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
371 	if( !rBHelper.bInDispose && !rBHelper.bDisposed )
372 	{
373 		// only add listeners if you are not disposed
374 		// a listener with no name means all properties
375 		if( rPropertyName.getLength() )
376 		{
377 			// get the map table
378 			IPropertyArrayHelper & rPH = getInfoHelper();
379 			// map the name to the handle
380 			sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
381 			if( nHandle == -1 ) {
382 				// property not known throw exception
383 				throw UnknownPropertyException();
384 			}
385 
386 			sal_Int16 nAttributes;
387 			rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
388 			if( !(nAttributes & PropertyAttribute::CONSTRAINED) )
389 			{
390 				OSL_ENSURE( sal_False, "addVetoableChangeListener, and property is not constrained" );
391 				// silent ignore this
392 				return;
393 			}
394 			// add the vetoable listener to the helper container
395 			aVetoableLC.addInterface( (sal_Int32)nHandle, rxListener );
396 		}
397 		else
398 			// add the vetoable listener to the helper container
399 			rBHelper.aLC.addInterface(
400 								getVetoableTypeIdentifier(  ),
401 								rxListener
402 									 );
403 	}
404 }
405 
406 // XPropertySet
407 void OPropertySetHelper::removeVetoableChangeListener(
408 	const OUString& rPropertyName,
409 	const Reference < XVetoableChangeListener > & rxListener )
410 	throw(::com::sun::star::beans::UnknownPropertyException,
411 		  ::com::sun::star::lang::WrappedTargetException,
412 		  ::com::sun::star::uno::RuntimeException)
413 {
414 	MutexGuard aGuard( rBHelper.rMutex );
415 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
416 	// all listeners are automaticly released in a dispose call
417 	if( !rBHelper.bInDispose && !rBHelper.bDisposed )
418 	{
419 		if( rPropertyName.getLength() )
420 		{
421 			// get the map table
422 			IPropertyArrayHelper & rPH = getInfoHelper();
423 			// map the name to the handle
424 			sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
425 			if( nHandle == -1 ) {
426 				// property not known throw exception
427 				throw UnknownPropertyException();
428 			}
429 			// remove the vetoable listener to the helper container
430 			aVetoableLC.removeInterface( (sal_Int32)nHandle, rxListener );
431 		}
432 		else
433 			// add the vetoable listener to the helper container
434 			rBHelper.aLC.removeInterface(
435 								getVetoableTypeIdentifier( ),
436 								rxListener
437 										);
438 	}
439 }
440 
441 void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle, const ::com::sun::star::uno::Any& i_value )
442 {
443     //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" );
444         // there is no such thing as Mutex.isAcquired, sadly ...
445 
446 	sal_Int16 nAttributes(0);
447 	IPropertyArrayHelper& rInfo = getInfoHelper();
448 	if ( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, i_handle ) )
449 		// unknown property
450 		throw UnknownPropertyException();
451 
452     // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
453     // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
454     // to change their value.
455 
456     Any aConverted, aOld;
457     sal_Bool bChanged = convertFastPropertyValue( aConverted, aOld, i_handle, i_value );
458     if ( !bChanged )
459         return;
460 
461     // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
462     // a good idea. The caler is responsible for not invoking this for constrained properties.
463     OSL_ENSURE( ( nAttributes & PropertyAttribute::CONSTRAINED ) == 0,
464         "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained properties!" );
465     (void)nAttributes;
466 
467 	// actually set the new value
468 	try
469 	{
470 		setFastPropertyValue_NoBroadcast( i_handle, aConverted );
471 	}
472 	catch (const UnknownPropertyException& )    { throw;	/* allowed to leave */ }
473 	catch (const PropertyVetoException& )       { throw;	/* allowed to leave */ }
474 	catch (const IllegalArgumentException& )    { throw;	/* allowed to leave */ }
475 	catch (const WrappedTargetException& )      { throw;	/* allowed to leave */ }
476 	catch (const RuntimeException& )            { throw;	/* allowed to leave */ }
477 	catch (const Exception& )
478 	{
479 		// not allowed to leave this meathod
480 		WrappedTargetException aWrapped;
481         aWrapped.TargetException <<= ::cppu::getCaughtException();
482 		aWrapped.Context = static_cast< XPropertySet* >( this );
483 		throw aWrapped;
484 	}
485 
486     // remember the handle/values, for the events to be fired later
487     m_pReserved->m_handles.push_back( i_handle );
488     m_pReserved->m_newValues.push_back( aConverted );   // TODO: setFastPropertyValue notifies the unconverted value here ...?
489     m_pReserved->m_oldValues.push_back( aOld );
490 }
491 
492 // XFastPropertySet
493 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
494 	 throw(::com::sun::star::beans::UnknownPropertyException,
495 		   ::com::sun::star::beans::PropertyVetoException,
496 		   ::com::sun::star::lang::IllegalArgumentException,
497 		   ::com::sun::star::lang::WrappedTargetException,
498 		   ::com::sun::star::uno::RuntimeException)
499 {
500 	OSL_ENSURE( !rBHelper.bInDispose, "do not setFastPropertyValue in the dispose call" );
501 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
502 
503 	IPropertyArrayHelper & rInfo = getInfoHelper();
504 	sal_Int16 nAttributes;
505 	if( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ) ) {
506 		// unknown property
507 		throw UnknownPropertyException();
508 	}
509 	if( nAttributes & PropertyAttribute::READONLY )
510 		throw PropertyVetoException();
511 
512 	Any	aConvertedVal;
513 	Any	aOldVal;
514 
515 	// Will the property change?
516 	sal_Bool bChanged;
517 	{
518 		MutexGuard aGuard( rBHelper.rMutex );
519 		bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue );
520 		// release guard to fire events
521 	}
522 	if( bChanged )
523 	{
524 		// Is it a constrained property?
525 		if( nAttributes & PropertyAttribute::CONSTRAINED )
526 		{
527 			// In aValue is the converted rValue
528 			// fire a constarined event
529 			// second parameter NULL means constrained
530 			fire( &nHandle, &rValue, &aOldVal, 1, sal_True );
531 		}
532 
533 		{
534 			MutexGuard aGuard( rBHelper.rMutex );
535 			try
536 			{
537 				// set the property to the new value
538 				setFastPropertyValue_NoBroadcast( nHandle, aConvertedVal );
539 			}
540 			catch (const ::com::sun::star::beans::UnknownPropertyException& )	{ throw;	/* allowed to leave */ }
541 			catch (const ::com::sun::star::beans::PropertyVetoException& )		{ throw;	/* allowed to leave */ }
542 			catch (const ::com::sun::star::lang::IllegalArgumentException& )	{ throw;	/* allowed to leave */ }
543 			catch (const ::com::sun::star::lang::WrappedTargetException& )		{ throw;	/* allowed to leave */ }
544 			catch (const ::com::sun::star::uno::RuntimeException& )				{ throw;	/* allowed to leave */ }
545 			catch (const ::com::sun::star::uno::Exception& e )
546 			{
547 				// not allowed to leave this meathod
548 				::com::sun::star::lang::WrappedTargetException aWrap;
549 				aWrap.Context = static_cast< ::com::sun::star::beans::XPropertySet* >( this );
550 				aWrap.TargetException <<= e;
551 
552 				throw ::com::sun::star::lang::WrappedTargetException( aWrap );
553 			}
554 
555 			// release guard to fire events
556 		}
557 		// file a change event, if the value changed
558 		impl_fireAll( &nHandle, &rValue, &aOldVal, 1 );
559 	}
560 }
561 
562 // XFastPropertySet
563 Any OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle )
564 	 throw(::com::sun::star::beans::UnknownPropertyException,
565 		   ::com::sun::star::lang::WrappedTargetException,
566 		   ::com::sun::star::uno::RuntimeException)
567 
568 {
569 	IPropertyArrayHelper & rInfo = getInfoHelper();
570 	if( !rInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) )
571 		// unknown property
572 		throw UnknownPropertyException();
573 
574 	Any aRet;
575 	MutexGuard aGuard( rBHelper.rMutex );
576 	getFastPropertyValue( aRet, nHandle );
577 	return aRet;
578 }
579 
580 //--------------------------------------------------------------------------
581 void OPropertySetHelper::impl_fireAll( sal_Int32* i_handles, const Any* i_newValues, const Any* i_oldValues, sal_Int32 i_count )
582 {
583     ClearableMutexGuard aGuard( rBHelper.rMutex );
584     if ( m_pReserved->m_handles.empty() )
585     {
586         aGuard.clear();
587         fire( i_handles, i_newValues, i_oldValues, i_count, sal_False );
588         return;
589     }
590 
591     const size_t additionalEvents = m_pReserved->m_handles.size();
592     OSL_ENSURE( additionalEvents == m_pReserved->m_newValues.size()
593             &&  additionalEvents == m_pReserved->m_oldValues.size(),
594             "OPropertySetHelper::impl_fireAll: inconsistency!" );
595 
596     ::std::vector< sal_Int32 > allHandles( additionalEvents + i_count );
597     ::std::copy( m_pReserved->m_handles.begin(), m_pReserved->m_handles.end(), allHandles.begin() );
598     ::std::copy( i_handles, i_handles + i_count, allHandles.begin() + additionalEvents );
599 
600     ::std::vector< Any > allNewValues( additionalEvents + i_count );
601     ::std::copy( m_pReserved->m_newValues.begin(), m_pReserved->m_newValues.end(), allNewValues.begin() );
602     ::std::copy( i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents );
603 
604     ::std::vector< Any > allOldValues( additionalEvents + i_count );
605     ::std::copy( m_pReserved->m_oldValues.begin(), m_pReserved->m_oldValues.end(), allOldValues.begin() );
606     ::std::copy( i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents );
607 
608     m_pReserved->m_handles.clear();
609     m_pReserved->m_newValues.clear();
610     m_pReserved->m_oldValues.clear();
611 
612     aGuard.clear();
613     fire( &allHandles[0], &allNewValues[0], &allOldValues[0], additionalEvents + i_count, sal_False );
614 }
615 
616 //--------------------------------------------------------------------------
617 void OPropertySetHelper::fire
618 (
619 	sal_Int32 * pnHandles,
620 	const Any * pNewValues,
621 	const Any * pOldValues,
622 	sal_Int32 nHandles, // These is the Count of the array
623 	sal_Bool bVetoable
624 )
625 {
626     OSL_ENSURE( m_pReserved.get(), "No OPropertySetHelper::Impl" );
627     if (m_pReserved->m_pFireEvents) {
628         m_pReserved->m_pFireEvents->fireEvents(
629             pnHandles, nHandles, bVetoable,
630             m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring);
631     }
632 
633 	// Only fire, if one or more properties changed
634 	if( nHandles )
635 	{
636 		// create the event sequence of all changed properties
637 		Sequence< PropertyChangeEvent > aEvts( nHandles );
638 		PropertyChangeEvent * pEvts = aEvts.getArray();
639 		Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
640 		sal_Int32 i;
641 		sal_Int32 nChangesLen = 0;
642 		// Loop over all changed properties to fill the event struct
643 		for( i = 0; i < nHandles; i++ )
644 		{
645 			// Vetoable fire and constrained attribute set or
646 			// Change fire and Changed and bound attribute set
647 			IPropertyArrayHelper & rInfo = getInfoHelper();
648 			sal_Int16	nAttributes;
649 			OUString aPropName;
650 			rInfo.fillPropertyMembersByHandle( &aPropName, &nAttributes, pnHandles[i] );
651 
652 			if(
653                (bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) ||
654                (!bVetoable && (nAttributes & PropertyAttribute::BOUND))
655               )
656 			{
657 				pEvts[nChangesLen].Source = xSource;
658 				pEvts[nChangesLen].PropertyName = aPropName;
659 				pEvts[nChangesLen].PropertyHandle = pnHandles[i];
660 				pEvts[nChangesLen].OldValue = pOldValues[i];
661 				pEvts[nChangesLen].NewValue = pNewValues[i];
662 				nChangesLen++;
663 			}
664 		}
665 
666         bool bIgnoreRuntimeExceptionsWhileFiring =
667                 m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring;
668 
669 		// fire the events for all changed properties
670 		for( i = 0; i < nChangesLen; i++ )
671 		{
672 			// get the listener container for the property name
673 			OInterfaceContainerHelper * pLC;
674 			if( bVetoable ) // fire change Events?
675 				pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle );
676 			else
677 				pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle );
678 			if( pLC )
679 			{
680 				// Ueber alle Listener iterieren und Events senden
681 				OInterfaceIteratorHelper aIt( *pLC);
682 				while( aIt.hasMoreElements() )
683 				{
684 					XInterface * pL = aIt.next();
685                     try
686                     {
687                         try
688                         {
689                             if( bVetoable ) // fire change Events?
690                             {
691                                 ((XVetoableChangeListener *)pL)->vetoableChange(
692                                     pEvts[i] );
693                             }
694                             else
695                             {
696                                 ((XPropertyChangeListener *)pL)->propertyChange(
697                                     pEvts[i] );
698                             }
699                         }
700                         catch (DisposedException & exc)
701                         {
702                             OSL_ENSURE( exc.Context.is(),
703                                         "DisposedException without Context!" );
704                             if (exc.Context == pL)
705                                 aIt.remove();
706                             else
707                                 throw;
708                         }
709                     }
710                     catch (RuntimeException & exc)
711                     {
712                         OSL_TRACE(
713                             OUStringToOString(
714                                 OUString( RTL_CONSTASCII_USTRINGPARAM(
715                                               "caught RuntimeException while "
716                                               "firing listeners: ") ) +
717                                 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
718                         if (! bIgnoreRuntimeExceptionsWhileFiring)
719                             throw;
720                     }
721 				}
722 			}
723 			// broadcast to all listeners with "" property name
724 			if( bVetoable ){
725 				// fire change Events?
726 				pLC = rBHelper.aLC.getContainer(
727 							getVetoableTypeIdentifier()
728 												);
729 			}
730 			else {
731 				pLC = rBHelper.aLC.getContainer(
732 							getPropertyTypeIdentifier(  )
733 												);
734 			}
735 			if( pLC )
736 			{
737 				// Ueber alle Listener iterieren und Events senden
738 				OInterfaceIteratorHelper aIt( *pLC);
739 				while( aIt.hasMoreElements() )
740 				{
741 					XInterface * pL = aIt.next();
742                     try
743                     {
744                         try
745                         {
746                             if( bVetoable ) // fire change Events?
747                             {
748                                 ((XVetoableChangeListener *)pL)->vetoableChange(
749                                     pEvts[i] );
750                             }
751                             else
752                             {
753                                 ((XPropertyChangeListener *)pL)->propertyChange(
754                                     pEvts[i] );
755                             }
756                         }
757                         catch (DisposedException & exc)
758                         {
759                             OSL_ENSURE( exc.Context.is(),
760                                         "DisposedException without Context!" );
761                             if (exc.Context == pL)
762                                 aIt.remove();
763                             else
764                                 throw;
765                         }
766                     }
767                     catch (RuntimeException & exc)
768                     {
769                         OSL_TRACE(
770                             OUStringToOString(
771                                 OUString( RTL_CONSTASCII_USTRINGPARAM(
772                                               "caught RuntimeException while "
773                                               "firing listeners: ") ) +
774                                 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
775                         if (! bIgnoreRuntimeExceptionsWhileFiring)
776                             throw;
777                     }
778 				}
779 			}
780 		}
781 
782 		// reduce array to changed properties
783 		aEvts.realloc( nChangesLen );
784 
785 		if( !bVetoable )
786 		{
787 			OInterfaceContainerHelper * pCont = 0;
788 			pCont = rBHelper.aLC.getContainer(
789 								getPropertiesTypeIdentifier(  )
790 											 );
791 			if( pCont )
792 			{
793 				// Here is a Bug, unbound properties are also fired
794 				OInterfaceIteratorHelper aIt( *pCont );
795 				while( aIt.hasMoreElements() )
796 				{
797 					XPropertiesChangeListener * pL =
798                         (XPropertiesChangeListener *)aIt.next();
799                     try
800                     {
801                         try
802                         {
803                             // fire the hole event sequence to the
804                             // XPropertiesChangeListener's
805                             pL->propertiesChange( aEvts );
806                         }
807                         catch (DisposedException & exc)
808                         {
809                             OSL_ENSURE( exc.Context.is(),
810                                         "DisposedException without Context!" );
811                             if (exc.Context == pL)
812                                 aIt.remove();
813                             else
814                                 throw;
815                         }
816                     }
817                     catch (RuntimeException & exc)
818                     {
819                         OSL_TRACE(
820                             OUStringToOString(
821                                 OUString( RTL_CONSTASCII_USTRINGPARAM(
822                                               "caught RuntimeException while "
823                                               "firing listeners: ") ) +
824                                 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
825                         if (! bIgnoreRuntimeExceptionsWhileFiring)
826                             throw;
827                     }
828 				}
829 			}
830 		}
831 	}
832 }
833 
834 // OPropertySetHelper
835 void OPropertySetHelper::setFastPropertyValues(
836 	sal_Int32 nSeqLen,
837 	sal_Int32 * pHandles,
838 	const Any * pValues,
839 	sal_Int32 nHitCount )
840 	SAL_THROW( (::com::sun::star::uno::Exception) )
841 {
842 	OSL_ENSURE( !rBHelper.bInDispose, "do not getFastPropertyValue in the dispose call" );
843 	OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
844 
845 	Any * pConvertedValues = NULL;
846 	Any * pOldValues = NULL;
847 
848 	try
849 	{
850 		// get the map table
851 		IPropertyArrayHelper & rPH = getInfoHelper();
852 
853 		pConvertedValues = new Any[ nHitCount ];
854 		pOldValues = new Any[ nHitCount ];
855 		sal_Int32 n = 0;
856 		sal_Int32 i;
857 
858 		{
859 		// must lock the mutex outside the loop. So all values are consistent.
860 		MutexGuard aGuard( rBHelper.rMutex );
861 		for( i = 0; i < nSeqLen; i++ )
862 		{
863 			if( pHandles[i] != -1 )
864 			{
865 				sal_Int16 nAttributes;
866 				rPH.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] );
867 				if( nAttributes & PropertyAttribute::READONLY ) {
868 					throw PropertyVetoException();
869 				}
870 				// Will the property change?
871 				if( convertFastPropertyValue( pConvertedValues[ n ], pOldValues[n],
872 											pHandles[i], pValues[i] ) )
873 				{
874 					// only increment if the property really change
875 					pHandles[n]			= pHandles[i];
876 					n++;
877 				}
878 			}
879 		}
880 		// release guard to fire events
881 		}
882 
883 		// fire vetoable events
884 		fire( pHandles, pConvertedValues, pOldValues, n, sal_True );
885 
886 		{
887 		// must lock the mutex outside the loop.
888 		MutexGuard aGuard( rBHelper.rMutex );
889 		// Loop over all changed properties
890 		for( i = 0; i < n; i++ )
891 		{
892 			// Will the property change?
893 			setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
894 		}
895 		// release guard to fire events
896 		}
897 
898 		// fire change events
899 		impl_fireAll( pHandles, pConvertedValues, pOldValues, n );
900 	}
901 	catch( ... )
902 	{
903 		delete [] pOldValues;
904 		delete [] pConvertedValues;
905 		throw;
906 	}
907 	delete [] pOldValues;
908 	delete [] pConvertedValues;
909 }
910 
911 // XMultiPropertySet
912 /**
913  * The sequence may be conatain not known properties. The implementation
914  * must ignore these properties.
915  */
916 void OPropertySetHelper::setPropertyValues(
917 	const Sequence<OUString>& rPropertyNames,
918 	const Sequence<Any>& rValues )
919 	throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
920 {
921 	sal_Int32 * pHandles = NULL;
922 	try
923 	{
924 		sal_Int32	nSeqLen = rPropertyNames.getLength();
925 		pHandles = new sal_Int32[ nSeqLen ];
926 		// get the map table
927 		IPropertyArrayHelper & rPH = getInfoHelper();
928 		// fill the handle array
929 		sal_Int32 nHitCount = rPH.fillHandles( pHandles, rPropertyNames );
930 		if( nHitCount != 0 )
931 			setFastPropertyValues( nSeqLen, pHandles, rValues.getConstArray(), nHitCount );
932 	}
933 	catch( ... )
934 	{
935 		delete [] pHandles;
936 		throw;
937 	}
938 	delete [] pHandles;
939 }
940 
941 // XMultiPropertySet
942 Sequence<Any> OPropertySetHelper::getPropertyValues( const Sequence<OUString>& rPropertyNames )
943 	throw(::com::sun::star::uno::RuntimeException)
944 {
945 	sal_Int32	nSeqLen = rPropertyNames.getLength();
946 	sal_Int32 *	pHandles = new sal_Int32[ nSeqLen ];
947 	Sequence< Any > aValues( nSeqLen );
948 
949 	// get the map table
950 	IPropertyArrayHelper & rPH = getInfoHelper();
951 	// fill the handle array
952 	rPH.fillHandles( pHandles, rPropertyNames );
953 
954 	Any * pValues = aValues.getArray();
955 
956 	MutexGuard aGuard( rBHelper.rMutex );
957 	// fill the sequence with the values
958 	for( sal_Int32 i = 0; i < nSeqLen; i++ )
959 		getFastPropertyValue( pValues[i], pHandles[i] );
960 
961 	delete [] pHandles;
962 	return aValues;
963 }
964 
965 // XMultiPropertySet
966 void OPropertySetHelper::addPropertiesChangeListener(
967 	const Sequence<OUString> & ,
968 	const Reference < XPropertiesChangeListener > & rListener )
969 	throw(::com::sun::star::uno::RuntimeException)
970 {
971 	rBHelper.addListener( getCppuType(&rListener) , rListener );
972 }
973 
974 // XMultiPropertySet
975 void OPropertySetHelper::removePropertiesChangeListener(
976 	const Reference < XPropertiesChangeListener > & rListener )
977 	throw(::com::sun::star::uno::RuntimeException)
978 {
979 	rBHelper.removeListener( getCppuType(&rListener) , rListener );
980 }
981 
982 // XMultiPropertySet
983 void OPropertySetHelper::firePropertiesChangeEvent(
984 	const Sequence<OUString>& rPropertyNames,
985 	const Reference < XPropertiesChangeListener >& rListener )
986 	throw(::com::sun::star::uno::RuntimeException)
987 {
988 	sal_Int32 nLen = rPropertyNames.getLength();
989 	sal_Int32 * pHandles = new sal_Int32[nLen];
990 	IPropertyArrayHelper & rPH = getInfoHelper();
991 	rPH.fillHandles( pHandles, rPropertyNames );
992 	const OUString* pNames = rPropertyNames.getConstArray();
993 
994 	// get the count of matching properties
995 	sal_Int32 nFireLen = 0;
996 	sal_Int32 i;
997 	for( i = 0; i < nLen; i++ )
998 		if( pHandles[i] != -1 )
999 			nFireLen++;
1000 
1001 	Sequence<PropertyChangeEvent> aChanges( nFireLen );
1002 	PropertyChangeEvent* pChanges = aChanges.getArray();
1003 
1004 	sal_Int32 nFirePos = 0;
1005 	{
1006 	// must lock the mutex outside the loop. So all values are consistent.
1007 	MutexGuard aGuard( rBHelper.rMutex );
1008 	Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
1009 	for( i = 0; i < nLen; i++ )
1010 	{
1011 		if( pHandles[i] != -1 )
1012 		{
1013 			pChanges[nFirePos].Source = xSource;
1014 			pChanges[nFirePos].PropertyName = pNames[i];
1015 			pChanges[nFirePos].PropertyHandle = pHandles[i];
1016 			getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] );
1017 			pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
1018 			nFirePos++;
1019 		}
1020 	}
1021 	// release guard to fire events
1022 	}
1023 	if( nFireLen )
1024 		rListener->propertiesChange( aChanges );
1025 
1026 	delete [] pHandles;
1027 }
1028 
1029 #ifdef xdvnsdfln
1030 // XPropertyState
1031 PropertyState OPropertySetHelper::getPropertyState( const OUString& PropertyName )
1032 {
1033 	PropertyState aState;
1034 	return aState;
1035 }
1036 
1037 // XPropertyState
1038 Sequence< PropertyState > OPropertySetHelper::getPropertyStates( const Sequence< OUString >& PropertyNames )
1039 {
1040 	ULONG nNames = PropertyNames.getLength();
1041 	const OUString* pNames = PropertyNames.getConstArray();
1042 
1043 	Sequence< PropertyState > aStates( nNames );
1044 	return aStates;
1045 
1046 }
1047 
1048 void OPropertySetHelper::setPropertyToDefault( const OUString& aPropertyName )
1049 {
1050 	setPropertyValue( aPropertyName, Any() );
1051 }
1052 
1053 Any OPropertySetHelper::getPropertyDefault( const OUString& aPropertyName ) const
1054 {
1055 	return Any();
1056 }
1057 
1058 void OPropertySetHelper::addPropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
1059 {
1060 }
1061 
1062 void OPropertySetHelper::removePropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
1063 {
1064 }
1065 #endif
1066 
1067 //========================================================================
1068 //== OPropertyArrayHelper ================================================
1069 //========================================================================
1070 
1071 //========================================================================
1072 
1073 //  static OUString makeOUString( sal_Char *p )
1074 //  {
1075 //  	sal_Int32 nLen = strlen(p);
1076 //  	sal_Unicode *pw = new sal_Unicode[nLen];
1077 
1078 //  	for( int i = 0 ; i < nLen ; i ++ ) {
1079 
1080 //  		// Only ascii strings allowed with this helper !
1081 //  		OSL_ASSERT( p[i] < 127 );
1082 //  		pw[i] = p[i];
1083 //  	}
1084 //  	OUString ow( pw , nLen );
1085 //  	delete pw;
1086 //  	return ow;
1087 //  }
1088 
1089 extern "C" {
1090 
1091 static int compare_Property_Impl( const void *arg1, const void *arg2 )
1092     SAL_THROW_EXTERN_C()
1093 {
1094    return ((Property *)arg1)->Name.compareTo( ((Property *)arg2)->Name );
1095 }
1096 
1097 }
1098 
1099 void OPropertyArrayHelper::init( sal_Bool bSorted ) SAL_THROW( () )
1100 {
1101 	sal_Int32 i, nElements = aInfos.getLength();
1102 	const Property* pProperties = aInfos.getConstArray();
1103 
1104 	for( i = 1; i < nElements; i++ )
1105 	{
1106 		if(  pProperties[i-1].Name >= pProperties[i].Name )
1107 		{
1108 #ifndef OS2 // YD disabled, too many troubles with debug builds!
1109             if (bSorted) {
1110                 OSL_ENSURE( false, "Property array is not sorted" );
1111             }
1112 #endif
1113 			// not sorted
1114 			qsort( aInfos.getArray(), nElements, sizeof( Property ),
1115 					compare_Property_Impl );
1116 			break;
1117 		}
1118 	}
1119 	// may be that the array is resorted
1120 	pProperties = aInfos.getConstArray();
1121 	for( i = 0; i < nElements; i++ )
1122 		if( pProperties[i].Handle != i )
1123 			return;
1124 	// The handle is the index
1125 	bRightOrdered = sal_True;
1126 }
1127 
1128 OPropertyArrayHelper::OPropertyArrayHelper(
1129 	Property * pProps,
1130 	sal_Int32 nEle,
1131 	sal_Bool bSorted )
1132 	SAL_THROW( () )
1133 	: aInfos(pProps, nEle)
1134 	, bRightOrdered( sal_False )
1135 {
1136 	init( bSorted );
1137 }
1138 
1139 OPropertyArrayHelper::OPropertyArrayHelper(
1140 	const Sequence< Property > & aProps,
1141 	sal_Bool bSorted )
1142 	SAL_THROW( () )
1143 	: aInfos(aProps)
1144 	, bRightOrdered( sal_False )
1145 {
1146 	init( bSorted );
1147 }
1148 
1149 //========================================================================
1150 sal_Int32 OPropertyArrayHelper::getCount() const
1151 {
1152 	return aInfos.getLength();
1153 }
1154 
1155 //========================================================================
1156 sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle
1157 (
1158 	OUString * pPropName,
1159 	sal_Int16 * pAttributes,
1160 	sal_Int32 nHandle
1161 )
1162 {
1163 	const Property* pProperties = aInfos.getConstArray();
1164 	sal_Int32 nElements = aInfos.getLength();
1165 
1166 	if( bRightOrdered )
1167 	{
1168 		if( nHandle < 0 || nHandle >= nElements )
1169 			return sal_False;
1170 		if( pPropName )
1171 			*pPropName = pProperties[ nHandle ].Name;
1172 		if( pAttributes )
1173 			*pAttributes = pProperties[ nHandle ].Attributes;
1174 		return sal_True;
1175 	}
1176 	else
1177 	{
1178 		// normally the array is sorted
1179 		for( sal_Int32 i = 0; i < nElements; i++ )
1180 		{
1181 			if( pProperties[i].Handle == nHandle )
1182 			{
1183 				if( pPropName )
1184 					*pPropName = pProperties[ i ].Name;
1185 				if( pAttributes )
1186 					*pAttributes = pProperties[ i ].Attributes;
1187 				return sal_True;
1188 			}
1189 		}
1190 	}
1191 	return sal_False;
1192 }
1193 
1194 //========================================================================
1195 Sequence< Property > OPropertyArrayHelper::getProperties(void)
1196 {
1197 	/*if( aInfos.getLength() != nElements )
1198 	{
1199 		((OPropertyArrayHelper *)this)->aInfos.realloc( nElements );
1200 		Property * pProps = ((OPropertyArrayHelper *)this)->aInfos.getArray();
1201 		for( sal_Int32 i = 0; i < nElements; i++ )
1202 		{
1203 			pProps[i].Name = pProperties[i].Name;
1204 			pProps[i].Handle = pProperties[i].Handle;
1205 			pProps[i].Type = pProperties[i].Type;
1206 			pProps[i].Attributes = pProperties[i].Attributes;
1207 		}
1208 	}*/
1209 	return aInfos;
1210 }
1211 
1212 //========================================================================
1213 Property OPropertyArrayHelper::getPropertyByName(const OUString& aPropertyName)
1214 		throw (UnknownPropertyException)
1215 {
1216 	Property * pR;
1217 	pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
1218                               sizeof( Property ),
1219 							  compare_OUString_Property_Impl );
1220 	if( !pR ) {
1221 		throw UnknownPropertyException();
1222 	}
1223 
1224 	/*Property aProp;
1225 	aProp.Name = pR->Name;
1226 	aProp.Handle = pR->Handle;
1227 	aProp.Type = pR->Type;
1228 	aProp.Attributes = pR->Attributes;
1229 	return aProp;*/
1230 	return *pR;
1231 }
1232 
1233 //========================================================================
1234 sal_Bool OPropertyArrayHelper::hasPropertyByName(const OUString& aPropertyName)
1235 {
1236 	Property * pR;
1237 	pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
1238                               sizeof( Property ),
1239 							  compare_OUString_Property_Impl );
1240 	return pR != NULL;
1241 }
1242 
1243 //========================================================================
1244 sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName )
1245 {
1246 	Property * pR;
1247 	pR = (Property *)bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(),
1248                               sizeof( Property ),
1249 							  compare_OUString_Property_Impl );
1250 	return pR ? pR->Handle : -1;
1251 }
1252 
1253 //========================================================================
1254 sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames )
1255 {
1256 	sal_Int32 nHitCount = 0;
1257 	const OUString * pReqProps = rPropNames.getConstArray();
1258 	sal_Int32 nReqLen = rPropNames.getLength();
1259 	const Property * pCur = aInfos.getConstArray();
1260 	const Property * pEnd = pCur + aInfos.getLength();
1261 
1262 	for( sal_Int32 i = 0; i < nReqLen; i++ )
1263 	{
1264 		// Logarithmus ermitteln
1265 		sal_Int32 n = (sal_Int32)(pEnd - pCur);
1266 		sal_Int32 nLog = 0;
1267 		while( n )
1268 		{
1269 			nLog += 1;
1270 			n = n >> 1;
1271 		}
1272 
1273 		// Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
1274 		// zu dursuchenden Properties.
1275 		if( (nReqLen - i) * nLog >= pEnd - pCur )
1276 		{
1277 			// linear search is better
1278 			while( pCur < pEnd && pReqProps[i] > pCur->Name )
1279 			{
1280 				pCur++;
1281 			}
1282 			if( pCur < pEnd && pReqProps[i] == pCur->Name )
1283 			{
1284 				pHandles[i] = pCur->Handle;
1285 				nHitCount++;
1286 			}
1287 			else
1288 				pHandles[i] = -1;
1289 		}
1290 		else
1291 		{
1292 			// binary search is better
1293 			sal_Int32	nCompVal = 1;
1294 			const Property * pOldEnd = pEnd--;
1295 			const Property * pMid = pCur;
1296 
1297 			while( nCompVal != 0 && pCur <= pEnd )
1298 			{
1299 				pMid = (pEnd - pCur) / 2 + pCur;
1300 
1301 				nCompVal = pReqProps[i].compareTo( pMid->Name );
1302 
1303 				if( nCompVal > 0 )
1304 					pCur = pMid + 1;
1305 				else
1306 					pEnd = pMid - 1;
1307 			}
1308 
1309 			if( nCompVal == 0 )
1310 			{
1311 				pHandles[i] = pMid->Handle;
1312 				nHitCount++;
1313 				pCur = pMid +1;
1314 			}
1315 			else if( nCompVal > 0 )
1316 			{
1317 				pHandles[i] = -1;
1318 				pCur = pMid +1;
1319 			}
1320 			else
1321 			{
1322 				pHandles[i] = -1;
1323 				pCur = pMid;
1324 			}
1325 			pEnd = pOldEnd;
1326 		}
1327 	}
1328 	return nHitCount;
1329 }
1330 
1331 } // end namespace cppu
1332 
1333 
1334 
1335