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