summaryrefslogtreecommitdiffstats
path: root/winaccessibility/source/UAccCOM/MAccessible.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'winaccessibility/source/UAccCOM/MAccessible.cxx')
-rw-r--r--winaccessibility/source/UAccCOM/MAccessible.cxx3262
1 files changed, 3262 insertions, 0 deletions
diff --git a/winaccessibility/source/UAccCOM/MAccessible.cxx b/winaccessibility/source/UAccCOM/MAccessible.cxx
new file mode 100644
index 000000000000..6216ac393d41
--- /dev/null
+++ b/winaccessibility/source/UAccCOM/MAccessible.cxx
@@ -0,0 +1,3262 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+#include "stdafx.h"
+#include "UAccCOM2.h"
+#include "MAccessible.h"
+
+#include <algorithm>
+#include "AccAction.h"
+
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleAction.hpp>
+#include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
+#include <com/sun/star/accessibility/XAccessibleHyperText.hpp>
+#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+#include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/TabStop.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include "AccessibleRole.h"
+
+
+using namespace com::sun::star::accessibility::AccessibleStateType;
+
+// IA2 states mapping, and name
+// maintenance the consistency, change one array, change the three all
+long IA2_STATES[] =
+ {
+ IA2_STATE_ACTIVE, // = 0x1;
+ IA2_STATE_ARMED, // = 0x2;
+ IA2_STATE_DEFUNCT, // = 0x4;
+ IA2_STATE_EDITABLE, // = 0x8;
+ IA2_STATE_HORIZONTAL, // = 0x10;
+ IA2_STATE_ICONIFIED, // = 0x20;
+ IA2_STATE_INVALID_ENTRY, // = 0x80;
+ IA2_STATE_MANAGES_DESCENDANTS, // = 0x100;
+ IA2_STATE_MODAL, // = 0x200;
+ IA2_STATE_MULTI_LINE, // = 0x400;
+ IA2_STATE_OPAQUE, // = 0x800;
+ IA2_STATE_REQUIRED, // = 0x2000;
+ IA2_STATE_SELECTABLE_TEXT, // = 0x3000;
+ IA2_STATE_SINGLE_LINE, // = 0x4000;
+ IA2_STATE_STALE, // = 0x8000;
+ IA2_STATE_SUPPORTS_AUTOCOMPLETION, // = 0x10000;
+ IA2_STATE_TRANSIENT, //= 0x20000;
+ IA2_STATE_VERTICAL // = 0x40000;
+ };
+/*
+
+<=== map ===>
+
+*/
+short UNO_STATES[] =
+ {
+ ACTIVE, // = (sal_Int16)1;
+ ARMED, // = (sal_Int16)2;
+ DEFUNC, // = (sal_Int16)5;
+ EDITABLE, // = (sal_Int16)6;
+ HORIZONTAL, // = (sal_Int16)12;
+ ICONIFIED, // = (sal_Int16)13;
+ -1, //IA2_STATE_INVALID_ENTRY
+ MANAGES_DESCENDANTS, // = (sal_Int16)15;
+ MODAL, // = (sal_Int16)16;
+ MULTI_LINE, // = (sal_Int16)17;
+ OPAQUE, // = (sal_Int16)19;
+ -1, //IA2_STATE_REQUIRED
+ -1, //IA2_STATE_SELECTABLE_TEXT
+ SINGLE_LINE, // = (sal_Int16)26;
+ STALE, // = (sal_Int16)27;
+ -1, //IA2_STATE_SUPPORTS_AUTOCOMPLETION
+ TRANSIENT, //IA2_STATE_TRANSIENT
+ VERTICAL // = (sal_Int16)29;
+ };
+
+// <=== map ===>
+
+BSTR IA2_STATES_NAME[] =
+ {
+ _T("Active"),
+ _T("Armed"),
+ _T("Defunct"),
+ _T("Editable"),
+ _T("Horizontal"),
+ _T("Iconified"),
+ _T("Invalid Entry"),
+ _T("Manages Decendents"),
+ _T("Modal"),
+ _T("Multi Line"),
+ _T("Opaque"),
+ _T("Required"),
+ _T("Selectable Text"),
+ _T("Single Line"),
+ _T("Stale"),
+ _T("Supports Autocompletion"),
+ _T("Transient"),
+ _T("Vertical")
+ };
+
+// IA2 states mapping, and name
+// maintenance the consistency. change one, change them all
+
+BSTR UNO_ALL_STATES[] =
+ {
+ _T("INVALID"), // INVALID ( 0 )
+ _T("ACTIVE"), // ACTIVE ( 1 )
+ _T("ARMED"), // ARMED ( 2 )
+ _T("BUSY"), // BUSY ( 3 )
+ _T("CHECKED"), // CHECKED ( 4 )
+ _T("DEFUNC"), // DEFUNC ( 5 )
+ _T("EDITABLE"), // EDITABLE ( 6 )
+ _T("ENABLED"), // ENABLED ( 7 )
+ _T("EXPANDABLE"), // EXPANDABLE ( 8 )
+ _T("EXPANDED"), // EXPANDED ( 9 )
+ _T("FOCUSABLE"), // FOCUSABLE ( 10 )
+ _T("FOCUSED"), // FOCUSED ( 11 )
+ _T("HORIZONTAL"), // HORIZONTAL ( 12 )
+ _T("ICONIFIED"), // ICONIFIED ( 13 )
+ _T("INDETERMINATE"), // INDETERMINATE ( 14 )
+ _T("MANAGES_DESCENDANTS"),// MANAGES_DESCENDANTS ( 15 )
+ _T("MODAL"), // MODAL ( 16 )
+ _T("MULTI_LINE"), // MULTI_LINE ( 17 )
+ _T("MULTI_SELECTABLE"), // MULTI_SELECTABLE ( 18 )
+ _T("OPAQUE"), // OPAQUE ( 19 )
+ _T("PRESSED"), // PRESSED ( 20 )
+ _T("RESIZABLE"), // RESIZABLE ( 21 )
+ _T("SELECTABLE"), // SELECTABLE ( 22 )
+ _T("SELECTED"), // SELECTED ( 23 )
+ _T("SENSITIVE"), // SENSITIVE ( 24 )
+ _T("SHOWING"), // SHOWING ( 25 )
+ _T("SINGLE_LINE"), // SINGLE_LINE ( 26 )
+ _T("STALE"), // STALE ( 27 )
+ _T("TRANSIENT"), // TRANSIENT ( 28 )
+ _T("VERTICAL"), // VERTICAL ( 29 )
+ _T("VISIBLE"), // VISIBLE ( 30 )
+ _T("MOVEABLE"), // MOVEABLE ( 31 )
+ _T("OFFSCREEN"), // OFFSCREEN ( 32 )
+ _T("COLLAPSE"), // COLLAPSE ( 33 )
+ _T("DEFAULT") // DEFAULT ( 34 )
+ };
+
+
+using namespace com::sun::star::accessibility::AccessibleRole;
+
+
+
+#define QUERYXINTERFACE(ainterface) \
+{ \
+ if(pXAcc == NULL) \
+ return FALSE; \
+ pRContext = pXAcc->getAccessibleContext(); \
+ if( !pRContext.is() ) \
+ { \
+ return FALSE; \
+ } \
+ Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
+ if( !pRXI.is() ) \
+ { \
+ return FALSE; \
+ } \
+ *ppXI = (XInterface*)pRXI.get(); \
+ return TRUE; \
+}
+
+#define ISDESTROY() \
+ if(m_isDestroy) \
+ return S_FALSE;
+
+
+AccObjectManagerAgent* CMAccessible::g_pAgent = NULL;
+
+CMAccessible::CMAccessible():
+ m_iRole(0x00),
+ m_dState(0x00),
+ m_dChildID(0x00),
+ m_dFocusChildID(UACC_NO_FOCUS),
+ m_hwnd(NULL),
+ m_pIParent(NULL),
+ m_pszName(NULL),
+ m_pszValue(NULL),
+ m_pszDescription(NULL),
+ m_isDestroy(FALSE),
+ m_pszActionDescription(NULL),
+ m_pXAction(NULL),
+ m_bRequiresSave(FALSE),
+ pUNOInterface(NULL)
+{
+ m_sLocation.m_dLeft=0;
+ m_sLocation.m_dTop = 0;
+ m_sLocation.m_dWidth=0;
+ m_sLocation.m_dHeight=0;
+ CEnumVariant::Create(&m_pEnumVar);
+}
+
+CMAccessible::~CMAccessible()
+{
+ if(m_pszName!=NULL)
+ {
+ SAFE_SYSFREESTRING(m_pszName);
+ m_pszName=NULL;
+ }
+ if(m_pszValue!=NULL)
+ {
+ SAFE_SYSFREESTRING(m_pszValue);
+ m_pszValue=NULL;
+ }
+ if(m_pszDescription!=NULL)
+ {
+ SAFE_SYSFREESTRING(m_pszDescription);
+ m_pszDescription=NULL;
+ }
+
+ if(m_pszActionDescription!=NULL)
+ {
+ SAFE_SYSFREESTRING(m_pszActionDescription);
+ m_pszActionDescription=NULL;
+ }
+
+ if(m_pIParent)
+ {
+ m_pIParent->Release();
+ m_pIParent=NULL;
+ }
+ pRef = NULL;
+ m_pEnumVar->Release();
+ m_containedObjects.clear();
+ pRContext = NULL;
+}
+
+/**
+* Returns the Parent IAccessible interface pointer to AT.
+* It should add reference, and the client should release the component.
+* It should return E_FAIL when the parent point is null.
+* @param ppdispParent [in,out] used to return the parent interface point.
+* when the point is null, should return null.
+* @return S_OK if successful and E_FAIL if the m_pIParent is NULL.
+*/
+STDMETHODIMP CMAccessible::get_accParent(IDispatch **ppdispParent)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(ppdispParent == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if(m_pIParent)
+ {
+ *ppdispParent = m_pIParent;
+ (*ppdispParent)->AddRef();
+ return S_OK;
+ }
+ else if(m_hwnd)
+ {
+ HRESULT hr = AccessibleObjectFromWindow(m_hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent);
+ if( ! SUCCEEDED( hr ) || ! ppdispParent )
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns child count of current COM object.
+* @param pcountChildren [in,out] used to return the children count.
+* @return S_OK if successful.
+*/
+STDMETHODIMP CMAccessible::get_accChildCount(long *pcountChildren)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pcountChildren == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if(!pUNOInterface)
+ return S_FALSE;
+
+ Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
+ if( pRContext.is() )
+ {
+ *pcountChildren = pRContext->getAccessibleChildCount();
+ }
+
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns child interface pointer for AT according to input child ID.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param ppdispChild, [in,out] use to return the child interface point.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(ppdispChild == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt==VT_I4)
+ {
+ //get child interface pointer due to child ID
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ AddRef();
+ *ppdispChild = this;
+ return S_OK;
+ }
+ *ppdispChild = GetChildInterface(varChild.lVal);
+ (*ppdispChild)->AddRef();
+ return (*ppdispChild)?S_OK:S_FALSE;
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible name of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszName, [in,out] use to return the name of the proper object.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accName(VARIANT varChild, BSTR *pszName)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszName == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ SAFE_SYSFREESTRING(*pszName);
+ *pszName = SysAllocString(m_pszName);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accName(varChild,pszName);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible value of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszValue, [in,out] use to return the value of the proper object.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accValue(VARIANT varChild, BSTR *pszValue)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if( pszValue == NULL )
+ {
+ return E_INVALIDARG;
+ }
+ if( varChild.vt==VT_I4 )
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ if(m_dState & STATE_SYSTEM_PROTECTED)
+ return E_ACCESSDENIED;
+
+ if ( m_pszValue !=NULL && wcslen(m_pszValue) == 0 )
+ return S_OK;
+
+ SAFE_SYSFREESTRING(*pszValue);
+ *pszValue = SysAllocString(m_pszValue);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accValue(varChild,pszValue);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible description of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszDescription, [in,out] use to return the description of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::get_accDescription(VARIANT varChild, BSTR *pszDescription)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszDescription == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ SAFE_SYSFREESTRING(*pszDescription);
+ *pszDescription = SysAllocString(m_pszDescription);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accDescription(varChild,pszDescription);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible role of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pvarRole, [in,out] use to return the role of the proper object.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accRole(VARIANT varChild, VARIANT *pvarRole)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarRole == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt == VT_I4)
+ {
+
+ if(varChild.lVal == CHILDID_SELF)
+ {
+ if( m_iRole < IA2_ROLE_CAPTION )
+ {
+ VariantInit(pvarRole);
+ pvarRole->vt = VT_I4;
+ pvarRole->lVal = m_iRole;
+ }
+ else
+ {
+ VariantInit(pvarRole);
+ pvarRole->vt = VT_I4;
+ pvarRole->lVal = ROLE_SYSTEM_CLIENT;
+ }
+ return S_OK;
+ }
+
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accRole(varChild,pvarRole);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible state of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pvarState, [in,out] use to return the state of the proper object.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accState(VARIANT varChild, VARIANT *pvarState)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarState == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal == CHILDID_SELF)
+ {
+ if(pUNOInterface)
+ {
+ Reference< XAccessibleContext > pContext = pUNOInterface->getAccessibleContext();
+ if(pContext.is())
+ {
+ // add the STATE_SYSTEM_LINKED state
+ Reference< XAccessibleHypertext > pRHypertext(pContext,UNO_QUERY);
+ if(pRHypertext.is())
+ {
+ if( pRHypertext->getHyperLinkCount() > 0 )
+ m_dState |= STATE_SYSTEM_LINKED;
+ else
+ m_dState &= ~STATE_SYSTEM_LINKED;
+ }
+ else
+ m_dState &= ~STATE_SYSTEM_LINKED;
+ }
+ }
+
+ VariantInit(pvarState);
+ pvarState->vt = VT_I4;
+ pvarState->lVal = m_dState;
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accState(varChild,pvarState);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the accessible helpString of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszHelp, [in,out] use to return the helpString of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::get_accHelp(VARIANT, BSTR *)
+{
+ return E_NOTIMPL;
+}
+
+/**
+* Returns the accessible HelpTopic of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
+* @param pidTopic, use to return the HelpTopic ID of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+* Not implemented yet
+*/
+STDMETHODIMP CMAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
+{
+ return E_NOTIMPL;
+}
+
+static void GetMnemonicChar( const ::rtl::OUString& aStr, WCHAR* wStr)
+{
+ int nLen = aStr.pData->length;
+ int i = 0;
+ WCHAR* text = aStr.pData->buffer;
+
+ while ( i < nLen )
+ {
+ if ( text[i] == L'~' )
+ if ( text[i+1] != L'~' )
+ {
+ wStr[0] = text[i+1];
+ break;
+ }
+ i++;
+ }
+}
+
+/**
+* Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+
+ ISDESTROY()
+ // #CHECK#
+ if(pszKeyboardShortcut == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal == CHILDID_SELF)
+ {
+ if( pUNOInterface )
+ {
+ Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
+ if( !pRContext.is() )
+ return S_FALSE;
+
+ Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
+
+ OLECHAR wString[64]={0};
+
+ if( pRXI.is() && pRXI->getAccessibleActionCount() >= 1)
+ {
+ Reference< XAccessibleKeyBinding > binding = pRXI->getAccessibleActionKeyBinding(0);
+ if( binding.is() )
+ {
+ long nCount = binding->getAccessibleKeyBindingCount();
+ if(nCount >= 1)
+ {
+ CAccAction::GetkeyBindingStrByXkeyBinding( binding->getAccessibleKeyBinding(0),wString );
+ }
+ }
+ }
+ if(wString[0] == 0)
+ {
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
+ if(!pRrelationSet.is())
+ {
+ return S_FALSE;
+ }
+
+ long nRelCount = pRrelationSet->getRelationCount();
+
+ // Modified by Steve Yin, for SODC_1552
+ if( /*nRelCount <= 0 &&*/ m_iRole == ROLE_SYSTEM_TEXT )
+ {
+ VARIANT varParentRole;
+ VariantInit( &varParentRole );
+
+ m_pIParent->get_accRole(varChild, &varParentRole);
+
+ if( m_pIParent && varParentRole.lVal == ROLE_SYSTEM_COMBOBOX ) // edit in comoboBox
+ {
+ m_pIParent->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
+ return S_OK;
+ }
+ }
+
+ AccessibleRelation *paccRelation = NULL;
+ AccessibleRelation accRelation;
+ for(int i=0; i<nRelCount ; i++)
+ {
+ if( pRrelationSet->getRelation(i).RelationType == 6 )
+ {
+ accRelation = pRrelationSet->getRelation(i);
+ paccRelation = &accRelation;
+ }
+ }
+
+ if(paccRelation == NULL)
+ return S_FALSE;
+
+ Sequence< Reference< XInterface > > xTargets = paccRelation->TargetSet;
+ Reference<XInterface> pRAcc = xTargets[0];
+
+ XAccessible* pXAcc = (XAccessible*)pRAcc.get();
+
+ Reference<XAccessibleContext> pRLebelContext = pXAcc->getAccessibleContext();
+ if(!pRLebelContext.is())
+ return S_FALSE;
+
+ pRrelationSet = pRLebelContext->getAccessibleRelationSet();
+ nRelCount = pRrelationSet->getRelationCount();
+
+ paccRelation = NULL;
+ for(int j=0; j<nRelCount ; j++)
+ {
+ if( pRrelationSet->getRelation(j).RelationType == 5 )
+ {
+ accRelation = pRrelationSet->getRelation(j);
+ paccRelation = &accRelation;
+ }
+ }
+
+ if(paccRelation)
+ {
+ xTargets = paccRelation->TargetSet;
+ pRAcc = xTargets[0];
+ if(pUNOInterface != (XAccessible*)pRAcc.get())
+ return S_FALSE;
+ }
+
+ Reference<XAccessibleExtendedComponent> pRXIE(pRLebelContext,UNO_QUERY);
+ if(!pRXIE.is())
+ return S_FALSE;
+
+ ::rtl::OUString ouStr = pRXIE->getTitledBorderText();
+ WCHAR key[2] = {NULL};
+ GetMnemonicChar(ouStr, key);
+ if(key[0] != 0)
+ {
+ wcscat(wString, L"Alt+");
+ wcscat(wString, key);
+ }
+ else
+ return S_FALSE;
+ }
+
+ SAFE_SYSFREESTRING(*pszKeyboardShortcut);
+ *pszKeyboardShortcut = SysAllocString(wString);
+
+ return S_OK;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+
+ return pChild->get_accKeyboardShortcut(varChild,pszKeyboardShortcut);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the current focused child to AT.
+* @param pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::get_accFocus(VARIANT *pvarChild)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarChild == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if( m_dFocusChildID==UACC_NO_FOCUS )
+ {
+ pvarChild->vt = VT_EMPTY;//no focus on the object and its children
+ return S_OK;
+ }
+ //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
+ else
+ {
+ IMAccessible* pIMAcc = NULL;
+ g_pAgent->GetIAccessibleFromResID(m_dFocusChildID,&pIMAcc);
+ pIMAcc->AddRef();
+ pvarChild->vt = VT_DISPATCH;
+ pvarChild->pdispVal = pIMAcc;
+
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the selection of the current COM object to AT.
+* @param pvarChildren,[in,out]
+* if selection num is 0,return VT_EMPTY for vt,
+* if selection num is 1,return VT_I4 for vt,and child index for lVal
+* if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarChildren == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ switch(m_pEnumVar->GetCountOfElements())
+ {
+ case 0:
+ pvarChildren->vt = VT_EMPTY;
+ break;
+ case 1:
+ VARIANT varTmp[1];
+ ULONG count;
+ VariantInit(&varTmp[0]);
+ m_pEnumVar->Next(1,varTmp,&count);
+ if(count!=1)
+ return S_FALSE;
+ pvarChildren->vt = VT_I4;
+ pvarChildren->lVal = varTmp[0].lVal;
+ VariantClear(&varTmp[0]);
+ m_pEnumVar->Reset();
+ break;
+ default:
+ pvarChildren->vt = VT_UNKNOWN;
+ m_pEnumVar->AddRef();
+ pvarChildren->punkVal = m_pEnumVar;
+ break;
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the location of the current COM object self or its one child to AT.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param pxLeft, [in,out] use to return the x-coordination of the proper object.
+* @param pyTop, [in,out] use to return the y-coordination of the proper object.
+* @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
+* @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pxLeft == NULL || pyTop == NULL || pcxWidth == NULL || pcyHeight == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+
+ if(pUNOInterface)
+ {
+ Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
+ if( !pRContext.is() )
+ return S_FALSE;
+ Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
+ if( !pRComponent.is() )
+ return S_FALSE;
+
+ ::com::sun::star::awt::Point pCPoint = pRComponent->getLocationOnScreen();
+ ::com::sun::star::awt::Size pCSize = pRComponent->getSize();
+ *pxLeft = pCPoint.X;
+ *pyTop = pCPoint.Y;
+ *pcxWidth = pCSize.Width;
+ *pcyHeight = pCSize.Height;
+ return S_OK;
+ }
+ else
+ {
+ *pxLeft = m_sLocation.m_dLeft;
+ *pyTop = m_sLocation.m_dTop;
+ *pcxWidth = m_sLocation.m_dWidth;
+ *pcyHeight = m_sLocation.m_dHeight;
+ return S_OK;
+ }
+ }
+
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Returns the current focused child to AT.
+* @param navDir, the direction flag of the navigation.
+* @param varStart, the start child id of this navigation action.
+* @param pvarEndUpAt, [in,out] the end up child of this navigation action.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarEndUpAt == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ HRESULT ret = E_FAIL;
+ switch (navDir)
+ {
+ case NAVDIR_FIRSTCHILD:
+ ret = GetFirstChild(varStart,pvarEndUpAt);
+ break;
+ case NAVDIR_LASTCHILD:
+ ret = GetLastChild(varStart,pvarEndUpAt);
+ break;
+ case NAVDIR_NEXT:
+ ret = GetNextSibling(varStart,pvarEndUpAt);
+ break;
+ case NAVDIR_PREVIOUS:
+ ret = GetPreSibling(varStart,pvarEndUpAt);
+ break;
+ case NAVDIR_DOWN://do not implement temporarily
+ break;
+ case NAVDIR_UP://do not implement temporarily
+ break;
+ case NAVDIR_LEFT://do not implement temporarily
+ break;
+ case NAVDIR_RIGHT://do not implement temporarily
+ break;
+ default:
+ break;
+ };
+ return ret;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarChild == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ long x, y, w, h;
+ VARIANT varSelf;
+ VariantInit(&varSelf);
+ varSelf.vt = VT_I4;
+ varSelf.lVal = CHILDID_SELF;
+ accLocation(&x,&y,&w,&h,varSelf);
+ if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
+ {
+ int i, nCount;
+ pvarChild->vt = VT_EMPTY;
+ Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
+ nCount = pRContext->getAccessibleChildCount();
+ if(nCount > 256)
+ return E_FAIL;
+ IMAccessible* child = NULL;
+ for( i = 0; i<nCount; i++)
+ {
+
+ child = GetChildInterface(i + 1);
+ if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
+ break;
+ }
+
+ if(pvarChild->vt == VT_DISPATCH)
+ return S_OK;
+
+ if( i < nCount)
+ {
+ pvarChild->vt = VT_DISPATCH;
+ pvarChild->pdispVal = child;
+ child->AddRef();
+ }
+ else
+ {
+ pvarChild->vt = VT_I4;
+ pvarChild->lVal = CHILDID_SELF;
+ }
+ return S_OK;
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Get The other Interface from CMAccessible.
+* @param guidService, must be IID_IAccessible here.
+* @param riid, the IID interface .
+* @return S_OK if successful and S_FALSE if failure.
+*/
+STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
+{
+ if( InlineIsEqualGUID(guidService, IID_IAccessible) )
+ return QueryInterface(riid, ppvObject);
+ return S_FALSE;
+}
+
+/**
+* Set the accessible name of the current COM object self or its one child from UNO.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param szName, the name used to set the name of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ SAFE_SYSFREESTRING(m_pszName);
+ m_pszName=SysAllocString(szName);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->put_accName(varChild,szName);
+ }
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set the accessible value of the current COM object self or its one child from UNO.
+* @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
+* the child ID specify child index from 0 to children count, 0 stands for object self.
+* @param szValue, the value used to set the value of the proper object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ SysAllocString(m_pszValue);
+ m_pszValue=SysAllocString(szValue);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->put_accValue(varChild,szValue);
+ }
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set the accessible name of the current COM object self from UNO.
+* @param pszName, the name value used to set the name of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszName == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ SAFE_SYSFREESTRING(m_pszName);//??
+ m_pszName = SysAllocString(pszName);
+ if(m_pszName==NULL)
+ return E_FAIL;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set the accessible role of the current COM object self from UNO.
+* @param pRole, the role value used to set the role of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
+{
+ m_iRole = pRole;
+ return S_OK;
+}
+
+/**
+* Add one state into the current state set for the current COM object from UNO.
+* @param pXSate, the state used to set the name of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
+{
+ m_dState &= (~pXSate);
+ return S_OK;
+}
+
+/**
+* Delete one state into the current state set for the current COM object from UNO.
+* @param pXSate, the state used to set the name of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
+{
+ m_dState |= pXSate;
+ return S_OK;
+}
+
+/**
+* Set state into the current state set for the current COM object from UNO.
+* @param pXSate, the state used to set the name of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
+{
+ m_dState = pXSate;
+ return S_OK;
+}
+
+
+
+/**
+* Set the accessible description of the current COM object self from UNO.
+* @param pszDescription, the name used to set the description of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszDescription == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ SAFE_SYSFREESTRING(m_pszDescription);
+ m_pszDescription = SysAllocString(pszDescription);
+
+ if(m_pszDescription==NULL)
+ return E_FAIL;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set the accessible value of the current COM object self from UNO.
+* @param pszAccValue, the name used to set the value of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszAccValue == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ SAFE_SYSFREESTRING(m_pszValue);
+ m_pszValue = SysAllocString(pszAccValue);
+ if(m_pszValue==NULL)
+ return E_FAIL;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
+* Object through the method AccessibleObjectFromWindow(...).
+* @param hwnd, the HWND used to set the value of the current object.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ m_hwnd = hwnd;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+* Set accessible focus by specifying child ID
+* @param dChildID, the child id identifies the focus child.
+* @return S_OK if successful and E_FAIL if failure.
+*/
+STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+
+ if(dChildID==CHILDID_SELF)
+ {
+ if(m_pIParent)
+ {
+ m_pIParent->Put_XAccFocus(m_dChildID);
+ }
+ }
+ else
+ {
+ m_dFocusChildID = dChildID;
+ //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
+ //any of the ancestors, this id can be used to get the IAccessible of focused object.
+ if(m_pIParent)
+ {
+ m_pIParent->Put_XAccFocus(dChildID);
+ }
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ *Set accessible object location for the current COM object
+ * @param sLocation, the location of the current object.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
+{
+
+ this->m_sLocation = sLocation;
+ return S_OK;
+}
+
+/**
+ * Set accessible parent object for the current COM object if
+ * the current object is a child of some COM object
+ * @param pIParent, the parent of the current object.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
+{
+ this->m_pIParent = pIParent;
+
+ if(pIParent)
+ m_pIParent->AddRef();
+
+ return S_OK;
+}
+
+/**
+ * Set unique child id to COM
+ * @param dChildID, the id of the current object.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
+{
+
+ this->m_dChildID = dChildID;
+ return S_OK;
+}
+
+/**
+ * Set AccObjectManagerAgent object pointer to COM
+ * @param pAgent, the AccObjectManagerAgent point.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+STDMETHODIMP CMAccessible::Put_XAccAgent(long pAgent)
+{
+ g_pAgent = (AccObjectManagerAgent*)pAgent;
+ return S_OK;
+}
+
+/**
+ * When a UNO control disposing, it disposes its listeners,
+ * then notify AccObject in bridge management, then notify
+ * COM that the XAccessible is invalid,so set pUNOInterface as NULL
+ * @param isDestroy, true is it need to be destroyed.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
+{
+
+ m_isDestroy = isDestroy;
+ pUNOInterface = NULL;
+ return S_OK;
+}
+
+/**
+ *private methods that help implement public functions
+ */
+
+/**
+ * Return child interface pointer by child ID,note: need to call AddRef()
+ * @param lChildID, specify child index,which AT(such as Inspect32) gives.
+ * @return IMAccessible*, pointer to the corresponding child object.
+ */
+IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
+{
+
+ long dChildIndex = 0;
+ if(dChildID<0)
+ {
+ if(g_pAgent)
+ {
+ IMAccessible* pIMAcc = NULL;
+ g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
+ return pIMAcc;
+ }
+ return NULL;
+ }
+ else
+ {
+ Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
+ if( !pRContext.is() )
+ return NULL;
+
+ if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
+ return NULL;
+
+ IAccessible* pChild = NULL;
+ Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
+ BOOL isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
+
+ if(!isGet)
+ {
+ g_pAgent->InsertAccObj(pXChild.get(),pUNOInterface,(long)m_hwnd);
+ isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
+ }
+
+ if(isGet)
+ {
+ IMAccessible* pIMAcc = (IMAccessible*)pChild;
+ return pIMAcc;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * For List, tree and table,these roles belong to manage_decendant in UNO,
+ * need to process specifically when navigate
+ * @return BOOL, if it is decendantmanager, return true.
+ */
+BOOL CMAccessible::IsDecendantManage()
+{
+
+ return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
+}
+
+/**
+ * for decendantmanager circumstance,provide child interface when navigate
+ * @param varCur, the current child.
+ * @param flags, the navigation direction.
+ * @return IMAccessible*, the child of the end up node.
+ */
+IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
+{
+
+ XAccessibleContext* pXContext = GetContextByXAcc(pUNOInterface);
+ if(pXContext==NULL)
+ {
+ return NULL;
+ }
+
+ int count = pXContext->getAccessibleChildCount();
+ if(count<1)
+ {
+ return NULL;
+ }
+
+ IMAccessible* pCurChild = NULL;
+ XAccessible* pChildXAcc = NULL;
+ Reference<XAccessible> pRChildXAcc;
+ XAccessibleContext* pChildContext = NULL;
+ int index = 0,delta=0;
+ switch(flags)
+ {
+ case DM_FIRSTCHILD:
+ pRChildXAcc = pXContext->getAccessibleChild(0);
+ break;
+ case DM_LASTCHILD:
+ pRChildXAcc = pXContext->getAccessibleChild(count-1);
+ break;
+ case DM_NEXTCHILD:
+ case DM_PREVCHILD:
+ pCurChild = GetChildInterface(varCur.lVal);
+ if(pCurChild==NULL)
+ {
+ return NULL;
+ }
+ pCurChild->GetUNOInterface((long*)&pChildXAcc);
+ if(pChildXAcc==NULL)
+ {
+ return NULL;
+ }
+ pChildContext = GetContextByXAcc(pChildXAcc);
+ if(pChildContext == NULL)
+ {
+ return NULL;
+ }
+ delta = (flags==DM_NEXTCHILD)?1:-1;
+ //currently, getAccessibleIndexInParent is error in UNO for
+ //some kind of List,such as ValueSet, the index will be less 1 than
+ //what should be, need to fix UNO code
+ index = pChildContext->getAccessibleIndexInParent()+delta;
+ if((index>=0)&&(index<=count-1))
+ {
+ pRChildXAcc = pXContext->getAccessibleChild(index);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if(!pRChildXAcc.is())
+ {
+ return NULL;
+ }
+ pChildXAcc = pRChildXAcc.get();
+ g_pAgent->InsertAccObj(pChildXAcc,pUNOInterface);
+ return g_pAgent->GetIMAccByXAcc(pChildXAcc);
+}
+
+/**
+ *the following 4 private methods are for accNavigate implementation
+ */
+
+/**
+ * Return first child for parent container, process differently according
+ * to whether it is decendant manage
+ * @param varStart, the start child id of this navigation action.
+ * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarEndUpAt == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varStart.vt != VT_I4)
+ {
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_INVALIDARG;
+ }
+
+ pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
+ if(pvarEndUpAt->pdispVal)
+ {
+ pvarEndUpAt->pdispVal->AddRef();
+ pvarEndUpAt->vt = VT_DISPATCH;
+ return S_OK;
+ }
+
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Return last child for parent container, process differently according
+ * to whether it is decendant manage
+ * @param varStart, the start child id of this navigation action.
+ * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarEndUpAt == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varStart.vt != VT_I4)
+ {
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_INVALIDARG;
+ }
+
+ pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
+ if(pvarEndUpAt->pdispVal)
+ {
+ pvarEndUpAt->pdispVal->AddRef();
+ pvarEndUpAt->vt = VT_DISPATCH;
+ return S_OK;
+ }
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * The method GetNextSibling is general, whatever it is decendant manage or not
+ * Get the next sibling object.
+ * @param varStart, the start child id of this navigation action.
+ * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(varStart.vt != VT_I4)
+ {
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_INVALIDARG;
+ }
+
+ Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
+ if(pRContext.is())
+ {
+ varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
+ if(m_pIParent)
+ if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
+ {
+ pvarEndUpAt->vt = VT_DISPATCH;
+ return S_OK;
+ }
+ }
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ *the method GetPreSibling is general, whatever it is decendant manage or not
+ * @param varStart, the start child id of this navigation action.
+ * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
+ * @return S_OK if successful and E_FAIL if failure.
+ */
+HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pvarEndUpAt == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varStart.vt != VT_I4)
+ {
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_INVALIDARG;
+ }
+
+ Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
+ if(pRContext.is())
+ {
+ varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
+ if(m_pIParent && varStart.iVal > 0)
+ if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
+ {
+ pvarEndUpAt->vt = VT_DISPATCH;
+ return S_OK;
+ }
+ }
+ pvarEndUpAt->vt = VT_EMPTY;
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * For IAccessible2 implementation methods
+ */
+STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+
+ // #CHECK#
+ if(nRelations == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ *nRelations = 0;
+
+ if( !pRContext.is() )
+ return E_FAIL;
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
+ if(!pRrelationSet.is())
+ {
+ *nRelations = 0;
+ return S_OK;
+ }
+
+ *nRelations = pRrelationSet->getRelationCount();
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(relation == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if( !pRContext.is() )
+ return E_FAIL;
+
+
+ long nMax = 0;
+ long nReal = 0;
+ get_nRelations(&nMax);
+
+ *relation = (IAccessibleRelation*)::CoTaskMemAlloc(sizeof(IAccessibleRelation));
+
+ // #CHECK Memory Allocation#
+ if(*relation == NULL)
+ {
+ return E_FAIL;
+ }
+
+ if( relationIndex < nMax )
+ {
+
+
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
+ if(!pRrelationSet.is())
+ {
+
+ return E_FAIL;
+ }
+
+ IAccessibleRelation* pRelation = NULL;
+ HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
+ IID_IAccessibleRelation,
+ (void **)&pRelation);
+ if(SUCCEEDED(hr))
+ {
+ IUNOXWrapper* wrapper = NULL;
+ hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
+ if(SUCCEEDED(hr))
+ {
+ AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
+ wrapper->put_XSubInterface((long)&accRelation);
+ wrapper->Release();
+ *relation = pRelation;
+ return S_OK;
+ }
+
+ }
+ }
+
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+
+ // #CHECK#
+ if(relation == NULL || nRelations == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ // #CHECK XInterface#
+
+ if( !pRContext.is() )
+ return E_FAIL;
+
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
+ if(!pRrelationSet.is())
+ {
+ *nRelations = 0;
+ return S_OK;
+ }
+
+ long nCount = pRrelationSet->getRelationCount();
+
+ *relation = (IAccessibleRelation*)::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation));
+
+ // #CHECK Memory Allocation#
+ if(*relation == NULL)
+ {
+ return E_FAIL;
+ }
+
+ for(int i=0; i<nCount ; i++)
+ {
+ IAccessibleRelation* pRelation = NULL;
+ HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
+ IID_IAccessibleRelation,
+ (void **)&pRelation);
+ if(SUCCEEDED(hr))
+ {
+ IUNOXWrapper* wrapper = NULL;
+ hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
+ if(SUCCEEDED(hr))
+ {
+ AccessibleRelation accRelation = pRrelationSet->getRelation(i);
+ wrapper->put_XSubInterface((long)&accRelation);
+ wrapper->Release();
+ }
+ (relation)[i] = pRelation;
+ }
+ }
+
+ *nRelations = nCount;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
+{
+ ENTER_PROTECTED_BLOCK
+
+ (*role) = m_iRole;
+
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+
+STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
+{
+
+ try
+ {
+ ISDESTROY()
+ // #CHECK#
+ if(nActions == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ *nActions = 0L;
+ IAccessibleAction* pAcc = NULL;
+ HRESULT hr = QueryInterface(IID_IAccessibleAction, (void**)&pAcc);
+ if( hr == S_OK )
+ {
+ pAcc->nActions(nActions);
+ pAcc->Release();
+ }
+
+ return S_OK;
+ }
+ catch(...)
+ {
+ *nActions = 0L;
+ return S_OK;
+ }
+}
+
+
+STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ return E_NOTIMPL;
+ LEAVE_PROTECTED_BLOCK
+
+}
+STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
+{
+ // #CHECK#
+ if(pXAcc == NULL)
+ {
+ return NULL;
+ }
+ Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
+ long nRelations = pRrelationSet->getRelationCount();
+ for(int i=0 ; i<nRelations ; i++)
+ {
+ AccessibleRelation accRelation = pRrelationSet->getRelation(i);
+ if(accRelation.RelationType == 7)
+ {
+ Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
+ return (XAccessible*)xTargets[0].get();
+ }
+ }
+ return NULL;
+}
+
+STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(groupLevel == NULL || similarItemsInGroup == NULL || positionInGroup == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
+ if(!pRContext.is())
+ return E_FAIL;
+ long Role = pRContext->getAccessibleRole();
+
+ *groupLevel = 0;
+ *similarItemsInGroup = 0;
+ *positionInGroup = 0;
+
+ if (Role != AccessibleRole::DOCUMENT)
+ {
+ Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
+ if ( xGroupPosition.is() )
+ {
+ Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
+ sal_Int32* pSeq = rSeq.getArray();
+ if ( pSeq )
+ {
+ *groupLevel = pSeq[0];
+ *similarItemsInGroup = pSeq[1];
+ *positionInGroup = pSeq[2];
+ return S_OK;
+ }
+ return S_OK;
+ }
+ }
+
+ Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
+ if( !pParentAcc.is() )
+ {
+ return S_OK;
+ }
+
+ Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
+
+ int level = 0;
+ int index = 0;
+ int number = 0;
+
+ if( Role == RADIO_BUTTON )
+ {
+ Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
+ long nRel = pRrelationSet->getRelationCount();
+ for(int i=0 ; i<nRel ; i++)
+ {
+ AccessibleRelation accRelation = pRrelationSet->getRelation(i);
+ if(accRelation.RelationType == 7)
+ {
+ Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
+ int nCount = xTargets.getLength();
+
+ Reference<XInterface> pRAcc = xTargets[0];
+ for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
+ {
+ if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
+ == (XAccessible*)pRAcc.get() &&
+ pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
+ number++;
+ if(pRParentContext->getAccessibleChild(j).get() == pUNOInterface)
+ index = number;
+ }
+ }
+ }
+ *groupLevel = 1;
+ *similarItemsInGroup = number;
+ *positionInGroup = index;
+ return S_OK;
+ }
+
+ else if ( COMBO_BOX == Role )
+ {
+ *groupLevel = 1;
+ *similarItemsInGroup = 0;
+ *positionInGroup = -1;
+
+ long nCount = pRContext->getAccessibleChildCount();
+ if( 2 != nCount)
+ {
+ return S_OK;
+ }
+ Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
+ if (!xList.is())
+ {
+ return S_OK;
+ }
+ Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
+ if (!xListContext.is())
+ {
+ return S_OK;
+ }
+ Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
+ if (!xListSel.is())
+ {
+ return S_OK;
+ }
+ *similarItemsInGroup = xListContext->getAccessibleChildCount();
+ if (*similarItemsInGroup > 0 )
+ {
+ try
+ {
+ Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
+ if (xChild.is())
+ {
+ Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
+ if (xChildContext.is())
+ {
+ *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
+ return S_OK;
+ }
+ }
+ }
+ catch(...)
+ {}
+ }
+ return S_OK;
+ }
+ else if ( PAGE_TAB == Role )
+ {
+ *groupLevel = 1;
+ *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
+
+ if (*similarItemsInGroup > 0 )
+ {
+ *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
+ }
+ else
+ {
+ *positionInGroup = -1;
+ }
+ return S_OK;
+ }
+
+
+ BOOL isFound = FALSE;
+ while( pParentAcc.is() && !isFound)
+ {
+ level++;
+ pRParentContext = pParentAcc->getAccessibleContext();
+ Role = pRParentContext->getAccessibleRole();
+ if( (Role == TREE) || (Role == LIST) )
+ isFound = TRUE;
+ pParentAcc = pRParentContext->getAccessibleParent();
+ }
+
+ if( isFound )
+ {
+ Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
+ pRParentContext = pTempAcc->getAccessibleContext();
+ *groupLevel = level;
+ *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
+ *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
+ }
+ else
+ {
+ *groupLevel = 0;
+ *similarItemsInGroup = 0;
+ *positionInGroup = 0;
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+
+STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(uniqueID == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ *uniqueID = m_dChildID;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(windowHandle == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HWND nHwnd = m_hwnd;
+ IAccessible* pParent = m_pIParent;
+ CMAccessible* pChild = this;
+ while((nHwnd==0) && pParent)
+ {
+ pChild = (CMAccessible*)pParent;
+ if(pChild)
+ {
+ pParent = (IAccessible*)pChild->m_pIParent;
+ nHwnd = (HWND)pChild->m_hwnd;
+ }
+ else
+ pParent = NULL;
+ }
+
+ *windowHandle = nHwnd;
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
+ * @param pXAcc, UNO XAccessible object point.
+ * @return XAccessibleContext*, the context of the pXAcc.
+ */
+XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
+{
+ Reference< XAccessibleContext > pRContext;
+ if( pXAcc == NULL)
+ return NULL;
+
+ pRContext = pXAcc->getAccessibleContext();
+ if( !pRContext.is() )
+ return NULL;
+ return pRContext.get();
+}
+
+/**
+ * Return the member variable m_pXAccessibleSelection, instead of
+ * get XAccessibleSelection according to XAccessibleContext because if so,it will
+ * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
+ * by bridge management system
+ * @return XAccessibleSelection*, the selection of the current object.
+ */
+Reference< XAccessibleSelection > CMAccessible::GetSelection()
+{
+ if( pUNOInterface == NULL )
+ return NULL;
+ Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
+ if(pRContext.is())
+ {
+ Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
+ return pRSelection;
+ }
+ return NULL;
+}
+
+/**
+ * Select one XAccessible item, for accSelect implementation
+ * @param pItem, the item should be selected.
+ * @return S_OK if successful.
+ */
+HRESULT CMAccessible::SelectChild(XAccessible* pItem)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
+ XAccessibleContext* pContext = GetContextByXAcc( pItem );
+ if( pParentContext == NULL || pContext == NULL )
+ return E_FAIL;
+
+ Reference< XAccessibleSelection > pRSelection = GetSelection();
+ if( !pRSelection.is() )
+ return E_FAIL;
+ long Index = pContext->getAccessibleIndexInParent();
+ pRSelection->selectAccessibleChild( Index );
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Deselect one XAccessible item, for accSelect implimentation
+ * @param pItem, the item should be deselected.
+ * @return S_OK if successful.
+ */
+HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
+ ;
+ XAccessibleContext* pContext = GetContextByXAcc( pItem );
+ if( pParentContext == NULL || pContext == NULL )
+ return E_INVALIDARG;
+
+ Reference< XAccessibleSelection > pRSelection = GetSelection();
+ if( !pRSelection.is() )
+ return E_FAIL;
+ long Index = pContext->getAccessibleIndexInParent();
+ pRSelection->deselectAccessibleChild( Index );
+
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Select multiple XAccessible items,for implementation of accSelect
+ * @param pItem, the items should be selected.
+ * @param size, the size of the items.
+ * @return S_OK if successful.
+ */
+HRESULT CMAccessible::SelectMutipleChidren( XAccessible** pItem,int size )
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pItem == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ for(int index = 0;index < size;index++)
+ {
+ SelectChild( pItem[index] );
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Deselect multiple XAccessible items,for implementation of accSelect
+ * @param pItem, the items should be selected.
+ * @param size, the size of the items.
+ * @return S_OK if successful.
+ */
+HRESULT CMAccessible::DeSelectMutipleChildren( XAccessible** pItem,int size )
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pItem == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ for(int index = 0;index < size;index++)
+ {
+ DeSelectChild( pItem[index] );
+ }
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * When COM is created, UNO set XAccessible pointer to it
+ * in order to COM can operate UNO information
+ * @param pXAcc, the XAccessible object of current object.
+ * @return S_OK if successful.
+ */
+STDMETHODIMP CMAccessible::SetXAccessible(long pXAcc)
+{
+ pUNOInterface = (XAccessible*)pXAcc;
+ pRef = pUNOInterface;
+ m_pEnumVar->PutSelection(/*XAccessibleSelection*/(long)pUNOInterface);
+
+ pRContext = pUNOInterface->getAccessibleContext();
+ pRContextInterface = (XAccessibleContext*)pRContext.is();
+
+ return S_OK;
+}
+
+/**
+ * accSelect method has many optional flags, needs to process comprehensively
+ * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
+ * The implementation of this flag is a little trouble-shooting,so we also
+ * do not implement it now
+ * @param flagsSelect, the selection flag of the select action.
+ * @param varChild, the child object pointer of current action.
+ * @return S_OK if successful.
+ */
+STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if( (flagsSelect&SELFLAG_ADDSELECTION) &&
+ (SELFLAG_REMOVESELECTION&flagsSelect) )
+ return E_INVALIDARG;
+
+ if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
+ (
+ (flagsSelect&SELFLAG_ADDSELECTION) ||
+ (flagsSelect&SELFLAG_REMOVESELECTION) ||
+ (flagsSelect&SELFLAG_EXTENDSELECTION )
+ )
+ )
+ return E_INVALIDARG;
+
+ if ( varChild.vt != VT_I4 )
+ return E_INVALIDARG;
+
+ IMAccessible* pSelectAcc;
+ if( varChild.lVal == CHILDID_SELF )
+ {
+ pSelectAcc = this;
+ pSelectAcc->AddRef();
+ }
+ else
+ {
+ pSelectAcc = GetChildInterface(varChild.lVal);
+ }
+
+ if( pSelectAcc == NULL )
+ return E_INVALIDARG;
+
+ if( flagsSelect&SELFLAG_TAKEFOCUS )
+ {
+ long pTempUNO = 0;
+ pSelectAcc->GetUNOInterface( &pTempUNO);
+
+ if( pTempUNO == NULL )
+ return NULL;
+
+ Reference< XAccessibleContext > pRContext = ( (XAccessible*)pTempUNO)->getAccessibleContext();
+ Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
+ Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
+ Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
+ Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
+ Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
+
+
+ pRComponent->grabFocus();
+
+ if( flagsSelect & SELFLAG_TAKESELECTION )
+ {
+ pRParentSelection->clearAccessibleSelection();
+ pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
+ }
+
+ if( flagsSelect & SELFLAG_ADDSELECTION )
+ {
+ pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
+ }
+
+ if( flagsSelect & SELFLAG_REMOVESELECTION )
+ {
+ pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
+ }
+
+ if( flagsSelect & SELFLAG_EXTENDSELECTION )
+ {
+ long indexInParrent = pRContext->getAccessibleIndexInParent();
+
+ if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
+ pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
+ {
+ pRParentSelection->selectAccessibleChild( indexInParrent );
+ }
+ }
+
+ }
+
+ pSelectAcc->Release();
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * Return XAccessible interface pointer when needed
+ * @param pXAcc, [in, out] the Uno interface of the current object.
+ * @return S_OK if successful.
+ */
+STDMETHODIMP CMAccessible::GetUNOInterface(long* pXAcc)
+{
+ // #CHECK#
+ if(pXAcc == NULL)
+ return E_INVALIDARG;
+
+ *pXAcc = (long)pUNOInterface;
+ return S_OK;
+}
+
+/**
+ * Helper method for Implementation of get_accDefaultAction
+ * @param pAction, the default action point of the current object.
+ * @return S_OK if successful.
+ */
+STDMETHODIMP CMAccessible::SetDefaultAction(long pAction)
+{
+ m_pXAction = (XAccessibleAction*)pAction;
+ return S_OK;
+}
+
+/**
+ * This method is called when AT open some UI elements initially
+ * the UI element takes the default action defined here
+ * @param varChild, the child id of the defaultaction.
+ * @param pszDefaultAction,[in/out] the description of the current action.
+ * @return S_OK if successful.
+ */
+HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(pszDefaultAction == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ if(varChild.vt==VT_I4)
+ {
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ if( m_pXAction == NULL )
+ return DISP_E_MEMBERNOTFOUND;
+ SAFE_SYSFREESTRING(*pszDefaultAction);
+ *pszDefaultAction = SysAllocString(m_pszActionDescription);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->get_accDefaultAction(varChild,pszDefaultAction);
+ }
+ return S_FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * AT call this method to operate application
+ * @param varChild, the child id of the action object.
+ * @return S_OK if successful.
+ */
+HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if( varChild.vt != VT_I4 )
+ return E_INVALIDARG;
+ if( m_pXAction == NULL )
+ return E_FAIL;
+ if( m_pXAction->getAccessibleActionCount() == 0 )
+ return E_FAIL;
+
+ if(varChild.lVal==CHILDID_SELF)
+ {
+ if(m_pXAction->getAccessibleActionCount() > 0)
+ m_pXAction->doAccessibleAction(0);
+ return S_OK;
+ }
+
+ long lVal = varChild.lVal;
+ varChild.lVal = CHILDID_SELF;
+ IMAccessible *pChild = this->GetChildInterface(lVal);
+ if(!pChild)
+ return E_FAIL;
+ return pChild->accDoDefaultAction( varChild );
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+/**
+ * UNO set description information for action to COM.
+ * @param szAction, the action description of the current object.
+ * @return S_OK if successful.
+ */
+STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(szAction == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ SAFE_SYSFREESTRING(m_pszActionDescription );
+ m_pszActionDescription = SysAllocString( szAction );
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
+{
+ Reference< XAccessibleContext > pRContext;
+
+ switch(index)
+ {
+ case XI_COMPONENT:
+ QUERYXINTERFACE(AccessibleComponent)
+ break;
+ case XI_TEXT:
+ QUERYXINTERFACE(AccessibleText)
+ break;
+ case XI_EDITABLETEXT:
+ QUERYXINTERFACE(AccessibleEditableText)
+ break;
+ case XI_TABLE:
+ QUERYXINTERFACE(AccessibleTable)
+ break;
+ case XI_SELECTION:
+ QUERYXINTERFACE(AccessibleSelection)
+ break;
+ case XI_EXTENDEDCOMP:
+ QUERYXINTERFACE(AccessibleExtendedComponent)
+ break;
+ case XI_KEYBINDING:
+ QUERYXINTERFACE(AccessibleKeyBinding)
+ break;
+ case XI_ACTION:
+ QUERYXINTERFACE(AccessibleAction)
+ break;
+ case XI_VALUE:
+ QUERYXINTERFACE(AccessibleValue)
+ break;
+ case XI_HYPERTEXT:
+ QUERYXINTERFACE(AccessibleHypertext)
+ break;
+ case XI_HYPERLINK:
+ QUERYXINTERFACE(AccessibleHyperlink)
+ break;
+ case XI_IMAGE:
+ QUERYXINTERFACE(AccessibleImage)
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+HRESULT WINAPI CMAccessible::SmartQI(void* pv, REFIID iid, void** ppvObject)
+{
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if( ImplIsEqualGUID(iid,IID_IAccIdentity) ||
+ ImplIsEqualGUID(iid,IID_IStdMarshalInfo) ||
+ ImplIsEqualGUID(iid,IID_IMarshal) ||
+ ImplIsEqualGUID(iid,IID_IExternalConnection)||
+ ImplIsEqualGUID(iid,IID_IOleWindow))
+ return E_FAIL;
+
+
+ _UNO_AGGMAP_ENTRY* pMap = _GetAggEntries();
+ while(pMap && pMap->piid)
+ {
+ if(ImplIsEqualGUID(iid, *pMap->piid))
+ {
+ XInterface* pXI = NULL;
+ BOOL bFound = GetXInterfaceFromXAccessible(pUNOInterface,&pXI,pMap->XIFIndex);
+ if(!bFound)
+ {
+ return E_FAIL;
+ }
+
+ XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
+ if ( pIndTemp != m_containedObjects.end() )
+ {
+ return pIndTemp->second.p->QueryInterface( iid, ppvObject );
+ }
+ else
+ {
+ HRESULT hr = pMap->pfnCreateInstance(pv, iid, ppvObject);
+ if(hr == S_OK)
+ {
+ m_containedObjects.insert(XGUIDToComObjHash::value_type(*pMap->piid,(IUnknown*)*ppvObject));
+ IUNOXWrapper* wrapper = NULL;
+ ((IUnknown*)*ppvObject)->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
+ if(wrapper)
+ {
+ wrapper->put_XInterface((long)pUNOInterface);
+ wrapper->Release();
+ }
+ return S_OK;
+ }
+ }
+ return E_FAIL;
+ }
+ pMap++;
+ }
+ return E_FAIL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+BOOL CMAccessible::get_IAccessibleFromXAccessible(long pXAcc, IAccessible **ppIA)
+{
+
+ ENTER_PROTECTED_BLOCK
+
+ // #CHECK#
+ if(ppIA == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ BOOL isGet = FALSE;
+ if(g_pAgent)
+ isGet = g_pAgent->GetIAccessibleFromXAccessible((XAccessible*)pXAcc,ppIA);
+
+ if(isGet)
+ return TRUE;
+ else
+ return FALSE;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+void CMAccessible::get_OLECHARFromAny(Any& pAny, OLECHAR* pChar)
+{
+ // #CHECK#
+ if(pChar == NULL)
+ return;
+
+ switch(pAny.getValueTypeClass())
+ {
+ case TypeClass_CHAR:
+ {
+ sal_Int8 val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ break;
+ }
+ case TypeClass_BOOLEAN:
+ {
+ sal_Bool val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ break;
+ }
+ case TypeClass_BYTE:
+ {
+ sal_Int8 val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ break;
+ }
+ case TypeClass_SHORT:
+ {
+ SHORT val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ break;
+ }
+ case TypeClass_UNSIGNED_SHORT:
+ {
+ USHORT val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ break;
+ }
+ case TypeClass_LONG:
+ {
+ LONG val;
+ pAny >>= val;
+ swprintf( pChar, L"%ld", val);
+ break;
+ }
+ case TypeClass_UNSIGNED_LONG:
+ {
+ ULONG val;
+ pAny >>= val;
+ swprintf( pChar, L"%ld", val);
+ break;
+ }
+ case TypeClass_FLOAT:
+ {
+ FLOAT val;
+ pAny >>= val;
+ swprintf( pChar, L"%.3f", val);
+ break;
+ }
+ case TypeClass_DOUBLE:
+ {
+ DOUBLE val;
+ pAny >>= val;
+ swprintf( pChar, L"%.6lf", val);
+ break;
+ }
+ case TypeClass_STRING:
+ {
+ ::rtl::OUString val;
+ pAny >>= val;
+ wcscpy(pChar, val.getStr());
+ break;
+ }
+ case TypeClass_SEQUENCE:
+ {
+ if(pAny.getValueType() == getCppuType( (Sequence< ::rtl::OUString > *)0 ) )
+ {
+ Sequence < ::rtl::OUString > val;
+ pAny >>= val;
+
+ ::rtl::OUString pString;
+
+ int count = val.getLength();
+
+ for( int iIndex = 0;iIndex < count;iIndex++ )
+ {
+ pString += val[iIndex];
+ }
+ wcscpy(pChar, pString.getStr());
+ }
+ else if (pAny.getValueType() == getCppuType( (Sequence< ::com::sun::star::style::TabStop >* )0 ) )
+ {
+ Sequence < ::com::sun::star::style::TabStop > val;
+ pAny >>= val;
+ int count = val.getLength();
+
+ for( int iIndex = 0;iIndex < count;iIndex++ )
+ {
+ OLECHAR pAttrs[512] = {NULL};
+
+ OLECHAR pAttrsPosition[512] = {NULL};
+ OLECHAR pAttrsDescimalChar[512] = {NULL};
+ OLECHAR pAttrsFillChar[512] = {NULL};
+
+ ::com::sun::star::style::TabStop sigleVal = val[iIndex];
+
+ swprintf( pAttrsPosition, L"Position=%ld,TabAlign=%ld",
+ sigleVal.Position, sigleVal.Alignment);
+
+ if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
+ sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
+ swprintf( pAttrsDescimalChar, L"DecimalChar=\\%c",sigleVal.DecimalChar);
+ else
+ swprintf( pAttrsDescimalChar, L"DecimalChar=%c",sigleVal.DecimalChar);
+
+ if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
+ sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
+ swprintf( pAttrsFillChar, L"FillChar=\\%c",sigleVal.FillChar);
+ else
+ swprintf( pAttrsFillChar, L"FillChar=%c",sigleVal.FillChar);
+
+ swprintf( pAttrs, L"%s,%s,%s,",pAttrsPosition,pAttrsDescimalChar,pAttrsFillChar);
+
+ wcscat(pChar,pAttrs);
+ }
+ }
+ break;
+ }
+ case TypeClass_ENUM:
+ {
+ if (pAny.getValueType() == getCppuType( (::com::sun::star::awt::FontSlant* )0 ) )
+ {
+ com::sun::star::awt::FontSlant val;
+ pAny >>= val;
+ swprintf( pChar, L"%d", val);
+ }
+ }
+ case TypeClass_STRUCT:
+ {
+ if (pAny.getValueType() == getCppuType( (::com::sun::star::style::LineSpacing* )0 ) )
+ {
+ com::sun::star::style::LineSpacing val;
+ pAny >>= val;
+ swprintf( pChar, L"Mode=%ld,Height=%ld,", val.Mode, val.Height);
+ }
+ else if (pAny.getValueType() == getCppuType( (com::sun::star::accessibility::TextSegment *)0 ) )
+ {
+ com::sun::star::accessibility::TextSegment val;
+ pAny >>= val;
+ ::rtl::OUString realVal(val.SegmentText);
+ wcscpy(pChar, realVal.getStr());
+ }
+ break;
+ }
+ case TypeClass_VOID:
+ case TypeClass_HYPER:
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_TYPE:
+ case TypeClass_ANY:
+ case TypeClass_TYPEDEF:
+ case TypeClass_UNION:
+ case TypeClass_EXCEPTION:
+ case TypeClass_ARRAY:
+ case TypeClass_INTERFACE:
+ case TypeClass_SERVICE:
+ case TypeClass_MODULE:
+ case TypeClass_INTERFACE_METHOD:
+ case TypeClass_INTERFACE_ATTRIBUTE:
+ case TypeClass_UNKNOWN:
+ case TypeClass_PROPERTY:
+ case TypeClass_CONSTANT:
+ case TypeClass_CONSTANTS:
+ case TypeClass_SINGLETON:
+ case TypeClass_MAKE_FIXED_SIZE:
+ break;
+ default:
+ break;
+ }
+}
+
+void CMAccessible::get_OLECHAR4Numbering(const Any& pAny, short numberingLevel,const OUString& numberingPrefix,OLECHAR* pChar)
+{
+ if(pChar == NULL)
+ return;
+ Reference< ::com::sun::star::container::XIndexReplace > pXIndex;
+ if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
+ {
+ Any aAny = pXIndex->getByIndex(numberingLevel);
+ Sequence< ::com::sun::star::beans::PropertyValue > aProps;
+ aAny >>= aProps;
+ const ::com::sun::star::beans::PropertyValue* pPropArray = aProps.getConstArray();
+ sal_Int32 nCount = aProps.getLength();
+ swprintf(pChar,L"Numbering:NumberingLevel=%d,",numberingLevel);
+ for( sal_Int32 i=0; i<nCount; i++ )
+ {
+ ::com::sun::star::beans::PropertyValue rProp = pPropArray[i];
+ if( (rProp.Name.compareTo(OUString::createFromAscii("BulletChar"))==0)||
+ (rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)||
+ (rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0))
+ {
+ OLECHAR propStr[512] = {NULL};
+ swprintf(propStr,L"%s=",rProp.Name.getStr());
+ OLECHAR pTemp[256] = {NULL};
+ CMAccessible::get_OLECHARFromAny(rProp.Value,pTemp);
+ if(rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)
+ {
+ OLECHAR* pOccur = wcschr(pTemp,':');
+ if(pOccur)
+ *pOccur = '.';
+ }
+ wcscat(propStr,pTemp);
+ wcscat(pChar,propStr);
+ wcscat(pChar,L",");
+
+ if(rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0)
+ {
+ if(numberingPrefix.getLength()!=0)
+ {
+ swprintf(pTemp,L"NumberingPrefix=%s,",numberingPrefix.getStr());
+ wcscat(pChar,pTemp);
+ }
+ }
+ }
+ }
+ }
+
+ //Because now have three types numbering level:
+ //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
+ //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
+ //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
+ // IAText:numberinglevel base on 0, but TOC's level base on 1,
+ // so NumberingLevel value will be decreased 1 in bridge code.
+ else if(numberingLevel >0)
+ {
+ swprintf(pChar,L"Numbering:NumberingLevel=%d,NumberingType=4,NumberingPrefix=,",numberingLevel-1);
+ }
+ else
+ {
+ swprintf(pChar,L"Numbering:");
+ }
+}
+
+void CMAccessible::ConvertAnyToVariant(const ::com::sun::star::uno::Any &rAnyVal, VARIANT *pvData)
+{
+ if(rAnyVal.hasValue())
+ {
+ // Clear VARIANT variable.
+ VariantClear(pvData);
+
+ // Set value according to value type.
+ switch(rAnyVal.getValueTypeClass())
+ {
+ case TypeClass_CHAR:
+ pvData->vt = VT_UI1;
+ memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
+ break;
+
+ case TypeClass_BOOLEAN:
+ pvData->vt = VT_BOOL;
+ memcpy(&pvData->boolVal, rAnyVal.getValue(), sizeof(sal_Bool));
+ break;
+
+ case TypeClass_BYTE:
+ pvData->vt = VT_UI1;
+ memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
+ break;
+
+ case TypeClass_SHORT:
+ pvData->vt = VT_I2;
+ memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
+ break;
+
+ case TypeClass_UNSIGNED_SHORT:
+ pvData->vt = VT_I2;
+ memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
+ break;
+
+ case TypeClass_LONG:
+ pvData->vt = VT_I4;
+ memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
+ break;
+
+ case TypeClass_UNSIGNED_LONG:
+ pvData->vt = VT_I4;
+ memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
+ break;
+
+ case TypeClass_FLOAT:
+ pvData->vt = VT_R4;
+ memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
+ break;
+
+ case TypeClass_DOUBLE:
+ pvData->vt = VT_R8;
+ memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
+ break;
+
+ case TypeClass_STRING:
+ {
+ pvData->vt = VT_BSTR;
+ ::rtl::OUString val;
+ rAnyVal >>= val;
+ pvData->bstrVal = SysAllocString((OLECHAR *)val.getStr());
+ break;
+ }
+
+ case TypeClass_VOID:
+ case TypeClass_HYPER:
+ case TypeClass_UNSIGNED_HYPER:
+ case TypeClass_TYPE:
+ case TypeClass_ANY:
+ case TypeClass_ENUM:
+ case TypeClass_TYPEDEF:
+ case TypeClass_STRUCT:
+ case TypeClass_UNION:
+ case TypeClass_EXCEPTION:
+ case TypeClass_SEQUENCE:
+ case TypeClass_ARRAY:
+ case TypeClass_INTERFACE:
+ {
+ Reference< XAccessible > pXAcc;
+ if(rAnyVal >>= pXAcc)
+ {
+ if(pXAcc.is())
+ {
+ IAccessible* pIAcc = NULL;
+ get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
+ if(pIAcc == NULL)
+ {
+ Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
+ g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
+ get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
+ }
+ if(pIAcc)
+ {
+ pIAcc->AddRef();
+
+ pvData->vt = VT_UNKNOWN;
+ pvData->pdispVal = (IAccessible2*)pIAcc;
+ break;
+ }
+ }
+ }
+ }
+ case TypeClass_SERVICE:
+ case TypeClass_MODULE:
+ case TypeClass_INTERFACE_METHOD:
+ case TypeClass_INTERFACE_ATTRIBUTE:
+ case TypeClass_UNKNOWN:
+ case TypeClass_PROPERTY:
+ case TypeClass_CONSTANT:
+ case TypeClass_CONSTANTS:
+ case TypeClass_SINGLETON:
+ case TypeClass_MAKE_FIXED_SIZE:
+ // Output the type string, if there is other uno value type.
+ pvData->vt = VT_BSTR;
+ pvData->bstrVal = SysAllocString(rAnyVal.getValueTypeName().getStr());
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ VariantClear(pvData);
+ }
+}
+
+STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
+{
+ // #CHECK#
+ if(childID == NULL)
+ {
+ return E_FAIL;
+ }
+ *childID = m_dChildID;
+ return S_OK;
+}
+STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK XInterface#
+ if( !pRContext.is() )
+ return E_FAIL;
+
+ Reference<XAccessibleStateSet> pRStateSet = pRContext.get()->getAccessibleStateSet();
+ if(!pRStateSet.is())
+ {
+ return S_OK;
+ }
+ Sequence<short> pStates = pRStateSet->getStates();
+
+
+ long count = pStates.getLength() ;
+ *states = 0x0;
+ for( int i = 0; i < count; i++ )
+ {
+ for( int j = 0; j < sizeof(UNO_STATES) / sizeof(UNO_STATES[0]); j++ )
+ {
+ if( pStates[i] == UNO_STATES[j] )
+ {
+ *states |= IA2_STATES[j];
+ break;
+ }
+ }
+ }
+ return S_OK;
+
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+// return the UNO roles
+STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR * )
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR * )
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+
+STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ return E_NOTIMPL;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+
+STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ // #CHECK#
+ if(accParentIndex == NULL)
+ return E_INVALIDARG;
+
+ // #CHECK XInterface#
+ if( !pRContext.is() )
+ return E_FAIL;
+
+ *accParentIndex = pRContext.get()->getAccessibleIndexInParent();
+ return S_OK;
+
+
+ LEAVE_PROTECTED_BLOCK
+}
+STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale )
+{
+
+ CHECK_ENABLE_INF
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(locale == NULL)
+ return E_INVALIDARG;
+ // #CHECK XInterface#
+
+ if( !pRContext.is() )
+ return E_FAIL;
+
+ ::com::sun::star::lang::Locale unoLoc = pRContext.get()->getLocale();
+ locale->language = SysAllocString((OLECHAR*)unoLoc.Language.getStr());
+ locale->country = SysAllocString((OLECHAR*)unoLoc.Country.getStr());
+ locale->variant = SysAllocString((OLECHAR*)unoLoc.Variant.getStr());
+
+ return S_OK;
+
+ LEAVE_PROTECTED_BLOCK
+}
+
+DWORD GetMSAAStateFromUNO(short xState)
+{
+ DWORD IState = STATE_SYSTEM_UNAVAILABLE;
+ switch( xState )
+ {
+ case /*AccessibleStateType::*/AccessibleStateType::BUSY:
+ IState = STATE_SYSTEM_BUSY;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::CHECKED:
+ IState = STATE_SYSTEM_CHECKED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::DEFUNC:
+ IState = STATE_SYSTEM_UNAVAILABLE;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::EXPANDED:
+ IState = STATE_SYSTEM_EXPANDED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::FOCUSABLE:
+ IState = STATE_SYSTEM_FOCUSABLE;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::FOCUSED:
+ IState = STATE_SYSTEM_FOCUSED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::INDETERMINATE:
+ IState = STATE_SYSTEM_MIXED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::MULTI_SELECTABLE:
+ IState = STATE_SYSTEM_MULTISELECTABLE;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::PRESSED:
+ IState = STATE_SYSTEM_PRESSED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::RESIZABLE:
+ IState = STATE_SYSTEM_SIZEABLE;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::SELECTABLE:
+ IState = STATE_SYSTEM_SELECTABLE;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::SELECTED:
+ IState = STATE_SYSTEM_SELECTED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::ARMED:
+ IState = STATE_SYSTEM_FOCUSED;
+ break;
+ case /*AccessibleStateType::*/AccessibleStateType::EXPANDABLE:
+ IState = STATE_SYSTEM_COLLAPSED;
+ break;
+ default:
+ break;
+ }
+ return IState;
+}
+
+STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(name == NULL)
+ return E_INVALIDARG;
+
+ *name = SysAllocString(OLESTR("Hannover"));
+ return S_OK;
+ LEAVE_PROTECTED_BLOCK
+}
+STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(version == NULL)
+ return E_INVALIDARG;
+ *version=SysAllocString(OLESTR("3.0"));
+ return S_OK;
+ LEAVE_PROTECTED_BLOCK
+}
+STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(name == NULL)
+ return E_INVALIDARG;
+ *name = SysAllocString(OLESTR(" "));
+ return S_OK;
+ LEAVE_PROTECTED_BLOCK
+}
+STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
+{
+
+ ENTER_PROTECTED_BLOCK
+ ISDESTROY()
+ if(version == NULL)
+ return E_INVALIDARG;
+ *version = SysAllocString(OLESTR(" "));
+ return S_OK;
+ LEAVE_PROTECTED_BLOCK
+}
+
+
+STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
+{
+ CHECK_ENABLE_INF
+ Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
+ if( !pRContext.is() )
+ {
+ return E_FAIL;
+ }
+ Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
+ if( !pRXI.is() )
+ return E_FAIL;
+ else
+ {
+ com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleExtendedAttributes> pRXAttr;
+ pRXAttr = pRXI.get();
+ ::com::sun::star::uno::Any anyVal = pRXAttr->getExtendedAttributes();
+
+ ::rtl::OUString val;
+ anyVal >>= val;
+
+ if(*pAttr)
+ SAFE_SYSFREESTRING(*pAttr);
+ *pAttr = SysAllocString((OLECHAR *)val.getStr());
+
+ return S_OK;
+ }
+}
+