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