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