Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / winaccessibility / source / UAccCOM / MAccessible.cxx
blobedbc31b78ad48131ae82368bac8d57aa029e67d8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "stdafx.h"
21 #include "MAccessible.h"
23 #if defined __clang__
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
26 #endif
27 #include "UAccCOM.h"
28 #if defined __clang__
29 #pragma clang diagnostic pop
30 #endif
32 #include <algorithm>
33 #include <cstddef>
35 #include "AccAction.h"
36 #include "AccRelation.h"
37 #include "AccComponent.h"
38 #include "AccText.h"
39 #include "AccEditableText.h"
40 #include "AccImage.h"
41 #include "AccTable.h"
42 #include "AccValue.h"
43 #include "AccHypertext.h"
44 #include "AccHyperLink.h"
46 #include <vcl/svapp.hxx>
48 #include <com/sun/star/accessibility/XAccessibleText.hpp>
49 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
50 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
51 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
52 #include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
53 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
54 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
55 #include <com/sun/star/accessibility/XAccessibleHyperText.hpp>
56 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
57 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
58 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
59 #include <com/sun/star/accessibility/AccessibleRole.hpp>
60 #include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
61 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
62 #include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
63 #include <com/sun/star/style/LineSpacing.hpp>
64 #include <com/sun/star/style/TabStop.hpp>
65 #include <com/sun/star/container/XIndexReplace.hpp>
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::accessibility;
70 using namespace com::sun::star::accessibility::AccessibleStateType;
72 enum XInterfaceIndex {
73 XI_COMPONENT = 0x01,
74 XI_TEXT = 0x02,
75 XI_TABLE = 0x03,
76 XI_EDITABLETEXT = 0x04,
77 XI_IMAGE = 0x05,
78 XI_SELECTION = 0x06,
79 XI_EXTENDEDCOMP = 0x07,
80 XI_VALUE = 0x08,
81 XI_KEYBINDING = 0x09,
82 XI_ACTION = 0x0A,
83 XI_HYPERTEXT = 0x0B,
84 XI_HYPERLINK = 0x0C,
85 XI_ATTRIBUTE = 0x0D,
86 XI_NULL = -1
89 // IA2 states mapping, and name
90 // maintenance the consistency, change one array, change the three all
91 long IA2_STATES[] =
93 IA2_STATE_ACTIVE, // = 0x1;
94 IA2_STATE_ARMED, // = 0x2;
95 IA2_STATE_DEFUNCT, // = 0x4;
96 IA2_STATE_EDITABLE, // = 0x8;
97 IA2_STATE_HORIZONTAL, // = 0x10;
98 IA2_STATE_ICONIFIED, // = 0x20;
99 IA2_STATE_INVALID_ENTRY, // = 0x80;
100 IA2_STATE_MANAGES_DESCENDANTS, // = 0x100;
101 IA2_STATE_MODAL, // = 0x200;
102 IA2_STATE_MULTI_LINE, // = 0x400;
103 IA2_STATE_OPAQUE, // = 0x800;
104 IA2_STATE_REQUIRED, // = 0x2000;
105 IA2_STATE_SELECTABLE_TEXT, // = 0x3000;
106 IA2_STATE_SINGLE_LINE, // = 0x4000;
107 IA2_STATE_STALE, // = 0x8000;
108 IA2_STATE_SUPPORTS_AUTOCOMPLETION, // = 0x10000;
109 IA2_STATE_TRANSIENT, //= 0x20000;
110 IA2_STATE_VERTICAL // = 0x40000;
114 <=== map ===>
117 short UNO_STATES[] =
119 ACTIVE, // = (sal_Int16)1;
120 ARMED, // = (sal_Int16)2;
121 DEFUNC, // = (sal_Int16)5;
122 EDITABLE, // = (sal_Int16)6;
123 HORIZONTAL, // = (sal_Int16)12;
124 ICONIFIED, // = (sal_Int16)13;
125 -1, //IA2_STATE_INVALID_ENTRY
126 MANAGES_DESCENDANTS, // = (sal_Int16)15;
127 MODAL, // = (sal_Int16)16;
128 MULTI_LINE, // = (sal_Int16)17;
129 OPAQUE, // = (sal_Int16)19;
130 -1, //IA2_STATE_REQUIRED
131 -1, //IA2_STATE_SELECTABLE_TEXT
132 SINGLE_LINE, // = (sal_Int16)26;
133 STALE, // = (sal_Int16)27;
134 -1, //IA2_STATE_SUPPORTS_AUTOCOMPLETION
135 TRANSIENT, //IA2_STATE_TRANSIENT
136 VERTICAL // = (sal_Int16)29;
139 using namespace com::sun::star::accessibility::AccessibleRole;
142 #define QUERYXINTERFACE(ainterface) \
144 if(pXAcc == NULL) \
145 return FALSE; \
146 pRContext = pXAcc->getAccessibleContext(); \
147 if( !pRContext.is() ) \
149 return FALSE; \
151 Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
152 if( !pRXI.is() ) \
154 return FALSE; \
156 *ppXI = (XInterface*)pRXI.get(); \
157 return TRUE; \
160 #define ISDESTROY() \
161 if(m_isDestroy) \
162 return S_FALSE;
165 AccObjectManagerAgent* CMAccessible::g_pAgent = NULL;
167 CMAccessible::CMAccessible():
168 m_pszName(NULL),
169 m_pszValue(NULL),
170 m_pszActionDescription(NULL),
171 m_iRole(0x00),
172 m_dState(0x00),
173 m_pszDescription(NULL),
174 m_pIParent(NULL),
175 m_dChildID(0x00),
176 m_dFocusChildID(UACC_NO_FOCUS),
177 m_hwnd(NULL),
178 m_isDestroy(FALSE),
179 m_bRequiresSave(FALSE)
181 m_sLocation.m_dLeft=0;
182 m_sLocation.m_dTop = 0;
183 m_sLocation.m_dWidth=0;
184 m_sLocation.m_dHeight=0;
185 CEnumVariant::Create(&m_pEnumVar);
186 m_containedObjects.clear();
189 CMAccessible::~CMAccessible()
191 SolarMutexGuard g;
193 if(m_pszName!=NULL)
195 SAFE_SYSFREESTRING(m_pszName);
196 m_pszName=NULL;
198 if(m_pszValue!=NULL)
200 SAFE_SYSFREESTRING(m_pszValue);
201 m_pszValue=NULL;
203 if(m_pszDescription!=NULL)
205 SAFE_SYSFREESTRING(m_pszDescription);
206 m_pszDescription=NULL;
209 if(m_pszActionDescription!=NULL)
211 SAFE_SYSFREESTRING(m_pszActionDescription);
212 m_pszActionDescription=NULL;
215 if(m_pIParent)
217 m_pIParent->Release();
218 m_pIParent=NULL;
220 m_pEnumVar->Release();
221 m_containedObjects.clear();
225 * Returns the Parent IAccessible interface pointer to AT.
226 * It should add reference, and the client should release the component.
227 * It should return E_FAIL when the parent point is null.
228 * @param ppdispParent [in,out] used to return the parent interface point.
229 * when the point is null, should return null.
230 * @return S_OK if successful and E_FAIL if the m_pIParent is NULL.
232 STDMETHODIMP CMAccessible::get_accParent(IDispatch **ppdispParent)
234 SolarMutexGuard g;
236 ENTER_PROTECTED_BLOCK
237 ISDESTROY()
238 // #CHECK#
239 if(ppdispParent == NULL)
241 return E_INVALIDARG;
244 if(m_pIParent)
246 *ppdispParent = m_pIParent;
247 (*ppdispParent)->AddRef();
248 return S_OK;
250 else if(m_hwnd)
252 HRESULT hr = AccessibleObjectFromWindow(m_hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent);
253 if( ! SUCCEEDED( hr ) || ! ppdispParent )
255 return S_FALSE;
257 return S_OK;
259 return S_FALSE;
261 LEAVE_PROTECTED_BLOCK
265 * Returns child count of current COM object.
266 * @param pcountChildren [in,out] used to return the children count.
267 * @return S_OK if successful.
269 STDMETHODIMP CMAccessible::get_accChildCount(long *pcountChildren)
271 SolarMutexGuard g;
273 ENTER_PROTECTED_BLOCK
274 ISDESTROY()
275 // #CHECK#
276 if(pcountChildren == NULL)
278 return E_INVALIDARG;
281 if (!m_xAccessible.is())
282 return S_FALSE;
284 Reference<XAccessibleContext> const pRContext =
285 m_xAccessible->getAccessibleContext();
286 if( pRContext.is() )
288 *pcountChildren = pRContext->getAccessibleChildCount();
291 return S_OK;
293 LEAVE_PROTECTED_BLOCK
297 * Returns child interface pointer for AT according to input child ID.
298 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
299 * the child ID specify child index from 0 to children count, 0 stands for object self.
300 * @param ppdispChild, [in,out] use to return the child interface point.
301 * @return S_OK if successful and S_FALSE if failure.
303 STDMETHODIMP CMAccessible::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
305 SolarMutexGuard g;
307 ENTER_PROTECTED_BLOCK
308 ISDESTROY()
309 // #CHECK#
310 if(ppdispChild == NULL)
312 return E_INVALIDARG;
314 if(varChild.vt==VT_I4)
316 //get child interface pointer due to child ID
317 if(varChild.lVal==CHILDID_SELF)
319 AddRef();
320 *ppdispChild = this;
321 return S_OK;
323 *ppdispChild = GetChildInterface(varChild.lVal);
324 if((*ppdispChild) == NULL)
325 return E_FAIL;
326 (*ppdispChild)->AddRef();
327 return S_OK;
329 return S_FALSE;
331 LEAVE_PROTECTED_BLOCK
335 * Returns the accessible name of the current COM object self or its one child to AT.
336 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
337 * the child ID specify child index from 0 to children count, 0 stands for object self.
338 * @param pszName, [in,out] use to return the name of the proper object.
339 * @return S_OK if successful and S_FALSE if failure.
341 STDMETHODIMP CMAccessible::get_accName(VARIANT varChild, BSTR *pszName)
343 SolarMutexGuard g;
345 ENTER_PROTECTED_BLOCK
346 ISDESTROY()
347 // #CHECK#
348 if(pszName == NULL)
350 return E_INVALIDARG;
352 if(varChild.vt==VT_I4)
354 if(varChild.lVal==CHILDID_SELF)
356 SAFE_SYSFREESTRING(*pszName);
357 *pszName = SysAllocString(m_pszName);
358 return S_OK;
361 long lVal = varChild.lVal;
362 varChild.lVal = CHILDID_SELF;
363 IMAccessible *pChild = this->GetChildInterface(lVal);
364 if(!pChild)
365 return E_FAIL;
366 return pChild->get_accName(varChild,pszName);
368 return S_FALSE;
370 LEAVE_PROTECTED_BLOCK
374 * Returns the accessible value of the current COM object self or its one child to AT.
375 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
376 * the child ID specify child index from 0 to children count, 0 stands for object self.
377 * @param pszValue, [in,out] use to return the value of the proper object.
378 * @return S_OK if successful and S_FALSE if failure.
380 STDMETHODIMP CMAccessible::get_accValue(VARIANT varChild, BSTR *pszValue)
382 SolarMutexGuard g;
384 ENTER_PROTECTED_BLOCK
385 ISDESTROY()
386 // #CHECK#
387 if( pszValue == NULL )
389 return E_INVALIDARG;
391 if( varChild.vt==VT_I4 )
393 if(varChild.lVal==CHILDID_SELF)
395 if(m_dState & STATE_SYSTEM_PROTECTED)
396 return E_ACCESSDENIED;
398 if ( m_pszValue !=NULL && wcslen(m_pszValue) == 0 )
399 return S_OK;
401 SAFE_SYSFREESTRING(*pszValue);
402 *pszValue = SysAllocString(m_pszValue);
403 return S_OK;
406 long lVal = varChild.lVal;
407 varChild.lVal = CHILDID_SELF;
408 IMAccessible *pChild = this->GetChildInterface(lVal);
409 if(!pChild)
410 return E_FAIL;
411 return pChild->get_accValue(varChild,pszValue);
413 return S_FALSE;
415 LEAVE_PROTECTED_BLOCK
419 * Returns the accessible description of the current COM object self or its one child to AT.
420 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
421 * the child ID specify child index from 0 to children count, 0 stands for object self.
422 * @param pszDescription, [in,out] use to return the description of the proper object.
423 * @return S_OK if successful and E_FAIL if failure.
425 STDMETHODIMP CMAccessible::get_accDescription(VARIANT varChild, BSTR *pszDescription)
427 SolarMutexGuard g;
429 ENTER_PROTECTED_BLOCK
430 ISDESTROY()
431 // #CHECK#
432 if(pszDescription == NULL)
434 return E_INVALIDARG;
436 if(varChild.vt==VT_I4)
438 if(varChild.lVal==CHILDID_SELF)
440 SAFE_SYSFREESTRING(*pszDescription);
441 *pszDescription = SysAllocString(m_pszDescription);
442 return S_OK;
445 long lVal = varChild.lVal;
446 varChild.lVal = CHILDID_SELF;
447 IMAccessible *pChild = this->GetChildInterface(lVal);
448 if(!pChild)
449 return E_FAIL;
450 return pChild->get_accDescription(varChild,pszDescription);
452 return S_FALSE;
454 LEAVE_PROTECTED_BLOCK
458 * Returns the accessible role of the current COM object self or its one child to AT.
459 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
460 * the child ID specify child index from 0 to children count, 0 stands for object self.
461 * @param pvarRole, [in,out] use to return the role of the proper object.
462 * @return S_OK if successful and S_FALSE if failure.
464 STDMETHODIMP CMAccessible::get_accRole(VARIANT varChild, VARIANT *pvarRole)
466 SolarMutexGuard g;
468 ENTER_PROTECTED_BLOCK
469 ISDESTROY()
470 // #CHECK#
471 if(pvarRole == NULL)
473 return E_INVALIDARG;
475 if(varChild.vt == VT_I4)
478 if(varChild.lVal == CHILDID_SELF)
480 if( m_iRole < IA2_ROLE_CAPTION )
482 VariantInit(pvarRole);
483 pvarRole->vt = VT_I4;
484 pvarRole->lVal = m_iRole;
486 else
488 VariantInit(pvarRole);
489 pvarRole->vt = VT_I4;
490 pvarRole->lVal = ROLE_SYSTEM_CLIENT;
492 return S_OK;
496 long lVal = varChild.lVal;
497 varChild.lVal = CHILDID_SELF;
498 IMAccessible *pChild = this->GetChildInterface(lVal);
499 if(!pChild)
500 return E_FAIL;
501 return pChild->get_accRole(varChild,pvarRole);
503 return S_FALSE;
505 LEAVE_PROTECTED_BLOCK
509 * Returns the accessible state of the current COM object self or its one child to AT.
510 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
511 * the child ID specify child index from 0 to children count, 0 stands for object self.
512 * @param pvarState, [in,out] use to return the state of the proper object.
513 * @return S_OK if successful and S_FALSE if failure.
515 STDMETHODIMP CMAccessible::get_accState(VARIANT varChild, VARIANT *pvarState)
517 SolarMutexGuard g;
519 ENTER_PROTECTED_BLOCK
520 ISDESTROY()
521 // #CHECK#
522 if(pvarState == NULL)
524 return E_INVALIDARG;
526 if(varChild.vt==VT_I4)
528 if(varChild.lVal == CHILDID_SELF)
530 if (m_xAccessible.is())
532 Reference<XAccessibleContext> const pContext =
533 m_xAccessible->getAccessibleContext();
534 if(pContext.is())
536 // add the STATE_SYSTEM_LINKED state
537 Reference< XAccessibleHypertext > pRHypertext(pContext,UNO_QUERY);
538 if(pRHypertext.is())
540 if( pRHypertext->getHyperLinkCount() > 0 )
541 m_dState |= STATE_SYSTEM_LINKED;
542 else
543 m_dState &= ~STATE_SYSTEM_LINKED;
545 else
546 m_dState &= ~STATE_SYSTEM_LINKED;
550 VariantInit(pvarState);
551 pvarState->vt = VT_I4;
552 pvarState->lVal = m_dState;
553 return S_OK;
556 long lVal = varChild.lVal;
557 varChild.lVal = CHILDID_SELF;
558 IMAccessible *pChild = this->GetChildInterface(lVal);
559 if(!pChild)
560 return E_FAIL;
561 return pChild->get_accState(varChild,pvarState);
563 return S_FALSE;
565 LEAVE_PROTECTED_BLOCK
569 * Returns the accessible helpString of the current COM object self or its one child to AT.
570 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
571 * the child ID specify child index from 0 to children count, 0 stands for object self.
572 * @param pszHelp, [in,out] use to return the helpString of the proper object.
573 * @return S_OK if successful and E_FAIL if failure.
575 STDMETHODIMP CMAccessible::get_accHelp(VARIANT, BSTR *)
577 return E_NOTIMPL;
581 * Returns the accessible HelpTopic of the current COM object self or its one child to AT.
582 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
583 * the child ID specify child index from 0 to children count, 0 stands for object self.
584 * @param pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
585 * @param pidTopic, use to return the HelpTopic ID of the proper object.
586 * @return S_OK if successful and E_FAIL if failure.
587 * Not implemented yet
589 STDMETHODIMP CMAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
591 return E_NOTIMPL;
594 static void GetMnemonicChar( const ::rtl::OUString& aStr, WCHAR* wStr)
596 int nLen = aStr.pData->length;
597 int i = 0;
598 WCHAR* text = aStr.pData->buffer;
600 while ( i < nLen )
602 if ( text[i] == L'~' )
603 if ( text[i+1] != L'~' )
605 wStr[0] = text[i+1];
606 break;
608 i++;
613 * Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
614 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
615 * the child ID specify child index from 0 to children count, 0 stands for object self.
616 * @param pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
617 * @return S_OK if successful and E_FAIL if failure.
619 STDMETHODIMP CMAccessible::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut)
621 SolarMutexGuard g;
623 ENTER_PROTECTED_BLOCK
625 ISDESTROY()
626 // #CHECK#
627 if(pszKeyboardShortcut == NULL)
629 return E_INVALIDARG;
632 if(varChild.vt==VT_I4)
634 if(varChild.lVal == CHILDID_SELF)
636 if (m_xAccessible.is())
638 Reference<XAccessibleContext> const pRContext =
639 m_xAccessible->getAccessibleContext();
640 if( !pRContext.is() )
641 return S_FALSE;
643 Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
645 OLECHAR wString[64]={0};
647 if( pRXI.is() && pRXI->getAccessibleActionCount() >= 1)
649 Reference< XAccessibleKeyBinding > binding = pRXI->getAccessibleActionKeyBinding(0);
650 if( binding.is() )
652 long nCount = binding->getAccessibleKeyBindingCount();
653 if(nCount >= 1)
655 CAccAction::GetkeyBindingStrByXkeyBinding( binding->getAccessibleKeyBinding(0),wString );
659 if(wString[0] == 0)
661 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
662 if(!pRrelationSet.is())
664 return S_FALSE;
667 long nRelCount = pRrelationSet->getRelationCount();
669 // Modified by Steve Yin, for SODC_1552
670 if( /*nRelCount <= 0 &&*/ m_iRole == ROLE_SYSTEM_TEXT )
672 VARIANT varParentRole;
673 VariantInit( &varParentRole );
675 m_pIParent->get_accRole(varChild, &varParentRole);
677 if( m_pIParent && varParentRole.lVal == ROLE_SYSTEM_COMBOBOX ) // edit in comboBox
679 m_pIParent->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
680 return S_OK;
684 AccessibleRelation *paccRelation = NULL;
685 AccessibleRelation accRelation;
686 for(int i=0; i<nRelCount ; i++)
688 if( pRrelationSet->getRelation(i).RelationType == 6 )
690 accRelation = pRrelationSet->getRelation(i);
691 paccRelation = &accRelation;
695 if(paccRelation == NULL)
696 return S_FALSE;
698 Sequence< Reference< XInterface > > xTargets = paccRelation->TargetSet;
699 Reference<XInterface> pRAcc = xTargets[0];
701 XAccessible* pXAcc = (XAccessible*)pRAcc.get();
703 Reference<XAccessibleContext> pRLebelContext = pXAcc->getAccessibleContext();
704 if(!pRLebelContext.is())
705 return S_FALSE;
707 pRrelationSet = pRLebelContext->getAccessibleRelationSet();
708 nRelCount = pRrelationSet->getRelationCount();
710 paccRelation = NULL;
711 for(int j=0; j<nRelCount ; j++)
713 if( pRrelationSet->getRelation(j).RelationType == 5 )
715 accRelation = pRrelationSet->getRelation(j);
716 paccRelation = &accRelation;
720 if(paccRelation)
722 xTargets = paccRelation->TargetSet;
723 pRAcc = xTargets[0];
724 if (m_xAccessible.get() != (XAccessible*)pRAcc.get())
725 return S_FALSE;
728 Reference<XAccessibleExtendedComponent> pRXIE(pRLebelContext,UNO_QUERY);
729 if(!pRXIE.is())
730 return S_FALSE;
732 ::rtl::OUString ouStr = pRXIE->getTitledBorderText();
733 WCHAR key[2] = {NULL};
734 GetMnemonicChar(ouStr, key);
735 if(key[0] != 0)
737 wcscat(wString, L"Alt+");
738 wcscat(wString, key);
740 else
741 return S_FALSE;
744 SAFE_SYSFREESTRING(*pszKeyboardShortcut);
745 *pszKeyboardShortcut = SysAllocString(wString);
747 return S_OK;
749 else
751 return S_FALSE;
755 long lVal = varChild.lVal;
756 varChild.lVal = CHILDID_SELF;
757 IMAccessible *pChild = this->GetChildInterface(lVal);
758 if(!pChild)
759 return E_FAIL;
761 return pChild->get_accKeyboardShortcut(varChild,pszKeyboardShortcut);
763 return S_FALSE;
765 LEAVE_PROTECTED_BLOCK
769 * Returns the current focused child to AT.
770 * @param pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
771 * the child ID specify child index from 0 to children count, 0 stands for object self.
772 * @return S_OK if successful and E_FAIL if failure.
774 STDMETHODIMP CMAccessible::get_accFocus(VARIANT *pvarChild)
776 SolarMutexGuard g;
778 ENTER_PROTECTED_BLOCK
779 ISDESTROY()
780 // #CHECK#
781 if(pvarChild == NULL)
783 return E_INVALIDARG;
785 if( m_dFocusChildID==UACC_NO_FOCUS )
787 pvarChild->vt = VT_EMPTY;//no focus on the object and its children
788 return S_OK;
790 //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
791 else
793 IMAccessible* pIMAcc = NULL;
794 g_pAgent->GetIAccessibleFromResID(m_dFocusChildID,&pIMAcc);
795 pIMAcc->AddRef();
796 pvarChild->vt = VT_DISPATCH;
797 pvarChild->pdispVal = pIMAcc;
800 return S_OK;
802 LEAVE_PROTECTED_BLOCK
806 * Returns the selection of the current COM object to AT.
807 * @param pvarChildren,[in,out]
808 * if selection num is 0,return VT_EMPTY for vt,
809 * if selection num is 1,return VT_I4 for vt,and child index for lVal
810 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
811 * @return S_OK if successful and S_FALSE if failure.
813 STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
815 SolarMutexGuard g;
817 ENTER_PROTECTED_BLOCK
818 ISDESTROY()
819 // #CHECK#
820 if(pvarChildren == NULL)
822 return E_INVALIDARG;
824 switch(m_pEnumVar->GetCountOfElements())
826 case 0:
827 pvarChildren->vt = VT_EMPTY;
828 break;
829 case 1:
830 VARIANT varTmp[1];
831 ULONG count;
832 VariantInit(&varTmp[0]);
833 m_pEnumVar->Next(1,varTmp,&count);
834 if(count!=1)
835 return S_FALSE;
836 pvarChildren->vt = VT_I4;
837 pvarChildren->lVal = varTmp[0].lVal;
838 VariantClear(&varTmp[0]);
839 m_pEnumVar->Reset();
840 break;
841 default:
842 pvarChildren->vt = VT_UNKNOWN;
843 m_pEnumVar->AddRef();
844 pvarChildren->punkVal = m_pEnumVar;
845 break;
847 return S_OK;
849 LEAVE_PROTECTED_BLOCK
853 * Returns the location of the current COM object self or its one child to AT.
854 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
855 * the child ID specify child index from 0 to children count, 0 stands for object self.
856 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
857 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
858 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
859 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
860 * @return S_OK if successful and S_FALSE if failure.
862 STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
864 SolarMutexGuard g;
866 ENTER_PROTECTED_BLOCK
867 ISDESTROY()
868 // #CHECK#
869 if(pxLeft == NULL || pyTop == NULL || pcxWidth == NULL || pcyHeight == NULL)
871 return E_INVALIDARG;
874 if(varChild.vt==VT_I4)
876 if(varChild.lVal==CHILDID_SELF)
879 if (m_xAccessible.is())
881 Reference<XAccessibleContext> const pRContext =
882 m_xAccessible->getAccessibleContext();
883 if( !pRContext.is() )
884 return S_FALSE;
885 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
886 if( !pRComponent.is() )
887 return S_FALSE;
889 css::awt::Point pCPoint = pRComponent->getLocationOnScreen();
890 css::awt::Size pCSize = pRComponent->getSize();
891 *pxLeft = pCPoint.X;
892 *pyTop = pCPoint.Y;
893 *pcxWidth = pCSize.Width;
894 *pcyHeight = pCSize.Height;
895 return S_OK;
897 else
899 *pxLeft = m_sLocation.m_dLeft;
900 *pyTop = m_sLocation.m_dTop;
901 *pcxWidth = m_sLocation.m_dWidth;
902 *pcyHeight = m_sLocation.m_dHeight;
903 return S_OK;
908 return S_FALSE;
910 LEAVE_PROTECTED_BLOCK
914 * Returns the current focused child to AT.
915 * @param navDir, the direction flag of the navigation.
916 * @param varStart, the start child id of this navigation action.
917 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
918 * @return S_OK if successful and E_FAIL if failure.
920 STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
922 SolarMutexGuard g;
924 ENTER_PROTECTED_BLOCK
925 ISDESTROY()
926 // #CHECK#
927 if(pvarEndUpAt == NULL)
929 return E_INVALIDARG;
931 HRESULT ret = E_FAIL;
932 switch (navDir)
934 case NAVDIR_FIRSTCHILD:
935 ret = GetFirstChild(varStart,pvarEndUpAt);
936 break;
937 case NAVDIR_LASTCHILD:
938 ret = GetLastChild(varStart,pvarEndUpAt);
939 break;
940 case NAVDIR_NEXT:
941 ret = GetNextSibling(varStart,pvarEndUpAt);
942 break;
943 case NAVDIR_PREVIOUS:
944 ret = GetPreSibling(varStart,pvarEndUpAt);
945 break;
946 case NAVDIR_DOWN://do not implement temporarily
947 break;
948 case NAVDIR_UP://do not implement temporarily
949 break;
950 case NAVDIR_LEFT://do not implement temporarily
951 break;
952 case NAVDIR_RIGHT://do not implement temporarily
953 break;
954 default:
955 break;
957 return ret;
959 LEAVE_PROTECTED_BLOCK
962 STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
964 SolarMutexGuard g;
966 ENTER_PROTECTED_BLOCK
967 ISDESTROY()
968 // #CHECK#
969 if(pvarChild == NULL)
971 return E_INVALIDARG;
973 long x, y, w, h;
974 VARIANT varSelf;
975 VariantInit(&varSelf);
976 varSelf.vt = VT_I4;
977 varSelf.lVal = CHILDID_SELF;
978 accLocation(&x,&y,&w,&h,varSelf);
979 if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
981 int i, nCount;
982 pvarChild->vt = VT_EMPTY;
983 Reference< XAccessibleContext > pRContext = GetContextByXAcc(m_xAccessible.get());
984 nCount = pRContext->getAccessibleChildCount();
985 if(nCount > 256)
986 return E_FAIL;
987 IMAccessible* child = NULL;
988 for( i = 0; i<nCount; i++)
991 child = GetChildInterface(i + 1);
992 if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
993 break;
996 if(pvarChild->vt == VT_DISPATCH)
997 return S_OK;
999 if( i < nCount)
1001 pvarChild->vt = VT_DISPATCH;
1002 pvarChild->pdispVal = child;
1003 child->AddRef();
1005 else
1007 pvarChild->vt = VT_I4;
1008 pvarChild->lVal = CHILDID_SELF;
1010 return S_OK;
1012 return S_FALSE;
1014 LEAVE_PROTECTED_BLOCK
1018 * Get The other Interface from CMAccessible.
1019 * @param guidService, must be IID_IAccessible here.
1020 * @param riid, the IID interface .
1021 * @return S_OK if successful and S_FALSE if failure.
1023 STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
1025 if( InlineIsEqualGUID(guidService, IID_IAccessible) )
1026 return QueryInterface(riid, ppvObject);
1027 return S_FALSE;
1031 * Set the accessible name of the current COM object self or its one child from UNO.
1032 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1033 * the child ID specify child index from 0 to children count, 0 stands for object self.
1034 * @param szName, the name used to set the name of the proper object.
1035 * @return S_OK if successful and E_FAIL if failure.
1037 STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
1039 SolarMutexGuard g;
1041 ENTER_PROTECTED_BLOCK
1042 ISDESTROY()
1043 if(varChild.vt==VT_I4)
1045 if(varChild.lVal==CHILDID_SELF)
1047 SAFE_SYSFREESTRING(m_pszName);
1048 m_pszName=SysAllocString(szName);
1049 return S_OK;
1052 long lVal = varChild.lVal;
1053 varChild.lVal = CHILDID_SELF;
1054 IMAccessible *pChild = this->GetChildInterface(lVal);
1055 if(!pChild)
1056 return E_FAIL;
1057 return pChild->put_accName(varChild,szName);
1059 return E_FAIL;
1061 LEAVE_PROTECTED_BLOCK
1065 * Set the accessible value of the current COM object self or its one child from UNO.
1066 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1067 * the child ID specify child index from 0 to children count, 0 stands for object self.
1068 * @param szValue, the value used to set the value of the proper object.
1069 * @return S_OK if successful and E_FAIL if failure.
1071 STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
1073 SolarMutexGuard g;
1075 ENTER_PROTECTED_BLOCK
1076 ISDESTROY()
1077 if(varChild.vt==VT_I4)
1079 if(varChild.lVal==CHILDID_SELF)
1081 SysAllocString(m_pszValue);
1082 m_pszValue=SysAllocString(szValue);
1083 return S_OK;
1086 long lVal = varChild.lVal;
1087 varChild.lVal = CHILDID_SELF;
1088 IMAccessible *pChild = this->GetChildInterface(lVal);
1089 if(!pChild)
1090 return E_FAIL;
1091 return pChild->put_accValue(varChild,szValue);
1093 return E_FAIL;
1095 LEAVE_PROTECTED_BLOCK
1099 * Set the accessible name of the current COM object self from UNO.
1100 * @param pszName, the name value used to set the name of the current object.
1101 * @return S_OK if successful and E_FAIL if failure.
1103 STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
1105 // internal IMAccessible - no mutex meeded
1107 ENTER_PROTECTED_BLOCK
1108 ISDESTROY()
1109 // #CHECK#
1110 if(pszName == NULL)
1112 return E_INVALIDARG;
1115 SAFE_SYSFREESTRING(m_pszName);//??
1116 m_pszName = SysAllocString(pszName);
1117 if(m_pszName==NULL)
1118 return E_FAIL;
1119 return S_OK;
1121 LEAVE_PROTECTED_BLOCK
1125 * Set the accessible role of the current COM object self from UNO.
1126 * @param pRole, the role value used to set the role of the current object.
1127 * @return S_OK if successful and E_FAIL if failure.
1129 STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
1131 // internal IMAccessible - no mutex meeded
1133 m_iRole = pRole;
1134 return S_OK;
1138 * Add one state into the current state set for the current COM object from UNO.
1139 * @param pXSate, the state used to set the name of the current object.
1140 * @return S_OK if successful and E_FAIL if failure.
1142 STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
1144 // internal IMAccessible - no mutex meeded
1146 m_dState &= (~pXSate);
1147 return S_OK;
1151 * Delete one state into the current state set for the current COM object from UNO.
1152 * @param pXSate, the state used to set the name of the current object.
1153 * @return S_OK if successful and E_FAIL if failure.
1155 STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
1157 // internal IMAccessible - no mutex meeded
1159 m_dState |= pXSate;
1160 return S_OK;
1164 * Set state into the current state set for the current COM object from UNO.
1165 * @param pXSate, the state used to set the name of the current object.
1166 * @return S_OK if successful and E_FAIL if failure.
1168 STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
1170 // internal IMAccessible - no mutex meeded
1172 m_dState = pXSate;
1173 return S_OK;
1178 * Set the accessible description of the current COM object self from UNO.
1179 * @param pszDescription, the name used to set the description of the current object.
1180 * @return S_OK if successful and E_FAIL if failure.
1182 STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
1184 // internal IMAccessible - no mutex meeded
1186 ENTER_PROTECTED_BLOCK
1187 ISDESTROY()
1188 // #CHECK#
1189 if(pszDescription == NULL)
1191 return E_INVALIDARG;
1194 SAFE_SYSFREESTRING(m_pszDescription);
1195 m_pszDescription = SysAllocString(pszDescription);
1197 if(m_pszDescription==NULL)
1198 return E_FAIL;
1199 return S_OK;
1201 LEAVE_PROTECTED_BLOCK
1205 * Set the accessible value of the current COM object self from UNO.
1206 * @param pszAccValue, the name used to set the value of the current object.
1207 * @return S_OK if successful and E_FAIL if failure.
1209 STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
1211 // internal IMAccessible - no mutex meeded
1213 ENTER_PROTECTED_BLOCK
1214 ISDESTROY()
1215 // #CHECK#
1216 if(pszAccValue == NULL)
1218 return E_INVALIDARG;
1220 SAFE_SYSFREESTRING(m_pszValue);
1221 m_pszValue = SysAllocString(pszAccValue);
1222 if(m_pszValue==NULL)
1223 return E_FAIL;
1224 return S_OK;
1226 LEAVE_PROTECTED_BLOCK
1230 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1231 * Object through the method AccessibleObjectFromWindow(...).
1232 * @param hwnd, the HWND used to set the value of the current object.
1233 * @return S_OK if successful and E_FAIL if failure.
1235 STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
1237 // internal IMAccessible - no mutex meeded
1239 ENTER_PROTECTED_BLOCK
1240 ISDESTROY()
1241 m_hwnd = hwnd;
1242 return S_OK;
1244 LEAVE_PROTECTED_BLOCK
1248 * Set accessible focus by specifying child ID
1249 * @param dChildID, the child id identifies the focus child.
1250 * @return S_OK if successful and E_FAIL if failure.
1252 STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
1254 // internal IMAccessible - no mutex meeded
1256 ENTER_PROTECTED_BLOCK
1257 ISDESTROY()
1259 if(dChildID==CHILDID_SELF)
1261 if(m_pIParent)
1263 m_pIParent->Put_XAccFocus(m_dChildID);
1266 else
1268 m_dFocusChildID = dChildID;
1269 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1270 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1271 if(m_pIParent)
1273 m_pIParent->Put_XAccFocus(dChildID);
1276 return S_OK;
1278 LEAVE_PROTECTED_BLOCK
1282 *Set accessible object location for the current COM object
1283 * @param sLocation, the location of the current object.
1284 * @return S_OK if successful and E_FAIL if failure.
1286 STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
1288 // internal IMAccessible - no mutex meeded
1290 this->m_sLocation = sLocation;
1291 return S_OK;
1295 * Set accessible parent object for the current COM object if
1296 * the current object is a child of some COM object
1297 * @param pIParent, the parent of the current object.
1298 * @return S_OK if successful and E_FAIL if failure.
1300 STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
1302 // internal IMAccessible - no mutex meeded
1304 this->m_pIParent = pIParent;
1306 if(pIParent)
1307 m_pIParent->AddRef();
1309 return S_OK;
1313 * Set unique child id to COM
1314 * @param dChildID, the id of the current object.
1315 * @return S_OK if successful and E_FAIL if failure.
1317 STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
1319 // internal IMAccessible - no mutex meeded
1321 this->m_dChildID = dChildID;
1322 return S_OK;
1326 * Set AccObjectManagerAgent object pointer to COM
1327 * @param pAgent, the AccObjectManagerAgent point.
1328 * @return S_OK if successful and E_FAIL if failure.
1330 STDMETHODIMP CMAccessible::Put_XAccAgent(hyper pAgent)
1332 // internal IMAccessible - no mutex meeded
1334 g_pAgent = reinterpret_cast<AccObjectManagerAgent*>(pAgent);
1335 return S_OK;
1339 * When a UNO control disposing, it disposes its listeners,
1340 * then notify AccObject in bridge management, then notify
1341 * COM that the XAccessible is invalid,so set m_xAccessible as NULL
1342 * @param isDestroy, true is it need to be destroyed.
1343 * @return S_OK if successful and E_FAIL if failure.
1345 STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
1347 // internal IMAccessible - no mutex meeded
1349 m_isDestroy = isDestroy;
1350 m_xAccessible.clear();
1351 return S_OK;
1355 *private methods that help implement public functions
1359 * Return child interface pointer by child ID,note: need to call AddRef()
1360 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1361 * @return IMAccessible*, pointer to the corresponding child object.
1363 IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
1365 if(dChildID<0)
1367 if(g_pAgent)
1369 IMAccessible* pIMAcc = NULL;
1370 g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
1371 return pIMAcc;
1373 return NULL;
1375 else
1377 if (!m_xAccessible.is())
1378 return NULL;
1380 Reference<XAccessibleContext> const pRContext =
1381 m_xAccessible->getAccessibleContext();
1382 if( !pRContext.is() )
1383 return NULL;
1385 if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
1386 return NULL;
1388 IAccessible* pChild = NULL;
1389 Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
1390 BOOL isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1392 if(!isGet)
1394 g_pAgent->InsertAccObj(pXChild.get(), m_xAccessible.get(),
1395 reinterpret_cast<sal_Int64>(m_hwnd));
1396 isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1399 if(isGet)
1401 IMAccessible* pIMAcc = (IMAccessible*)pChild;
1402 return pIMAcc;
1406 return NULL;
1410 * For List, tree and table,these roles belong to manage_descendant in UNO,
1411 * need to process specifically when navigate
1412 * @return BOOL, if it is descendantmanager, return true.
1414 BOOL CMAccessible::IsDescendantManage()
1417 return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
1421 * for descendantmanager circumstance,provide child interface when navigate
1422 * @param varCur, the current child.
1423 * @param flags, the navigation direction.
1424 * @return IMAccessible*, the child of the end up node.
1426 IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
1429 XAccessibleContext* pXContext = GetContextByXAcc(m_xAccessible.get());
1430 if(pXContext==NULL)
1432 return NULL;
1435 int count = pXContext->getAccessibleChildCount();
1436 if(count<1)
1438 return NULL;
1441 IMAccessible* pCurChild = NULL;
1442 XAccessible* pChildXAcc = NULL;
1443 Reference<XAccessible> pRChildXAcc;
1444 XAccessibleContext* pChildContext = NULL;
1445 int index = 0,delta=0;
1446 switch(flags)
1448 case DM_FIRSTCHILD:
1449 pRChildXAcc = pXContext->getAccessibleChild(0);
1450 break;
1451 case DM_LASTCHILD:
1452 pRChildXAcc = pXContext->getAccessibleChild(count-1);
1453 break;
1454 case DM_NEXTCHILD:
1455 case DM_PREVCHILD:
1456 pCurChild = GetChildInterface(varCur.lVal);
1457 if(pCurChild==NULL)
1459 return NULL;
1461 pCurChild->GetUNOInterface(reinterpret_cast<hyper*>(&pChildXAcc));
1462 if(pChildXAcc==NULL)
1464 return NULL;
1466 pChildContext = GetContextByXAcc(pChildXAcc);
1467 if(pChildContext == NULL)
1469 return NULL;
1471 delta = (flags==DM_NEXTCHILD)?1:-1;
1472 //currently, getAccessibleIndexInParent is error in UNO for
1473 //some kind of List,such as ValueSet, the index will be less 1 than
1474 //what should be, need to fix UNO code
1475 index = pChildContext->getAccessibleIndexInParent()+delta;
1476 if((index>=0)&&(index<=count-1))
1478 pRChildXAcc = pXContext->getAccessibleChild(index);
1480 break;
1481 default:
1482 break;
1485 if(!pRChildXAcc.is())
1487 return NULL;
1489 pChildXAcc = pRChildXAcc.get();
1490 g_pAgent->InsertAccObj(pChildXAcc, m_xAccessible.get());
1491 return g_pAgent->GetIMAccByXAcc(pChildXAcc);
1495 *the following 4 private methods are for accNavigate implementation
1499 * Return first child for parent container, process differently according
1500 * to whether it is descendant manage
1501 * @param varStart, the start child id of this navigation action.
1502 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1503 * @return S_OK if successful and E_FAIL if failure.
1505 HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1508 ENTER_PROTECTED_BLOCK
1509 ISDESTROY()
1510 // #CHECK#
1511 if(pvarEndUpAt == NULL)
1513 return E_INVALIDARG;
1515 if(varStart.vt != VT_I4)
1517 pvarEndUpAt->vt = VT_EMPTY;
1518 return E_INVALIDARG;
1521 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
1522 if(pvarEndUpAt->pdispVal)
1524 pvarEndUpAt->pdispVal->AddRef();
1525 pvarEndUpAt->vt = VT_DISPATCH;
1526 return S_OK;
1529 pvarEndUpAt->vt = VT_EMPTY;
1530 return E_FAIL;
1532 LEAVE_PROTECTED_BLOCK
1536 * Return last child for parent container, process differently according
1537 * to whether it is descendant manage
1538 * @param varStart, the start child id of this navigation action.
1539 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1540 * @return S_OK if successful and E_FAIL if failure.
1542 HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1545 ENTER_PROTECTED_BLOCK
1546 ISDESTROY()
1547 // #CHECK#
1548 if(pvarEndUpAt == NULL)
1550 return E_INVALIDARG;
1552 if(varStart.vt != VT_I4)
1554 pvarEndUpAt->vt = VT_EMPTY;
1555 return E_INVALIDARG;
1558 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
1559 if(pvarEndUpAt->pdispVal)
1561 pvarEndUpAt->pdispVal->AddRef();
1562 pvarEndUpAt->vt = VT_DISPATCH;
1563 return S_OK;
1565 pvarEndUpAt->vt = VT_EMPTY;
1566 return E_FAIL;
1568 LEAVE_PROTECTED_BLOCK
1572 * The method GetNextSibling is general, whatever it is descendant manage or not
1573 * Get the next sibling object.
1574 * @param varStart, the start child id of this navigation action.
1575 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1576 * @return S_OK if successful and E_FAIL if failure.
1578 HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1581 ENTER_PROTECTED_BLOCK
1582 ISDESTROY()
1583 if(varStart.vt != VT_I4)
1585 pvarEndUpAt->vt = VT_EMPTY;
1586 return E_INVALIDARG;
1589 Reference<XAccessibleContext> const pRContext =
1590 GetContextByXAcc(m_xAccessible.get());
1591 if(pRContext.is())
1593 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
1594 if(m_pIParent)
1595 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1597 pvarEndUpAt->vt = VT_DISPATCH;
1598 return S_OK;
1601 pvarEndUpAt->vt = VT_EMPTY;
1602 return E_FAIL;
1604 LEAVE_PROTECTED_BLOCK
1608 *the method GetPreSibling is general, whatever it is descendant manage or not
1609 * @param varStart, the start child id of this navigation action.
1610 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1611 * @return S_OK if successful and E_FAIL if failure.
1613 HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1616 ENTER_PROTECTED_BLOCK
1617 ISDESTROY()
1618 // #CHECK#
1619 if(pvarEndUpAt == NULL)
1621 return E_INVALIDARG;
1623 if(varStart.vt != VT_I4)
1625 pvarEndUpAt->vt = VT_EMPTY;
1626 return E_INVALIDARG;
1629 Reference<XAccessibleContext> const pRContext =
1630 GetContextByXAcc(m_xAccessible.get());
1631 if(pRContext.is())
1633 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
1634 if(m_pIParent && varStart.iVal > 0)
1635 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1637 pvarEndUpAt->vt = VT_DISPATCH;
1638 return S_OK;
1641 pvarEndUpAt->vt = VT_EMPTY;
1642 return E_FAIL;
1644 LEAVE_PROTECTED_BLOCK
1648 * For IAccessible2 implementation methods
1650 STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
1652 SolarMutexGuard g;
1654 ENTER_PROTECTED_BLOCK
1655 ISDESTROY()
1657 // #CHECK#
1658 if(nRelations == NULL)
1660 return E_INVALIDARG;
1663 *nRelations = 0;
1665 if (!m_xContext.is())
1666 return E_FAIL;
1667 Reference<XAccessibleRelationSet> pRrelationSet =
1668 m_xContext.get()->getAccessibleRelationSet();
1669 if(!pRrelationSet.is())
1671 *nRelations = 0;
1672 return S_OK;
1675 *nRelations = pRrelationSet->getRelationCount();
1676 return S_OK;
1678 LEAVE_PROTECTED_BLOCK
1681 STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
1683 SolarMutexGuard g;
1685 ENTER_PROTECTED_BLOCK
1686 ISDESTROY()
1687 // #CHECK#
1688 if(relation == NULL)
1690 return E_INVALIDARG;
1693 if (!m_xContext.is())
1694 return E_FAIL;
1697 long nMax = 0;
1698 get_nRelations(&nMax);
1700 *relation = (IAccessibleRelation*)::CoTaskMemAlloc(sizeof(IAccessibleRelation));
1702 // #CHECK Memory Allocation#
1703 if(*relation == NULL)
1705 return E_FAIL;
1708 if( relationIndex < nMax )
1710 Reference<XAccessibleRelationSet> const pRrelationSet =
1711 m_xContext.get()->getAccessibleRelationSet();
1712 if(!pRrelationSet.is())
1715 return E_FAIL;
1718 IAccessibleRelation* pRelation = NULL;
1719 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1720 &pRelation);
1721 if(SUCCEEDED(hr))
1723 IUNOXWrapper* wrapper = NULL;
1724 hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1725 if(SUCCEEDED(hr))
1727 AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
1728 wrapper->put_XSubInterface(
1729 reinterpret_cast<hyper>(&accRelation));
1730 wrapper->Release();
1731 *relation = pRelation;
1732 return S_OK;
1738 return E_FAIL;
1740 LEAVE_PROTECTED_BLOCK
1743 STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
1745 SolarMutexGuard g;
1747 ENTER_PROTECTED_BLOCK
1748 ISDESTROY()
1750 // #CHECK#
1751 if(relation == NULL || nRelations == NULL)
1753 return E_INVALIDARG;
1755 // #CHECK XInterface#
1757 if (!m_xContext.is())
1758 return E_FAIL;
1760 Reference<XAccessibleRelationSet> const pRrelationSet =
1761 m_xContext.get()->getAccessibleRelationSet();
1762 if(!pRrelationSet.is())
1764 *nRelations = 0;
1765 return S_OK;
1768 long nCount = pRrelationSet->getRelationCount();
1770 *relation = (IAccessibleRelation*)::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation));
1772 // #CHECK Memory Allocation#
1773 if(*relation == NULL)
1775 return E_FAIL;
1778 for(int i=0; i<nCount ; i++)
1780 IAccessibleRelation* pRelation = NULL;
1781 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1782 &pRelation);
1783 if(SUCCEEDED(hr))
1785 IUNOXWrapper* wrapper = NULL;
1786 hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1787 if(SUCCEEDED(hr))
1789 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1790 wrapper->put_XSubInterface(
1791 reinterpret_cast<hyper>(&accRelation));
1792 wrapper->Release();
1794 (relation)[i] = pRelation;
1798 *nRelations = nCount;
1799 return S_OK;
1801 LEAVE_PROTECTED_BLOCK
1804 STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
1806 SolarMutexGuard g;
1808 ENTER_PROTECTED_BLOCK
1810 (*role) = m_iRole;
1812 return S_OK;
1814 LEAVE_PROTECTED_BLOCK
1818 STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
1820 SolarMutexGuard g;
1824 ISDESTROY()
1825 // #CHECK#
1826 if(nActions == NULL)
1828 return E_INVALIDARG;
1830 *nActions = 0L;
1831 IAccessibleAction* pAcc = NULL;
1832 HRESULT hr = QueryInterface(IID_IAccessibleAction, (void**)&pAcc);
1833 if( hr == S_OK )
1835 pAcc->nActions(nActions);
1836 pAcc->Release();
1839 return S_OK;
1841 catch(...)
1843 *nActions = 0L;
1844 return S_OK;
1849 STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
1851 return E_NOTIMPL;
1854 STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
1856 return E_NOTIMPL;
1859 static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
1861 // #CHECK#
1862 if(pXAcc == NULL)
1864 return NULL;
1866 Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
1867 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1868 long nRelations = pRrelationSet->getRelationCount();
1869 for(int i=0 ; i<nRelations ; i++)
1871 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1872 if(accRelation.RelationType == 7)
1874 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1875 return (XAccessible*)xTargets[0].get();
1878 return NULL;
1881 STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
1883 SolarMutexGuard g;
1885 ENTER_PROTECTED_BLOCK
1886 ISDESTROY()
1887 // #CHECK#
1888 if(groupLevel == NULL || similarItemsInGroup == NULL || positionInGroup == NULL)
1890 return E_INVALIDARG;
1893 if (!m_xAccessible.is())
1894 return E_FAIL;
1896 Reference<XAccessibleContext> const pRContext =
1897 m_xAccessible->getAccessibleContext();
1898 if(!pRContext.is())
1899 return E_FAIL;
1900 long Role = pRContext->getAccessibleRole();
1902 *groupLevel = 0;
1903 *similarItemsInGroup = 0;
1904 *positionInGroup = 0;
1906 if (Role != AccessibleRole::DOCUMENT && Role != AccessibleRole::DOCUMENT_PRESENTATION &&
1907 Role != AccessibleRole::DOCUMENT_SPREADSHEET && Role != AccessibleRole::DOCUMENT_TEXT)
1909 Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
1910 if ( xGroupPosition.is() )
1912 Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
1913 sal_Int32* pSeq = rSeq.getArray();
1914 if ( pSeq )
1916 *groupLevel = pSeq[0];
1917 *similarItemsInGroup = pSeq[1];
1918 *positionInGroup = pSeq[2];
1919 return S_OK;
1921 return S_OK;
1925 Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
1926 if( !pParentAcc.is() )
1928 return S_OK;
1931 Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
1933 int level = 0;
1934 int index = 0;
1935 int number = 0;
1937 if( Role == RADIO_BUTTON )
1939 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1940 long nRel = pRrelationSet->getRelationCount();
1941 for(int i=0 ; i<nRel ; i++)
1943 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1944 if(accRelation.RelationType == 7)
1946 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1948 Reference<XInterface> pRAcc = xTargets[0];
1949 for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
1951 if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
1952 == (XAccessible*)pRAcc.get() &&
1953 pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
1954 number++;
1955 if (pRParentContext->getAccessibleChild(j).get() == m_xAccessible.get())
1956 index = number;
1960 *groupLevel = 1;
1961 *similarItemsInGroup = number;
1962 *positionInGroup = index;
1963 return S_OK;
1966 else if ( COMBO_BOX == Role )
1968 *groupLevel = 1;
1969 *similarItemsInGroup = 0;
1970 *positionInGroup = -1;
1972 long nCount = pRContext->getAccessibleChildCount();
1973 if( 2 != nCount)
1975 return S_OK;
1977 Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
1978 if (!xList.is())
1980 return S_OK;
1982 Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
1983 if (!xListContext.is())
1985 return S_OK;
1987 Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
1988 if (!xListSel.is())
1990 return S_OK;
1992 *similarItemsInGroup = xListContext->getAccessibleChildCount();
1993 if (*similarItemsInGroup > 0 )
1997 Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
1998 if (xChild.is())
2000 Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
2001 if (xChildContext.is())
2003 *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
2004 return S_OK;
2008 catch(...)
2011 return S_OK;
2013 else if ( PAGE_TAB == Role )
2015 *groupLevel = 1;
2016 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2018 if (*similarItemsInGroup > 0 )
2020 *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
2022 else
2024 *positionInGroup = -1;
2026 return S_OK;
2030 BOOL isFound = FALSE;
2031 while( pParentAcc.is() && !isFound)
2033 level++;
2034 pRParentContext = pParentAcc->getAccessibleContext();
2035 Role = pRParentContext->getAccessibleRole();
2036 if( (Role == TREE) || (Role == LIST) )
2037 isFound = TRUE;
2038 pParentAcc = pRParentContext->getAccessibleParent();
2041 if( isFound )
2043 Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
2044 pRParentContext = pTempAcc->getAccessibleContext();
2045 *groupLevel = level;
2046 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2047 *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
2049 else
2051 *groupLevel = 0;
2052 *similarItemsInGroup = 0;
2053 *positionInGroup = 0;
2055 return S_OK;
2057 LEAVE_PROTECTED_BLOCK
2060 STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
2062 return E_NOTIMPL;
2066 STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
2068 SolarMutexGuard g;
2070 ENTER_PROTECTED_BLOCK
2071 ISDESTROY()
2072 // #CHECK#
2073 if(uniqueID == NULL)
2075 return E_INVALIDARG;
2077 *uniqueID = m_dChildID;
2078 return S_OK;
2080 LEAVE_PROTECTED_BLOCK
2083 STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
2085 SolarMutexGuard g;
2087 ENTER_PROTECTED_BLOCK
2088 ISDESTROY()
2089 // #CHECK#
2090 if(windowHandle == NULL)
2092 return E_INVALIDARG;
2095 HWND nHwnd = m_hwnd;
2096 IAccessible* pParent = m_pIParent;
2097 CMAccessible* pChild = this;
2098 while((nHwnd==0) && pParent)
2100 pChild = (CMAccessible*)pParent;
2101 if(pChild)
2103 pParent = (IAccessible*)pChild->m_pIParent;
2104 nHwnd = (HWND)pChild->m_hwnd;
2106 else
2107 pParent = NULL;
2110 *windowHandle = nHwnd;
2111 return S_OK;
2113 LEAVE_PROTECTED_BLOCK
2117 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2118 * @param pXAcc, UNO XAccessible object point.
2119 * @return XAccessibleContext*, the context of the pXAcc.
2121 XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
2123 Reference< XAccessibleContext > pRContext;
2124 if( pXAcc == NULL)
2125 return NULL;
2127 pRContext = pXAcc->getAccessibleContext();
2128 if( !pRContext.is() )
2129 return NULL;
2130 return pRContext.get();
2134 * Return the member variable m_pXAccessibleSelection, instead of
2135 * get XAccessibleSelection according to XAccessibleContext because if so,it will
2136 * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2137 * by bridge management system
2138 * @return XAccessibleSelection*, the selection of the current object.
2140 Reference< XAccessibleSelection > CMAccessible::GetSelection()
2142 if (!m_xAccessible.is())
2143 return NULL;
2144 Reference<XAccessibleContext> const pRContext =
2145 m_xAccessible->getAccessibleContext();
2146 if(pRContext.is())
2148 Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
2149 return pRSelection;
2151 return NULL;
2155 * Select one XAccessible item, for accSelect implementation
2156 * @param pItem, the item should be selected.
2157 * @return S_OK if successful.
2159 HRESULT CMAccessible::SelectChild(XAccessible* pItem)
2162 ENTER_PROTECTED_BLOCK
2163 ISDESTROY()
2164 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2165 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2166 if( pParentContext == NULL || pContext == NULL )
2167 return E_FAIL;
2169 Reference< XAccessibleSelection > pRSelection = GetSelection();
2170 if( !pRSelection.is() )
2171 return E_FAIL;
2172 long Index = pContext->getAccessibleIndexInParent();
2173 pRSelection->selectAccessibleChild( Index );
2174 return S_OK;
2176 LEAVE_PROTECTED_BLOCK
2180 * Deselect one XAccessible item, for accSelect implimentation
2181 * @param pItem, the item should be deselected.
2182 * @return S_OK if successful.
2184 HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
2187 ENTER_PROTECTED_BLOCK
2188 ISDESTROY()
2189 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2191 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2192 if( pParentContext == NULL || pContext == NULL )
2193 return E_INVALIDARG;
2195 Reference< XAccessibleSelection > pRSelection = GetSelection();
2196 if( !pRSelection.is() )
2197 return E_FAIL;
2198 long Index = pContext->getAccessibleIndexInParent();
2199 pRSelection->deselectAccessibleChild( Index );
2201 return S_OK;
2203 LEAVE_PROTECTED_BLOCK
2207 * Select multiple XAccessible items,for implementation of accSelect
2208 * @param pItem, the items should be selected.
2209 * @param size, the size of the items.
2210 * @return S_OK if successful.
2212 HRESULT CMAccessible::SelectMutipleChidren( XAccessible** pItem,int size )
2215 ENTER_PROTECTED_BLOCK
2216 ISDESTROY()
2217 // #CHECK#
2218 if(pItem == NULL)
2220 return E_INVALIDARG;
2222 for(int index = 0;index < size;index++)
2224 SelectChild( pItem[index] );
2226 return S_OK;
2228 LEAVE_PROTECTED_BLOCK
2232 * Deselect multiple XAccessible items,for implementation of accSelect
2233 * @param pItem, the items should be selected.
2234 * @param size, the size of the items.
2235 * @return S_OK if successful.
2237 HRESULT CMAccessible::DeSelectMutipleChildren( XAccessible** pItem,int size )
2240 ENTER_PROTECTED_BLOCK
2241 ISDESTROY()
2242 // #CHECK#
2243 if(pItem == NULL)
2245 return E_INVALIDARG;
2247 for(int index = 0;index < size;index++)
2249 DeSelectChild( pItem[index] );
2251 return S_OK;
2253 LEAVE_PROTECTED_BLOCK
2257 * When COM is created, UNO set XAccessible pointer to it
2258 * in order to COM can operate UNO information
2259 * @param pXAcc, the XAccessible object of current object.
2260 * @return S_OK if successful.
2262 STDMETHODIMP CMAccessible::SetXAccessible(hyper pXAcc)
2264 // internal IMAccessible - no mutex meeded
2266 m_xAccessible = reinterpret_cast<XAccessible*>(pXAcc);
2267 m_pEnumVar->PutSelection(/*XAccessibleSelection*/
2268 reinterpret_cast<hyper>(m_xAccessible.get()));
2270 m_xContext = m_xAccessible->getAccessibleContext();
2272 return S_OK;
2276 * accSelect method has many optional flags, needs to process comprehensively
2277 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2278 * The implementation of this flag is a little trouble-shooting,so we also
2279 * do not implement it now
2280 * @param flagsSelect, the selection flag of the select action.
2281 * @param varChild, the child object pointer of current action.
2282 * @return S_OK if successful.
2284 STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
2286 SolarMutexGuard g;
2288 ENTER_PROTECTED_BLOCK
2289 ISDESTROY()
2290 if( (flagsSelect&SELFLAG_ADDSELECTION) &&
2291 (SELFLAG_REMOVESELECTION&flagsSelect) )
2292 return E_INVALIDARG;
2294 if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
2296 (flagsSelect&SELFLAG_ADDSELECTION) ||
2297 (flagsSelect&SELFLAG_REMOVESELECTION) ||
2298 (flagsSelect&SELFLAG_EXTENDSELECTION )
2301 return E_INVALIDARG;
2303 if ( varChild.vt != VT_I4 )
2304 return E_INVALIDARG;
2306 IMAccessible* pSelectAcc;
2307 if( varChild.lVal == CHILDID_SELF )
2309 pSelectAcc = this;
2310 pSelectAcc->AddRef();
2312 else
2314 pSelectAcc = GetChildInterface(varChild.lVal);
2317 if( pSelectAcc == NULL )
2318 return E_INVALIDARG;
2320 if( flagsSelect&SELFLAG_TAKEFOCUS )
2322 XAccessible * pTempUNO = 0;
2323 pSelectAcc->GetUNOInterface(reinterpret_cast<hyper*>(&pTempUNO));
2325 if( pTempUNO == NULL )
2326 return NULL;
2328 Reference<XAccessibleContext> pRContext = pTempUNO->getAccessibleContext();
2329 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
2330 Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
2331 Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
2332 Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
2333 Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
2336 pRComponent->grabFocus();
2338 if( flagsSelect & SELFLAG_TAKESELECTION )
2340 pRParentSelection->clearAccessibleSelection();
2341 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2344 if( flagsSelect & SELFLAG_ADDSELECTION )
2346 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2349 if( flagsSelect & SELFLAG_REMOVESELECTION )
2351 pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2354 if( flagsSelect & SELFLAG_EXTENDSELECTION )
2356 long indexInParrent = pRContext->getAccessibleIndexInParent();
2358 if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
2359 pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
2361 pRParentSelection->selectAccessibleChild( indexInParrent );
2367 pSelectAcc->Release();
2368 return S_OK;
2370 LEAVE_PROTECTED_BLOCK
2374 * Return XAccessible interface pointer when needed
2375 * @param pXAcc, [in, out] the Uno interface of the current object.
2376 * @return S_OK if successful.
2378 STDMETHODIMP CMAccessible::GetUNOInterface(hyper * pXAcc)
2380 // internal IMAccessible - no mutex meeded
2382 if(pXAcc == NULL)
2383 return E_INVALIDARG;
2385 *pXAcc = reinterpret_cast<hyper>(m_xAccessible.get());
2386 return S_OK;
2390 * Helper method for Implementation of get_accDefaultAction
2391 * @param pAction, the default action point of the current object.
2392 * @return S_OK if successful.
2394 STDMETHODIMP CMAccessible::SetDefaultAction(hyper pAction)
2396 // internal IMAccessible - no mutex meeded
2398 m_xAction = reinterpret_cast<XAccessibleAction*>(pAction);
2399 return S_OK;
2403 * This method is called when AT open some UI elements initially
2404 * the UI element takes the default action defined here
2405 * @param varChild, the child id of the defaultaction.
2406 * @param pszDefaultAction,[in/out] the description of the current action.
2407 * @return S_OK if successful.
2409 HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
2411 SolarMutexGuard g;
2413 ENTER_PROTECTED_BLOCK
2414 ISDESTROY()
2415 // #CHECK#
2416 if(pszDefaultAction == NULL)
2418 return E_INVALIDARG;
2420 if(varChild.vt==VT_I4)
2422 if(varChild.lVal==CHILDID_SELF)
2424 if (!m_xAction.is())
2425 return DISP_E_MEMBERNOTFOUND;
2426 SAFE_SYSFREESTRING(*pszDefaultAction);
2427 *pszDefaultAction = SysAllocString(m_pszActionDescription);
2428 return S_OK;
2431 long lVal = varChild.lVal;
2432 varChild.lVal = CHILDID_SELF;
2433 IMAccessible *pChild = this->GetChildInterface(lVal);
2434 if(!pChild)
2435 return E_FAIL;
2436 return pChild->get_accDefaultAction(varChild,pszDefaultAction);
2438 return S_FALSE;
2440 LEAVE_PROTECTED_BLOCK
2444 * AT call this method to operate application
2445 * @param varChild, the child id of the action object.
2446 * @return S_OK if successful.
2448 HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
2450 SolarMutexGuard g;
2452 ENTER_PROTECTED_BLOCK
2453 ISDESTROY()
2454 if( varChild.vt != VT_I4 )
2455 return E_INVALIDARG;
2456 if (!m_xAction.is())
2457 return E_FAIL;
2458 if (m_xAction->getAccessibleActionCount() == 0)
2459 return E_FAIL;
2461 if(varChild.lVal==CHILDID_SELF)
2463 if (m_xAction->getAccessibleActionCount() > 0)
2464 m_xAction->doAccessibleAction(0);
2465 return S_OK;
2468 long lVal = varChild.lVal;
2469 varChild.lVal = CHILDID_SELF;
2470 IMAccessible *pChild = this->GetChildInterface(lVal);
2471 if(!pChild)
2472 return E_FAIL;
2473 return pChild->accDoDefaultAction( varChild );
2475 LEAVE_PROTECTED_BLOCK
2479 * UNO set description information for action to COM.
2480 * @param szAction, the action description of the current object.
2481 * @return S_OK if successful.
2483 STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
2485 // internal IMAccessible - no mutex meeded
2487 ENTER_PROTECTED_BLOCK
2488 ISDESTROY()
2489 // #CHECK#
2490 if(szAction == NULL)
2492 return E_INVALIDARG;
2494 SAFE_SYSFREESTRING(m_pszActionDescription );
2495 m_pszActionDescription = SysAllocString( szAction );
2496 return S_OK;
2498 LEAVE_PROTECTED_BLOCK
2501 BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
2503 Reference< XAccessibleContext > pRContext;
2505 switch(index)
2507 case XI_COMPONENT:
2508 QUERYXINTERFACE(AccessibleComponent)
2509 break;
2510 case XI_TEXT:
2511 QUERYXINTERFACE(AccessibleText)
2512 break;
2513 case XI_EDITABLETEXT:
2514 QUERYXINTERFACE(AccessibleEditableText)
2515 break;
2516 case XI_TABLE:
2517 QUERYXINTERFACE(AccessibleTable)
2518 break;
2519 case XI_SELECTION:
2520 QUERYXINTERFACE(AccessibleSelection)
2521 break;
2522 case XI_EXTENDEDCOMP:
2523 QUERYXINTERFACE(AccessibleExtendedComponent)
2524 break;
2525 case XI_KEYBINDING:
2526 QUERYXINTERFACE(AccessibleKeyBinding)
2527 break;
2528 case XI_ACTION:
2529 QUERYXINTERFACE(AccessibleAction)
2530 break;
2531 case XI_VALUE:
2532 QUERYXINTERFACE(AccessibleValue)
2533 break;
2534 case XI_HYPERTEXT:
2535 QUERYXINTERFACE(AccessibleHypertext)
2536 break;
2537 case XI_HYPERLINK:
2538 QUERYXINTERFACE(AccessibleHyperlink)
2539 break;
2540 case XI_IMAGE:
2541 QUERYXINTERFACE(AccessibleImage)
2542 break;
2543 default:
2544 break;
2547 return FALSE;
2550 template<typename T> HRESULT
2551 createAggInstance(CMAccessible &rOuter, void ** ppvObject)
2553 // Note: CComAggObject has special handling for IUnknown - must
2554 // query for that when creating it! Otherwise we get a T member of it
2555 // which will redirect QueryInterface back to CMAccessible infinitely.
2556 // (CComAggObject has its own ref-count too which is not a problem
2557 // since it is inserted in m_containedObjects.)
2558 return CComCreator< CComAggObject<T> >::CreateInstance(
2559 rOuter.GetControllingUnknown(), IID_IUnknown, ppvObject);
2562 typedef HRESULT (AggCreatorFunc)(CMAccessible &, void **);
2564 struct AggMapEntry
2566 const IID* piid;
2567 AggCreatorFunc* pfnCreateInstance;
2568 int XIFIndex;
2571 static AggMapEntry g_CMAccessible_AggMap[] = {
2572 { &IID_IAccessibleComponent, &createAggInstance<CAccComponent>, XI_COMPONENT },
2573 { &IID_IAccessibleText, &createAggInstance<CAccText>, XI_TEXT },
2574 { &IID_IAccessibleEditableText, &createAggInstance<CAccEditableText>, XI_EDITABLETEXT },
2575 { &IID_IAccessibleImage, &createAggInstance<CAccImage>, XI_IMAGE },
2576 { &IID_IAccessibleTable, &createAggInstance<CAccTable>, XI_TABLE },
2577 { &IID_IAccessibleAction, &createAggInstance<CAccAction>, XI_ACTION },
2578 { &IID_IAccessibleValue, &createAggInstance<CAccValue>, XI_VALUE },
2579 { &IID_IAccessibleHypertext, &createAggInstance<CAccHypertext>, XI_HYPERTEXT },
2580 { &IID_IAccessibleHyperlink, &createAggInstance<CAccHyperLink>, XI_HYPERLINK },
2581 { 0, 0, 0 },
2585 HRESULT WINAPI CMAccessible::SmartQI(void* /*pv*/, REFIID iid, void** ppvObject)
2587 ENTER_PROTECTED_BLOCK
2589 ISDESTROY()
2590 if (InlineIsEqualGUID(iid,IID_IAccIdentity) ||
2591 InlineIsEqualGUID(iid,IID_IStdMarshalInfo) ||
2592 InlineIsEqualGUID(iid,IID_IMarshal) ||
2593 InlineIsEqualGUID(iid,IID_IExternalConnection)||
2594 InlineIsEqualGUID(iid,IID_IOleWindow))
2596 return E_FAIL;
2599 AggMapEntry * pMap = &g_CMAccessible_AggMap[0];
2600 while(pMap && pMap->piid)
2602 if (InlineIsEqualGUID(iid, *pMap->piid))
2604 SolarMutexGuard g;
2606 XInterface* pXI = NULL;
2607 BOOL bFound = GetXInterfaceFromXAccessible(m_xAccessible.get(),
2608 &pXI, pMap->XIFIndex);
2609 if(!bFound)
2611 return E_FAIL;
2614 XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
2615 if ( pIndTemp != m_containedObjects.end() )
2617 return pIndTemp->second.p->QueryInterface( iid, ppvObject );
2619 else
2621 HRESULT hr = pMap->pfnCreateInstance(*this, ppvObject);
2622 assert(hr == S_OK);
2623 if(hr == S_OK)
2625 m_containedObjects.insert(XGUIDToComObjHash::value_type(*pMap->piid,(IUnknown*)*ppvObject));
2626 IUNOXWrapper* wrapper = NULL;
2627 ((IUnknown*)*ppvObject)->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
2628 if(wrapper)
2630 wrapper->put_XInterface(
2631 reinterpret_cast<hyper>(m_xAccessible.get()));
2632 wrapper->Release();
2634 return S_OK;
2637 return E_FAIL;
2639 pMap++;
2641 return E_FAIL;
2643 LEAVE_PROTECTED_BLOCK
2646 BOOL
2647 CMAccessible::get_IAccessibleFromXAccessible(XAccessible * pXAcc, IAccessible **ppIA)
2650 ENTER_PROTECTED_BLOCK
2652 // #CHECK#
2653 if(ppIA == NULL)
2655 return E_INVALIDARG;
2657 BOOL isGet = FALSE;
2658 if(g_pAgent)
2659 isGet = g_pAgent->GetIAccessibleFromXAccessible(pXAcc, ppIA);
2661 if(isGet)
2662 return TRUE;
2663 else
2664 return FALSE;
2666 LEAVE_PROTECTED_BLOCK
2669 void CMAccessible::get_OLECHARFromAny(Any& pAny, OLECHAR* pChar)
2671 // #CHECK#
2672 if(pChar == NULL)
2673 return;
2675 switch(pAny.getValueTypeClass())
2677 case TypeClass_CHAR:
2679 sal_Int8 val;
2680 pAny >>= val;
2681 swprintf( pChar, L"%d", val);
2682 break;
2684 case TypeClass_BOOLEAN:
2686 sal_Bool val;
2687 pAny >>= val;
2688 swprintf( pChar, L"%d", val);
2689 break;
2691 case TypeClass_BYTE:
2693 sal_Int8 val;
2694 pAny >>= val;
2695 swprintf( pChar, L"%d", val);
2696 break;
2698 case TypeClass_SHORT:
2700 SHORT val;
2701 pAny >>= val;
2702 swprintf( pChar, L"%d", val);
2703 break;
2705 case TypeClass_UNSIGNED_SHORT:
2707 USHORT val;
2708 pAny >>= val;
2709 swprintf( pChar, L"%d", val);
2710 break;
2712 case TypeClass_LONG:
2714 LONG val;
2715 pAny >>= val;
2716 swprintf( pChar, L"%ld", val);
2717 break;
2719 case TypeClass_UNSIGNED_LONG:
2721 ULONG val;
2722 pAny >>= val;
2723 swprintf( pChar, L"%ld", val);
2724 break;
2726 case TypeClass_FLOAT:
2728 FLOAT val;
2729 pAny >>= val;
2730 swprintf( pChar, L"%.3f", val);
2731 break;
2733 case TypeClass_DOUBLE:
2735 DOUBLE val;
2736 pAny >>= val;
2737 swprintf( pChar, L"%.6lf", val);
2738 break;
2740 case TypeClass_STRING:
2742 ::rtl::OUString val;
2743 pAny >>= val;
2744 wcscpy(pChar, val.getStr());
2745 break;
2747 case TypeClass_SEQUENCE:
2749 if(pAny.getValueType() == cppu::UnoType<Sequence< ::rtl::OUString >>::get())
2751 Sequence < ::rtl::OUString > val;
2752 pAny >>= val;
2754 ::rtl::OUString pString;
2756 int count = val.getLength();
2758 for( int iIndex = 0;iIndex < count;iIndex++ )
2760 pString += val[iIndex];
2762 wcscpy(pChar, pString.getStr());
2764 else if (pAny.getValueType() == cppu::UnoType<Sequence< css::style::TabStop >>::get())
2766 Sequence < css::style::TabStop > val;
2767 pAny >>= val;
2768 int count = val.getLength();
2770 for( int iIndex = 0;iIndex < count;iIndex++ )
2772 OLECHAR pAttrs[512] = {NULL};
2774 OLECHAR pAttrsPosition[512] = {NULL};
2775 OLECHAR pAttrsDescimalChar[512] = {NULL};
2776 OLECHAR pAttrsFillChar[512] = {NULL};
2778 css::style::TabStop sigleVal = val[iIndex];
2780 swprintf( pAttrsPosition, L"Position=%ld,TabAlign=%ld",
2781 sigleVal.Position, sigleVal.Alignment);
2783 if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
2784 sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
2785 swprintf( pAttrsDescimalChar, L"DecimalChar=\\%c",sigleVal.DecimalChar);
2786 else
2787 swprintf( pAttrsDescimalChar, L"DecimalChar=%c",sigleVal.DecimalChar);
2789 if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
2790 sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
2791 swprintf( pAttrsFillChar, L"FillChar=\\%c",sigleVal.FillChar);
2792 else
2793 swprintf( pAttrsFillChar, L"FillChar=%c",sigleVal.FillChar);
2795 swprintf( pAttrs, L"%s,%s,%s,",pAttrsPosition,pAttrsDescimalChar,pAttrsFillChar);
2797 wcscat(pChar,pAttrs);
2800 break;
2802 case TypeClass_ENUM:
2804 if (pAny.getValueType() == cppu::UnoType<css::awt::FontSlant>::get())
2806 css::awt::FontSlant val;
2807 pAny >>= val;
2808 swprintf( pChar, L"%d", val);
2810 break;
2812 case TypeClass_STRUCT:
2814 if (pAny.getValueType() == cppu::UnoType<css::style::LineSpacing>::get())
2816 css::style::LineSpacing val;
2817 pAny >>= val;
2818 swprintf( pChar, L"Mode=%ld,Height=%ld,", val.Mode, val.Height);
2820 else if (pAny.getValueType() == cppu::UnoType<css::accessibility::TextSegment>::get())
2822 css::accessibility::TextSegment val;
2823 pAny >>= val;
2824 ::rtl::OUString realVal(val.SegmentText);
2825 wcscpy(pChar, realVal.getStr());
2827 break;
2829 case TypeClass_VOID:
2830 case TypeClass_HYPER:
2831 case TypeClass_UNSIGNED_HYPER:
2832 case TypeClass_TYPE:
2833 case TypeClass_ANY:
2834 case TypeClass_TYPEDEF:
2835 case TypeClass_EXCEPTION:
2836 case TypeClass_INTERFACE:
2837 case TypeClass_SERVICE:
2838 case TypeClass_MODULE:
2839 case TypeClass_INTERFACE_METHOD:
2840 case TypeClass_INTERFACE_ATTRIBUTE:
2841 case TypeClass_UNKNOWN:
2842 case TypeClass_PROPERTY:
2843 case TypeClass_CONSTANT:
2844 case TypeClass_CONSTANTS:
2845 case TypeClass_SINGLETON:
2846 case TypeClass_MAKE_FIXED_SIZE:
2847 break;
2848 default:
2849 break;
2853 void CMAccessible::get_OLECHAR4Numbering(const Any& pAny, short numberingLevel,const OUString& numberingPrefix,OLECHAR* pChar)
2855 if(pChar == NULL)
2856 return;
2857 Reference< css::container::XIndexReplace > pXIndex;
2858 if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
2860 Any aAny = pXIndex->getByIndex(numberingLevel);
2861 Sequence< css::beans::PropertyValue > aProps;
2862 aAny >>= aProps;
2863 const css::beans::PropertyValue* pPropArray = aProps.getConstArray();
2864 sal_Int32 nCount = aProps.getLength();
2865 swprintf(pChar,L"Numbering:NumberingLevel=%d,",numberingLevel);
2866 for( sal_Int32 i=0; i<nCount; i++ )
2868 css::beans::PropertyValue rProp = pPropArray[i];
2869 if( (rProp.Name == "BulletChar" ) ||
2870 (rProp.Name == "GraphicURL" ) ||
2871 (rProp.Name == "NumberingType" ))
2873 OLECHAR propStr[512] = {NULL};
2874 swprintf(propStr,L"%s=",rProp.Name.getStr());
2875 OLECHAR pTemp[256] = {NULL};
2876 CMAccessible::get_OLECHARFromAny(rProp.Value,pTemp);
2877 if(rProp.Name == "GraphicURL")
2879 OLECHAR* pOccur = wcschr(pTemp,':');
2880 if(pOccur)
2881 *pOccur = '.';
2883 wcscat(propStr,pTemp);
2884 wcscat(pChar,propStr);
2885 wcscat(pChar,L",");
2887 if(rProp.Name == "NumberingType")
2889 if(numberingPrefix.getLength()!=0)
2891 swprintf(pTemp,L"NumberingPrefix=%s,",numberingPrefix.getStr());
2892 wcscat(pChar,pTemp);
2899 //Because now have three types numbering level:
2900 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2901 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2902 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2903 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2904 // so NumberingLevel value will be decreased 1 in bridge code.
2905 else if(numberingLevel >0)
2907 swprintf(pChar,L"Numbering:NumberingLevel=%d,NumberingType=4,NumberingPrefix=,",numberingLevel-1);
2909 else
2911 swprintf(pChar,L"Numbering:");
2915 void CMAccessible::ConvertAnyToVariant(const css::uno::Any &rAnyVal, VARIANT *pvData)
2917 if(rAnyVal.hasValue())
2919 // Clear VARIANT variable.
2920 VariantClear(pvData);
2922 // Set value according to value type.
2923 switch(rAnyVal.getValueTypeClass())
2925 case TypeClass_CHAR:
2926 pvData->vt = VT_UI1;
2927 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
2928 break;
2930 case TypeClass_BOOLEAN:
2931 pvData->vt = VT_BOOL;
2932 memcpy(&pvData->boolVal, rAnyVal.getValue(), sizeof(sal_Bool));
2933 break;
2935 case TypeClass_BYTE:
2936 pvData->vt = VT_UI1;
2937 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
2938 break;
2940 case TypeClass_SHORT:
2941 pvData->vt = VT_I2;
2942 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
2943 break;
2945 case TypeClass_UNSIGNED_SHORT:
2946 pvData->vt = VT_I2;
2947 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
2948 break;
2950 case TypeClass_LONG:
2951 pvData->vt = VT_I4;
2952 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
2953 break;
2955 case TypeClass_UNSIGNED_LONG:
2956 pvData->vt = VT_I4;
2957 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
2958 break;
2960 case TypeClass_FLOAT:
2961 pvData->vt = VT_R4;
2962 memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
2963 break;
2965 case TypeClass_DOUBLE:
2966 pvData->vt = VT_R8;
2967 memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
2968 break;
2970 case TypeClass_STRING:
2972 pvData->vt = VT_BSTR;
2973 ::rtl::OUString val;
2974 rAnyVal >>= val;
2975 pvData->bstrVal = SysAllocString((OLECHAR *)val.getStr());
2976 break;
2979 case TypeClass_VOID:
2980 case TypeClass_HYPER:
2981 case TypeClass_UNSIGNED_HYPER:
2982 case TypeClass_TYPE:
2983 case TypeClass_ANY:
2984 case TypeClass_ENUM:
2985 case TypeClass_TYPEDEF:
2986 case TypeClass_STRUCT:
2987 case TypeClass_EXCEPTION:
2988 case TypeClass_SEQUENCE:
2989 case TypeClass_INTERFACE:
2991 Reference< XAccessible > pXAcc;
2992 if(rAnyVal >>= pXAcc)
2994 if(pXAcc.is())
2996 IAccessible* pIAcc = NULL;
2997 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
2998 if(pIAcc == NULL)
3000 Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
3001 g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
3002 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
3004 if(pIAcc)
3006 pIAcc->AddRef();
3008 pvData->vt = VT_UNKNOWN;
3009 pvData->pdispVal = (IAccessible2*)pIAcc;
3010 break;
3014 SAL_FALLTHROUGH;
3016 case TypeClass_SERVICE:
3017 case TypeClass_MODULE:
3018 case TypeClass_INTERFACE_METHOD:
3019 case TypeClass_INTERFACE_ATTRIBUTE:
3020 case TypeClass_UNKNOWN:
3021 case TypeClass_PROPERTY:
3022 case TypeClass_CONSTANT:
3023 case TypeClass_CONSTANTS:
3024 case TypeClass_SINGLETON:
3025 case TypeClass_MAKE_FIXED_SIZE:
3026 // Output the type string, if there is other uno value type.
3027 pvData->vt = VT_BSTR;
3028 pvData->bstrVal = SysAllocString(rAnyVal.getValueTypeName().getStr());
3029 break;
3031 default:
3032 break;
3035 else
3037 VariantClear(pvData);
3041 STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
3043 // internal IMAccessible - no mutex meeded
3045 if(childID == NULL)
3047 return E_FAIL;
3049 *childID = m_dChildID;
3050 return S_OK;
3053 STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
3055 SolarMutexGuard g;
3057 ENTER_PROTECTED_BLOCK
3058 ISDESTROY()
3060 if (!m_xContext.is())
3061 return E_FAIL;
3063 Reference<XAccessibleStateSet> const pRStateSet =
3064 m_xContext.get()->getAccessibleStateSet();
3065 if(!pRStateSet.is())
3067 return S_OK;
3069 Sequence<short> pStates = pRStateSet->getStates();
3072 long count = pStates.getLength() ;
3073 *states = 0x0;
3074 for( int i = 0; i < count; i++ )
3076 for( std::size_t j = 0; j < SAL_N_ELEMENTS(UNO_STATES); j++ )
3078 if( pStates[i] == UNO_STATES[j] )
3080 *states |= IA2_STATES[j];
3081 break;
3085 return S_OK;
3088 LEAVE_PROTECTED_BLOCK
3091 // return the UNO roles
3092 STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR * )
3094 return E_NOTIMPL;
3097 STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR * )
3099 return E_NOTIMPL;
3102 STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
3104 return E_NOTIMPL;
3108 STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
3110 return E_NOTIMPL;
3114 STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
3116 ENTER_PROTECTED_BLOCK
3117 ISDESTROY()
3118 // #CHECK#
3119 if(accParentIndex == NULL)
3120 return E_INVALIDARG;
3122 if (!m_xContext.is())
3123 return E_FAIL;
3125 *accParentIndex = m_xContext.get()->getAccessibleIndexInParent();
3126 return S_OK;
3129 LEAVE_PROTECTED_BLOCK
3131 STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale )
3133 ENTER_PROTECTED_BLOCK
3134 ISDESTROY()
3135 if(locale == NULL)
3136 return E_INVALIDARG;
3138 if (!m_xContext.is())
3139 return E_FAIL;
3141 css::lang::Locale unoLoc = m_xContext.get()->getLocale();
3142 locale->language = SysAllocString((OLECHAR*)unoLoc.Language.getStr());
3143 locale->country = SysAllocString((OLECHAR*)unoLoc.Country.getStr());
3144 locale->variant = SysAllocString((OLECHAR*)unoLoc.Variant.getStr());
3146 return S_OK;
3148 LEAVE_PROTECTED_BLOCK
3151 DWORD GetMSAAStateFromUNO(short xState)
3153 DWORD IState = STATE_SYSTEM_UNAVAILABLE;
3154 switch( xState )
3156 case /*AccessibleStateType::*/AccessibleStateType::BUSY:
3157 IState = STATE_SYSTEM_BUSY;
3158 break;
3159 case /*AccessibleStateType::*/AccessibleStateType::CHECKED:
3160 IState = STATE_SYSTEM_CHECKED;
3161 break;
3162 case /*AccessibleStateType::*/AccessibleStateType::DEFUNC:
3163 IState = STATE_SYSTEM_UNAVAILABLE;
3164 break;
3165 case /*AccessibleStateType::*/AccessibleStateType::EXPANDED:
3166 IState = STATE_SYSTEM_EXPANDED;
3167 break;
3168 case /*AccessibleStateType::*/AccessibleStateType::FOCUSABLE:
3169 IState = STATE_SYSTEM_FOCUSABLE;
3170 break;
3171 case /*AccessibleStateType::*/AccessibleStateType::FOCUSED:
3172 IState = STATE_SYSTEM_FOCUSED;
3173 break;
3174 case /*AccessibleStateType::*/AccessibleStateType::INDETERMINATE:
3175 IState = STATE_SYSTEM_MIXED;
3176 break;
3177 case /*AccessibleStateType::*/AccessibleStateType::MULTI_SELECTABLE:
3178 IState = STATE_SYSTEM_MULTISELECTABLE;
3179 break;
3180 case /*AccessibleStateType::*/AccessibleStateType::PRESSED:
3181 IState = STATE_SYSTEM_PRESSED;
3182 break;
3183 case /*AccessibleStateType::*/AccessibleStateType::RESIZABLE:
3184 IState = STATE_SYSTEM_SIZEABLE;
3185 break;
3186 case /*AccessibleStateType::*/AccessibleStateType::SELECTABLE:
3187 IState = STATE_SYSTEM_SELECTABLE;
3188 break;
3189 case /*AccessibleStateType::*/AccessibleStateType::SELECTED:
3190 IState = STATE_SYSTEM_SELECTED;
3191 break;
3192 case /*AccessibleStateType::*/AccessibleStateType::ARMED:
3193 IState = STATE_SYSTEM_FOCUSED;
3194 break;
3195 case /*AccessibleStateType::*/AccessibleStateType::EXPANDABLE:
3196 IState = STATE_SYSTEM_COLLAPSED;
3197 break;
3198 default:
3199 break;
3201 return IState;
3204 STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
3206 SolarMutexGuard g;
3208 ENTER_PROTECTED_BLOCK
3209 ISDESTROY()
3210 if(name == NULL)
3211 return E_INVALIDARG;
3213 *name = SysAllocString(OLESTR("Hannover"));
3214 return S_OK;
3215 LEAVE_PROTECTED_BLOCK
3217 STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
3219 SolarMutexGuard g;
3221 ENTER_PROTECTED_BLOCK
3222 ISDESTROY()
3223 if(version == NULL)
3224 return E_INVALIDARG;
3225 *version=SysAllocString(OLESTR("3.0"));
3226 return S_OK;
3227 LEAVE_PROTECTED_BLOCK
3229 STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
3231 SolarMutexGuard g;
3233 ENTER_PROTECTED_BLOCK
3234 ISDESTROY()
3235 if(name == NULL)
3236 return E_INVALIDARG;
3237 *name = SysAllocString(OLESTR(" "));
3238 return S_OK;
3239 LEAVE_PROTECTED_BLOCK
3241 STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
3243 SolarMutexGuard g;
3245 ENTER_PROTECTED_BLOCK
3246 ISDESTROY()
3247 if(version == NULL)
3248 return E_INVALIDARG;
3249 *version = SysAllocString(OLESTR(" "));
3250 return S_OK;
3251 LEAVE_PROTECTED_BLOCK
3255 STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
3257 SolarMutexGuard g;
3259 ENTER_PROTECTED_BLOCK
3260 ISDESTROY()
3262 if (!m_xAccessible.is())
3263 return E_FAIL;
3265 Reference<XAccessibleContext> pRContext = m_xAccessible->getAccessibleContext();
3266 if( !pRContext.is() )
3268 return E_FAIL;
3270 Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
3271 if( !pRXI.is() )
3272 return E_FAIL;
3273 else
3275 css::uno::Reference<css::accessibility::XAccessibleExtendedAttributes> pRXAttr;
3276 pRXAttr = pRXI.get();
3277 css::uno::Any anyVal = pRXAttr->getExtendedAttributes();
3279 ::rtl::OUString val;
3280 anyVal >>= val;
3282 if(*pAttr)
3283 SAFE_SYSFREESTRING(*pAttr);
3284 *pAttr = SysAllocString((OLECHAR *)val.getStr());
3286 return S_OK;
3288 LEAVE_PROTECTED_BLOCK
3291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */