xref: /trunk/main/cppuhelper/source/propshlp.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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