1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26
27 #define _SV_VALUESET_CXX
28
29 #include <unotools/accessiblestatesethelper.hxx>
30 #include <vcl/svapp.hxx>
31 #include <svtools/valueset.hxx>
32 #include "valueimp.hxx"
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36
37 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLERELATIONTYPE_HPP_
39 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
40 #endif
41 #ifndef _UTL_ACCESSIBLERELATIONSETHELPER_HXX_
42 #include <unotools/accessiblerelationsethelper.hxx>
43 #endif
44 using namespace ::com::sun::star;
45
46 // ----------------
47 // - ValueSetItem -
48 // ----------------
49
ValueSetItem(ValueSet & rParent)50 ValueSetItem::ValueSetItem( ValueSet& rParent ) :
51 mrParent( rParent ),
52 mnId( 0 ),
53 mnBits( 0 ),
54 mpData( NULL ),
55 mpxAcc( NULL )
56 {
57 }
58
59 // -----------------------------------------------------------------------
60
~ValueSetItem()61 ValueSetItem::~ValueSetItem()
62 {
63 if( mpxAcc )
64 {
65 static_cast< ValueItemAcc* >( mpxAcc->get() )->ParentDestroyed();
66 delete mpxAcc;
67 }
68 }
69
70 // -----------------------------------------------------------------------
71
GetAccessible(bool bIsTransientChildrenDisabled)72 uno::Reference< accessibility::XAccessible > ValueSetItem::GetAccessible( bool bIsTransientChildrenDisabled )
73 {
74 if( !mpxAcc )
75 mpxAcc = new uno::Reference< accessibility::XAccessible >( new ValueItemAcc( this, bIsTransientChildrenDisabled ) );
76
77 return *mpxAcc;
78 }
79
80 // -----------------------------------------------------------------------
81
ClearAccessible()82 void ValueSetItem::ClearAccessible()
83 {
84 if( mpxAcc )
85 delete mpxAcc, mpxAcc = NULL;
86 }
87
88
89 // ---------------
90 // - ValueSetAcc -
91 // ---------------
92
ValueSetAcc(ValueSet * pParent,bool bIsTransientChildrenDisabled)93 ValueSetAcc::ValueSetAcc( ValueSet* pParent, bool bIsTransientChildrenDisabled ) :
94 ValueSetAccComponentBase (m_aMutex),
95 mpParent( pParent ),
96 mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ),
97 mbIsFocused(false)
98 {
99 }
100
101 // -----------------------------------------------------------------------------
102
~ValueSetAcc()103 ValueSetAcc::~ValueSetAcc()
104 {
105 }
106
107 // -----------------------------------------------------------------------
108
FireAccessibleEvent(short nEventId,const uno::Any & rOldValue,const uno::Any & rNewValue)109 void ValueSetAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
110 {
111 if( nEventId )
112 {
113 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
114 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() );
115 accessibility::AccessibleEventObject aEvtObject;
116
117 aEvtObject.EventId = nEventId;
118 aEvtObject.Source = static_cast<uno::XWeak*>(this);
119 aEvtObject.NewValue = rNewValue;
120 aEvtObject.OldValue = rOldValue;
121
122 while( aIter != aTmpListeners.end() )
123 {
124 try
125 {
126 (*aIter)->notifyEvent( aEvtObject );
127 }
128 catch( uno::Exception& )
129 {
130 }
131
132 aIter++;
133 }
134 }
135 }
136
137 // -----------------------------------------------------------------------------
138
getUnoTunnelId()139 const uno::Sequence< sal_Int8 >& ValueSetAcc::getUnoTunnelId()
140 {
141 static uno::Sequence< sal_Int8 > aSeq;
142
143 if( !aSeq.getLength() )
144 {
145 static osl::Mutex aCreateMutex;
146 osl::Guard< osl::Mutex > aGuard( aCreateMutex );
147
148 aSeq.realloc( 16 );
149 rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
150 }
151
152 return aSeq;
153 }
154
155 // -----------------------------------------------------------------------------
156
getImplementation(const uno::Reference<uno::XInterface> & rxData)157 ValueSetAcc* ValueSetAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
158 throw()
159 {
160 try
161 {
162 uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
163 return( xUnoTunnel.is() ? reinterpret_cast<ValueSetAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueSetAcc::getUnoTunnelId() ))) : NULL );
164 }
165 catch( const ::com::sun::star::uno::Exception& )
166 {
167 return NULL;
168 }
169 }
170
171
172 // -----------------------------------------------------------------------------
173
GetFocus(void)174 void ValueSetAcc::GetFocus (void)
175 {
176 mbIsFocused = true;
177
178 // Boradcast the state change.
179 ::com::sun::star::uno::Any aOldState, aNewState;
180 aNewState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
181 FireAccessibleEvent(
182 ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
183 aOldState, aNewState);
184 }
185
186 // -----------------------------------------------------------------------------
187
LoseFocus(void)188 void ValueSetAcc::LoseFocus (void)
189 {
190 mbIsFocused = false;
191
192 // Boradcast the state change.
193 ::com::sun::star::uno::Any aOldState, aNewState;
194 aOldState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
195 FireAccessibleEvent(
196 ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
197 aOldState, aNewState);
198 }
199
200 // -----------------------------------------------------------------------------
201
getAccessibleContext()202 uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueSetAcc::getAccessibleContext()
203 throw (uno::RuntimeException)
204 {
205 ThrowIfDisposed();
206 return this;
207 }
208
209 // -----------------------------------------------------------------------------
210
getAccessibleChildCount()211 sal_Int32 SAL_CALL ValueSetAcc::getAccessibleChildCount()
212 throw (uno::RuntimeException)
213 {
214 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
215 ThrowIfDisposed();
216
217 sal_Int32 nCount = mpParent->ImplGetVisibleItemCount();
218 if (HasNoneField())
219 nCount += 1;
220 return nCount;
221 }
222
223 // -----------------------------------------------------------------------------
224
getAccessibleChild(sal_Int32 i)225 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleChild( sal_Int32 i )
226 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
227 {
228 ThrowIfDisposed();
229 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
230 uno::Reference< accessibility::XAccessible > xRet;
231 ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i));
232
233 if( pItem )
234 xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
235 else
236 throw lang::IndexOutOfBoundsException();
237
238 return xRet;
239 }
240
241 // -----------------------------------------------------------------------------
242
getAccessibleParent()243 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleParent()
244 throw (uno::RuntimeException)
245 {
246 ThrowIfDisposed();
247 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
248 Window* pParent = mpParent->GetParent();
249 uno::Reference< accessibility::XAccessible > xRet;
250
251 if( pParent )
252 xRet = pParent->GetAccessible();
253
254 return xRet;
255 }
256
257 // -----------------------------------------------------------------------------
258
getAccessibleIndexInParent()259 sal_Int32 SAL_CALL ValueSetAcc::getAccessibleIndexInParent()
260 throw (uno::RuntimeException)
261 {
262 ThrowIfDisposed();
263 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
264 Window* pParent = mpParent->GetParent();
265 sal_Int32 nRet = 0;
266
267 if( pParent )
268 {
269 sal_Bool bFound = sal_False;
270
271 for( sal_uInt16 i = 0, nCount = pParent->GetChildCount(); ( i < nCount ) && !bFound; i++ )
272 {
273 if( pParent->GetChild( i ) == mpParent )
274 {
275 nRet = i;
276 bFound = sal_True;
277 }
278 }
279 }
280
281 return nRet;
282 }
283
284 // -----------------------------------------------------------------------------
285
getAccessibleRole()286 sal_Int16 SAL_CALL ValueSetAcc::getAccessibleRole()
287 throw (uno::RuntimeException)
288 {
289 ThrowIfDisposed();
290 // #i73746# As the Java Access Bridge (v 2.0.1) uses "managesDescendants"
291 // always if the role is LIST, we need a different role in this case
292 return (mbIsTransientChildrenDisabled
293 ? accessibility::AccessibleRole::PANEL
294 : accessibility::AccessibleRole::LIST );
295 }
296
297 // -----------------------------------------------------------------------------
298
getAccessibleDescription()299 ::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleDescription()
300 throw (uno::RuntimeException)
301 {
302 ThrowIfDisposed();
303 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
304 String aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet" ) );
305
306 return aRet;
307 }
308
309 // -----------------------------------------------------------------------------
310
getAccessibleName()311 ::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleName()
312 throw (uno::RuntimeException)
313 {
314 ThrowIfDisposed();
315 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
316 String aRet;
317
318 if ( mpParent )
319 aRet = mpParent->GetAccessibleName();
320
321 if ( !aRet.Len() )
322 {
323 Window* pLabel = mpParent->GetAccessibleRelationLabeledBy();
324 if ( pLabel && pLabel != mpParent )
325 aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() );
326
327 if ( !aRet.Len() )
328 aRet = mpParent->GetQuickHelpText();
329 }
330
331 return aRet;
332 }
333
334 // -----------------------------------------------------------------------------
335
getAccessibleRelationSet()336 uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueSetAcc::getAccessibleRelationSet()
337 throw (uno::RuntimeException)
338 {
339 ThrowIfDisposed();
340 uno::Reference< accessibility::XAccessibleRelationSet > xRelSet;
341 Window* pWindow = (Window*)mpParent;
342 if ( pWindow )
343 {
344 utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper;
345 xRelSet = pRelationSet;
346
347 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
348 if ( pLabeledBy && pLabeledBy != pWindow )
349 {
350 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
351 aSequence[0] = pLabeledBy->GetAccessible();
352 pRelationSet->AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
353 }
354
355 Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
356 if ( pMemberOf && pMemberOf != pWindow )
357 {
358 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
359 aSequence[0] = pMemberOf->GetAccessible();
360 pRelationSet->AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
361 }
362 }
363 return xRelSet;
364 }
365
366 // -----------------------------------------------------------------------------
367
getAccessibleStateSet()368 uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueSetAcc::getAccessibleStateSet()
369 throw (uno::RuntimeException)
370 {
371 ThrowIfDisposed();
372 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
373
374 // Set some states.
375 pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
376 pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
377 pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
378 pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
379 if ( !mbIsTransientChildrenDisabled )
380 pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS);
381 pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE);
382 if (mbIsFocused)
383 pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED);
384
385 return pStateSet;
386 }
387
388 // -----------------------------------------------------------------------------
389
getLocale()390 lang::Locale SAL_CALL ValueSetAcc::getLocale()
391 throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
392 {
393 ThrowIfDisposed();
394 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
395 const ::rtl::OUString aEmptyStr;
396 uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
397 lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
398
399 if( xParent.is() )
400 {
401 uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
402
403 if( xParentContext.is() )
404 aRet = xParentContext->getLocale ();
405 }
406
407 return aRet;
408 }
409
410 // -----------------------------------------------------------------------------
411
addEventListener(const uno::Reference<accessibility::XAccessibleEventListener> & rxListener)412 void SAL_CALL ValueSetAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
413 throw (uno::RuntimeException)
414 {
415 ThrowIfDisposed();
416 ::osl::MutexGuard aGuard (m_aMutex);
417
418 if( rxListener.is() )
419 {
420 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
421 sal_Bool bFound = sal_False;
422
423 while( !bFound && ( aIter != mxEventListeners.end() ) )
424 {
425 if( *aIter == rxListener )
426 bFound = sal_True;
427 else
428 aIter++;
429 }
430
431 if (!bFound)
432 mxEventListeners.push_back( rxListener );
433 }
434 }
435
436 // -----------------------------------------------------------------------------
437
removeEventListener(const uno::Reference<accessibility::XAccessibleEventListener> & rxListener)438 void SAL_CALL ValueSetAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
439 throw (uno::RuntimeException)
440 {
441 ThrowIfDisposed();
442 ::osl::MutexGuard aGuard (m_aMutex);
443
444 if( rxListener.is() )
445 {
446 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
447 sal_Bool bFound = sal_False;
448
449 while( !bFound && ( aIter != mxEventListeners.end() ) )
450 {
451 if( *aIter == rxListener )
452 {
453 mxEventListeners.erase( aIter );
454 bFound = sal_True;
455 }
456 else
457 aIter++;
458 }
459 }
460 }
461
462 // -----------------------------------------------------------------------------
463
containsPoint(const awt::Point & aPoint)464 sal_Bool SAL_CALL ValueSetAcc::containsPoint( const awt::Point& aPoint )
465 throw (uno::RuntimeException)
466 {
467 ThrowIfDisposed();
468 const awt::Rectangle aRect( getBounds() );
469 const Point aSize( aRect.Width, aRect.Height );
470 const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
471
472 return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
473 }
474
475 // -----------------------------------------------------------------------------
476
getAccessibleAtPoint(const awt::Point & aPoint)477 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleAtPoint( const awt::Point& aPoint )
478 throw (uno::RuntimeException)
479 {
480 ThrowIfDisposed();
481 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
482 const sal_uInt16 nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) );
483 uno::Reference< accessibility::XAccessible > xRet;
484
485 if( VALUESET_ITEM_NOTFOUND != nItemId )
486 {
487 const sal_uInt16 nItemPos = mpParent->GetItemPos( nItemId );
488
489 if( VALUESET_ITEM_NONEITEM != nItemPos )
490 {
491 ValueSetItem* pItem = mpParent->mpImpl->mpItemList->GetObject( nItemPos );
492
493 if( ( pItem->meType != VALUESETITEM_SPACE ) && !pItem->maRect.IsEmpty() )
494 xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
495 }
496 }
497
498 return xRet;
499 }
500
501 // -----------------------------------------------------------------------------
502
getBounds()503 awt::Rectangle SAL_CALL ValueSetAcc::getBounds()
504 throw (uno::RuntimeException)
505 {
506 ThrowIfDisposed();
507 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
508 const Point aOutPos( mpParent->GetPosPixel() );
509 const Size aOutSize( mpParent->GetOutputSizePixel() );
510 awt::Rectangle aRet;
511
512 aRet.X = aOutPos.X();
513 aRet.Y = aOutPos.Y();
514 aRet.Width = aOutSize.Width();
515 aRet.Height = aOutSize.Height();
516
517 return aRet;
518 }
519
520 // -----------------------------------------------------------------------------
521
getLocation()522 awt::Point SAL_CALL ValueSetAcc::getLocation()
523 throw (uno::RuntimeException)
524 {
525 ThrowIfDisposed();
526 const awt::Rectangle aRect( getBounds() );
527 awt::Point aRet;
528
529 aRet.X = aRect.X;
530 aRet.Y = aRect.Y;
531
532 return aRet;
533 }
534
535 // -----------------------------------------------------------------------------
536
getLocationOnScreen()537 awt::Point SAL_CALL ValueSetAcc::getLocationOnScreen()
538 throw (uno::RuntimeException)
539 {
540 ThrowIfDisposed();
541 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
542 const Point aScreenPos( mpParent->OutputToAbsoluteScreenPixel( Point() ) );
543 awt::Point aRet;
544
545 aRet.X = aScreenPos.X();
546 aRet.Y = aScreenPos.Y();
547
548 return aRet;
549 }
550
551 // -----------------------------------------------------------------------------
552
getSize()553 awt::Size SAL_CALL ValueSetAcc::getSize()
554 throw (uno::RuntimeException)
555 {
556 ThrowIfDisposed();
557 const awt::Rectangle aRect( getBounds() );
558 awt::Size aRet;
559
560 aRet.Width = aRect.Width;
561 aRet.Height = aRect.Height;
562
563 return aRet;
564 }
565
566 // -----------------------------------------------------------------------------
567
grabFocus()568 void SAL_CALL ValueSetAcc::grabFocus()
569 throw (uno::RuntimeException)
570 {
571 ThrowIfDisposed();
572 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
573 mpParent->GrabFocus();
574 }
575
576 // -----------------------------------------------------------------------------
577
getAccessibleKeyBinding()578 uno::Any SAL_CALL ValueSetAcc::getAccessibleKeyBinding()
579 throw (uno::RuntimeException)
580 {
581 ThrowIfDisposed();
582 return uno::Any();
583 }
584
585 // -----------------------------------------------------------------------------
586
getForeground()587 sal_Int32 SAL_CALL ValueSetAcc::getForeground( )
588 throw (uno::RuntimeException)
589 {
590 ThrowIfDisposed();
591 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
592 return static_cast<sal_Int32>(nColor);
593 }
594
595 // -----------------------------------------------------------------------------
596
getBackground()597 sal_Int32 SAL_CALL ValueSetAcc::getBackground( )
598 throw (uno::RuntimeException)
599 {
600 ThrowIfDisposed();
601 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
602 return static_cast<sal_Int32>(nColor);
603 }
604
605 // -----------------------------------------------------------------------------
606
selectAccessibleChild(sal_Int32 nChildIndex)607 void SAL_CALL ValueSetAcc::selectAccessibleChild( sal_Int32 nChildIndex )
608 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
609 {
610 ThrowIfDisposed();
611 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
612 ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
613
614 if(pItem != NULL)
615 {
616 mpParent->SelectItem( pItem->mnId );
617 mpParent->Select ();
618 }
619 else
620 throw lang::IndexOutOfBoundsException();
621 }
622
623 // -----------------------------------------------------------------------------
624
isAccessibleChildSelected(sal_Int32 nChildIndex)625 sal_Bool SAL_CALL ValueSetAcc::isAccessibleChildSelected( sal_Int32 nChildIndex )
626 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
627 {
628 ThrowIfDisposed();
629 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
630 ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
631 sal_Bool bRet = sal_False;
632
633 if (pItem != NULL)
634 bRet = mpParent->IsItemSelected( pItem->mnId );
635 else
636 throw lang::IndexOutOfBoundsException();
637
638 return bRet;
639 }
640
641 // -----------------------------------------------------------------------------
642
clearAccessibleSelection()643 void SAL_CALL ValueSetAcc::clearAccessibleSelection()
644 throw (uno::RuntimeException)
645 {
646 ThrowIfDisposed();
647 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
648 mpParent->SetNoSelection();
649 }
650
651 // -----------------------------------------------------------------------------
652
selectAllAccessibleChildren()653 void SAL_CALL ValueSetAcc::selectAllAccessibleChildren()
654 throw (uno::RuntimeException)
655 {
656 ThrowIfDisposed();
657 // unsupported due to single selection only
658 }
659
660 // -----------------------------------------------------------------------------
661
getSelectedAccessibleChildCount()662 sal_Int32 SAL_CALL ValueSetAcc::getSelectedAccessibleChildCount()
663 throw (uno::RuntimeException)
664 {
665 ThrowIfDisposed();
666 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
667 sal_Int32 nRet = 0;
668
669 for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ )
670 {
671 ValueSetItem* pItem = getItem (i);
672
673 if( pItem && mpParent->IsItemSelected( pItem->mnId ) )
674 ++nRet;
675 }
676
677 return nRet;
678 }
679
680 // -----------------------------------------------------------------------------
681
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)682 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
683 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
684 {
685 ThrowIfDisposed();
686 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
687 uno::Reference< accessibility::XAccessible > xRet;
688
689 for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ )
690 {
691 ValueSetItem* pItem = getItem(i);
692
693 if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) )
694 xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
695 }
696
697 return xRet;
698 }
699
700 // -----------------------------------------------------------------------------
701
deselectAccessibleChild(sal_Int32 nChildIndex)702 void SAL_CALL ValueSetAcc::deselectAccessibleChild( sal_Int32 nChildIndex )
703 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
704 {
705 ThrowIfDisposed();
706 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
707 // Because of the single selection we can reset the whole selection when
708 // the specified child is currently selected.
709 if (isAccessibleChildSelected(nChildIndex))
710 mpParent->SetNoSelection();
711 }
712
713 // -----------------------------------------------------------------------------
714
getSomething(const uno::Sequence<sal_Int8> & rId)715 sal_Int64 SAL_CALL ValueSetAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
716 {
717 sal_Int64 nRet;
718
719 if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueSetAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
720 nRet = reinterpret_cast< sal_Int64 >( this );
721 else
722 nRet = 0;
723
724 return nRet;
725 }
726
727
728
729
disposing(void)730 void SAL_CALL ValueSetAcc::disposing (void)
731 {
732 ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy;
733
734 {
735 // Make a copy of the list and clear the original.
736 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
737 ::osl::MutexGuard aGuard (m_aMutex);
738 aListenerListCopy = mxEventListeners;
739 mxEventListeners.clear();
740
741 // Reset the pointer to the parent. It has to be the one who has
742 // disposed us because he is dying.
743 mpParent = NULL;
744 }
745
746 // Inform all listeners that this objects is disposing.
747 ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> >::const_iterator
748 aListenerIterator (aListenerListCopy.begin());
749 lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this));
750 while (aListenerIterator != aListenerListCopy.end())
751 {
752 try
753 {
754 (*aListenerIterator)->disposing (aEvent);
755 }
756 catch( uno::Exception& )
757 {
758 // Ignore exceptions.
759 }
760
761 ++aListenerIterator;
762 }
763 }
764
765
getItemCount(void) const766 sal_uInt16 ValueSetAcc::getItemCount (void) const
767 {
768 sal_uInt16 nCount = mpParent->ImplGetVisibleItemCount();
769 // When the None-Item is visible then increase the number of items by
770 // one.
771 if (HasNoneField())
772 nCount += 1;
773 return nCount;
774 }
775
776
getItem(sal_uInt16 nIndex) const777 ValueSetItem* ValueSetAcc::getItem (sal_uInt16 nIndex) const
778 {
779 ValueSetItem* pItem = NULL;
780
781 if (HasNoneField())
782 {
783 if (nIndex == 0)
784 // When present the first item is the then allways visible none field.
785 pItem = mpParent->ImplGetItem (VALUESET_ITEM_NONEITEM);
786 else
787 // Shift down the index to compensate for the none field.
788 nIndex -= 1;
789 }
790 if (pItem == NULL)
791 pItem = mpParent->ImplGetItem (static_cast<sal_uInt16>(nIndex));
792
793 return pItem;
794 }
795
796
797
798
ThrowIfDisposed(void)799 void ValueSetAcc::ThrowIfDisposed (void)
800 throw (::com::sun::star::lang::DisposedException)
801 {
802 if (rBHelper.bDisposed || rBHelper.bInDispose)
803 {
804 OSL_TRACE ("Calling disposed object. Throwing exception:");
805 throw lang::DisposedException (
806 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
807 static_cast<uno::XWeak*>(this));
808 }
809 else
810 {
811 DBG_ASSERT (mpParent!=NULL, "ValueSetAcc not disposed but mpParent == NULL");
812 }
813 }
814
815
816
IsDisposed(void)817 sal_Bool ValueSetAcc::IsDisposed (void)
818 {
819 return (rBHelper.bDisposed || rBHelper.bInDispose);
820 }
821
822
823
824
HasNoneField(void) const825 bool ValueSetAcc::HasNoneField (void) const
826 {
827 DBG_ASSERT (mpParent!=NULL, "ValueSetAcc::HasNoneField called with mpParent==NULL");
828 return ((mpParent->GetStyle() & WB_NONEFIELD) != 0);
829 }
830
831
832
833
834 // ----------------
835 // - ValueItemAcc -
836 // ----------------
837
ValueItemAcc(ValueSetItem * pParent,bool bIsTransientChildrenDisabled)838 ValueItemAcc::ValueItemAcc( ValueSetItem* pParent, bool bIsTransientChildrenDisabled ) :
839 mpParent( pParent ),
840 mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled )
841 {
842 }
843
844 // -----------------------------------------------------------------------------
845
~ValueItemAcc()846 ValueItemAcc::~ValueItemAcc()
847 {
848 }
849
850 // -----------------------------------------------------------------------
851
FireAccessibleEvent(short nEventId,const uno::Any & rOldValue,const uno::Any & rNewValue)852 void ValueItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
853 {
854 if( nEventId )
855 {
856 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
857 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() );
858 accessibility::AccessibleEventObject aEvtObject;
859
860 aEvtObject.EventId = nEventId;
861 aEvtObject.Source = static_cast<uno::XWeak*>(this);
862 aEvtObject.NewValue = rNewValue;
863 aEvtObject.OldValue = rOldValue;
864
865 while( aIter != aTmpListeners.end() )
866 {
867 (*aIter)->notifyEvent( aEvtObject );
868 aIter++;
869 }
870 }
871 }
872
873 // -----------------------------------------------------------------------------
874
ParentDestroyed()875 void ValueItemAcc::ParentDestroyed()
876 {
877 const ::vos::OGuard aGuard( maMutex );
878 mpParent = NULL;
879 }
880
881 // -----------------------------------------------------------------------------
882
getUnoTunnelId()883 const uno::Sequence< sal_Int8 >& ValueItemAcc::getUnoTunnelId()
884 {
885 static uno::Sequence< sal_Int8 > aSeq;
886
887 if( !aSeq.getLength() )
888 {
889 static osl::Mutex aCreateMutex;
890 osl::Guard< osl::Mutex > aGuard( aCreateMutex );
891
892 aSeq.realloc( 16 );
893 rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
894 }
895
896 return aSeq;
897 }
898
899 // -----------------------------------------------------------------------------
900
getImplementation(const uno::Reference<uno::XInterface> & rxData)901 ValueItemAcc* ValueItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
902 throw()
903 {
904 try
905 {
906 uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
907 return( xUnoTunnel.is() ? reinterpret_cast<ValueItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueItemAcc::getUnoTunnelId() ))) : NULL );
908 }
909 catch( const ::com::sun::star::uno::Exception& )
910 {
911 return NULL;
912 }
913 }
914
915 // -----------------------------------------------------------------------------
916
getAccessibleContext()917 uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueItemAcc::getAccessibleContext()
918 throw (uno::RuntimeException)
919 {
920 return this;
921 }
922
923 // -----------------------------------------------------------------------------
924
getAccessibleChildCount()925 sal_Int32 SAL_CALL ValueItemAcc::getAccessibleChildCount()
926 throw (uno::RuntimeException)
927 {
928 return 0;
929 }
930
931 // -----------------------------------------------------------------------------
932
getAccessibleChild(sal_Int32)933 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleChild( sal_Int32 )
934 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
935 {
936 throw lang::IndexOutOfBoundsException();
937 }
938
939 // -----------------------------------------------------------------------------
940
getAccessibleParent()941 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleParent()
942 throw (uno::RuntimeException)
943 {
944 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
945 uno::Reference< accessibility::XAccessible > xRet;
946
947 if( mpParent )
948 xRet = mpParent->mrParent.GetAccessible();
949
950 return xRet;
951 }
952
953 // -----------------------------------------------------------------------------
954
getAccessibleIndexInParent()955 sal_Int32 SAL_CALL ValueItemAcc::getAccessibleIndexInParent()
956 throw (uno::RuntimeException)
957 {
958 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
959 // The index defaults to -1 to indicate the child does not belong to its
960 // parent.
961 sal_Int32 nIndexInParent = -1;
962
963 if( mpParent )
964 {
965 bool bDone = false;
966
967 sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount();
968 ValueSetItem* pItem;
969 for (sal_uInt16 i=0; i<nCount && !bDone; i++)
970 {
971 // Guard the retrieval of the i-th child with a try/catch block
972 // just in case the number of children changes in the mean time.
973 try
974 {
975 pItem = mpParent->mrParent.ImplGetItem(i);
976 }
977 catch (lang::IndexOutOfBoundsException aException)
978 {
979 pItem = NULL;
980 }
981
982 // Do not create an accessible object for the test.
983 if (pItem != NULL && pItem->mpxAcc != NULL)
984 if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this )
985 {
986 nIndexInParent = i;
987 bDone = true;
988 }
989 }
990 }
991
992 //if this valueset contain a none field(common value is default), then we should increase the real index and set the noitem index value equal 0.
993 if ( mpParent && ( (mpParent->mrParent.GetStyle() & WB_NONEFIELD) != 0 ) )
994 {
995 ValueSetItem* pFirstItem = mpParent->mrParent.ImplGetItem (VALUESET_ITEM_NONEITEM);
996 if( pFirstItem && pFirstItem ->GetAccessible(mbIsTransientChildrenDisabled).get() == this )
997 nIndexInParent = 0;
998 else
999 nIndexInParent++;
1000 }
1001 return nIndexInParent;
1002 }
1003
1004 // -----------------------------------------------------------------------------
1005
getAccessibleRole()1006 sal_Int16 SAL_CALL ValueItemAcc::getAccessibleRole()
1007 throw (uno::RuntimeException)
1008 {
1009 return accessibility::AccessibleRole::LIST_ITEM;
1010 }
1011
1012 // -----------------------------------------------------------------------------
1013
getAccessibleDescription()1014 ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleDescription()
1015 throw (uno::RuntimeException)
1016 {
1017 return ::rtl::OUString();
1018 }
1019
1020 // -----------------------------------------------------------------------------
1021
getAccessibleName()1022 ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleName()
1023 throw (uno::RuntimeException)
1024 {
1025 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1026 String aRet;
1027
1028 if( mpParent )
1029 {
1030 aRet = mpParent->maText;
1031
1032 if( !aRet.Len() )
1033 {
1034 aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) );
1035 aRet += String::CreateFromInt32( mpParent->mnId );
1036 }
1037 }
1038
1039 return aRet;
1040 }
1041
1042 // -----------------------------------------------------------------------------
1043
getAccessibleRelationSet()1044 uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueItemAcc::getAccessibleRelationSet()
1045 throw (uno::RuntimeException)
1046 {
1047 return uno::Reference< accessibility::XAccessibleRelationSet >();
1048 }
1049
1050 // -----------------------------------------------------------------------------
1051
getAccessibleStateSet()1052 uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueItemAcc::getAccessibleStateSet()
1053 throw (uno::RuntimeException)
1054 {
1055 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1056 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper;
1057
1058 if( mpParent )
1059 {
1060 pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
1061 pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
1062 pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
1063 pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
1064 if ( !mbIsTransientChildrenDisabled )
1065 pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT);
1066
1067 // SELECTABLE
1068 pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE );
1069 // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE );
1070
1071 // SELECTED
1072 if( mpParent->mrParent.GetSelectItemId() == mpParent->mnId )
1073 {
1074 pStateSet->AddState( accessibility::AccessibleStateType::SELECTED );
1075 // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED );
1076 }
1077 }
1078
1079 return pStateSet;
1080 }
1081
1082 // -----------------------------------------------------------------------------
1083
getLocale()1084 lang::Locale SAL_CALL ValueItemAcc::getLocale()
1085 throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
1086 {
1087 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1088 const ::rtl::OUString aEmptyStr;
1089 uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
1090 lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
1091
1092 if( xParent.is() )
1093 {
1094 uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
1095
1096 if( xParentContext.is() )
1097 aRet = xParentContext->getLocale();
1098 }
1099
1100 return aRet;
1101 }
1102
1103 // -----------------------------------------------------------------------------
1104
addEventListener(const uno::Reference<accessibility::XAccessibleEventListener> & rxListener)1105 void SAL_CALL ValueItemAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
1106 throw (uno::RuntimeException)
1107 {
1108 const ::vos::OGuard aGuard( maMutex );
1109
1110 if( rxListener.is() )
1111 {
1112 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
1113 sal_Bool bFound = sal_False;
1114
1115 while( !bFound && ( aIter != mxEventListeners.end() ) )
1116 {
1117 if( *aIter == rxListener )
1118 bFound = sal_True;
1119 else
1120 aIter++;
1121 }
1122
1123 if (!bFound)
1124 mxEventListeners.push_back( rxListener );
1125 }
1126 }
1127
1128 // -----------------------------------------------------------------------------
1129
removeEventListener(const uno::Reference<accessibility::XAccessibleEventListener> & rxListener)1130 void SAL_CALL ValueItemAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
1131 throw (uno::RuntimeException)
1132 {
1133 const ::vos::OGuard aGuard( maMutex );
1134
1135 if( rxListener.is() )
1136 {
1137 ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
1138 sal_Bool bFound = sal_False;
1139
1140 while( !bFound && ( aIter != mxEventListeners.end() ) )
1141 {
1142 if( *aIter == rxListener )
1143 {
1144 mxEventListeners.erase( aIter );
1145 bFound = sal_True;
1146 }
1147 else
1148 aIter++;
1149 }
1150 }
1151 }
1152
1153 // -----------------------------------------------------------------------------
1154
containsPoint(const awt::Point & aPoint)1155 sal_Bool SAL_CALL ValueItemAcc::containsPoint( const awt::Point& aPoint )
1156 throw (uno::RuntimeException)
1157 {
1158 const awt::Rectangle aRect( getBounds() );
1159 const Point aSize( aRect.Width, aRect.Height );
1160 const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
1161
1162 return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
1163 }
1164
1165 // -----------------------------------------------------------------------------
1166
getAccessibleAtPoint(const awt::Point &)1167 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleAtPoint( const awt::Point& )
1168 throw (uno::RuntimeException)
1169 {
1170 uno::Reference< accessibility::XAccessible > xRet;
1171 return xRet;
1172 }
1173
1174 // -----------------------------------------------------------------------------
1175
getBounds()1176 awt::Rectangle SAL_CALL ValueItemAcc::getBounds()
1177 throw (uno::RuntimeException)
1178 {
1179 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1180 awt::Rectangle aRet;
1181
1182 if( mpParent )
1183 {
1184 Rectangle aRect( mpParent->maRect );
1185 Point aOrigin;
1186 Rectangle aParentRect( aOrigin, mpParent->mrParent.GetOutputSizePixel() );
1187
1188 aRect.Intersection( aParentRect );
1189
1190 aRet.X = aRect.Left();
1191 aRet.Y = aRect.Top();
1192 aRet.Width = aRect.GetWidth();
1193 aRet.Height = aRect.GetHeight();
1194 }
1195
1196 return aRet;
1197 }
1198
1199 // -----------------------------------------------------------------------------
1200
getLocation()1201 awt::Point SAL_CALL ValueItemAcc::getLocation()
1202 throw (uno::RuntimeException)
1203 {
1204 const awt::Rectangle aRect( getBounds() );
1205 awt::Point aRet;
1206
1207 aRet.X = aRect.X;
1208 aRet.Y = aRect.Y;
1209
1210 return aRet;
1211 }
1212
1213 // -----------------------------------------------------------------------------
1214
getLocationOnScreen()1215 awt::Point SAL_CALL ValueItemAcc::getLocationOnScreen()
1216 throw (uno::RuntimeException)
1217 {
1218 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1219 awt::Point aRet;
1220
1221 if( mpParent )
1222 {
1223 const Point aScreenPos( mpParent->mrParent.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) );
1224
1225 aRet.X = aScreenPos.X();
1226 aRet.Y = aScreenPos.Y();
1227 }
1228
1229 return aRet;
1230 }
1231
1232 // -----------------------------------------------------------------------------
1233
getSize()1234 awt::Size SAL_CALL ValueItemAcc::getSize()
1235 throw (uno::RuntimeException)
1236 {
1237 const awt::Rectangle aRect( getBounds() );
1238 awt::Size aRet;
1239
1240 aRet.Width = aRect.Width;
1241 aRet.Height = aRect.Height;
1242
1243 return aRet;
1244 }
1245
1246 // -----------------------------------------------------------------------------
1247
grabFocus()1248 void SAL_CALL ValueItemAcc::grabFocus()
1249 throw (uno::RuntimeException)
1250 {
1251 // nothing to do
1252 }
1253
1254 // -----------------------------------------------------------------------------
1255
getAccessibleKeyBinding()1256 uno::Any SAL_CALL ValueItemAcc::getAccessibleKeyBinding()
1257 throw (uno::RuntimeException)
1258 {
1259 return uno::Any();
1260 }
1261
1262 // -----------------------------------------------------------------------------
1263
getForeground()1264 sal_Int32 SAL_CALL ValueItemAcc::getForeground( )
1265 throw (uno::RuntimeException)
1266 {
1267 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
1268 return static_cast<sal_Int32>(nColor);
1269 }
1270
1271 // -----------------------------------------------------------------------------
1272
getBackground()1273 sal_Int32 SAL_CALL ValueItemAcc::getBackground( )
1274 throw (uno::RuntimeException)
1275 {
1276 sal_uInt32 nColor;
1277 if (mpParent && mpParent->meType == VALUESETITEM_COLOR)
1278 nColor = mpParent->maColor.GetColor();
1279 else
1280 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
1281 return static_cast<sal_Int32>(nColor);
1282 }
1283
1284 // -----------------------------------------------------------------------------
1285
getSomething(const uno::Sequence<sal_Int8> & rId)1286 sal_Int64 SAL_CALL ValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
1287 {
1288 sal_Int64 nRet;
1289
1290 if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
1291 nRet = reinterpret_cast< sal_Int64 >( this );
1292 else
1293 nRet = 0;
1294
1295 return nRet;
1296 }
1297