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