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