1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright IBM Corporation 2010.
6  * Copyright 2000, 2010 Oracle and/or its affiliates.
7  *
8  * OpenOffice.org - a multi-platform office productivity suite
9  *
10  * This file is part of OpenOffice.org.
11  *
12  * OpenOffice.org is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License version 3
14  * only, as published by the Free Software Foundation.
15  *
16  * OpenOffice.org is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License version 3 for more details
20  * (a copy is included in the LICENSE file that accompanied this code).
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * version 3 along with OpenOffice.org.  If not, see
24  * <http://www.openoffice.org/license.html>
25  * for a copy of the LGPLv3 License.
26  *
27  ************************************************************************/
28 
29 #include "stdafx.h"
30 #include "UAccCOM2.h"
31 #include "MAccessible.h"
32 
33 #include <algorithm>
34 #include "AccAction.h"
35 
36 #include <com/sun/star/accessibility/XAccessibleText.hpp>
37 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
38 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
39 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
40 #include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
41 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
42 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
43 #include <com/sun/star/accessibility/XAccessibleHyperText.hpp>
44 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
45 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
46 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
47 #include <com/sun/star/accessibility/AccessibleRole.hpp>
48 #include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
49 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
50 #include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
51 #include <com/sun/star/style/LineSpacing.hpp>
52 #include <com/sun/star/style/TabStop.hpp>
53 #include <com/sun/star/container/XIndexReplace.hpp>
54 
55 #include "AccessibleRole.h"
56 
57 using namespace com::sun::star::accessibility::AccessibleStateType;
58 
59 // IA2 states mapping, and name
60 // maintenance the consistency, change one array, change the three all
61 long IA2_STATES[] =
62     {
63         IA2_STATE_ACTIVE,					// =					0x1;
64         IA2_STATE_ARMED,					// =					0x2;
65         IA2_STATE_DEFUNCT,					// =					0x4;
66         IA2_STATE_EDITABLE,					// =					0x8;
67         IA2_STATE_HORIZONTAL,				// =					0x10;
68         IA2_STATE_ICONIFIED,				// =					0x20;
69         IA2_STATE_INVALID_ENTRY,			// =					0x80;
70         IA2_STATE_MANAGES_DESCENDANTS,		// =					0x100;
71         IA2_STATE_MODAL,					// =					0x200;
72         IA2_STATE_MULTI_LINE,				// =					0x400;
73         IA2_STATE_OPAQUE,					// =					0x800;
74         IA2_STATE_REQUIRED,					// =					0x2000;
75         IA2_STATE_SELECTABLE_TEXT,			// =					0x3000;
76         IA2_STATE_SINGLE_LINE,				// =					0x4000;
77         IA2_STATE_STALE,					// =					0x8000;
78         IA2_STATE_SUPPORTS_AUTOCOMPLETION,	// =					0x10000;
79         IA2_STATE_TRANSIENT,				//=						0x20000;
80         IA2_STATE_VERTICAL					// =					0x40000;
81     };
82 /*
83 
84 <=== map ===>
85 
86 */
87 short UNO_STATES[] =
88     {
89         ACTIVE,			// = (sal_Int16)1;
90         ARMED,			// = (sal_Int16)2;
91         DEFUNC,			// = (sal_Int16)5;
92         EDITABLE,		// = (sal_Int16)6;
93         HORIZONTAL,		// = (sal_Int16)12;
94         ICONIFIED,		// = (sal_Int16)13;
95         -1,				//IA2_STATE_INVALID_ENTRY
96         MANAGES_DESCENDANTS, // = (sal_Int16)15;
97         MODAL,			// = (sal_Int16)16;
98         MULTI_LINE,		// = (sal_Int16)17;
99         OPAQUE,			// = (sal_Int16)19;
100         -1,				//IA2_STATE_REQUIRED
101         -1,				//IA2_STATE_SELECTABLE_TEXT
102         SINGLE_LINE,	// = (sal_Int16)26;
103         STALE,			// = (sal_Int16)27;
104         -1,				//IA2_STATE_SUPPORTS_AUTOCOMPLETION
105         TRANSIENT,		//IA2_STATE_TRANSIENT
106         VERTICAL		// = (sal_Int16)29;
107     };
108 
109 //  <=== map ===>
110 
111 BSTR IA2_STATES_NAME[] =
112     {
113         _T("Active"),
114         _T("Armed"),
115         _T("Defunct"),
116         _T("Editable"),
117         _T("Horizontal"),
118         _T("Iconified"),
119         _T("Invalid Entry"),
120         _T("Manages Decendents"),
121         _T("Modal"),
122         _T("Multi Line"),
123         _T("Opaque"),
124         _T("Required"),
125         _T("Selectable Text"),
126         _T("Single Line"),
127         _T("Stale"),
128         _T("Supports Autocompletion"),
129         _T("Transient"),
130         _T("Vertical")
131     };
132 
133 // IA2 states mapping, and name
134 // maintenance the consistency. change one, change them all
135 
136 BSTR UNO_ALL_STATES[] =
137     {
138         _T("INVALID"),			// 	INVALID	( 0 )
139         _T("ACTIVE"),			// 	ACTIVE	( 1 )
140         _T("ARMED"),			// 	ARMED	( 2 )
141         _T("BUSY"),				// 	BUSY	( 3 )
142         _T("CHECKED"),			// 	CHECKED	( 4 )
143         _T("DEFUNC"),			// 	DEFUNC	( 5 )
144         _T("EDITABLE"),			// 	EDITABLE	( 6 )
145         _T("ENABLED"),			// 	ENABLED	( 7 )
146         _T("EXPANDABLE"),		// 	EXPANDABLE	( 8 )
147         _T("EXPANDED"),			// 	EXPANDED	( 9 )
148         _T("FOCUSABLE"),		// 	FOCUSABLE	( 10 )
149         _T("FOCUSED"),			// 	FOCUSED	( 11 )
150         _T("HORIZONTAL"),		// 	HORIZONTAL	( 12 )
151         _T("ICONIFIED"),		// 	ICONIFIED	( 13 )
152         _T("INDETERMINATE"),	// 	INDETERMINATE	( 14 )
153         _T("MANAGES_DESCENDANTS"),// 	MANAGES_DESCENDANTS	( 15 )
154         _T("MODAL"),			// 	MODAL	( 16 )
155         _T("MULTI_LINE"),		// 	MULTI_LINE	( 17 )
156         _T("MULTI_SELECTABLE"),	// 	MULTI_SELECTABLE	( 18 )
157         _T("OPAQUE"),			// 	OPAQUE	( 19 )
158         _T("PRESSED"),			// 	PRESSED	( 20 )
159         _T("RESIZABLE"),		// 	RESIZABLE	( 21 )
160         _T("SELECTABLE"),		// 	SELECTABLE	( 22 )
161         _T("SELECTED"),			// 	SELECTED	( 23 )
162         _T("SENSITIVE"),		// 	SENSITIVE	( 24 )
163         _T("SHOWING"),			// 	SHOWING	( 25 )
164         _T("SINGLE_LINE"),		// 	SINGLE_LINE	( 26 )
165         _T("STALE"),			// 	STALE	( 27 )
166         _T("TRANSIENT"),		// 	TRANSIENT	( 28 )
167         _T("VERTICAL"),			// 	VERTICAL	( 29 )
168         _T("VISIBLE"),			// 	VISIBLE	( 30 )
169         _T("MOVEABLE"),			//  MOVEABLE ( 31 )
170         _T("OFFSCREEN"),		//  OFFSCREEN ( 32 )
171         _T("COLLAPSE"),			//  COLLAPSE ( 33 )
172         _T("DEFAULT")			//  DEFAULT ( 34 )
173     };
174 
175 
176 using namespace com::sun::star::accessibility::AccessibleRole;
177 
178 
179 
180 #define QUERYXINTERFACE(ainterface)	\
181 {							\
182 	if(pXAcc == NULL)		\
183 		return FALSE;		\
184 	pRContext = pXAcc->getAccessibleContext();	\
185 	if( !pRContext.is() )	\
186 	{						\
187 		return FALSE;		\
188 	}						\
189 	Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
190 	if( !pRXI.is() )		\
191 	{						\
192 		return FALSE;		\
193 	}						\
194 	*ppXI = (XInterface*)pRXI.get();		\
195 	return TRUE;			\
196 }
197 
198 #define ISDESTROY()	\
199 	if(m_isDestroy)	\
200 		return S_FALSE;
201 
202 
203 AccObjectManagerAgent* CMAccessible::g_pAgent = NULL;
204 
205 CMAccessible::CMAccessible():
206         m_iRole(0x00),
207         m_dState(0x00),
208         m_dChildID(0x00),
209         m_dFocusChildID(UACC_NO_FOCUS),
210         m_hwnd(NULL),
211         m_pIParent(NULL),
212         m_pszName(NULL),
213         m_pszValue(NULL),
214         m_pszDescription(NULL),
215         m_isDestroy(FALSE),
216         m_pszActionDescription(NULL),
217         m_pXAction(NULL),
218         m_bRequiresSave(FALSE),
219         pUNOInterface(NULL)
220 {
221     m_sLocation.m_dLeft=0;
222     m_sLocation.m_dTop = 0;
223     m_sLocation.m_dWidth=0;
224     m_sLocation.m_dHeight=0;
225     CEnumVariant::Create(&m_pEnumVar);
226 }
227 
228 CMAccessible::~CMAccessible()
229 {
230         if(m_pszName!=NULL)
231     {
232         SAFE_SYSFREESTRING(m_pszName);
233         m_pszName=NULL;
234     }
235     if(m_pszValue!=NULL)
236     {
237         SAFE_SYSFREESTRING(m_pszValue);
238         m_pszValue=NULL;
239     }
240     if(m_pszDescription!=NULL)
241     {
242         SAFE_SYSFREESTRING(m_pszDescription);
243         m_pszDescription=NULL;
244     }
245 
246     if(m_pszActionDescription!=NULL)
247     {
248         SAFE_SYSFREESTRING(m_pszActionDescription);
249         m_pszActionDescription=NULL;
250     }
251 
252     if(m_pIParent)
253     {
254         m_pIParent->Release();
255         m_pIParent=NULL;
256     }
257     pRef = NULL;
258     m_pEnumVar->Release();
259     m_containedObjects.clear();
260     pRContext = NULL;
261 }
262 
263 /**
264 * Returns the Parent IAccessible interface pointer to AT.
265 * It should add reference, and the client should release the component.
266 * It should return E_FAIL when the parent point is null.
267 * @param	ppdispParent [in,out] used to return the parent interface point.
268 *			when the point is null, should return null.
269 * @return   S_OK if successful and E_FAIL if the m_pIParent is NULL.
270 */
271 STDMETHODIMP CMAccessible::get_accParent(IDispatch **ppdispParent)
272 {
273 
274 	CHECK_ENABLE_INF
275     ENTER_PROTECTED_BLOCK
276     ISDESTROY()
277     // #CHECK#
278     if(ppdispParent == NULL)
279     {
280         return E_INVALIDARG;
281     }
282 
283     if(m_pIParent)
284     {
285         *ppdispParent = m_pIParent;
286         (*ppdispParent)->AddRef();
287         return S_OK;
288     }
289     else if(m_hwnd)
290     {
291         HRESULT hr = AccessibleObjectFromWindow(m_hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent);
292         if( ! SUCCEEDED( hr ) || ! ppdispParent )
293         {
294             return S_FALSE;
295         }
296         return S_OK;
297     }
298     return S_FALSE;
299 
300     LEAVE_PROTECTED_BLOCK
301 }
302 
303 /**
304 * Returns child count of current COM object.
305 * @param	pcountChildren [in,out] used to return the children count.
306 * @return   S_OK if successful.
307 */
308 STDMETHODIMP CMAccessible::get_accChildCount(long *pcountChildren)
309 {
310 
311 	CHECK_ENABLE_INF
312     ENTER_PROTECTED_BLOCK
313     ISDESTROY()
314     // #CHECK#
315     if(pcountChildren == NULL)
316     {
317         return E_INVALIDARG;
318     }
319 
320     if(!pUNOInterface)
321         return S_FALSE;
322 
323     Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
324     if( pRContext.is() )
325     {
326         *pcountChildren = pRContext->getAccessibleChildCount();
327     }
328 
329     return S_OK;
330 
331     LEAVE_PROTECTED_BLOCK
332 }
333 
334 /**
335 * Returns child interface pointer for AT according to input child ID.
336 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
337 * the child ID specify child index from 0 to children count, 0 stands for object self.
338 * @param	ppdispChild, [in,out] use to return the child interface point.
339 * @return   S_OK if successful and S_FALSE if failure.
340 */
341 STDMETHODIMP CMAccessible::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
342 {
343 
344 	CHECK_ENABLE_INF
345     ENTER_PROTECTED_BLOCK
346     ISDESTROY()
347     // #CHECK#
348     if(ppdispChild == NULL)
349     {
350         return E_INVALIDARG;
351     }
352     if(varChild.vt==VT_I4)
353     {
354         //get child interface pointer due to child ID
355         if(varChild.lVal==CHILDID_SELF)
356         {
357             AddRef();
358             *ppdispChild = this;
359             return S_OK;
360         }
361         *ppdispChild = GetChildInterface(varChild.lVal);
362         (*ppdispChild)->AddRef();
363         return (*ppdispChild)?S_OK:S_FALSE;
364     }
365     return S_FALSE;
366 
367     LEAVE_PROTECTED_BLOCK
368 }
369 
370 /**
371 * Returns the accessible name of the current COM object self or its one child to AT.
372 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
373 * the child ID specify child index from 0 to children count, 0 stands for object self.
374 * @param	pszName, [in,out] use to return the name of the proper object.
375 * @return   S_OK if successful and S_FALSE if failure.
376 */
377 STDMETHODIMP CMAccessible::get_accName(VARIANT varChild, BSTR *pszName)
378 {
379 
380 	CHECK_ENABLE_INF
381     ENTER_PROTECTED_BLOCK
382     ISDESTROY()
383     // #CHECK#
384     if(pszName == NULL)
385     {
386         return E_INVALIDARG;
387     }
388     if(varChild.vt==VT_I4)
389     {
390         if(varChild.lVal==CHILDID_SELF)
391         {
392             SAFE_SYSFREESTRING(*pszName);
393             *pszName = SysAllocString(m_pszName);
394             return S_OK;
395         }
396 
397         long lVal = varChild.lVal;
398         varChild.lVal = CHILDID_SELF;
399         IMAccessible *pChild = this->GetChildInterface(lVal);
400         if(!pChild)
401             return E_FAIL;
402         return pChild->get_accName(varChild,pszName);
403     }
404     return S_FALSE;
405 
406     LEAVE_PROTECTED_BLOCK
407 }
408 
409 /**
410 * Returns the accessible value of the current COM object self or its one child to AT.
411 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
412 * the child ID specify child index from 0 to children count, 0 stands for object self.
413 * @param	pszValue, [in,out] use to return the value of the proper object.
414 * @return   S_OK if successful and S_FALSE if failure.
415 */
416 STDMETHODIMP CMAccessible::get_accValue(VARIANT varChild, BSTR *pszValue)
417 {
418 
419 	CHECK_ENABLE_INF
420     ENTER_PROTECTED_BLOCK
421     ISDESTROY()
422     // #CHECK#
423     if( pszValue == NULL )
424     {
425         return E_INVALIDARG;
426     }
427     if( varChild.vt==VT_I4 )
428     {
429         if(varChild.lVal==CHILDID_SELF)
430         {
431             if(m_dState & STATE_SYSTEM_PROTECTED)
432                 return E_ACCESSDENIED;
433 
434             if ( m_pszValue !=NULL && wcslen(m_pszValue) == 0 )
435                 return S_OK;
436 
437             SAFE_SYSFREESTRING(*pszValue);
438             *pszValue = SysAllocString(m_pszValue);
439             return S_OK;
440         }
441 
442         long lVal = varChild.lVal;
443         varChild.lVal = CHILDID_SELF;
444         IMAccessible *pChild = this->GetChildInterface(lVal);
445         if(!pChild)
446             return E_FAIL;
447         return pChild->get_accValue(varChild,pszValue);
448     }
449     return S_FALSE;
450 
451     LEAVE_PROTECTED_BLOCK
452 }
453 
454 /**
455 * Returns the accessible description of the current COM object self or its one child to AT.
456 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
457 * the child ID specify child index from 0 to children count, 0 stands for object self.
458 * @param	pszDescription, [in,out] use to return the description of the proper object.
459 * @return   S_OK if successful and E_FAIL if failure.
460 */
461 STDMETHODIMP CMAccessible::get_accDescription(VARIANT varChild, BSTR *pszDescription)
462 {
463 
464 	CHECK_ENABLE_INF
465     ENTER_PROTECTED_BLOCK
466     ISDESTROY()
467     // #CHECK#
468     if(pszDescription == NULL)
469     {
470         return E_INVALIDARG;
471     }
472     if(varChild.vt==VT_I4)
473     {
474         if(varChild.lVal==CHILDID_SELF)
475         {
476             SAFE_SYSFREESTRING(*pszDescription);
477             *pszDescription = SysAllocString(m_pszDescription);
478             return S_OK;
479         }
480 
481         long lVal = varChild.lVal;
482         varChild.lVal = CHILDID_SELF;
483         IMAccessible *pChild = this->GetChildInterface(lVal);
484         if(!pChild)
485             return E_FAIL;
486         return pChild->get_accDescription(varChild,pszDescription);
487     }
488     return S_FALSE;
489 
490     LEAVE_PROTECTED_BLOCK
491 }
492 
493 /**
494 * Returns the accessible role of the current COM object self or its one child to AT.
495 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
496 * the child ID specify child index from 0 to children count, 0 stands for object self.
497 * @param	pvarRole, [in,out] use to return the role of the proper object.
498 * @return   S_OK if successful and S_FALSE if failure.
499 */
500 STDMETHODIMP CMAccessible::get_accRole(VARIANT varChild, VARIANT *pvarRole)
501 {
502 
503 	CHECK_ENABLE_INF
504     ENTER_PROTECTED_BLOCK
505     ISDESTROY()
506     // #CHECK#
507     if(pvarRole == NULL)
508     {
509         return E_INVALIDARG;
510     }
511     if(varChild.vt == VT_I4)
512     {
513 
514         if(varChild.lVal == CHILDID_SELF)
515         {
516             if( m_iRole < IA2_ROLE_CAPTION )
517             {
518                 VariantInit(pvarRole);
519                 pvarRole->vt = VT_I4;
520                 pvarRole->lVal = m_iRole;
521             }
522             else
523             {
524                 VariantInit(pvarRole);
525                 pvarRole->vt = VT_I4;
526                 pvarRole->lVal = ROLE_SYSTEM_CLIENT;
527             }
528             return S_OK;
529         }
530 
531 
532         long lVal = varChild.lVal;
533         varChild.lVal = CHILDID_SELF;
534         IMAccessible *pChild = this->GetChildInterface(lVal);
535         if(!pChild)
536             return E_FAIL;
537         return pChild->get_accRole(varChild,pvarRole);
538     }
539     return S_FALSE;
540 
541     LEAVE_PROTECTED_BLOCK
542 }
543 
544 /**
545 * Returns the accessible state of the current COM object self or its one child to AT.
546 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
547 * the child ID specify child index from 0 to children count, 0 stands for object self.
548 * @param	pvarState, [in,out] use to return the state of the proper object.
549 * @return   S_OK if successful and S_FALSE if failure.
550 */
551 STDMETHODIMP CMAccessible::get_accState(VARIANT varChild, VARIANT *pvarState)
552 {
553 
554 	CHECK_ENABLE_INF
555     ENTER_PROTECTED_BLOCK
556     ISDESTROY()
557     // #CHECK#
558     if(pvarState == NULL)
559     {
560         return E_INVALIDARG;
561     }
562     if(varChild.vt==VT_I4)
563     {
564         if(varChild.lVal == CHILDID_SELF)
565         {
566             if(pUNOInterface)
567             {
568                 Reference< XAccessibleContext > pContext = pUNOInterface->getAccessibleContext();
569                 if(pContext.is())
570                 {
571 					// add the STATE_SYSTEM_LINKED state
572                     Reference< XAccessibleHypertext > pRHypertext(pContext,UNO_QUERY);
573                     if(pRHypertext.is())
574                     {
575                         if( pRHypertext->getHyperLinkCount() > 0 )
576                             m_dState |= STATE_SYSTEM_LINKED;
577                         else
578                             m_dState &= ~STATE_SYSTEM_LINKED;
579                     }
580                     else
581                         m_dState &= ~STATE_SYSTEM_LINKED;
582                 }
583             }
584 
585             VariantInit(pvarState);
586             pvarState->vt = VT_I4;
587             pvarState->lVal = m_dState;
588             return S_OK;
589         }
590 
591         long lVal = varChild.lVal;
592         varChild.lVal = CHILDID_SELF;
593         IMAccessible *pChild = this->GetChildInterface(lVal);
594         if(!pChild)
595             return E_FAIL;
596         return pChild->get_accState(varChild,pvarState);
597     }
598     return S_FALSE;
599 
600     LEAVE_PROTECTED_BLOCK
601 }
602 
603 /**
604 * Returns the accessible helpString of the current COM object self or its one child to AT.
605 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
606 * the child ID specify child index from 0 to children count, 0 stands for object self.
607 * @param	pszHelp, [in,out] use to return the helpString of the proper object.
608 * @return   S_OK if successful and E_FAIL if failure.
609 */
610 STDMETHODIMP CMAccessible::get_accHelp(VARIANT, BSTR *)
611 {
612         return E_NOTIMPL;
613 }
614 
615 /**
616 * Returns the accessible HelpTopic of the current COM object self or its one child to AT.
617 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
618 * the child ID specify child index from 0 to children count, 0 stands for object self.
619 * @param	pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
620 * @param	pidTopic, use to return the HelpTopic ID of the proper object.
621 * @return   S_OK if successful and E_FAIL if failure.
622 * Not implemented yet
623 */
624 STDMETHODIMP CMAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
625 {
626         return E_NOTIMPL;
627 }
628 
629 static void GetMnemonicChar( const ::rtl::OUString& aStr, WCHAR* wStr)
630 {
631     int  nLen    = aStr.pData->length;
632     int  i       = 0;
633     WCHAR* text = aStr.pData->buffer;
634 
635     while ( i < nLen )
636     {
637         if ( text[i] == L'~' )
638             if ( text[i+1] != L'~' )
639             {
640                 wStr[0] = text[i+1];
641                 break;
642             }
643         i++;
644     }
645 }
646 
647 /**
648 * Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
649 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
650 * the child ID specify child index from 0 to children count, 0 stands for object self.
651 * @param	pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
652 * @return   S_OK if successful and E_FAIL if failure.
653 */
654 STDMETHODIMP CMAccessible::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut)
655 {
656 
657 	CHECK_ENABLE_INF
658     ENTER_PROTECTED_BLOCK
659 
660     ISDESTROY()
661     // #CHECK#
662     if(pszKeyboardShortcut == NULL)
663     {
664         return E_INVALIDARG;
665     }
666 
667     if(varChild.vt==VT_I4)
668     {
669         if(varChild.lVal == CHILDID_SELF)
670         {
671             if( pUNOInterface )
672             {
673                 Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
674                 if( !pRContext.is() )
675                     return S_FALSE;
676 
677 				Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
678 
679                 OLECHAR wString[64]={0};
680 
681                 if( pRXI.is() && pRXI->getAccessibleActionCount() >= 1)
682                 {
683                     Reference< XAccessibleKeyBinding > binding = pRXI->getAccessibleActionKeyBinding(0);
684                     if( binding.is() )
685                     {
686                         long nCount = binding->getAccessibleKeyBindingCount();
687                         if(nCount >= 1)
688                         {
689                             CAccAction::GetkeyBindingStrByXkeyBinding( binding->getAccessibleKeyBinding(0),wString );
690                         }
691                     }
692                 }
693                 if(wString[0] == 0)
694                 {
695                     Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
696                     if(!pRrelationSet.is())
697                     {
698                         return S_FALSE;
699                     }
700 
701                     long nRelCount = pRrelationSet->getRelationCount();
702 
703                     // Modified by Steve Yin, for SODC_1552
704 					if( /*nRelCount <= 0 &&*/ m_iRole == ROLE_SYSTEM_TEXT )
705                     {
706                         VARIANT varParentRole;
707                         VariantInit( &varParentRole );
708 
709 						m_pIParent->get_accRole(varChild, &varParentRole);
710 
711 						if( m_pIParent && varParentRole.lVal == ROLE_SYSTEM_COMBOBOX ) // edit in comoboBox
712                         {
713                             m_pIParent->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
714                             return S_OK;
715                         }
716                     }
717 
718                     AccessibleRelation *paccRelation = NULL;
719 					AccessibleRelation accRelation;
720                     for(int i=0; i<nRelCount ; i++)
721                     {
722                         if( pRrelationSet->getRelation(i).RelationType == 6 )
723 						{
724 							accRelation = pRrelationSet->getRelation(i);
725 							paccRelation = &accRelation;
726 						}
727                     }
728 
729                     if(paccRelation == NULL)
730                         return S_FALSE;
731 
732                     Sequence< Reference< XInterface > > xTargets = paccRelation->TargetSet;
733                     Reference<XInterface> pRAcc = xTargets[0];
734 
735                     XAccessible* pXAcc = (XAccessible*)pRAcc.get();
736 
737                     Reference<XAccessibleContext> pRLebelContext = pXAcc->getAccessibleContext();
738                     if(!pRLebelContext.is())
739                         return S_FALSE;
740 
741                     pRrelationSet = pRLebelContext->getAccessibleRelationSet();
742                     nRelCount = pRrelationSet->getRelationCount();
743 
744                     paccRelation = NULL;
745                     for(int j=0; j<nRelCount ; j++)
746                     {
747                         if( pRrelationSet->getRelation(j).RelationType == 5 )
748 						{
749 							accRelation = pRrelationSet->getRelation(j);
750 							paccRelation = &accRelation;
751 						}
752                     }
753 
754                     if(paccRelation)
755                     {
756                         xTargets = paccRelation->TargetSet;
757                         pRAcc = xTargets[0];
758                         if(pUNOInterface != (XAccessible*)pRAcc.get())
759                             return S_FALSE;
760                     }
761 
762                     Reference<XAccessibleExtendedComponent> pRXIE(pRLebelContext,UNO_QUERY);
763                     if(!pRXIE.is())
764                         return S_FALSE;
765 
766                     ::rtl::OUString ouStr = pRXIE->getTitledBorderText();
767                     WCHAR key[2] = {NULL};
768                     GetMnemonicChar(ouStr, key);
769                     if(key[0] != 0)
770                     {
771                         wcscat(wString, L"Alt+");
772                         wcscat(wString, key);
773                     }
774                     else
775                         return S_FALSE;
776                 }
777 
778                 SAFE_SYSFREESTRING(*pszKeyboardShortcut);
779                 *pszKeyboardShortcut = SysAllocString(wString);
780 
781                 return S_OK;
782             }
783             else
784             {
785                 return S_FALSE;
786             }
787         }
788 
789         long lVal = varChild.lVal;
790         varChild.lVal = CHILDID_SELF;
791         IMAccessible *pChild = this->GetChildInterface(lVal);
792         if(!pChild)
793             return E_FAIL;
794 
795         return pChild->get_accKeyboardShortcut(varChild,pszKeyboardShortcut);
796     }
797     return S_FALSE;
798 
799     LEAVE_PROTECTED_BLOCK
800 }
801 
802 /**
803 * Returns the current focused child to AT.
804 * @param	pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
805 * the child ID specify child index from 0 to children count, 0 stands for object self.
806 * @return   S_OK if successful and E_FAIL if failure.
807 */
808 STDMETHODIMP CMAccessible::get_accFocus(VARIANT *pvarChild)
809 {
810 
811 	CHECK_ENABLE_INF
812     ENTER_PROTECTED_BLOCK
813     ISDESTROY()
814     // #CHECK#
815     if(pvarChild == NULL)
816     {
817         return E_INVALIDARG;
818     }
819     if( m_dFocusChildID==UACC_NO_FOCUS )
820     {
821         pvarChild->vt = VT_EMPTY;//no focus on the object and its children
822         return S_OK;
823     }
824 	//if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
825 	else
826 	{
827 	    IMAccessible* pIMAcc = NULL;
828         g_pAgent->GetIAccessibleFromResID(m_dFocusChildID,&pIMAcc);
829 		pIMAcc->AddRef();
830 		pvarChild->vt = VT_DISPATCH;
831         pvarChild->pdispVal = pIMAcc;
832 
833 	}
834     return S_OK;
835 
836     LEAVE_PROTECTED_BLOCK
837 }
838 
839 /**
840 * Returns the selection of the current COM object to AT.
841 * @param	pvarChildren,[in,out]
842 * if selection num is 0,return VT_EMPTY for vt,
843 * if selection num is 1,return VT_I4 for vt,and child index for lVal
844 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
845 * @return   S_OK if successful and S_FALSE if failure.
846 */
847 STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
848 {
849 
850 	CHECK_ENABLE_INF
851     ENTER_PROTECTED_BLOCK
852     ISDESTROY()
853     // #CHECK#
854     if(pvarChildren == NULL)
855     {
856         return E_INVALIDARG;
857     }
858     switch(m_pEnumVar->GetCountOfElements())
859     {
860     case 0:
861         pvarChildren->vt = VT_EMPTY;
862         break;
863     case 1:
864         VARIANT varTmp[1];
865         ULONG count;
866         VariantInit(&varTmp[0]);
867         m_pEnumVar->Next(1,varTmp,&count);
868         if(count!=1)
869             return S_FALSE;
870         pvarChildren->vt = VT_I4;
871         pvarChildren->lVal = varTmp[0].lVal;
872         VariantClear(&varTmp[0]);
873         m_pEnumVar->Reset();
874         break;
875     default:
876         pvarChildren->vt = VT_UNKNOWN;
877         m_pEnumVar->AddRef();
878         pvarChildren->punkVal = m_pEnumVar;
879         break;
880     }
881     return S_OK;
882 
883     LEAVE_PROTECTED_BLOCK
884 }
885 
886 /**
887 * Returns the location of the current COM object self or its one child to AT.
888 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
889 * the child ID specify child index from 0 to children count, 0 stands for object self.
890 * @param	pxLeft, [in,out] use to return the x-coordination of the proper object.
891 * @param	pyTop,  [in,out] use to return the y-coordination of the proper object.
892 * @param	pcxWidth, [in,out] use to return the x-coordination width of the proper object.
893 * @param	pcyHeight, [in,out] use to return the y-coordination height of the proper object.
894 * @return   S_OK if successful and S_FALSE if failure.
895 */
896 STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
897 {
898 
899 	CHECK_ENABLE_INF
900     ENTER_PROTECTED_BLOCK
901     ISDESTROY()
902     // #CHECK#
903     if(pxLeft == NULL || pyTop == NULL || pcxWidth == NULL || pcyHeight == NULL)
904     {
905         return E_INVALIDARG;
906     }
907 
908     if(varChild.vt==VT_I4)
909     {
910         if(varChild.lVal==CHILDID_SELF)
911         {
912 
913             if(pUNOInterface)
914             {
915                 Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
916                 if( !pRContext.is() )
917                     return S_FALSE;
918                 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
919                 if( !pRComponent.is() )
920                     return S_FALSE;
921 
922                 ::com::sun::star::awt::Point pCPoint = pRComponent->getLocationOnScreen();
923                 ::com::sun::star::awt::Size pCSize = pRComponent->getSize();
924                 *pxLeft = pCPoint.X;
925                 *pyTop =  pCPoint.Y;
926                 *pcxWidth = pCSize.Width;
927                 *pcyHeight = pCSize.Height;
928                 return S_OK;
929             }
930             else
931             {
932                 *pxLeft = m_sLocation.m_dLeft;
933                 *pyTop = m_sLocation.m_dTop;
934                 *pcxWidth = m_sLocation.m_dWidth;
935                 *pcyHeight = m_sLocation.m_dHeight;
936                 return S_OK;
937             }
938         }
939 
940     }
941     return S_FALSE;
942 
943     LEAVE_PROTECTED_BLOCK
944 }
945 
946 /**
947 * Returns the current focused child to AT.
948 * @param	navDir, the direction flag of the navigation.
949 * @param	varStart, the start child id of this navigation action.
950 * @param	pvarEndUpAt, [in,out] the end up child of this navigation action.
951 * @return   S_OK if successful and E_FAIL if failure.
952 */
953 STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
954 {
955 
956 	CHECK_ENABLE_INF
957     ENTER_PROTECTED_BLOCK
958     ISDESTROY()
959     // #CHECK#
960     if(pvarEndUpAt == NULL)
961     {
962         return E_INVALIDARG;
963     }
964     HRESULT ret = E_FAIL;
965     switch (navDir)
966     {
967     case NAVDIR_FIRSTCHILD:
968         ret = GetFirstChild(varStart,pvarEndUpAt);
969         break;
970     case NAVDIR_LASTCHILD:
971         ret = GetLastChild(varStart,pvarEndUpAt);
972         break;
973     case NAVDIR_NEXT:
974         ret = GetNextSibling(varStart,pvarEndUpAt);
975         break;
976     case NAVDIR_PREVIOUS:
977         ret = GetPreSibling(varStart,pvarEndUpAt);
978         break;
979     case NAVDIR_DOWN://do not implement temporarily
980         break;
981     case NAVDIR_UP://do not implement temporarily
982         break;
983     case NAVDIR_LEFT://do not implement temporarily
984         break;
985     case NAVDIR_RIGHT://do not implement temporarily
986         break;
987     default:
988         break;
989     };
990     return ret;
991 
992     LEAVE_PROTECTED_BLOCK
993 }
994 
995 STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
996 {
997 
998 	CHECK_ENABLE_INF
999     ENTER_PROTECTED_BLOCK
1000     ISDESTROY()
1001     // #CHECK#
1002     if(pvarChild == NULL)
1003     {
1004         return E_INVALIDARG;
1005     }
1006     long x, y, w, h;
1007     VARIANT varSelf;
1008     VariantInit(&varSelf);
1009     varSelf.vt = VT_I4;
1010     varSelf.lVal = CHILDID_SELF;
1011     accLocation(&x,&y,&w,&h,varSelf);
1012     if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
1013     {
1014         int i, nCount;
1015         pvarChild->vt = VT_EMPTY;
1016         Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1017         nCount = pRContext->getAccessibleChildCount();
1018         if(nCount > 256)
1019             return E_FAIL;
1020         IMAccessible* child = NULL;
1021         for( i = 0; i<nCount; i++)
1022         {
1023 
1024             child = GetChildInterface(i + 1);
1025             if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
1026                 break;
1027         }
1028 
1029         if(pvarChild->vt == VT_DISPATCH)
1030             return S_OK;
1031 
1032         if( i < nCount)
1033         {
1034             pvarChild->vt = VT_DISPATCH;
1035             pvarChild->pdispVal = child;
1036             child->AddRef();
1037         }
1038         else
1039         {
1040             pvarChild->vt = VT_I4;
1041             pvarChild->lVal = CHILDID_SELF;
1042         }
1043         return S_OK;
1044     }
1045     return S_FALSE;
1046 
1047     LEAVE_PROTECTED_BLOCK
1048 }
1049 
1050 /**
1051 * Get The other Interface from CMAccessible.
1052 * @param	guidService, must be IID_IAccessible here.
1053 * @param	riid, the IID interface .
1054 * @return   S_OK if successful and S_FALSE if failure.
1055 */
1056 STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
1057 {
1058     if( InlineIsEqualGUID(guidService, IID_IAccessible) )
1059         return QueryInterface(riid, ppvObject);
1060     return S_FALSE;
1061 }
1062 
1063 /**
1064 * Set the accessible name of the current COM object self or its one child from UNO.
1065 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1066 * the child ID specify child index from 0 to children count, 0 stands for object self.
1067 * @param	szName, the name used to set the name of the proper object.
1068 * @return   S_OK if successful and E_FAIL if failure.
1069 */
1070 STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
1071 {
1072 
1073     ENTER_PROTECTED_BLOCK
1074     ISDESTROY()
1075     if(varChild.vt==VT_I4)
1076     {
1077         if(varChild.lVal==CHILDID_SELF)
1078         {
1079             SAFE_SYSFREESTRING(m_pszName);
1080             m_pszName=SysAllocString(szName);
1081             return S_OK;
1082         }
1083 
1084         long lVal = varChild.lVal;
1085         varChild.lVal = CHILDID_SELF;
1086         IMAccessible *pChild = this->GetChildInterface(lVal);
1087         if(!pChild)
1088             return E_FAIL;
1089         return pChild->put_accName(varChild,szName);
1090     }
1091     return E_FAIL;
1092 
1093     LEAVE_PROTECTED_BLOCK
1094 }
1095 
1096 /**
1097 * Set the accessible value of the current COM object self or its one child from UNO.
1098 * @param	varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1099 * the child ID specify child index from 0 to children count, 0 stands for object self.
1100 * @param	szValue, the value used to set the value of the proper object.
1101 * @return   S_OK if successful and E_FAIL if failure.
1102 */
1103 STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
1104 {
1105 
1106     ENTER_PROTECTED_BLOCK
1107     ISDESTROY()
1108     if(varChild.vt==VT_I4)
1109     {
1110         if(varChild.lVal==CHILDID_SELF)
1111         {
1112             SysAllocString(m_pszValue);
1113             m_pszValue=SysAllocString(szValue);
1114             return S_OK;
1115         }
1116 
1117         long lVal = varChild.lVal;
1118         varChild.lVal = CHILDID_SELF;
1119         IMAccessible *pChild = this->GetChildInterface(lVal);
1120         if(!pChild)
1121             return E_FAIL;
1122         return pChild->put_accValue(varChild,szValue);
1123     }
1124     return E_FAIL;
1125 
1126     LEAVE_PROTECTED_BLOCK
1127 }
1128 
1129 /**
1130 * Set the accessible name of the current COM object self from UNO.
1131 * @param	pszName, the name value used to set the name of the current object.
1132 * @return   S_OK if successful and E_FAIL if failure.
1133 */
1134 STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
1135 {
1136 
1137     ENTER_PROTECTED_BLOCK
1138     ISDESTROY()
1139     // #CHECK#
1140     if(pszName == NULL)
1141     {
1142         return E_INVALIDARG;
1143     }
1144 
1145     SAFE_SYSFREESTRING(m_pszName);//??
1146     m_pszName = SysAllocString(pszName);
1147     if(m_pszName==NULL)
1148         return E_FAIL;
1149     return S_OK;
1150 
1151     LEAVE_PROTECTED_BLOCK
1152 }
1153 
1154 /**
1155 * Set the accessible role of the current COM object self from UNO.
1156 * @param	pRole, the role value used to set the role of the current object.
1157 * @return   S_OK if successful and E_FAIL if failure.
1158 */
1159 STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
1160 {
1161         m_iRole = pRole;
1162     return S_OK;
1163 }
1164 
1165 /**
1166 * Add one state into the current state set for the current COM object from UNO.
1167 * @param	pXSate, the state used to set the name of the current object.
1168 * @return   S_OK if successful and E_FAIL if failure.
1169 */
1170 STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
1171 {
1172         m_dState &= (~pXSate);
1173     return S_OK;
1174 }
1175 
1176 /**
1177 * Delete one state into the current state set for the current COM object from UNO.
1178 * @param	pXSate, the state used to set the name of the current object.
1179 * @return   S_OK if successful and E_FAIL if failure.
1180 */
1181 STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
1182 {
1183         m_dState |= pXSate;
1184     return S_OK;
1185 }
1186 
1187 /**
1188 * Set state into the current state set for the current COM object from UNO.
1189 * @param	pXSate, the state used to set the name of the current object.
1190 * @return   S_OK if successful and E_FAIL if failure.
1191 */
1192 STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
1193 {
1194         m_dState = pXSate;
1195     return S_OK;
1196 }
1197 
1198 
1199 
1200 /**
1201 * Set the accessible description of the current COM object self from UNO.
1202 * @param	pszDescription, the name used to set the description of the current object.
1203 * @return   S_OK if successful and E_FAIL if failure.
1204 */
1205 STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
1206 {
1207 
1208     ENTER_PROTECTED_BLOCK
1209     ISDESTROY()
1210     // #CHECK#
1211     if(pszDescription == NULL)
1212     {
1213         return E_INVALIDARG;
1214     }
1215 
1216     SAFE_SYSFREESTRING(m_pszDescription);
1217     m_pszDescription = SysAllocString(pszDescription);
1218 
1219     if(m_pszDescription==NULL)
1220         return E_FAIL;
1221     return S_OK;
1222 
1223     LEAVE_PROTECTED_BLOCK
1224 }
1225 
1226 /**
1227 * Set the accessible value of the current COM object self from UNO.
1228 * @param	pszAccValue, the name used to set the value of the current object.
1229 * @return   S_OK if successful and E_FAIL if failure.
1230 */
1231 STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
1232 {
1233 
1234     ENTER_PROTECTED_BLOCK
1235     ISDESTROY()
1236     // #CHECK#
1237     if(pszAccValue == NULL)
1238     {
1239         return E_INVALIDARG;
1240     }
1241     SAFE_SYSFREESTRING(m_pszValue);
1242     m_pszValue = SysAllocString(pszAccValue);
1243     if(m_pszValue==NULL)
1244         return E_FAIL;
1245     return S_OK;
1246 
1247     LEAVE_PROTECTED_BLOCK
1248 }
1249 
1250 /**
1251 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1252 * Object through the method AccessibleObjectFromWindow(...).
1253 * @param	hwnd, the HWND used to set the value of the current object.
1254 * @return   S_OK if successful and E_FAIL if failure.
1255 */
1256 STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
1257 {
1258 
1259     ENTER_PROTECTED_BLOCK
1260     ISDESTROY()
1261     m_hwnd = hwnd;
1262     return S_OK;
1263 
1264     LEAVE_PROTECTED_BLOCK
1265 }
1266 
1267 /**
1268 * Set accessible focus by specifying child ID
1269 * @param	dChildID, the child id identifies the focus child.
1270 * @return   S_OK if successful and E_FAIL if failure.
1271 */
1272 STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
1273 {
1274 
1275     ENTER_PROTECTED_BLOCK
1276     ISDESTROY()
1277 
1278     if(dChildID==CHILDID_SELF)
1279     {
1280         if(m_pIParent)
1281         {
1282             m_pIParent->Put_XAccFocus(m_dChildID);
1283         }
1284     }
1285     else
1286     {
1287         m_dFocusChildID = dChildID;
1288 		//traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1289 		//any of the ancestors, this id can be used to get the IAccessible of focused object.
1290 		if(m_pIParent)
1291         {
1292             m_pIParent->Put_XAccFocus(dChildID);
1293         }
1294     }
1295     return S_OK;
1296 
1297     LEAVE_PROTECTED_BLOCK
1298 }
1299 
1300 /**
1301  *Set accessible object location for the current COM object
1302  * @param	sLocation, the location of the current object.
1303  * @return   S_OK if successful and E_FAIL if failure.
1304  */
1305 STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
1306 {
1307 
1308     this->m_sLocation = sLocation;
1309     return S_OK;
1310 }
1311 
1312 /**
1313  * Set accessible parent object for the current COM object if
1314  * the current object is a child of some COM object
1315  * @param	pIParent, the parent of the current object.
1316  * @return   S_OK if successful and E_FAIL if failure.
1317  */
1318 STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
1319 {
1320     this->m_pIParent = pIParent;
1321 
1322     if(pIParent)
1323         m_pIParent->AddRef();
1324 
1325     return S_OK;
1326 }
1327 
1328 /**
1329  * Set unique child id to COM
1330  * @param	dChildID, the id of the current object.
1331  * @return   S_OK if successful and E_FAIL if failure.
1332  */
1333 STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
1334 {
1335 
1336     this->m_dChildID = dChildID;
1337     return S_OK;
1338 }
1339 
1340 /**
1341  * Set AccObjectManagerAgent object pointer to COM
1342  * @param	pAgent, the AccObjectManagerAgent point.
1343  * @return   S_OK if successful and E_FAIL if failure.
1344  */
1345 STDMETHODIMP CMAccessible::Put_XAccAgent(long pAgent)
1346 {
1347     g_pAgent = (AccObjectManagerAgent*)pAgent;
1348     return S_OK;
1349 }
1350 
1351 /**
1352  * When a UNO control disposing, it disposes its listeners,
1353  * then notify AccObject in bridge management, then notify
1354  * COM that the XAccessible is invalid,so set pUNOInterface as NULL
1355  * @param	isDestroy, true is it need to be destroyed.
1356  * @return   S_OK if successful and E_FAIL if failure.
1357  */
1358 STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
1359 {
1360 
1361     m_isDestroy = isDestroy;
1362     pUNOInterface = NULL;
1363     return S_OK;
1364 }
1365 
1366 /**
1367  *private methods that help implement public functions
1368  */
1369 
1370 /**
1371  * Return child interface pointer by child ID,note: need to call AddRef()
1372  * @param	lChildID, specify child index,which AT(such as Inspect32) gives.
1373  * @return  IMAccessible*, pointer to the corresponding child object.
1374  */
1375 IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
1376 {
1377 
1378     long dChildIndex = 0;
1379     if(dChildID<0)
1380     {
1381         if(g_pAgent)
1382         {
1383             IMAccessible* pIMAcc = NULL;
1384             g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
1385             return pIMAcc;
1386         }
1387         return NULL;
1388     }
1389     else
1390     {
1391         Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
1392         if( !pRContext.is() )
1393             return NULL;
1394 
1395         if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
1396             return NULL;
1397 
1398         IAccessible* pChild = NULL;
1399         Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
1400         BOOL isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
1401 
1402         if(!isGet)
1403         {
1404             g_pAgent->InsertAccObj(pXChild.get(),pUNOInterface,(long)m_hwnd);
1405             isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
1406         }
1407 
1408         if(isGet)
1409         {
1410             IMAccessible* pIMAcc =  (IMAccessible*)pChild;
1411             return pIMAcc;
1412         }
1413     }
1414 
1415     return NULL;
1416 }
1417 
1418 /**
1419  * For List, tree and table,these roles belong to manage_decendant in UNO,
1420  * need to process specifically when navigate
1421  * @return  BOOL, if it is decendantmanager, return true.
1422  */
1423 BOOL CMAccessible::IsDecendantManage()
1424 {
1425 
1426     return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
1427 }
1428 
1429 /**
1430  * for decendantmanager circumstance,provide child interface when navigate
1431  * @param	varCur, the current child.
1432  * @param	flags, the navigation direction.
1433  * @return  IMAccessible*, the child of the end up node.
1434  */
1435 IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
1436 {
1437 
1438     XAccessibleContext* pXContext = GetContextByXAcc(pUNOInterface);
1439     if(pXContext==NULL)
1440     {
1441         return NULL;
1442     }
1443 
1444     int count = pXContext->getAccessibleChildCount();
1445     if(count<1)
1446     {
1447         return NULL;
1448     }
1449 
1450     IMAccessible* pCurChild = NULL;
1451     XAccessible* pChildXAcc = NULL;
1452     Reference<XAccessible> pRChildXAcc;
1453     XAccessibleContext* pChildContext = NULL;
1454     int index = 0,delta=0;
1455     switch(flags)
1456     {
1457     case DM_FIRSTCHILD:
1458         pRChildXAcc = pXContext->getAccessibleChild(0);
1459         break;
1460     case DM_LASTCHILD:
1461         pRChildXAcc = pXContext->getAccessibleChild(count-1);
1462         break;
1463     case DM_NEXTCHILD:
1464     case DM_PREVCHILD:
1465         pCurChild = GetChildInterface(varCur.lVal);
1466         if(pCurChild==NULL)
1467         {
1468             return NULL;
1469         }
1470         pCurChild->GetUNOInterface((long*)&pChildXAcc);
1471         if(pChildXAcc==NULL)
1472         {
1473             return NULL;
1474         }
1475         pChildContext = GetContextByXAcc(pChildXAcc);
1476         if(pChildContext == NULL)
1477         {
1478             return NULL;
1479         }
1480         delta = (flags==DM_NEXTCHILD)?1:-1;
1481         //currently, getAccessibleIndexInParent is error in UNO for
1482         //some kind of List,such as ValueSet, the index will be less 1 than
1483         //what should be, need to fix UNO code
1484         index = pChildContext->getAccessibleIndexInParent()+delta;
1485         if((index>=0)&&(index<=count-1))
1486         {
1487             pRChildXAcc = pXContext->getAccessibleChild(index);
1488         }
1489         break;
1490     default:
1491         break;
1492     }
1493 
1494     if(!pRChildXAcc.is())
1495     {
1496         return NULL;
1497     }
1498     pChildXAcc = pRChildXAcc.get();
1499     g_pAgent->InsertAccObj(pChildXAcc,pUNOInterface);
1500     return g_pAgent->GetIMAccByXAcc(pChildXAcc);
1501 }
1502 
1503 /**
1504  *the following 4 private methods are for accNavigate implementation
1505  */
1506 
1507 /**
1508  * Return first child for parent container, process differently according
1509  * to whether it is decendant manage
1510  * @param	varStart, the start child id of this navigation action.
1511  * @param	pvarEndUpAt, [in,out] the end up child of this navigation action.
1512  * @return   S_OK if successful and E_FAIL if failure.
1513  */
1514 HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1515 {
1516 
1517     ENTER_PROTECTED_BLOCK
1518     ISDESTROY()
1519     // #CHECK#
1520     if(pvarEndUpAt == NULL)
1521     {
1522         return E_INVALIDARG;
1523     }
1524     if(varStart.vt != VT_I4)
1525     {
1526         pvarEndUpAt->vt = VT_EMPTY;
1527         return E_INVALIDARG;
1528     }
1529 
1530     pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
1531     if(pvarEndUpAt->pdispVal)
1532     {
1533         pvarEndUpAt->pdispVal->AddRef();
1534         pvarEndUpAt->vt = VT_DISPATCH;
1535         return S_OK;
1536     }
1537 
1538     pvarEndUpAt->vt = VT_EMPTY;
1539     return E_FAIL;
1540 
1541     LEAVE_PROTECTED_BLOCK
1542 }
1543 
1544 /**
1545  * Return last child for parent container, process differently according
1546  * to whether it is decendant manage
1547  * @param	varStart, the start child id of this navigation action.
1548  * @param	pvarEndUpAt, [in,out] the end up child of this navigation action.
1549  * @return   S_OK if successful and E_FAIL if failure.
1550  */
1551 HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1552 {
1553 
1554     ENTER_PROTECTED_BLOCK
1555     ISDESTROY()
1556     // #CHECK#
1557     if(pvarEndUpAt == NULL)
1558     {
1559         return E_INVALIDARG;
1560     }
1561     if(varStart.vt != VT_I4)
1562     {
1563         pvarEndUpAt->vt = VT_EMPTY;
1564         return E_INVALIDARG;
1565     }
1566 
1567     pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
1568     if(pvarEndUpAt->pdispVal)
1569     {
1570         pvarEndUpAt->pdispVal->AddRef();
1571         pvarEndUpAt->vt = VT_DISPATCH;
1572         return S_OK;
1573     }
1574     pvarEndUpAt->vt = VT_EMPTY;
1575     return E_FAIL;
1576 
1577     LEAVE_PROTECTED_BLOCK
1578 }
1579 
1580 /**
1581  * The method GetNextSibling is general, whatever it is decendant manage or not
1582  * Get the next sibling object.
1583  * @param	varStart, the start child id of this navigation action.
1584  * @param	pvarEndUpAt, [in,out] the end up child of this navigation action.
1585  * @return   S_OK if successful and E_FAIL if failure.
1586  */
1587 HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1588 {
1589 
1590     ENTER_PROTECTED_BLOCK
1591     ISDESTROY()
1592     if(varStart.vt != VT_I4)
1593     {
1594         pvarEndUpAt->vt = VT_EMPTY;
1595         return E_INVALIDARG;
1596     }
1597 
1598     Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1599     if(pRContext.is())
1600     {
1601         varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
1602         if(m_pIParent)
1603             if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1604             {
1605                 pvarEndUpAt->vt = VT_DISPATCH;
1606                 return S_OK;
1607             }
1608     }
1609     pvarEndUpAt->vt = VT_EMPTY;
1610     return E_FAIL;
1611 
1612     LEAVE_PROTECTED_BLOCK
1613 }
1614 
1615 /**
1616  *the method GetPreSibling is general, whatever it is decendant manage or not
1617  * @param	varStart, the start child id of this navigation action.
1618  * @param	pvarEndUpAt, [in,out] the end up child of this navigation action.
1619  * @return   S_OK if successful and E_FAIL if failure.
1620  */
1621 HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1622 {
1623 
1624     ENTER_PROTECTED_BLOCK
1625     ISDESTROY()
1626     // #CHECK#
1627     if(pvarEndUpAt == NULL)
1628     {
1629         return E_INVALIDARG;
1630     }
1631     if(varStart.vt != VT_I4)
1632     {
1633         pvarEndUpAt->vt = VT_EMPTY;
1634         return E_INVALIDARG;
1635     }
1636 
1637     Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1638     if(pRContext.is())
1639     {
1640         varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
1641         if(m_pIParent && varStart.iVal > 0)
1642             if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1643             {
1644                 pvarEndUpAt->vt = VT_DISPATCH;
1645                 return S_OK;
1646             }
1647     }
1648     pvarEndUpAt->vt = VT_EMPTY;
1649     return E_FAIL;
1650 
1651     LEAVE_PROTECTED_BLOCK
1652 }
1653 
1654 /**
1655  * For IAccessible2 implementation methods
1656  */
1657 STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
1658 {
1659 
1660 	CHECK_ENABLE_INF
1661     ENTER_PROTECTED_BLOCK
1662 
1663     // #CHECK#
1664     if(nRelations == NULL)
1665     {
1666         return E_INVALIDARG;
1667     }
1668 
1669     *nRelations = 0;
1670 
1671     if( !pRContext.is() )
1672         return E_FAIL;
1673     Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1674     if(!pRrelationSet.is())
1675     {
1676         *nRelations = 0;
1677         return S_OK;
1678     }
1679 
1680     *nRelations = pRrelationSet->getRelationCount();
1681     return S_OK;
1682 
1683     LEAVE_PROTECTED_BLOCK
1684 }
1685 
1686 STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
1687 {
1688 
1689 	CHECK_ENABLE_INF
1690     ENTER_PROTECTED_BLOCK
1691     ISDESTROY()
1692     // #CHECK#
1693     if(relation == NULL)
1694     {
1695         return E_INVALIDARG;
1696     }
1697 
1698     if( !pRContext.is() )
1699         return E_FAIL;
1700 
1701 
1702     long nMax = 0;
1703     long nReal = 0;
1704     get_nRelations(&nMax);
1705 
1706     *relation = (IAccessibleRelation*)::CoTaskMemAlloc(sizeof(IAccessibleRelation));
1707 
1708     // #CHECK Memory Allocation#
1709     if(*relation == NULL)
1710     {
1711         return E_FAIL;
1712     }
1713 
1714     if( relationIndex < nMax )
1715     {
1716 
1717 
1718         Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1719         if(!pRrelationSet.is())
1720         {
1721 
1722             return E_FAIL;
1723         }
1724 
1725         IAccessibleRelation* pRelation = NULL;
1726         HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
1727                                        IID_IAccessibleRelation,
1728                                        (void **)&pRelation);
1729         if(SUCCEEDED(hr))
1730         {
1731             IUNOXWrapper* wrapper = NULL;
1732             hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1733             if(SUCCEEDED(hr))
1734             {
1735                 AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
1736                 wrapper->put_XSubInterface((long)&accRelation);
1737                 wrapper->Release();
1738                 *relation = pRelation;
1739                 return S_OK;
1740             }
1741 
1742         }
1743     }
1744 
1745     return E_FAIL;
1746 
1747     LEAVE_PROTECTED_BLOCK
1748 }
1749 
1750 STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
1751 {
1752 
1753 	CHECK_ENABLE_INF
1754     ENTER_PROTECTED_BLOCK
1755 
1756     // #CHECK#
1757     if(relation == NULL || nRelations == NULL)
1758     {
1759         return E_INVALIDARG;
1760     }
1761     // #CHECK XInterface#
1762 
1763     if( !pRContext.is() )
1764         return E_FAIL;
1765 
1766     Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1767     if(!pRrelationSet.is())
1768     {
1769         *nRelations = 0;
1770         return S_OK;
1771     }
1772 
1773     long nCount = pRrelationSet->getRelationCount();
1774 
1775     *relation = (IAccessibleRelation*)::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation));
1776 
1777     // #CHECK Memory Allocation#
1778     if(*relation == NULL)
1779     {
1780         return E_FAIL;
1781     }
1782 
1783     for(int i=0; i<nCount ; i++)
1784     {
1785         IAccessibleRelation* pRelation = NULL;
1786         HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
1787                                        IID_IAccessibleRelation,
1788                                        (void **)&pRelation);
1789         if(SUCCEEDED(hr))
1790         {
1791             IUNOXWrapper* wrapper = NULL;
1792             hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1793             if(SUCCEEDED(hr))
1794             {
1795                 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1796                 wrapper->put_XSubInterface((long)&accRelation);
1797                 wrapper->Release();
1798             }
1799             (relation)[i] = pRelation;
1800         }
1801     }
1802 
1803     *nRelations = nCount;
1804     return S_OK;
1805 
1806     LEAVE_PROTECTED_BLOCK
1807 }
1808 
1809 STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
1810 {
1811     ENTER_PROTECTED_BLOCK
1812 
1813     (*role) = m_iRole;
1814 
1815     return S_OK;
1816 
1817     LEAVE_PROTECTED_BLOCK
1818 }
1819 
1820 
1821 STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
1822 {
1823 
1824     try
1825     {
1826         ISDESTROY()
1827         // #CHECK#
1828         if(nActions == NULL)
1829         {
1830             return E_INVALIDARG;
1831         }
1832         *nActions = 0L;
1833         IAccessibleAction* pAcc = NULL;
1834         HRESULT hr = QueryInterface(IID_IAccessibleAction, (void**)&pAcc);
1835         if( hr == S_OK )
1836         {
1837             pAcc->nActions(nActions);
1838             pAcc->Release();
1839         }
1840 
1841         return S_OK;
1842     }
1843     catch(...)
1844     {
1845         *nActions = 0L;
1846         return S_OK;
1847     }
1848 }
1849 
1850 
1851 STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
1852 {
1853 
1854     ENTER_PROTECTED_BLOCK
1855     ISDESTROY()
1856     return E_NOTIMPL;
1857     LEAVE_PROTECTED_BLOCK
1858 
1859 }
1860 STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
1861 {
1862 
1863     ENTER_PROTECTED_BLOCK
1864     ISDESTROY()
1865 
1866     return E_NOTIMPL;
1867 
1868     LEAVE_PROTECTED_BLOCK
1869 }
1870 
1871 static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
1872 {
1873     // #CHECK#
1874     if(pXAcc == NULL)
1875     {
1876         return NULL;
1877     }
1878     Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
1879     Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1880     long nRelations = pRrelationSet->getRelationCount();
1881     for(int i=0 ; i<nRelations ; i++)
1882     {
1883         AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1884         if(accRelation.RelationType == 7)
1885         {
1886             Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1887             return (XAccessible*)xTargets[0].get();
1888         }
1889     }
1890     return NULL;
1891 }
1892 
1893 STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
1894 {
1895 
1896 	CHECK_ENABLE_INF
1897     ENTER_PROTECTED_BLOCK
1898     ISDESTROY()
1899     // #CHECK#
1900     if(groupLevel == NULL || similarItemsInGroup == NULL || positionInGroup == NULL)
1901     {
1902         return E_INVALIDARG;
1903     }
1904 
1905     Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
1906     if(!pRContext.is())
1907         return E_FAIL;
1908     long Role = pRContext->getAccessibleRole();
1909 
1910     *groupLevel = 0;
1911     *similarItemsInGroup = 0;
1912     *positionInGroup = 0;
1913 
1914     if (Role != AccessibleRole::DOCUMENT)
1915     {
1916         Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
1917         if ( xGroupPosition.is() )
1918         {
1919             Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
1920             sal_Int32* pSeq = rSeq.getArray();
1921             if ( pSeq )
1922             {
1923                 *groupLevel = pSeq[0];
1924                 *similarItemsInGroup = pSeq[1];
1925                 *positionInGroup = pSeq[2];
1926                 return S_OK;
1927             }
1928             return S_OK;
1929         }
1930     }
1931 
1932     Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
1933     if( !pParentAcc.is() )
1934     {
1935         return S_OK;
1936     }
1937 
1938     Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
1939 
1940     int level = 0;
1941     int index = 0;
1942     int number = 0;
1943 
1944     if( Role ==  RADIO_BUTTON )
1945     {
1946         Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1947         long nRel = pRrelationSet->getRelationCount();
1948         for(int i=0 ; i<nRel ; i++)
1949         {
1950             AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1951             if(accRelation.RelationType == 7)
1952             {
1953                 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1954                 int nCount = xTargets.getLength();
1955 
1956                 Reference<XInterface> pRAcc = xTargets[0];
1957                 for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
1958                 {
1959                     if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
1960                             == (XAccessible*)pRAcc.get() &&
1961                             pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
1962                         number++;
1963                     if(pRParentContext->getAccessibleChild(j).get() == pUNOInterface)
1964                         index = number;
1965                 }
1966             }
1967         }
1968         *groupLevel = 1;
1969         *similarItemsInGroup = number;
1970         *positionInGroup = index;
1971         return S_OK;
1972     }
1973 
1974     else if ( COMBO_BOX == Role )
1975     {
1976         *groupLevel = 1;
1977         *similarItemsInGroup = 0;
1978         *positionInGroup = -1;
1979 
1980         long nCount = pRContext->getAccessibleChildCount();
1981         if( 2 != nCount)
1982         {
1983             return S_OK;
1984         }
1985         Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
1986         if (!xList.is())
1987         {
1988             return S_OK;
1989         }
1990         Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
1991         if (!xListContext.is())
1992         {
1993             return S_OK;
1994         }
1995         Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
1996         if (!xListSel.is())
1997         {
1998             return S_OK;
1999         }
2000         *similarItemsInGroup = xListContext->getAccessibleChildCount();
2001         if (*similarItemsInGroup > 0 )
2002         {
2003             try
2004             {
2005                 Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
2006                 if (xChild.is())
2007                 {
2008                     Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
2009                     if (xChildContext.is())
2010                     {
2011                         *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
2012                         return S_OK;
2013                     }
2014                 }
2015             }
2016             catch(...)
2017             {}
2018         }
2019         return S_OK;
2020     }
2021     else if ( PAGE_TAB == Role )
2022     {
2023         *groupLevel = 1;
2024         *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2025 
2026         if (*similarItemsInGroup > 0 )
2027         {
2028             *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
2029         }
2030         else
2031         {
2032             *positionInGroup = -1;
2033         }
2034         return S_OK;
2035     }
2036 
2037 
2038     BOOL isFound = FALSE;
2039     while( pParentAcc.is() && !isFound)
2040     {
2041         level++;
2042         pRParentContext = pParentAcc->getAccessibleContext();
2043         Role = pRParentContext->getAccessibleRole();
2044         if( (Role == TREE) || (Role == LIST) )
2045             isFound = TRUE;
2046         pParentAcc = pRParentContext->getAccessibleParent();
2047     }
2048 
2049     if( isFound )
2050     {
2051         Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
2052         pRParentContext = pTempAcc->getAccessibleContext();
2053         *groupLevel = level;
2054         *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2055         *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
2056     }
2057     else
2058     {
2059         *groupLevel = 0;
2060         *similarItemsInGroup = 0;
2061         *positionInGroup = 0;
2062     }
2063     return S_OK;
2064 
2065     LEAVE_PROTECTED_BLOCK
2066 }
2067 
2068 STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
2069 {
2070 
2071 	CHECK_ENABLE_INF
2072     ENTER_PROTECTED_BLOCK
2073     ISDESTROY()
2074 
2075     return E_NOTIMPL;
2076 
2077     LEAVE_PROTECTED_BLOCK
2078 }
2079 
2080 
2081 STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
2082 {
2083 
2084     ENTER_PROTECTED_BLOCK
2085     ISDESTROY()
2086     // #CHECK#
2087     if(uniqueID == NULL)
2088     {
2089         return E_INVALIDARG;
2090     }
2091     *uniqueID = m_dChildID;
2092     return S_OK;
2093 
2094     LEAVE_PROTECTED_BLOCK
2095 }
2096 
2097 STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
2098 {
2099 
2100     ENTER_PROTECTED_BLOCK
2101     ISDESTROY()
2102     // #CHECK#
2103     if(windowHandle == NULL)
2104     {
2105         return E_INVALIDARG;
2106     }
2107 
2108     HWND nHwnd = m_hwnd;
2109     IAccessible* pParent = m_pIParent;
2110     CMAccessible* pChild = this;
2111     while((nHwnd==0) && pParent)
2112     {
2113         pChild = (CMAccessible*)pParent;
2114         if(pChild)
2115         {
2116             pParent = (IAccessible*)pChild->m_pIParent;
2117             nHwnd = (HWND)pChild->m_hwnd;
2118         }
2119         else
2120             pParent = NULL;
2121     }
2122 
2123     *windowHandle = nHwnd;
2124     return S_OK;
2125 
2126     LEAVE_PROTECTED_BLOCK
2127 }
2128 
2129 /**
2130  * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2131  * @param	pXAcc, UNO XAccessible object point.
2132  * @return   XAccessibleContext*, the context of the pXAcc.
2133  */
2134 XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
2135 {
2136         Reference< XAccessibleContext > pRContext;
2137     if( pXAcc == NULL)
2138         return NULL;
2139 
2140     pRContext = pXAcc->getAccessibleContext();
2141     if( !pRContext.is() )
2142         return NULL;
2143     return pRContext.get();
2144 }
2145 
2146 /**
2147  * Return the member variable m_pXAccessibleSelection, instead of
2148  * get XAccessibleSelection according to XAccessibleContext because if so,it will
2149  * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2150  * by bridge management system
2151  * @return   XAccessibleSelection*, the selection of the current object.
2152  */
2153 Reference< XAccessibleSelection > CMAccessible::GetSelection()
2154 {
2155         if( pUNOInterface == NULL )
2156         return NULL;
2157     Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
2158     if(pRContext.is())
2159     {
2160         Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
2161         return pRSelection;
2162     }
2163     return NULL;
2164 }
2165 
2166 /**
2167  * Select one XAccessible item, for accSelect implementation
2168  * @param	pItem, the item should be selected.
2169  * @return  S_OK if successful.
2170  */
2171 HRESULT CMAccessible::SelectChild(XAccessible* pItem)
2172 {
2173 
2174     ENTER_PROTECTED_BLOCK
2175     ISDESTROY()
2176     XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
2177     XAccessibleContext* pContext = GetContextByXAcc( pItem );
2178     if( pParentContext == NULL || pContext == NULL )
2179         return E_FAIL;
2180 
2181     Reference< XAccessibleSelection > pRSelection = GetSelection();
2182     if( !pRSelection.is() )
2183         return E_FAIL;
2184     long Index = pContext->getAccessibleIndexInParent();
2185     pRSelection->selectAccessibleChild( Index );
2186     return S_OK;
2187 
2188     LEAVE_PROTECTED_BLOCK
2189 }
2190 
2191 /**
2192  * Deselect one XAccessible item, for accSelect implimentation
2193  * @param	pItem, the item should be deselected.
2194  * @return  S_OK if successful.
2195  */
2196 HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
2197 {
2198 
2199     ENTER_PROTECTED_BLOCK
2200     ISDESTROY()
2201     XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
2202     ;
2203     XAccessibleContext* pContext = GetContextByXAcc( pItem );
2204     if( pParentContext == NULL || pContext == NULL )
2205         return E_INVALIDARG;
2206 
2207     Reference< XAccessibleSelection > pRSelection = GetSelection();
2208     if( !pRSelection.is() )
2209         return E_FAIL;
2210     long Index = pContext->getAccessibleIndexInParent();
2211     pRSelection->deselectAccessibleChild( Index );
2212 
2213     return S_OK;
2214 
2215     LEAVE_PROTECTED_BLOCK
2216 }
2217 
2218 /**
2219  * Select multiple XAccessible items,for implementation of accSelect
2220  * @param	pItem, the items should be selected.
2221  * @param	size, the size of the items.
2222  * @return  S_OK if successful.
2223  */
2224 HRESULT	CMAccessible::SelectMutipleChidren( XAccessible** pItem,int size )
2225 {
2226 
2227     ENTER_PROTECTED_BLOCK
2228     ISDESTROY()
2229     // #CHECK#
2230     if(pItem == NULL)
2231     {
2232         return E_INVALIDARG;
2233     }
2234     for(int index = 0;index < size;index++)
2235     {
2236         SelectChild( pItem[index] );
2237     }
2238     return S_OK;
2239 
2240     LEAVE_PROTECTED_BLOCK
2241 }
2242 
2243 /**
2244  * Deselect multiple XAccessible items,for implementation of accSelect
2245  * @param	pItem, the items should be selected.
2246  * @param	size, the size of the items.
2247  * @return  S_OK if successful.
2248  */
2249 HRESULT CMAccessible::DeSelectMutipleChildren( XAccessible** pItem,int size )
2250 {
2251 
2252     ENTER_PROTECTED_BLOCK
2253     ISDESTROY()
2254     // #CHECK#
2255     if(pItem == NULL)
2256     {
2257         return E_INVALIDARG;
2258     }
2259     for(int index = 0;index < size;index++)
2260     {
2261         DeSelectChild( pItem[index] );
2262     }
2263     return S_OK;
2264 
2265     LEAVE_PROTECTED_BLOCK
2266 }
2267 
2268 /**
2269  * When COM is created, UNO set XAccessible pointer to it
2270  * in order to COM can operate UNO information
2271  * @param	pXAcc, the XAccessible object of current object.
2272  * @return  S_OK if successful.
2273  */
2274 STDMETHODIMP CMAccessible::SetXAccessible(long pXAcc)
2275 {
2276     pUNOInterface = (XAccessible*)pXAcc;
2277     pRef = pUNOInterface;
2278     m_pEnumVar->PutSelection(/*XAccessibleSelection*/(long)pUNOInterface);
2279 
2280     pRContext = pUNOInterface->getAccessibleContext();
2281     pRContextInterface = (XAccessibleContext*)pRContext.is();
2282 
2283     return S_OK;
2284 }
2285 
2286 /**
2287  * accSelect method has many optional flags, needs to process comprehensively
2288  * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2289  * The implementation of this flag is a little trouble-shooting,so we also
2290  * do not implement it now
2291  * @param	flagsSelect, the selection flag of the select action.
2292  * @param	varChild, the child object pointer of current action.
2293  * @return  S_OK if successful.
2294  */
2295 STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
2296 {
2297 
2298 	CHECK_ENABLE_INF
2299     ENTER_PROTECTED_BLOCK
2300     ISDESTROY()
2301     if( (flagsSelect&SELFLAG_ADDSELECTION) &&
2302             (SELFLAG_REMOVESELECTION&flagsSelect) )
2303         return E_INVALIDARG;
2304 
2305     if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
2306             (
2307                 (flagsSelect&SELFLAG_ADDSELECTION) ||
2308                 (flagsSelect&SELFLAG_REMOVESELECTION) ||
2309                 (flagsSelect&SELFLAG_EXTENDSELECTION )
2310             )
2311        )
2312         return E_INVALIDARG;
2313 
2314     if ( varChild.vt !=	VT_I4 )
2315         return E_INVALIDARG;
2316 
2317     IMAccessible* pSelectAcc;
2318     if( varChild.lVal == CHILDID_SELF )
2319     {
2320         pSelectAcc = this;
2321         pSelectAcc->AddRef();
2322     }
2323     else
2324     {
2325         pSelectAcc = GetChildInterface(varChild.lVal);
2326     }
2327 
2328     if( pSelectAcc == NULL )
2329         return E_INVALIDARG;
2330 
2331     if( flagsSelect&SELFLAG_TAKEFOCUS )
2332     {
2333         long pTempUNO = 0;
2334         pSelectAcc->GetUNOInterface( &pTempUNO);
2335 
2336         if( pTempUNO == NULL )
2337             return NULL;
2338 
2339         Reference< XAccessibleContext > pRContext = ( (XAccessible*)pTempUNO)->getAccessibleContext();
2340         Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
2341         Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
2342         Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
2343         Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
2344         Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
2345 
2346 
2347         pRComponent->grabFocus();
2348 
2349         if( flagsSelect & SELFLAG_TAKESELECTION )
2350         {
2351             pRParentSelection->clearAccessibleSelection();
2352             pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2353         }
2354 
2355         if( flagsSelect & SELFLAG_ADDSELECTION  )
2356         {
2357             pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2358         }
2359 
2360         if( flagsSelect & SELFLAG_REMOVESELECTION )
2361         {
2362             pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2363         }
2364 
2365         if( flagsSelect & SELFLAG_EXTENDSELECTION  )
2366         {
2367             long indexInParrent = pRContext->getAccessibleIndexInParent();
2368 
2369             if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
2370                     pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
2371             {
2372                 pRParentSelection->selectAccessibleChild( indexInParrent );
2373             }
2374         }
2375 
2376     }
2377 
2378     pSelectAcc->Release();
2379     return S_OK;
2380 
2381     LEAVE_PROTECTED_BLOCK
2382 }
2383 
2384 /**
2385  * Return XAccessible interface pointer when needed
2386  * @param pXAcc, [in, out] the Uno interface of the current object.
2387  * @return S_OK if successful.
2388  */
2389 STDMETHODIMP CMAccessible::GetUNOInterface(long* pXAcc)
2390 {
2391         // #CHECK#
2392     if(pXAcc == NULL)
2393         return E_INVALIDARG;
2394 
2395     *pXAcc = (long)pUNOInterface;
2396     return S_OK;
2397 }
2398 
2399 /**
2400  * Helper method for Implementation of get_accDefaultAction
2401  * @param pAction, the default action point of the current object.
2402  * @return S_OK if successful.
2403  */
2404 STDMETHODIMP CMAccessible::SetDefaultAction(long pAction)
2405 {
2406     m_pXAction = (XAccessibleAction*)pAction;
2407     return S_OK;
2408 }
2409 
2410 /**
2411  * This method is called when AT open some UI elements initially
2412  * the UI element takes the default action defined here
2413  * @param varChild, the child id of the defaultaction.
2414  * @param pszDefaultAction,[in/out] the description of the current action.
2415  * @return S_OK if successful.
2416  */
2417 HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
2418 {
2419 
2420     ENTER_PROTECTED_BLOCK
2421     ISDESTROY()
2422     // #CHECK#
2423     if(pszDefaultAction == NULL)
2424     {
2425         return E_INVALIDARG;
2426     }
2427     if(varChild.vt==VT_I4)
2428     {
2429         if(varChild.lVal==CHILDID_SELF)
2430         {
2431             if( m_pXAction == NULL )
2432                 return DISP_E_MEMBERNOTFOUND;
2433             SAFE_SYSFREESTRING(*pszDefaultAction);
2434             *pszDefaultAction = SysAllocString(m_pszActionDescription);
2435             return S_OK;
2436         }
2437 
2438         long lVal = varChild.lVal;
2439         varChild.lVal = CHILDID_SELF;
2440         IMAccessible *pChild = this->GetChildInterface(lVal);
2441         if(!pChild)
2442             return E_FAIL;
2443         return pChild->get_accDefaultAction(varChild,pszDefaultAction);
2444     }
2445     return S_FALSE;
2446 
2447     LEAVE_PROTECTED_BLOCK
2448 }
2449 
2450 /**
2451  * AT call this method to operate application
2452  * @param varChild, the child id of the action object.
2453  * @return S_OK if successful.
2454  */
2455 HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
2456 {
2457 
2458     ENTER_PROTECTED_BLOCK
2459     ISDESTROY()
2460     if( varChild.vt != VT_I4 )
2461         return E_INVALIDARG;
2462     if( m_pXAction == NULL )
2463         return E_FAIL;
2464     if( m_pXAction->getAccessibleActionCount() == 0 )
2465         return E_FAIL;
2466 
2467     if(varChild.lVal==CHILDID_SELF)
2468     {
2469         if(m_pXAction->getAccessibleActionCount() > 0)
2470             m_pXAction->doAccessibleAction(0);
2471         return S_OK;
2472     }
2473 
2474     long lVal = varChild.lVal;
2475     varChild.lVal = CHILDID_SELF;
2476     IMAccessible *pChild = this->GetChildInterface(lVal);
2477     if(!pChild)
2478         return E_FAIL;
2479     return pChild->accDoDefaultAction( varChild );
2480 
2481     LEAVE_PROTECTED_BLOCK
2482 }
2483 
2484 /**
2485  * UNO set description information for action to COM.
2486  * @param szAction, the action description of the current object.
2487  * @return S_OK if successful.
2488  */
2489 STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
2490 {
2491 
2492     ENTER_PROTECTED_BLOCK
2493     ISDESTROY()
2494     // #CHECK#
2495     if(szAction == NULL)
2496     {
2497         return E_INVALIDARG;
2498     }
2499     SAFE_SYSFREESTRING(m_pszActionDescription );
2500     m_pszActionDescription = SysAllocString( szAction );
2501     return S_OK;
2502 
2503     LEAVE_PROTECTED_BLOCK
2504 }
2505 
2506 BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
2507 {
2508         Reference< XAccessibleContext > pRContext;
2509 
2510     switch(index)
2511     {
2512     case XI_COMPONENT:
2513         QUERYXINTERFACE(AccessibleComponent)
2514         break;
2515     case XI_TEXT:
2516         QUERYXINTERFACE(AccessibleText)
2517         break;
2518     case XI_EDITABLETEXT:
2519         QUERYXINTERFACE(AccessibleEditableText)
2520         break;
2521     case XI_TABLE:
2522         QUERYXINTERFACE(AccessibleTable)
2523         break;
2524     case XI_SELECTION:
2525         QUERYXINTERFACE(AccessibleSelection)
2526         break;
2527     case XI_EXTENDEDCOMP:
2528         QUERYXINTERFACE(AccessibleExtendedComponent)
2529         break;
2530     case XI_KEYBINDING:
2531         QUERYXINTERFACE(AccessibleKeyBinding)
2532         break;
2533     case XI_ACTION:
2534         QUERYXINTERFACE(AccessibleAction)
2535         break;
2536     case XI_VALUE:
2537         QUERYXINTERFACE(AccessibleValue)
2538         break;
2539     case XI_HYPERTEXT:
2540         QUERYXINTERFACE(AccessibleHypertext)
2541         break;
2542     case XI_HYPERLINK:
2543         QUERYXINTERFACE(AccessibleHyperlink)
2544         break;
2545     case XI_IMAGE:
2546         QUERYXINTERFACE(AccessibleImage)
2547         break;
2548     default:
2549         break;
2550     }
2551 
2552     return FALSE;
2553 }
2554 
2555 HRESULT WINAPI CMAccessible::SmartQI(void* pv, REFIID iid, void** ppvObject)
2556 {
2557     ENTER_PROTECTED_BLOCK
2558     ISDESTROY()
2559     if( ImplIsEqualGUID(iid,IID_IAccIdentity) ||
2560             ImplIsEqualGUID(iid,IID_IStdMarshalInfo) ||
2561             ImplIsEqualGUID(iid,IID_IMarshal) ||
2562             ImplIsEqualGUID(iid,IID_IExternalConnection)||
2563             ImplIsEqualGUID(iid,IID_IOleWindow))
2564         return E_FAIL;
2565 
2566 
2567     _UNO_AGGMAP_ENTRY* pMap = _GetAggEntries();
2568     while(pMap && pMap->piid)
2569     {
2570         if(ImplIsEqualGUID(iid, *pMap->piid))
2571         {
2572                         XInterface* pXI = NULL;
2573                         BOOL bFound = GetXInterfaceFromXAccessible(pUNOInterface,&pXI,pMap->XIFIndex);
2574             if(!bFound)
2575             {
2576                                 return E_FAIL;
2577             }
2578 
2579             XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
2580             if ( pIndTemp != m_containedObjects.end() )
2581             {
2582                                 return pIndTemp->second.p->QueryInterface( iid, ppvObject );
2583             }
2584             else
2585             {
2586                                 HRESULT hr = pMap->pfnCreateInstance(pv, iid, ppvObject);
2587                 if(hr == S_OK)
2588                 {
2589                     m_containedObjects.insert(XGUIDToComObjHash::value_type(*pMap->piid,(IUnknown*)*ppvObject));
2590                     IUNOXWrapper* wrapper = NULL;
2591                     ((IUnknown*)*ppvObject)->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
2592                     if(wrapper)
2593                     {
2594                         wrapper->put_XInterface((long)pUNOInterface);
2595                         wrapper->Release();
2596                     }
2597                     return S_OK;
2598                 }
2599             }
2600             return E_FAIL;
2601         }
2602         pMap++;
2603     }
2604     return E_FAIL;
2605 
2606     LEAVE_PROTECTED_BLOCK
2607 }
2608 
2609 BOOL CMAccessible::get_IAccessibleFromXAccessible(long pXAcc, IAccessible **ppIA)
2610 {
2611 
2612     ENTER_PROTECTED_BLOCK
2613 
2614     // #CHECK#
2615     if(ppIA == NULL)
2616     {
2617         return E_INVALIDARG;
2618     }
2619     BOOL isGet = FALSE;
2620     if(g_pAgent)
2621         isGet = g_pAgent->GetIAccessibleFromXAccessible((XAccessible*)pXAcc,ppIA);
2622 
2623     if(isGet)
2624         return TRUE;
2625     else
2626         return FALSE;
2627 
2628     LEAVE_PROTECTED_BLOCK
2629 }
2630 
2631 void CMAccessible::get_OLECHARFromAny(Any& pAny, OLECHAR* pChar)
2632 {
2633     // #CHECK#
2634     if(pChar == NULL)
2635         return;
2636 
2637     switch(pAny.getValueTypeClass())
2638     {
2639     case TypeClass_CHAR:
2640         {
2641             sal_Int8 val;
2642             pAny >>= val;
2643             swprintf( pChar, L"%d", val);
2644             break;
2645         }
2646     case TypeClass_BOOLEAN:
2647         {
2648             sal_Bool val;
2649             pAny >>= val;
2650             swprintf( pChar, L"%d", val);
2651             break;
2652         }
2653     case TypeClass_BYTE:
2654         {
2655             sal_Int8 val;
2656             pAny >>= val;
2657             swprintf( pChar, L"%d", val);
2658             break;
2659         }
2660     case TypeClass_SHORT:
2661         {
2662             SHORT val;
2663             pAny >>= val;
2664             swprintf( pChar, L"%d", val);
2665             break;
2666         }
2667     case TypeClass_UNSIGNED_SHORT:
2668         {
2669             USHORT val;
2670             pAny >>= val;
2671             swprintf( pChar, L"%d", val);
2672             break;
2673         }
2674     case TypeClass_LONG:
2675         {
2676             LONG val;
2677             pAny >>= val;
2678             swprintf( pChar, L"%ld", val);
2679             break;
2680         }
2681     case TypeClass_UNSIGNED_LONG:
2682         {
2683             ULONG val;
2684             pAny >>= val;
2685             swprintf( pChar, L"%ld", val);
2686             break;
2687         }
2688     case TypeClass_FLOAT:
2689         {
2690             FLOAT val;
2691             pAny >>= val;
2692             swprintf( pChar, L"%.3f", val);
2693             break;
2694         }
2695     case TypeClass_DOUBLE:
2696         {
2697             DOUBLE val;
2698             pAny >>= val;
2699             swprintf( pChar, L"%.6lf", val);
2700             break;
2701         }
2702     case TypeClass_STRING:
2703         {
2704             ::rtl::OUString val;
2705             pAny >>= val;
2706             wcscpy(pChar, val.getStr());
2707             break;
2708         }
2709     case TypeClass_SEQUENCE:
2710         {
2711             if(pAny.getValueType() == getCppuType( (Sequence< ::rtl::OUString > *)0 ) )
2712             {
2713                 Sequence < ::rtl::OUString > val;
2714                 pAny >>= val;
2715 
2716                 ::rtl::OUString pString;
2717 
2718                 int count = val.getLength();
2719 
2720                 for( int iIndex = 0;iIndex < count;iIndex++ )
2721                 {
2722                     pString += val[iIndex];
2723                 }
2724                 wcscpy(pChar, pString.getStr());
2725             }
2726             else if (pAny.getValueType() == getCppuType( (Sequence< ::com::sun::star::style::TabStop >* )0 ) )
2727             {
2728                 Sequence < ::com::sun::star::style::TabStop > val;
2729                 pAny >>= val;
2730                 int count = val.getLength();
2731 
2732                 for( int iIndex = 0;iIndex < count;iIndex++ )
2733                 {
2734                     OLECHAR pAttrs[512] = {NULL};
2735 
2736                     OLECHAR pAttrsPosition[512] = {NULL};
2737                     OLECHAR pAttrsDescimalChar[512] = {NULL};
2738                     OLECHAR pAttrsFillChar[512] = {NULL};
2739 
2740                     ::com::sun::star::style::TabStop sigleVal = val[iIndex];
2741 
2742                     swprintf( pAttrsPosition, L"Position=%ld,TabAlign=%ld",
2743                               sigleVal.Position, sigleVal.Alignment);
2744 
2745                     if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
2746                             sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
2747                         swprintf( pAttrsDescimalChar, L"DecimalChar=\\%c",sigleVal.DecimalChar);
2748                     else
2749                         swprintf( pAttrsDescimalChar, L"DecimalChar=%c",sigleVal.DecimalChar);
2750 
2751                     if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
2752                             sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
2753                         swprintf( pAttrsFillChar, L"FillChar=\\%c",sigleVal.FillChar);
2754                     else
2755                         swprintf( pAttrsFillChar, L"FillChar=%c",sigleVal.FillChar);
2756 
2757                     swprintf( pAttrs, L"%s,%s,%s,",pAttrsPosition,pAttrsDescimalChar,pAttrsFillChar);
2758 
2759                     wcscat(pChar,pAttrs);
2760                 }
2761             }
2762             break;
2763         }
2764     case TypeClass_ENUM:
2765         {
2766             if (pAny.getValueType() == getCppuType( (::com::sun::star::awt::FontSlant* )0 ) )
2767             {
2768                 com::sun::star::awt::FontSlant val;
2769                 pAny >>= val;
2770                 swprintf( pChar, L"%d", val);
2771             }
2772         }
2773     case TypeClass_STRUCT:
2774         {
2775             if (pAny.getValueType() == getCppuType( (::com::sun::star::style::LineSpacing* )0 ) )
2776             {
2777                 com::sun::star::style::LineSpacing val;
2778                 pAny >>= val;
2779                 swprintf( pChar, L"Mode=%ld,Height=%ld,", val.Mode, val.Height);
2780             }
2781             else if (pAny.getValueType() == getCppuType( (com::sun::star::accessibility::TextSegment *)0 ) )
2782             {
2783                 com::sun::star::accessibility::TextSegment val;
2784                 pAny >>= val;
2785                 ::rtl::OUString realVal(val.SegmentText);
2786                 wcscpy(pChar, realVal.getStr());
2787             }
2788             break;
2789         }
2790     case TypeClass_VOID:
2791     case TypeClass_HYPER:
2792     case TypeClass_UNSIGNED_HYPER:
2793     case TypeClass_TYPE:
2794     case TypeClass_ANY:
2795     case TypeClass_TYPEDEF:
2796     case TypeClass_UNION:
2797     case TypeClass_EXCEPTION:
2798     case TypeClass_ARRAY:
2799     case TypeClass_INTERFACE:
2800     case TypeClass_SERVICE:
2801     case TypeClass_MODULE:
2802     case TypeClass_INTERFACE_METHOD:
2803     case TypeClass_INTERFACE_ATTRIBUTE:
2804     case TypeClass_UNKNOWN:
2805     case TypeClass_PROPERTY:
2806     case TypeClass_CONSTANT:
2807     case TypeClass_CONSTANTS:
2808     case TypeClass_SINGLETON:
2809     case TypeClass_MAKE_FIXED_SIZE:
2810         break;
2811     default:
2812         break;
2813     }
2814 }
2815 
2816 void CMAccessible::get_OLECHAR4Numbering(const Any& pAny, short numberingLevel,const OUString& numberingPrefix,OLECHAR* pChar)
2817 {
2818     if(pChar == NULL)
2819         return;
2820     Reference< ::com::sun::star::container::XIndexReplace > pXIndex;
2821     if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
2822     {
2823         Any aAny = pXIndex->getByIndex(numberingLevel);
2824         Sequence< ::com::sun::star::beans::PropertyValue > aProps;
2825         aAny >>= aProps;
2826         const ::com::sun::star::beans::PropertyValue* pPropArray = aProps.getConstArray();
2827         sal_Int32 nCount = aProps.getLength();
2828         swprintf(pChar,L"Numbering:NumberingLevel=%d,",numberingLevel);
2829         for( sal_Int32 i=0; i<nCount; i++ )
2830         {
2831             ::com::sun::star::beans::PropertyValue rProp = pPropArray[i];
2832             if(	(rProp.Name.compareTo(OUString::createFromAscii("BulletChar"))==0)||
2833                     (rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)||
2834                     (rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0))
2835             {
2836                 OLECHAR propStr[512] = {NULL};
2837                 swprintf(propStr,L"%s=",rProp.Name.getStr());
2838                 OLECHAR pTemp[256] = {NULL};
2839                 CMAccessible::get_OLECHARFromAny(rProp.Value,pTemp);
2840                 if(rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)
2841                 {
2842                     OLECHAR* pOccur = wcschr(pTemp,':');
2843                     if(pOccur)
2844                         *pOccur = '.';
2845                 }
2846                 wcscat(propStr,pTemp);
2847                 wcscat(pChar,propStr);
2848                 wcscat(pChar,L",");
2849 
2850                 if(rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0)
2851                 {
2852                     if(numberingPrefix.getLength()!=0)
2853                     {
2854                         swprintf(pTemp,L"NumberingPrefix=%s,",numberingPrefix.getStr());
2855                         wcscat(pChar,pTemp);
2856                     }
2857                 }
2858             }
2859         }
2860     }
2861 
2862     //Because now have three types numbering level:
2863     //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2864     //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2865     //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2866     // IAText:numberinglevel base on 0, but TOC's level base on 1,
2867     // so NumberingLevel value will be decreased 1 in bridge code.
2868     else if(numberingLevel >0)
2869     {
2870         swprintf(pChar,L"Numbering:NumberingLevel=%d,NumberingType=4,NumberingPrefix=,",numberingLevel-1);
2871     }
2872     else
2873     {
2874         swprintf(pChar,L"Numbering:");
2875     }
2876 }
2877 
2878 void CMAccessible::ConvertAnyToVariant(const ::com::sun::star::uno::Any &rAnyVal, VARIANT *pvData)
2879 {
2880     if(rAnyVal.hasValue())
2881     {
2882         // Clear VARIANT variable.
2883         VariantClear(pvData);
2884 
2885         // Set value according to value type.
2886         switch(rAnyVal.getValueTypeClass())
2887         {
2888         case TypeClass_CHAR:
2889             pvData->vt = VT_UI1;
2890             memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
2891             break;
2892 
2893         case TypeClass_BOOLEAN:
2894             pvData->vt = VT_BOOL;
2895             memcpy(&pvData->boolVal, rAnyVal.getValue(), sizeof(sal_Bool));
2896             break;
2897 
2898         case TypeClass_BYTE:
2899             pvData->vt = VT_UI1;
2900             memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
2901             break;
2902 
2903         case TypeClass_SHORT:
2904             pvData->vt = VT_I2;
2905             memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
2906             break;
2907 
2908         case TypeClass_UNSIGNED_SHORT:
2909             pvData->vt = VT_I2;
2910             memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
2911             break;
2912 
2913         case TypeClass_LONG:
2914             pvData->vt = VT_I4;
2915             memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
2916             break;
2917 
2918         case TypeClass_UNSIGNED_LONG:
2919             pvData->vt = VT_I4;
2920             memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
2921             break;
2922 
2923         case TypeClass_FLOAT:
2924             pvData->vt = VT_R4;
2925             memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
2926             break;
2927 
2928         case TypeClass_DOUBLE:
2929             pvData->vt = VT_R8;
2930             memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
2931             break;
2932 
2933         case TypeClass_STRING:
2934             {
2935                 pvData->vt = VT_BSTR;
2936                 ::rtl::OUString val;
2937                 rAnyVal >>= val;
2938                 pvData->bstrVal = SysAllocString((OLECHAR *)val.getStr());
2939                 break;
2940             }
2941 
2942         case TypeClass_VOID:
2943         case TypeClass_HYPER:
2944         case TypeClass_UNSIGNED_HYPER:
2945         case TypeClass_TYPE:
2946         case TypeClass_ANY:
2947         case TypeClass_ENUM:
2948         case TypeClass_TYPEDEF:
2949         case TypeClass_STRUCT:
2950         case TypeClass_UNION:
2951         case TypeClass_EXCEPTION:
2952         case TypeClass_SEQUENCE:
2953         case TypeClass_ARRAY:
2954         case TypeClass_INTERFACE:
2955             {
2956                 Reference< XAccessible > pXAcc;
2957                 if(rAnyVal >>= pXAcc)
2958                 {
2959                     if(pXAcc.is())
2960                     {
2961                         IAccessible* pIAcc = NULL;
2962                         get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
2963                         if(pIAcc == NULL)
2964                         {
2965                             Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
2966                             g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
2967                             get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
2968                         }
2969                         if(pIAcc)
2970                         {
2971                             pIAcc->AddRef();
2972 
2973                             pvData->vt = VT_UNKNOWN;
2974                             pvData->pdispVal = (IAccessible2*)pIAcc;
2975                             break;
2976                         }
2977                     }
2978                 }
2979             }
2980         case TypeClass_SERVICE:
2981         case TypeClass_MODULE:
2982         case TypeClass_INTERFACE_METHOD:
2983         case TypeClass_INTERFACE_ATTRIBUTE:
2984         case TypeClass_UNKNOWN:
2985         case TypeClass_PROPERTY:
2986         case TypeClass_CONSTANT:
2987         case TypeClass_CONSTANTS:
2988         case TypeClass_SINGLETON:
2989         case TypeClass_MAKE_FIXED_SIZE:
2990             // Output the type string, if there is other uno value type.
2991             pvData->vt = VT_BSTR;
2992             pvData->bstrVal = SysAllocString(rAnyVal.getValueTypeName().getStr());
2993             break;
2994 
2995         default:
2996             break;
2997         }
2998     }
2999     else
3000     {
3001         VariantClear(pvData);
3002     }
3003 }
3004 
3005 STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
3006 {
3007     // #CHECK#
3008     if(childID == NULL)
3009     {
3010         return E_FAIL;
3011     }
3012     *childID = m_dChildID;
3013     return S_OK;
3014 }
3015 STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
3016 {
3017 
3018 	CHECK_ENABLE_INF
3019     ENTER_PROTECTED_BLOCK
3020     ISDESTROY()
3021     // #CHECK XInterface#
3022     if( !pRContext.is() )
3023         return E_FAIL;
3024 
3025     Reference<XAccessibleStateSet> pRStateSet = pRContext.get()->getAccessibleStateSet();
3026     if(!pRStateSet.is())
3027     {
3028         return S_OK;
3029     }
3030     Sequence<short> pStates = pRStateSet->getStates();
3031 
3032 
3033     long count = pStates.getLength() ;
3034     *states = 0x0;
3035     for( int i = 0; i < count; i++  )
3036     {
3037         for( int j = 0; j < sizeof(UNO_STATES) / sizeof(UNO_STATES[0]); j++ )
3038         {
3039             if( pStates[i] == UNO_STATES[j] )
3040             {
3041                 *states |= IA2_STATES[j];
3042                 break;
3043             }
3044         }
3045     }
3046     return S_OK;
3047 
3048 
3049     LEAVE_PROTECTED_BLOCK
3050 }
3051 
3052 // return the UNO roles
3053 STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR *  )
3054 {
3055 
3056 	CHECK_ENABLE_INF
3057     ENTER_PROTECTED_BLOCK
3058     ISDESTROY()
3059 
3060     return E_NOTIMPL;
3061 
3062     LEAVE_PROTECTED_BLOCK
3063 }
3064 
3065 STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR *  )
3066 {
3067 
3068     ENTER_PROTECTED_BLOCK
3069     ISDESTROY()
3070     return E_NOTIMPL;
3071 
3072     LEAVE_PROTECTED_BLOCK
3073 }
3074 STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
3075 {
3076 
3077 	CHECK_ENABLE_INF
3078     ENTER_PROTECTED_BLOCK
3079     ISDESTROY()
3080 
3081     return E_NOTIMPL;
3082 
3083     LEAVE_PROTECTED_BLOCK
3084 }
3085 
3086 
3087 STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
3088 {
3089 
3090     ENTER_PROTECTED_BLOCK
3091     ISDESTROY()
3092     return E_NOTIMPL;
3093 
3094     LEAVE_PROTECTED_BLOCK
3095 }
3096 
3097 
3098 STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
3099 {
3100 
3101 	CHECK_ENABLE_INF
3102     ENTER_PROTECTED_BLOCK
3103     ISDESTROY()
3104     // #CHECK#
3105     if(accParentIndex == NULL)
3106         return E_INVALIDARG;
3107 
3108     // #CHECK XInterface#
3109     if( !pRContext.is() )
3110         return E_FAIL;
3111 
3112     *accParentIndex = pRContext.get()->getAccessibleIndexInParent();
3113     return S_OK;
3114 
3115 
3116     LEAVE_PROTECTED_BLOCK
3117 }
3118 STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale  )
3119 {
3120 
3121 	CHECK_ENABLE_INF
3122     ENTER_PROTECTED_BLOCK
3123     ISDESTROY()
3124     if(locale == NULL)
3125         return E_INVALIDARG;
3126     // #CHECK XInterface#
3127 
3128     if( !pRContext.is() )
3129         return E_FAIL;
3130 
3131     ::com::sun::star::lang::Locale unoLoc = pRContext.get()->getLocale();
3132     locale->language = SysAllocString((OLECHAR*)unoLoc.Language.getStr());
3133     locale->country = SysAllocString((OLECHAR*)unoLoc.Country.getStr());
3134     locale->variant = SysAllocString((OLECHAR*)unoLoc.Variant.getStr());
3135 
3136     return S_OK;
3137 
3138     LEAVE_PROTECTED_BLOCK
3139 }
3140 
3141 DWORD GetMSAAStateFromUNO(short xState)
3142 {
3143     DWORD IState = STATE_SYSTEM_UNAVAILABLE;
3144     switch( xState )
3145     {
3146     case /*AccessibleStateType::*/AccessibleStateType::BUSY:
3147         IState = STATE_SYSTEM_BUSY;
3148         break;
3149     case /*AccessibleStateType::*/AccessibleStateType::CHECKED:
3150         IState = STATE_SYSTEM_CHECKED;
3151         break;
3152     case /*AccessibleStateType::*/AccessibleStateType::DEFUNC:
3153         IState = STATE_SYSTEM_UNAVAILABLE;
3154         break;
3155     case /*AccessibleStateType::*/AccessibleStateType::EXPANDED:
3156         IState = STATE_SYSTEM_EXPANDED;
3157         break;
3158     case /*AccessibleStateType::*/AccessibleStateType::FOCUSABLE:
3159         IState = STATE_SYSTEM_FOCUSABLE;
3160         break;
3161     case /*AccessibleStateType::*/AccessibleStateType::FOCUSED:
3162         IState = STATE_SYSTEM_FOCUSED;
3163         break;
3164     case /*AccessibleStateType::*/AccessibleStateType::INDETERMINATE:
3165         IState = STATE_SYSTEM_MIXED;
3166         break;
3167     case /*AccessibleStateType::*/AccessibleStateType::MULTI_SELECTABLE:
3168         IState = STATE_SYSTEM_MULTISELECTABLE;
3169         break;
3170     case /*AccessibleStateType::*/AccessibleStateType::PRESSED:
3171         IState = STATE_SYSTEM_PRESSED;
3172         break;
3173     case /*AccessibleStateType::*/AccessibleStateType::RESIZABLE:
3174         IState = STATE_SYSTEM_SIZEABLE;
3175         break;
3176     case /*AccessibleStateType::*/AccessibleStateType::SELECTABLE:
3177         IState = STATE_SYSTEM_SELECTABLE;
3178         break;
3179     case /*AccessibleStateType::*/AccessibleStateType::SELECTED:
3180         IState = STATE_SYSTEM_SELECTED;
3181         break;
3182     case /*AccessibleStateType::*/AccessibleStateType::ARMED:
3183         IState = STATE_SYSTEM_FOCUSED;
3184         break;
3185     case /*AccessibleStateType::*/AccessibleStateType::EXPANDABLE:
3186         IState = STATE_SYSTEM_COLLAPSED;
3187         break;
3188     default:
3189         break;
3190     }
3191     return IState;
3192 }
3193 
3194 STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
3195 {
3196 
3197     ENTER_PROTECTED_BLOCK
3198     ISDESTROY()
3199     if(name == NULL)
3200         return E_INVALIDARG;
3201 
3202     *name = SysAllocString(OLESTR("Hannover"));
3203     return S_OK;
3204     LEAVE_PROTECTED_BLOCK
3205 }
3206 STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
3207 {
3208 
3209     ENTER_PROTECTED_BLOCK
3210     ISDESTROY()
3211     if(version == NULL)
3212         return E_INVALIDARG;
3213     *version=SysAllocString(OLESTR("3.0"));
3214     return S_OK;
3215     LEAVE_PROTECTED_BLOCK
3216 }
3217 STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
3218 {
3219 
3220     ENTER_PROTECTED_BLOCK
3221     ISDESTROY()
3222     if(name == NULL)
3223         return E_INVALIDARG;
3224     *name = SysAllocString(OLESTR(" "));
3225     return S_OK;
3226     LEAVE_PROTECTED_BLOCK
3227 }
3228 STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
3229 {
3230 
3231     ENTER_PROTECTED_BLOCK
3232     ISDESTROY()
3233     if(version == NULL)
3234         return E_INVALIDARG;
3235     *version = SysAllocString(OLESTR(" "));
3236     return S_OK;
3237     LEAVE_PROTECTED_BLOCK
3238 }
3239 
3240 
3241 STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
3242 {
3243 	CHECK_ENABLE_INF
3244     Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
3245     if( !pRContext.is() )
3246     {
3247         return E_FAIL;
3248     }
3249     Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
3250     if( !pRXI.is() )
3251         return E_FAIL;
3252     else
3253     {
3254         com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleExtendedAttributes> pRXAttr;
3255         pRXAttr = pRXI.get();
3256         ::com::sun::star::uno::Any	anyVal = pRXAttr->getExtendedAttributes();
3257 
3258         ::rtl::OUString val;
3259         anyVal >>= val;
3260 
3261         if(*pAttr)
3262             SAFE_SYSFREESTRING(*pAttr);
3263         *pAttr = SysAllocString((OLECHAR *)val.getStr());
3264 
3265         return S_OK;
3266     }
3267 }
3268 
3269