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