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