File: | comphelper/source/eventattachermgr/eventattachermgr.cxx |
Location: | line 278, column 52 |
Description: | Called C++ object pointer is null |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | ||||
21 | #if defined( UNX1 ) | |||
22 | #include <wchar.h> | |||
23 | #endif | |||
24 | #include <osl/mutex.hxx> | |||
25 | #include <osl/diagnose.h> | |||
26 | #include <comphelper/eventattachermgr.hxx> | |||
27 | #include <com/sun/star/beans/XIntrospection.hpp> | |||
28 | #include <com/sun/star/io/XObjectInputStream.hpp> | |||
29 | #include <com/sun/star/io/XPersistObject.hpp> | |||
30 | #include <com/sun/star/io/XObjectOutputStream.hpp> | |||
31 | #include <com/sun/star/io/XMarkableStream.hpp> | |||
32 | #include <com/sun/star/lang/XInitialization.hpp> | |||
33 | #include <com/sun/star/lang/XMultiServiceFactory.hpp> | |||
34 | #include <com/sun/star/reflection/XIdlClass.hpp> | |||
35 | #include <com/sun/star/reflection/XIdlReflection.hpp> | |||
36 | #include <com/sun/star/reflection/XIdlMethod.hpp> | |||
37 | #include <com/sun/star/script/XTypeConverter.hpp> | |||
38 | #include <com/sun/star/script/XEngineListener.hpp> | |||
39 | #include <com/sun/star/script/XEventAttacher2.hpp> | |||
40 | #include <com/sun/star/script/XEventAttacherManager.hpp> | |||
41 | #include <com/sun/star/script/XScriptListener.hpp> | |||
42 | #include <cppuhelper/weak.hxx> | |||
43 | #include <cppuhelper/interfacecontainer.hxx> | |||
44 | #include <cppuhelper/implbase1.hxx> | |||
45 | #include <cppuhelper/implbase2.hxx> | |||
46 | ||||
47 | #include <deque> | |||
48 | #include <algorithm> | |||
49 | #include <functional> | |||
50 | ||||
51 | using namespace com::sun::star::uno; | |||
52 | using namespace com::sun::star::io; | |||
53 | using namespace com::sun::star::lang; | |||
54 | using namespace com::sun::star::beans; | |||
55 | using namespace com::sun::star::script; | |||
56 | using namespace com::sun::star::reflection; | |||
57 | using namespace cppu; | |||
58 | using namespace osl; | |||
59 | ||||
60 | using ::rtl::OUString; | |||
61 | ||||
62 | namespace comphelper | |||
63 | { | |||
64 | ||||
65 | //----------------------------------------------------------------------------- | |||
66 | struct AttachedObject_Impl | |||
67 | { | |||
68 | Reference< XInterface > xTarget; | |||
69 | Sequence< Reference< XEventListener > > aAttachedListenerSeq; | |||
70 | Any aHelper; | |||
71 | ||||
72 | bool operator<( const AttachedObject_Impl & ) const; | |||
73 | bool operator==( const AttachedObject_Impl & ) const; | |||
74 | }; | |||
75 | ||||
76 | struct AttacherIndex_Impl | |||
77 | { | |||
78 | ::std::deque< ScriptEventDescriptor > aEventList; | |||
79 | ::std::deque< AttachedObject_Impl > aObjList; | |||
80 | ||||
81 | bool operator<( const AttacherIndex_Impl & ) const; | |||
82 | bool operator==( const AttacherIndex_Impl & ) const; | |||
83 | }; | |||
84 | ||||
85 | //----------------------------------------------------------------------------- | |||
86 | class ImplEventAttacherManager | |||
87 | : public WeakImplHelper2< XEventAttacherManager, XPersistObject > | |||
88 | { | |||
89 | friend class AttacherAllListener_Impl; | |||
90 | ::std::deque< AttacherIndex_Impl > aIndex; | |||
91 | Mutex aLock; | |||
92 | // Container for the ScriptListener | |||
93 | OInterfaceContainerHelper aScriptListeners; | |||
94 | // Instance of EventAttacher | |||
95 | Reference< XEventAttacher2 > xAttacher; | |||
96 | Reference< XMultiServiceFactory > mxSMgr; | |||
97 | Reference< XIdlReflection > mxCoreReflection; | |||
98 | Reference< XIntrospection > mxIntrospection; | |||
99 | Reference< XTypeConverter > xConverter; | |||
100 | sal_Int16 nVersion; | |||
101 | public: | |||
102 | ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection, | |||
103 | const Reference< XMultiServiceFactory > rSMgr ); | |||
104 | ~ImplEventAttacherManager(); | |||
105 | ||||
106 | // Methods of XEventAttacherManager | |||
107 | virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent) | |||
108 | throw( IllegalArgumentException, RuntimeException ); | |||
109 | virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents) | |||
110 | throw( IllegalArgumentException, RuntimeException ); | |||
111 | virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam) | |||
112 | throw( IllegalArgumentException, RuntimeException ); | |||
113 | virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index) | |||
114 | throw( IllegalArgumentException, RuntimeException ); | |||
115 | virtual void SAL_CALL insertEntry(sal_Int32 Index) | |||
116 | throw( IllegalArgumentException, RuntimeException ); | |||
117 | virtual void SAL_CALL removeEntry(sal_Int32 Index) | |||
118 | throw( IllegalArgumentException, RuntimeException ); | |||
119 | virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index) | |||
120 | throw( IllegalArgumentException, RuntimeException ); | |||
121 | virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper) | |||
122 | throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException ); | |||
123 | virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject) | |||
124 | throw( IllegalArgumentException, RuntimeException ); | |||
125 | virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener) | |||
126 | throw( IllegalArgumentException, RuntimeException ); | |||
127 | virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener) | |||
128 | throw( IllegalArgumentException, RuntimeException ); | |||
129 | ||||
130 | // Methods of XPersistObject | |||
131 | virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException ); | |||
132 | virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException ); | |||
133 | virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException ); | |||
134 | ||||
135 | private: | |||
136 | Reference< XIdlReflection > getReflection() throw( Exception ); | |||
137 | ||||
138 | /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not | |||
139 | @param _nIndex | |||
140 | the index to check | |||
141 | @return | |||
142 | the iterator pointing to the position indicated by the index | |||
143 | */ | |||
144 | ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) ); | |||
145 | }; | |||
146 | ||||
147 | //======================================================================== | |||
148 | //======================================================================== | |||
149 | //======================================================================== | |||
150 | ||||
151 | ||||
152 | // Implementation of an EventAttacher-subclass 'AllListeners', which | |||
153 | // only passes individual events of the general AllListeners. | |||
154 | class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener > | |||
155 | { | |||
156 | ImplEventAttacherManager* mpManager; | |||
157 | Reference< XEventAttacherManager > xManager; | |||
158 | OUString aScriptType; | |||
159 | OUString aScriptCode; | |||
160 | ||||
161 | void convertToEventReturn( Any & rRet, const Type & rRetType ) | |||
162 | throw( CannotConvertException ); | |||
163 | public: | |||
164 | AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_, | |||
165 | const OUString & rScriptCode_ ); | |||
166 | ||||
167 | // Methods of XAllListener | |||
168 | virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException ); | |||
169 | virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException ); | |||
170 | ||||
171 | // Methods of XEventListener | |||
172 | virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException ); | |||
173 | }; | |||
174 | ||||
175 | //======================================================================== | |||
176 | AttacherAllListener_Impl::AttacherAllListener_Impl | |||
177 | ( | |||
178 | ImplEventAttacherManager* pManager_, | |||
179 | const OUString & rScriptType_, | |||
180 | const OUString & rScriptCode_ | |||
181 | ) | |||
182 | : mpManager( pManager_ ) | |||
183 | , xManager( pManager_ ) | |||
184 | , aScriptType( rScriptType_ ) | |||
185 | , aScriptCode( rScriptCode_ ) | |||
186 | { | |||
187 | } | |||
188 | ||||
189 | ||||
190 | //======================================================================== | |||
191 | // Methods of XAllListener | |||
192 | void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event) | |||
193 | throw( RuntimeException ) | |||
194 | { | |||
195 | ScriptEvent aScriptEvent; | |||
196 | aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface | |||
197 | aScriptEvent.ListenerType = Event.ListenerType; | |||
198 | aScriptEvent.MethodName = Event.MethodName; | |||
199 | aScriptEvent.Arguments = Event.Arguments; | |||
200 | aScriptEvent.Helper = Event.Helper; | |||
201 | aScriptEvent.ScriptType = aScriptType; | |||
202 | aScriptEvent.ScriptCode = aScriptCode; | |||
203 | ||||
204 | // Iterate over all listeners and pass events. | |||
205 | OInterfaceIteratorHelper aIt( mpManager->aScriptListeners ); | |||
206 | while( aIt.hasMoreElements() ) | |||
207 | ((XScriptListener *)aIt.next())->firing( aScriptEvent ); | |||
208 | } | |||
209 | ||||
210 | //======================================================================== | |||
211 | // Convert to the standard event return | |||
212 | void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType ) | |||
213 | throw( CannotConvertException ) | |||
214 | { | |||
215 | // no return value? Set to the specified values | |||
216 | if( rRet.getValueType().getTypeClass() == TypeClass_VOID ) | |||
217 | { | |||
218 | switch( rRetType.getTypeClass() ) | |||
219 | { | |||
220 | case TypeClass_INTERFACE: | |||
221 | { | |||
222 | rRet <<= Reference< XInterface >(); | |||
223 | } | |||
224 | break; | |||
225 | ||||
226 | case TypeClass_BOOLEAN: | |||
227 | rRet <<= sal_True((sal_Bool)1); | |||
228 | break; | |||
229 | ||||
230 | case TypeClass_STRING: | |||
231 | rRet <<= OUString(); | |||
232 | break; | |||
233 | ||||
234 | case TypeClass_FLOAT: rRet <<= float(0); break; | |||
235 | case TypeClass_DOUBLE: rRet <<= double(0.0); break; | |||
236 | case TypeClass_BYTE: rRet <<= sal_uInt8(0); break; | |||
237 | case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break; | |||
238 | case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break; | |||
239 | case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break; | |||
240 | case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break; | |||
241 | ||||
242 | default: | |||
243 | OSL_ASSERT(false)do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/comphelper/source/eventattachermgr/eventattachermgr.cxx" ":" "243" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); | |||
244 | break; | |||
245 | } | |||
246 | } | |||
247 | else if( !rRet.getValueType().equals( rRetType ) ) | |||
248 | { | |||
249 | if( mpManager->xConverter.is() ) | |||
250 | rRet = mpManager->xConverter->convertTo( rRet, rRetType ); | |||
251 | else | |||
252 | throw CannotConvertException(); | |||
253 | } | |||
254 | } | |||
255 | ||||
256 | //======================================================================== | |||
257 | // Methods of XAllListener | |||
258 | Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event ) | |||
259 | throw( InvocationTargetException, RuntimeException ) | |||
260 | { | |||
261 | ScriptEvent aScriptEvent; | |||
262 | aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface | |||
263 | aScriptEvent.ListenerType = Event.ListenerType; | |||
264 | aScriptEvent.MethodName = Event.MethodName; | |||
265 | aScriptEvent.Arguments = Event.Arguments; | |||
266 | aScriptEvent.Helper = Event.Helper; | |||
267 | aScriptEvent.ScriptType = aScriptType; | |||
268 | aScriptEvent.ScriptCode = aScriptCode; | |||
269 | ||||
270 | Any aRet; | |||
271 | // Iterate over all listeners and pass events. | |||
272 | OInterfaceIteratorHelper aIt( mpManager->aScriptListeners ); | |||
273 | while( aIt.hasMoreElements() ) | |||
| ||||
274 | { | |||
275 | aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent ); | |||
276 | try | |||
277 | { | |||
278 | Reference< XIdlClass > xListenerType = mpManager->getReflection()-> | |||
| ||||
279 | forName( Event.ListenerType.getTypeName() ); | |||
280 | Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); | |||
281 | if( xMeth.is() ) | |||
282 | { | |||
283 | Reference< XIdlClass > xRetType = xMeth->getReturnType(); | |||
284 | Type aRetType(xRetType->getTypeClass(), xRetType->getName()); | |||
285 | convertToEventReturn( aRet, aRetType ); | |||
286 | } | |||
287 | ||||
288 | switch( aRet.getValueType().getTypeClass() ) | |||
289 | { | |||
290 | case TypeClass_INTERFACE: | |||
291 | { | |||
292 | // Interface not null, return | |||
293 | Reference< XInterface > x; | |||
294 | aRet >>= x; | |||
295 | if( x.is() ) | |||
296 | return aRet; | |||
297 | } | |||
298 | break; | |||
299 | ||||
300 | case TypeClass_BOOLEAN: | |||
301 | // FALSE -> Return | |||
302 | if( !(*(sal_Bool*)aRet.getValue()) ) | |||
303 | return aRet; | |||
304 | break; | |||
305 | ||||
306 | case TypeClass_STRING: | |||
307 | // none empty string -> return | |||
308 | if( !((OUString*)aRet.getValue())->isEmpty() ) | |||
309 | return aRet; | |||
310 | break; | |||
311 | ||||
312 | // none zero number -> return | |||
313 | case TypeClass_FLOAT: if( *((float*)aRet.getValue()) ) return aRet; break; | |||
314 | case TypeClass_DOUBLE: if( *((double*)aRet.getValue()) ) return aRet; break; | |||
315 | case TypeClass_BYTE: if( *((sal_uInt8*)aRet.getValue()) ) return aRet; break; | |||
316 | case TypeClass_SHORT: if( *((sal_Int16*)aRet.getValue()) ) return aRet; break; | |||
317 | case TypeClass_LONG: if( *((sal_Int32*)aRet.getValue()) ) return aRet; break; | |||
318 | case TypeClass_UNSIGNED_SHORT: if( *((sal_uInt16*)aRet.getValue()) ) return aRet; break; | |||
319 | case TypeClass_UNSIGNED_LONG: if( *((sal_uInt32*)aRet.getValue()) ) return aRet; break; | |||
320 | ||||
321 | default: | |||
322 | OSL_ASSERT(false)do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/comphelper/source/eventattachermgr/eventattachermgr.cxx" ":" "322" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); | |||
323 | break; | |||
324 | } | |||
325 | } | |||
326 | catch( CannotConvertException& ) | |||
327 | { | |||
328 | // silent ignore conversions errors from a script call | |||
329 | Reference< XIdlClass > xListenerType = mpManager->getReflection()-> | |||
330 | forName( Event.ListenerType.getTypeName() ); | |||
331 | Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); | |||
332 | if( xMeth.is() ) | |||
333 | { | |||
334 | Reference< XIdlClass > xRetType = xMeth->getReturnType(); | |||
335 | Type aRetType(xRetType->getTypeClass(), xRetType->getName()); | |||
336 | aRet.clear(); | |||
337 | convertToEventReturn( aRet, aRetType ); | |||
338 | } | |||
339 | } | |||
340 | } | |||
341 | return aRet; | |||
342 | } | |||
343 | ||||
344 | //======================================================================== | |||
345 | // Methods of XEventListener | |||
346 | void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& ) | |||
347 | throw( RuntimeException ) | |||
348 | { | |||
349 | // It is up to the container to release the object | |||
350 | } | |||
351 | ||||
352 | ||||
353 | // Constructor method for EventAttacherManager | |||
354 | Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XMultiServiceFactory > & rSMgr ) | |||
355 | throw( Exception ) | |||
356 | { | |||
357 | if ( rSMgr.is() ) | |||
358 | { | |||
359 | Reference< XInterface > xIFace( rSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" )(&("com.sun.star.beans.Introspection")[0]), ((sal_Int32)( (sizeof ("com.sun.star.beans.Introspection") / sizeof (("com.sun.star.beans.Introspection" )[0]))-1)), (((rtl_TextEncoding) 11))) ) ); | |||
360 | if ( xIFace.is() ) | |||
361 | { | |||
362 | Reference< XIntrospection > xIntrospection( xIFace, UNO_QUERY); | |||
363 | return new ImplEventAttacherManager( xIntrospection, rSMgr ); | |||
364 | } | |||
365 | } | |||
366 | ||||
367 | return Reference< XEventAttacherManager >(); | |||
368 | } | |||
369 | ||||
370 | //----------------------------------------------------------------------------- | |||
371 | ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection, | |||
372 | const Reference< XMultiServiceFactory > rSMgr ) | |||
373 | : aScriptListeners( aLock ) | |||
374 | , mxSMgr( rSMgr ) | |||
375 | , mxIntrospection( rIntrospection ) | |||
376 | { | |||
377 | if ( rSMgr.is() ) | |||
378 | { | |||
379 | Reference< XInterface > xIFace( rSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.EventAttacher" )(&("com.sun.star.script.EventAttacher")[0]), ((sal_Int32) ((sizeof ("com.sun.star.script.EventAttacher") / sizeof (("com.sun.star.script.EventAttacher" )[0]))-1)), (((rtl_TextEncoding) 11))) ) ); | |||
380 | if ( xIFace.is() ) | |||
381 | { | |||
382 | xAttacher = Reference< XEventAttacher2 >::query( xIFace ); | |||
383 | } | |||
384 | xIFace = rSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" )(&("com.sun.star.script.Converter")[0]), ((sal_Int32)((sizeof ("com.sun.star.script.Converter") / sizeof (("com.sun.star.script.Converter" )[0]))-1)), (((rtl_TextEncoding) 11))) ); | |||
385 | if ( xIFace.is() ) | |||
386 | { | |||
387 | xConverter = Reference< XTypeConverter >::query( xIFace ); | |||
388 | } | |||
389 | } | |||
390 | ||||
391 | Reference< XInitialization > xInit( xAttacher, UNO_QUERY ); | |||
392 | if( xInit.is() ) | |||
393 | { | |||
394 | Sequence< Any > Arguments( 1 ); | |||
395 | Arguments[0] <<= rIntrospection; | |||
396 | xInit->initialize( Arguments ); | |||
397 | } | |||
398 | } | |||
399 | ||||
400 | //----------------------------------------------------------------------------- | |||
401 | ImplEventAttacherManager::~ImplEventAttacherManager() | |||
402 | { | |||
403 | } | |||
404 | ||||
405 | Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception ) | |||
406 | { | |||
407 | Guard< Mutex > aGuard( aLock ); | |||
408 | // Do we already have a service? If not, create one. | |||
409 | if( !mxCoreReflection.is() ) | |||
410 | { | |||
411 | Reference< XInterface > xIFace( mxSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" )(&("com.sun.star.reflection.CoreReflection")[0]), ((sal_Int32 )((sizeof ("com.sun.star.reflection.CoreReflection") / sizeof (("com.sun.star.reflection.CoreReflection")[0]))-1)), (((rtl_TextEncoding ) 11))) ) ); | |||
412 | mxCoreReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY); | |||
413 | } | |||
414 | return mxCoreReflection; | |||
415 | } | |||
416 | ||||
417 | ||||
418 | //----------------------------------------------------------------------------- | |||
419 | ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) ) | |||
420 | { | |||
421 | if (_nIndex < 0) | |||
422 | throw IllegalArgumentException(); | |||
423 | ||||
424 | ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin(); | |||
425 | for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt ) | |||
426 | ; | |||
427 | ||||
428 | if( aIt == aIndex.end() ) | |||
429 | throw IllegalArgumentException(); | |||
430 | ||||
431 | return aIt; | |||
432 | } | |||
433 | ||||
434 | namespace { | |||
435 | ||||
436 | class DetachObject : public std::unary_function<AttachedObject_Impl, void> | |||
437 | { | |||
438 | ImplEventAttacherManager& mrMgr; | |||
439 | sal_Int32 mnIdx; | |||
440 | public: | |||
441 | DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) : | |||
442 | mrMgr(rMgr), mnIdx(nIdx) {} | |||
443 | ||||
444 | void operator() (AttachedObject_Impl& rObj) | |||
445 | { | |||
446 | mrMgr.detach(mnIdx, rObj.xTarget); | |||
447 | } | |||
448 | }; | |||
449 | ||||
450 | class AttachObject : public std::unary_function<AttachedObject_Impl, void> | |||
451 | { | |||
452 | ImplEventAttacherManager& mrMgr; | |||
453 | sal_Int32 mnIdx; | |||
454 | public: | |||
455 | AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) : | |||
456 | mrMgr(rMgr), mnIdx(nIdx) {} | |||
457 | ||||
458 | void operator() (AttachedObject_Impl& rObj) | |||
459 | { | |||
460 | mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper); | |||
461 | } | |||
462 | }; | |||
463 | ||||
464 | } | |||
465 | ||||
466 | //----------------------------------------------------------------------------- | |||
467 | // Methods of XEventAttacherManager | |||
468 | void SAL_CALL ImplEventAttacherManager::registerScriptEvent | |||
469 | ( | |||
470 | sal_Int32 nIndex, | |||
471 | const ScriptEventDescriptor& ScriptEvent | |||
472 | ) | |||
473 | throw( IllegalArgumentException, RuntimeException ) | |||
474 | { | |||
475 | Guard< Mutex > aGuard( aLock ); | |||
476 | ||||
477 | // Examine the index and apply the array | |||
478 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
479 | ||||
480 | ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList; | |||
481 | ||||
482 | ScriptEventDescriptor aEvt = ScriptEvent; | |||
483 | const sal_Unicode* pLastDot = aEvt.ListenerType.getStr(); | |||
484 | pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' ); | |||
485 | if( pLastDot ) | |||
486 | aEvt.ListenerType = pLastDot +1; | |||
487 | (*aIt).aEventList.push_back( aEvt ); | |||
488 | ||||
489 | // register new new Event | |||
490 | ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin(); | |||
491 | ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end(); | |||
492 | while( aObjIt != aObjEnd ) | |||
493 | { | |||
494 | // resize | |||
495 | sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength(); | |||
496 | (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 ); | |||
497 | Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray(); | |||
498 | ||||
499 | Reference< XAllListener > xAll = | |||
500 | new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode ); | |||
501 | try | |||
502 | { | |||
503 | pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll, | |||
504 | (*aObjIt).aHelper, ScriptEvent.ListenerType, | |||
505 | ScriptEvent.AddListenerParam, ScriptEvent.EventMethod ); | |||
506 | } | |||
507 | catch( Exception& ) | |||
508 | { | |||
509 | } | |||
510 | ||||
511 | ++aObjIt; | |||
512 | } | |||
513 | } | |||
514 | ||||
515 | //----------------------------------------------------------------------------- | |||
516 | void SAL_CALL ImplEventAttacherManager::registerScriptEvents | |||
517 | ( | |||
518 | sal_Int32 nIndex, | |||
519 | const Sequence< ScriptEventDescriptor >& ScriptEvents | |||
520 | ) | |||
521 | throw( IllegalArgumentException, RuntimeException ) | |||
522 | { | |||
523 | Guard< Mutex > aGuard( aLock ); | |||
524 | ||||
525 | // Examine the index and apply the array | |||
526 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
527 | ||||
528 | ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList; | |||
529 | ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex)); | |||
530 | ||||
531 | const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray(); | |||
532 | sal_Int32 nLen = ScriptEvents.getLength(); | |||
533 | for( sal_Int32 i = 0 ; i < nLen ; i++ ) | |||
534 | registerScriptEvent( nIndex, pArray[ i ] ); | |||
535 | ||||
536 | ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex)); | |||
537 | } | |||
538 | ||||
539 | //----------------------------------------------------------------------------- | |||
540 | void SAL_CALL ImplEventAttacherManager::revokeScriptEvent | |||
541 | ( | |||
542 | sal_Int32 nIndex, | |||
543 | const OUString& ListenerType, | |||
544 | const OUString& EventMethod, | |||
545 | const OUString& ToRemoveListenerParam | |||
546 | ) | |||
547 | throw( IllegalArgumentException, RuntimeException ) | |||
548 | { | |||
549 | Guard< Mutex > aGuard( aLock ); | |||
550 | ||||
551 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
552 | ||||
553 | ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList; | |||
554 | ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex)); | |||
555 | ||||
556 | OUString aLstType = ListenerType; | |||
557 | const sal_Unicode * pLastDot = aLstType.getStr(); | |||
558 | pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' ); | |||
559 | if( pLastDot ) | |||
560 | aLstType = pLastDot +1; | |||
561 | ||||
562 | ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin(); | |||
563 | ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end(); | |||
564 | while( aEvtIt != aEvtEnd ) | |||
565 | { | |||
566 | if( aLstType == (*aEvtIt).ListenerType | |||
567 | && EventMethod == (*aEvtIt).EventMethod | |||
568 | && ToRemoveListenerParam == (*aEvtIt).AddListenerParam ) | |||
569 | { | |||
570 | (*aIt).aEventList.erase( aEvtIt ); | |||
571 | break; | |||
572 | } | |||
573 | ||||
574 | ++aEvtIt; | |||
575 | } | |||
576 | ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex)); | |||
577 | } | |||
578 | ||||
579 | //----------------------------------------------------------------------------- | |||
580 | void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex ) | |||
581 | throw( IllegalArgumentException, RuntimeException ) | |||
582 | { | |||
583 | Guard< Mutex > aGuard( aLock ); | |||
584 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
585 | ||||
586 | ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList; | |||
587 | ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex)); | |||
588 | (*aIt).aEventList.clear(); | |||
589 | ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex)); | |||
590 | } | |||
591 | ||||
592 | //----------------------------------------------------------------------------- | |||
593 | void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex) | |||
594 | throw( IllegalArgumentException, RuntimeException ) | |||
595 | { | |||
596 | Guard< Mutex > aGuard( aLock ); | |||
597 | if( nIndex < 0 ) | |||
598 | throw IllegalArgumentException(); | |||
599 | ||||
600 | if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() ) | |||
601 | aIndex.resize(nIndex+1); | |||
602 | ||||
603 | AttacherIndex_Impl aTmp; | |||
604 | aIndex.insert( aIndex.begin() + nIndex, aTmp ); | |||
605 | } | |||
606 | ||||
607 | //----------------------------------------------------------------------------- | |||
608 | void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex) | |||
609 | throw( IllegalArgumentException, RuntimeException ) | |||
610 | { | |||
611 | Guard< Mutex > aGuard( aLock ); | |||
612 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
613 | ||||
614 | ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList; | |||
615 | ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex)); | |||
616 | aIndex.erase( aIt ); | |||
617 | } | |||
618 | ||||
619 | //----------------------------------------------------------------------------- | |||
620 | Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex) | |||
621 | throw( IllegalArgumentException, RuntimeException ) | |||
622 | { | |||
623 | Guard< Mutex > aGuard( aLock ); | |||
624 | ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); | |||
625 | ||||
626 | Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() ); | |||
627 | ScriptEventDescriptor * pArray = aSeq.getArray(); | |||
628 | ||||
629 | ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin(); | |||
630 | ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end(); | |||
631 | sal_Int32 i = 0; | |||
632 | while( aEvtIt != aEvtEnd ) | |||
633 | { | |||
634 | pArray[i++] = *aEvtIt; | |||
635 | ++aEvtIt; | |||
636 | } | |||
637 | return aSeq; | |||
638 | } | |||
639 | ||||
640 | //----------------------------------------------------------------------------- | |||
641 | void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) | |||
642 | throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException ) | |||
643 | { | |||
644 | Guard< Mutex > aGuard( aLock ); | |||
645 | if( nIndex < 0 || !xObject.is() ) | |||
646 | throw IllegalArgumentException(); | |||
647 | ||||
648 | if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() ) | |||
649 | { | |||
650 | // read older files | |||
651 | if( nVersion == 1 ) | |||
652 | { | |||
653 | insertEntry( nIndex ); | |||
654 | attach( nIndex, xObject, Helper ); | |||
655 | return; | |||
656 | } | |||
657 | else | |||
658 | throw IllegalArgumentException(); | |||
659 | } | |||
660 | ||||
661 | ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex; | |||
662 | ||||
663 | AttachedObject_Impl aTmp; | |||
664 | aTmp.xTarget = xObject; | |||
665 | aTmp.aHelper = Helper; | |||
666 | aCurrentPosition->aObjList.push_back( aTmp ); | |||
667 | ||||
668 | //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back(); | |||
669 | AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back(); | |||
670 | rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() ); | |||
671 | ||||
672 | if (aCurrentPosition->aEventList.empty()) | |||
673 | return; | |||
674 | ||||
675 | Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size()); | |||
676 | std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin(); | |||
677 | std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end(); | |||
678 | ::com::sun::star::script::EventListener* p = aEvents.getArray(); | |||
679 | size_t i = 0; | |||
680 | for (; itr != itrEnd; ++itr) | |||
681 | { | |||
682 | com::sun::star::script::EventListener aListener; | |||
683 | aListener.AllListener = | |||
684 | new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode); | |||
685 | aListener.Helper = rCurObj.aHelper; | |||
686 | aListener.ListenerType = itr->ListenerType; | |||
687 | aListener.EventMethod = itr->EventMethod; | |||
688 | aListener.AddListenerParam = itr->AddListenerParam; | |||
689 | p[i++] = aListener; | |||
690 | } | |||
691 | ||||
692 | try | |||
693 | { | |||
694 | rCurObj.aAttachedListenerSeq = | |||
695 | xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents); | |||
696 | } | |||
697 | catch (const Exception&) | |||
698 | { | |||
699 | // Fail gracefully. | |||
700 | } | |||
701 | } | |||
702 | ||||
703 | //----------------------------------------------------------------------------- | |||
704 | void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject) | |||
705 | throw( IllegalArgumentException, RuntimeException ) | |||
706 | { | |||
707 | Guard< Mutex > aGuard( aLock ); | |||
708 | //return; | |||
709 | if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() ) | |||
710 | throw IllegalArgumentException(); | |||
711 | ||||
712 | ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex; | |||
713 | ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin(); | |||
714 | ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end(); | |||
715 | while( aObjIt != aObjEnd ) | |||
716 | { | |||
717 | if( (*aObjIt).xTarget == xObject ) | |||
718 | { | |||
719 | Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray(); | |||
720 | ||||
721 | ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin(); | |||
722 | ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end(); | |||
723 | sal_Int32 i = 0; | |||
724 | while( aEvtIt != aEvtEnd ) | |||
725 | { | |||
726 | if( pArray[i].is() ) | |||
727 | { | |||
728 | try | |||
729 | { | |||
730 | xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType, | |||
731 | (*aEvtIt).AddListenerParam, pArray[i] ); | |||
732 | } | |||
733 | catch( Exception& ) | |||
734 | { | |||
735 | } | |||
736 | } | |||
737 | i++; | |||
738 | ++aEvtIt; | |||
739 | } | |||
740 | aCurrentPosition->aObjList.erase( aObjIt ); | |||
741 | break; | |||
742 | } | |||
743 | ++aObjIt; | |||
744 | } | |||
745 | } | |||
746 | ||||
747 | void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener) | |||
748 | throw( IllegalArgumentException, RuntimeException ) | |||
749 | { | |||
750 | Guard< Mutex > aGuard( aLock ); | |||
751 | aScriptListeners.addInterface( aListener ); | |||
752 | } | |||
753 | ||||
754 | void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener) | |||
755 | throw( IllegalArgumentException, RuntimeException ) | |||
756 | { | |||
757 | Guard< Mutex > aGuard( aLock ); | |||
758 | aScriptListeners.removeInterface( aListener ); | |||
759 | } | |||
760 | ||||
761 | ||||
762 | // Methods of XPersistObject | |||
763 | OUString SAL_CALL ImplEventAttacherManager::getServiceName(void) | |||
764 | throw( RuntimeException ) | |||
765 | { | |||
766 | return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.script.EventAttacherManager")(&("com.sun.star.uno.script.EventAttacherManager")[0]), ( (sal_Int32)((sizeof ("com.sun.star.uno.script.EventAttacherManager" ) / sizeof (("com.sun.star.uno.script.EventAttacherManager")[ 0]))-1)), (((rtl_TextEncoding) 11)) ); | |||
767 | } | |||
768 | ||||
769 | void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream) | |||
770 | throw( IOException, RuntimeException ) | |||
771 | { | |||
772 | Guard< Mutex > aGuard( aLock ); | |||
773 | // Don't run without XMarkableStream | |||
774 | Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY ); | |||
775 | if( !xMarkStream.is() ) | |||
776 | return; | |||
777 | ||||
778 | // Write out the version | |||
779 | OutStream->writeShort( 2 ); | |||
780 | ||||
781 | // Remember position for length | |||
782 | sal_Int32 nObjLenMark = xMarkStream->createMark(); | |||
783 | OutStream->writeLong( 0L ); | |||
784 | ||||
785 | OutStream->writeLong( aIndex.size() ); | |||
786 | ||||
787 | // Write out sequences | |||
788 | ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin(); | |||
789 | ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end(); | |||
790 | while( aIt != aEnd ) | |||
791 | { | |||
792 | // Write out the length of the sequence and all descriptions | |||
793 | OutStream->writeLong( (*aIt).aEventList.size() ); | |||
794 | ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin(); | |||
795 | ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end(); | |||
796 | while( aEvtIt != aEvtEnd ) | |||
797 | { | |||
798 | const ScriptEventDescriptor& rDesc = (*aEvtIt); | |||
799 | OutStream->writeUTF( rDesc.ListenerType ); | |||
800 | OutStream->writeUTF( rDesc.EventMethod ); | |||
801 | OutStream->writeUTF( rDesc.AddListenerParam ); | |||
802 | OutStream->writeUTF( rDesc.ScriptType ); | |||
803 | OutStream->writeUTF( rDesc.ScriptCode ); | |||
804 | ||||
805 | ++aEvtIt; | |||
806 | } | |||
807 | ++aIt; | |||
808 | } | |||
809 | ||||
810 | // The length is now known | |||
811 | sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4; | |||
812 | xMarkStream->jumpToMark( nObjLenMark ); | |||
813 | OutStream->writeLong( nObjLen ); | |||
814 | xMarkStream->jumpToFurthest(); | |||
815 | xMarkStream->deleteMark( nObjLenMark ); | |||
816 | } | |||
817 | ||||
818 | void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream) | |||
819 | throw( IOException, RuntimeException ) | |||
820 | { | |||
821 | Guard< Mutex > aGuard( aLock ); | |||
822 | // Don't run without XMarkableStream | |||
823 | Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY ); | |||
824 | if( !xMarkStream.is() ) | |||
825 | return; | |||
826 | ||||
827 | // Read in the version | |||
828 | nVersion = InStream->readShort(); | |||
829 | ||||
830 | // At first there's the data according to version 1 -- | |||
831 | // this part needs to be kept in later versions. | |||
832 | sal_Int32 nLen = InStream->readLong(); | |||
833 | ||||
834 | // Position for comparative purposes | |||
835 | sal_Int32 nObjLenMark = xMarkStream->createMark(); | |||
836 | ||||
837 | // Number of read sequences | |||
838 | sal_Int32 nItemCount = InStream->readLong(); | |||
839 | ||||
840 | for( sal_Int32 i = 0 ; i < nItemCount ; i++ ) | |||
841 | { | |||
842 | insertEntry( i ); | |||
843 | // Read the length of the sequence | |||
844 | sal_Int32 nSeqLen = InStream->readLong(); | |||
845 | ||||
846 | // Display the sequences and read the descriptions | |||
847 | Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen ); | |||
848 | ScriptEventDescriptor* pArray = aSEDSeq.getArray(); | |||
849 | for( sal_Int32 j = 0 ; j < nSeqLen ; j++ ) | |||
850 | { | |||
851 | ScriptEventDescriptor& rDesc = pArray[ j ]; | |||
852 | rDesc.ListenerType = InStream->readUTF(); | |||
853 | rDesc.EventMethod = InStream->readUTF(); | |||
854 | rDesc.AddListenerParam = InStream->readUTF(); | |||
855 | rDesc.ScriptType = InStream->readUTF(); | |||
856 | rDesc.ScriptCode = InStream->readUTF(); | |||
857 | } | |||
858 | registerScriptEvents( i, aSEDSeq ); | |||
859 | } | |||
860 | ||||
861 | // Have we read the specified length? | |||
862 | sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark ); | |||
863 | if( nRealLen != nLen ) | |||
864 | { | |||
865 | // Only if the StreamVersion is > 1 and the date still follows, can | |||
866 | // this be true. Otherwise, something is completely gone. | |||
867 | if( nRealLen > nLen || nVersion == 1 ) | |||
868 | { | |||
869 | OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/comphelper/source/eventattachermgr/eventattachermgr.cxx" ":" "869" ": "), "%s", "ImplEventAttacherManager::read(): Fatal Error, wrong object length" ); } } while (false); | |||
870 | } | |||
871 | else | |||
872 | { // TODO: Examine if caching the dates would be useful | |||
873 | // But for now, it's easier to skip it. | |||
874 | sal_Int32 nSkipCount = nLen - nRealLen; | |||
875 | InStream->skipBytes( nSkipCount ); | |||
876 | } | |||
877 | } | |||
878 | xMarkStream->jumpToFurthest(); | |||
879 | xMarkStream->deleteMark( nObjLenMark ); | |||
880 | } | |||
881 | ||||
882 | } // namesapce comphelper | |||
883 | ||||
884 | ||||
885 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |