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