2014-12-24 19:15:45 -06:00
// 24 december 2014
2015-02-16 01:31:34 -06:00
// notes:
// - TODO figure out what to do about header
// - a row extends as far right as the right edge of the last cell in the row; anything to the right of that is treated as table space (just like with mouse selection)
// - this has the added effect that hit-testing can only ever return either the table or a cell, never a row
2015-02-14 13:15:51 -06:00
// TODOs:
// - make sure E_POINTER and RPC_E_DISCONNECTED are correct returns for IAccessible
2015-02-14 15:46:43 -06:00
// uncomment this to debug table linked list management
2015-02-15 14:37:16 -06:00
//#define TABLE_DEBUG_LINKEDLIST
2015-02-14 15:46:43 -06:00
2015-02-15 02:48:14 -06:00
// TODO get rid of this
2015-02-14 08:24:59 -06:00
typedef struct tableAccWhat tableAccWhat ;
struct tableAccWhat {
LONG role ;
intptr_t row ;
2015-02-14 09:39:26 -06:00
intptr_t column ;
2015-02-14 08:24:59 -06:00
} ;
2014-12-24 19:15:45 -06:00
struct tableAcc {
2015-02-13 15:19:54 -06:00
const IAccessibleVtbl * vtbl ;
2014-12-24 19:15:45 -06:00
ULONG refcount ;
struct table * t ;
2015-01-04 00:13:35 -06:00
IAccessible * std ;
2015-02-14 08:24:59 -06:00
tableAccWhat what ;
2015-02-14 13:15:51 -06:00
// the list of currently active accessibility objects is a doubly linked list
struct tableAcc * prev ;
struct tableAcc * next ;
2014-12-24 19:15:45 -06:00
} ;
2015-02-14 15:46:43 -06:00
# ifdef TABLE_DEBUG_LINKEDLIST
void list ( struct table * t )
{
struct tableAcc * ta ;
printf ( " \n " ) ;
if ( t - > firstAcc = = NULL ) {
printf ( " \t empty \n " ) ;
return ;
}
printf ( " \t -> " ) ;
for ( ta = t - > firstAcc ; ta ! = NULL ; ta = ta - > next )
printf ( " %p " , ta ) ;
printf ( " \n \t <- " ) ;
for ( ta = t - > firstAcc ; ta - > next ! = NULL ; ta = ta - > next )
;
for ( ; ta ! = NULL ; ta = ta - > prev )
printf ( " %p " , ta ) ;
printf ( " \n " ) ;
}
# endif
2015-02-14 09:39:26 -06:00
// called after each allocation
2015-02-14 13:15:51 -06:00
static struct tableAcc * newTableAcc ( struct table * t , LONG role , intptr_t row , intptr_t column ) ;
2015-02-14 09:39:26 -06:00
2015-02-14 08:24:59 -06:00
// common validation for accessibility functions that take varChild
// also normalizes what as if varChild == CHILDID_SELF
static HRESULT normalizeWhat ( struct tableAcc * ta , VARIANT varChild , tableAccWhat * what )
{
LONG cid ;
if ( varChild . vt ! = VT_I4 )
return E_INVALIDARG ;
cid = varChild . lVal ;
if ( cid = = CHILDID_SELF )
return S_OK ;
cid - - ;
if ( cid < 0 )
return E_INVALIDARG ;
switch ( what - > role ) {
case ROLE_SYSTEM_TABLE :
// TODO +1?
if ( cid > = ta - > t - > count )
return E_INVALIDARG ;
what - > role = ROLE_SYSTEM_ROW ;
what - > row = ( intptr_t ) cid ;
what - > column = - 1 ;
break ;
case ROLE_SYSTEM_ROW :
case ROLE_SYSTEM_CELL :
// TODO
2015-02-16 03:51:17 -06:00
// TODO also figure out what to do if the current row/cell become invalid (rows being removed, etc.)
2015-02-14 08:24:59 -06:00
break ;
}
return S_OK ;
}
2015-01-03 23:54:38 -06:00
# define TA ((struct tableAcc *) this)
2014-12-24 19:55:13 -06:00
static HRESULT STDMETHODCALLTYPE tableAccQueryInterface ( IAccessible * this , REFIID riid , void * * ppvObject )
2014-12-24 19:15:45 -06:00
{
if ( ppvObject = = NULL )
return E_POINTER ;
2014-12-24 20:53:30 -06:00
if ( IsEqualIID ( riid , & IID_IUnknown ) | |
IsEqualIID ( riid , & IID_IDispatch ) | |
IsEqualIID ( riid , & IID_IAccessible ) ) {
2015-02-13 15:19:54 -06:00
IAccessible_AddRef ( this ) ;
2014-12-24 19:15:45 -06:00
* ppvObject = ( void * ) this ;
return S_OK ;
}
* ppvObject = NULL ;
return E_NOINTERFACE ;
}
// TODO use InterlockedIncrement()/InterlockedDecrement() for these?
2014-12-24 19:55:13 -06:00
static ULONG STDMETHODCALLTYPE tableAccAddRef ( IAccessible * this )
2014-12-24 19:15:45 -06:00
{
TA - > refcount + + ;
2014-12-25 14:56:06 -06:00
// TODO correct?
2014-12-24 19:15:45 -06:00
return TA - > refcount ;
}
2014-12-24 19:55:13 -06:00
static ULONG STDMETHODCALLTYPE tableAccRelease ( IAccessible * this )
2014-12-24 19:15:45 -06:00
{
TA - > refcount - - ;
if ( TA - > refcount = = 0 ) {
2015-02-14 13:15:51 -06:00
struct tableAcc * prev , * next ;
2015-02-14 15:46:43 -06:00
# ifdef TABLE_DEBUG_LINKEDLIST
if ( TA - > t ! = NULL ) { printf ( " before delete: " ) ; list ( TA - > t ) ; }
# endif
2015-02-14 13:19:04 -06:00
if ( TA - > t ! = NULL & & TA - > t - > firstAcc = = TA )
TA - > t - > firstAcc = TA - > next ;
2015-02-14 13:15:51 -06:00
prev = TA - > prev ;
next = TA - > next ;
if ( prev ! = NULL )
prev - > next = next ;
if ( next ! = NULL )
next - > prev = prev ;
2015-02-14 15:46:43 -06:00
# ifdef TABLE_DEBUG_LINKEDLIST
if ( TA - > t ! = NULL ) { printf ( " after delete: " ) ; list ( TA - > t ) ; }
# endif
2015-02-14 13:15:51 -06:00
if ( TA - > std ! = NULL )
IAccessible_Release ( TA - > std ) ;
2015-01-03 23:58:28 -06:00
tableFree ( TA , " error freeing Table accessibility object " ) ;
2014-12-24 19:15:45 -06:00
return 0 ;
}
return TA - > refcount ;
}
2015-02-13 13:31:03 -06:00
// IDispatch
// TODO make sure relegating these to the standard accessibility object is harmless
2014-12-24 19:55:13 -06:00
static HRESULT STDMETHODCALLTYPE tableAccGetTypeInfoCount ( IAccessible * this , UINT * pctinfo )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_GetTypeInfoCount ( TA - > std , pctinfo ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccGetTypeInfo ( IAccessible * this , UINT iTInfo , LCID lcid , ITypeInfo * * ppTInfo )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_GetTypeInfo ( TA - > std , iTInfo , lcid , ppTInfo ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccGetIDsOfNames ( IAccessible * this , REFIID riid , LPOLESTR * rgszNames , UINT cNames , LCID lcid , DISPID * rgDispId )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_GetIDsOfNames ( TA - > std , riid , rgszNames , cNames , lcid , rgDispId ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccInvoke ( IAccessible * this , DISPID dispIdMember , REFIID riid , LCID lcid , WORD wFlags , DISPPARAMS * pDispParams , VARIANT * pVarResult , EXCEPINFO * pExcepInfo , UINT * puArgErr )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_Invoke ( TA - > std , dispIdMember , riid , lcid , wFlags , pDispParams , pVarResult , pExcepInfo , puArgErr ) ;
2014-12-24 19:55:13 -06:00
}
// IAccessible
static HRESULT STDMETHODCALLTYPE tableAccget_accParent ( IAccessible * this , IDispatch * * ppdispParent )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accParent ( TA - > std , ppdispParent ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accChildCount ( IAccessible * this , long * pcountChildren )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-14 11:29:05 -06:00
//TODO
if ( pcountChildren = = NULL )
return E_POINTER ;
* pcountChildren = 0 ;
return S_OK ;
2015-02-13 13:31:03 -06:00
return IAccessible_get_accChildCount ( TA - > std , pcountChildren ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accChild ( IAccessible * this , VARIANT varChild , IDispatch * * ppdispChild )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accChild ( TA - > std , varChild , ppdispChild ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accName ( IAccessible * this , VARIANT varChild , BSTR * pszName )
{
2015-02-14 15:46:43 -06:00
printf ( " get_accName() t %p std %p \n " , TA - > t , TA - > std ) ;
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
2015-02-14 15:46:43 -06:00
printf ( " returning RPC_E_DISCONNECTED \n " ) ;
2015-02-14 13:15:51 -06:00
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-14 15:46:43 -06:00
printf ( " running main function \n " ) ;
2015-02-14 11:29:05 -06:00
//TODO
if ( pszName = = NULL )
return E_POINTER ;
* pszName = SysAllocString ( L " accessible table " ) ;
return S_OK ;
2015-02-13 13:31:03 -06:00
return IAccessible_get_accName ( TA - > std , varChild , pszName ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accValue ( IAccessible * this , VARIANT varChild , BSTR * pszValue )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accValue ( TA - > std , varChild , pszValue ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accDescription ( IAccessible * this , VARIANT varChild , BSTR * pszDescription )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accDescription ( TA - > std , varChild , pszDescription ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accRole ( IAccessible * this , VARIANT varChild , VARIANT * pvarRole )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-14 11:29:05 -06:00
//TODO
if ( pvarRole = = NULL )
return E_POINTER ;
pvarRole - > vt = VT_I4 ;
pvarRole - > lVal = TA - > what . role ;
return S_OK ;
2015-02-13 13:31:03 -06:00
return IAccessible_get_accRole ( TA - > std , varChild , pvarRole ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accState ( IAccessible * this , VARIANT varChild , VARIANT * pvarState )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accState ( TA - > std , varChild , pvarState ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accHelp ( IAccessible * this , VARIANT varChild , BSTR * pszHelp )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accHelp ( TA - > std , varChild , pszHelp ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accHelpTopic ( IAccessible * this , BSTR * pszHelpFile , VARIANT varChild , long * pidTopic )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accHelpTopic ( TA - > std , pszHelpFile , varChild , pidTopic ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accKeyboardShortcut ( IAccessible * this , VARIANT varChild , BSTR * pszKeyboardShortcut )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accKeyboardShortcut ( TA - > std , varChild , pszKeyboardShortcut ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accFocus ( IAccessible * this , VARIANT * pvarChild )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accFocus ( TA - > std , pvarChild ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accSelection ( IAccessible * this , VARIANT * pvarChildren )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accSelection ( TA - > std , pvarChildren ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccget_accDefaultAction ( IAccessible * this , VARIANT varChild , BSTR * pszDefaultAction )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_get_accDefaultAction ( TA - > std , varChild , pszDefaultAction ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccaccSelect ( IAccessible * this , long flagsSelect , VARIANT varChild )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_accSelect ( TA - > std , flagsSelect , varChild ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccaccLocation ( IAccessible * this , long * pxLeft , long * pyTop , long * pcxWidth , long * pcyHeight , VARIANT varChild )
{
2015-02-15 02:48:14 -06:00
HRESULT hr ;
tableAccWhat what ;
RECT r ;
POINT pt ;
struct rowcol rc ;
if ( pxLeft = = NULL | | pyTop = = NULL | | pcxWidth = = NULL | | pcyHeight = = NULL )
return E_POINTER ;
// TODO set the out parameters to zero?
if ( TA - > t = = NULL | | TA - > std = = NULL )
2015-02-14 13:15:51 -06:00
return RPC_E_DISCONNECTED ;
2015-02-15 02:48:14 -06:00
what = TA - > what ;
hr = normalizeWhat ( TA , varChild , & what ) ;
if ( hr ! = S_OK )
return hr ;
switch ( what . role ) {
case ROLE_SYSTEM_TABLE :
return IAccessible_accLocation ( TA - > std , pxLeft , pyTop , pcxWidth , pcyHeight , varChild ) ;
case ROLE_SYSTEM_ROW :
2015-02-16 01:31:34 -06:00
// TODO actually write this
2015-02-15 02:48:14 -06:00
return E_FAIL ;
case ROLE_SYSTEM_CELL :
rc . row = what . row ;
rc . column = what . column ;
if ( ! rowColumnToClientRect ( TA - > t , rc , & r ) ) {
// TODO what do we do here?
2015-02-16 01:31:34 -06:00
// TODO we have to return something indicating that the object is off-screen
2015-02-15 02:48:14 -06:00
}
2015-02-16 01:31:34 -06:00
// TODO intersect with client rect?
2015-02-15 02:48:14 -06:00
break ;
2015-02-14 13:15:51 -06:00
}
2015-02-15 02:48:14 -06:00
pt . x = r . left ;
pt . y = r . top ;
if ( ClientToScreen ( TA - > t - > hwnd , & pt ) = = 0 )
2015-02-15 03:54:14 -06:00
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
2015-02-15 02:48:14 -06:00
* pxLeft = pt . x ;
* pyTop = pt . y ;
* pcxWidth = r . right - r . left ;
* pcyHeight = r . bottom - r . top ;
return S_OK ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccaccNavigate ( IAccessible * this , long navDir , VARIANT varStart , VARIANT * pvarEndUpAt )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-01-04 00:13:35 -06:00
return IAccessible_accNavigate ( TA - > std , navDir , varStart , pvarEndUpAt ) ;
2014-12-24 19:55:13 -06:00
}
2015-02-16 03:51:17 -06:00
// TODO should this ever return parents?
2014-12-24 19:55:13 -06:00
static HRESULT STDMETHODCALLTYPE tableAccaccHitTest ( IAccessible * this , long xLeft , long yTop , VARIANT * pvarChild )
{
2015-02-15 02:37:00 -06:00
POINT pt ;
struct rowcol rc ;
RECT r ;
if ( pvarChild = = NULL )
return E_POINTER ;
2015-02-15 02:48:14 -06:00
// TODO set pvarChild to an invalid value?
2015-02-15 02:37:00 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL )
2015-02-14 13:15:51 -06:00
return RPC_E_DISCONNECTED ;
2015-02-15 02:37:00 -06:00
pt . x = xLeft ;
pt . y = yTop ;
if ( ScreenToClient ( TA - > t - > hwnd , & pt ) = = 0 )
2015-02-15 03:54:14 -06:00
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
2015-02-15 02:37:00 -06:00
2015-02-16 01:31:34 -06:00
// first see if the point is even IN the table
if ( GetClientRect ( TA - > t - > hwnd , & r ) = = 0 )
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
r . top + = TA - > t - > headerHeight ;
if ( PtInRect ( & r , pt ) = = 0 )
goto outside ;
// now see if we're in a cell or in the table
// TODO also handle GetLastError() here
rc = clientCoordToRowColumn ( TA - > t , pt ) ;
2015-02-15 02:37:00 -06:00
switch ( TA - > what . role ) {
case ROLE_SYSTEM_TABLE :
2015-02-16 01:31:34 -06:00
// either the table or the cell
if ( rc . row = = - 1 | | rc . column = = - 1 )
goto self ;
goto specificCell ;
2015-02-15 02:37:00 -06:00
case ROLE_SYSTEM_ROW :
2015-02-16 01:31:34 -06:00
// a specific cell, but only if in the same row
// TODO actually do we really need these spurious rc.column ==/!= -1 checks?
if ( rc . row = = TA - > what . row ) {
if ( rc . column = = - 1 )
// TODO de-GetLastError() this
panic ( " impossible situation TODO write this " ) ;
goto specificCell ;
}
goto outside ;
2015-02-15 02:37:00 -06:00
case ROLE_SYSTEM_CELL :
2015-02-16 01:31:34 -06:00
if ( rc . row = = TA - > what . row & & rc . column = = TA - > what . column )
goto self ;
goto outside ;
2015-02-15 02:37:00 -06:00
}
2015-02-16 01:31:34 -06:00
// TODO actually do this right
// TODO un-GetLastError() this
panic ( " impossible blah blah blah TODO write this " ) ;
return E_FAIL ;
outside :
pvarChild - > vt = VT_EMPTY ;
return S_FALSE ;
self :
pvarChild - > vt = VT_I4 ;
pvarChild - > lVal = CHILDID_SELF ;
return S_OK ;
2015-02-15 02:37:00 -06:00
2015-02-16 01:31:34 -06:00
specificCell :
2015-02-15 02:37:00 -06:00
pvarChild - > vt = VT_DISPATCH ;
2015-02-16 01:31:34 -06:00
// TODO GetLastError() here too
2015-02-15 02:37:00 -06:00
pvarChild - > pdispVal = ( IDispatch * ) newTableAcc ( TA - > t , ROLE_SYSTEM_CELL , rc . row , rc . column ) ;
return S_OK ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccaccDoDefaultAction ( IAccessible * this , VARIANT varChild )
{
2015-02-15 02:14:04 -06:00
HRESULT hr ;
tableAccWhat what ;
if ( TA - > t = = NULL | | TA - > std = = NULL )
2015-02-14 13:15:51 -06:00
return RPC_E_DISCONNECTED ;
2015-02-15 02:14:04 -06:00
what = TA - > what ;
hr = normalizeWhat ( TA , varChild , & what ) ;
if ( hr ! = S_OK )
return hr ;
if ( what . role = = ROLE_SYSTEM_CELL )
; // TODO implement this for checkbox cells?
return DISP_E_MEMBERNOTFOUND ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccput_accName ( IAccessible * this , VARIANT varChild , BSTR szName )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_put_accName ( TA - > std , varChild , szName ) ;
2014-12-24 19:55:13 -06:00
}
static HRESULT STDMETHODCALLTYPE tableAccput_accValue ( IAccessible * this , VARIANT varChild , BSTR szValue )
{
2015-02-14 13:15:51 -06:00
if ( TA - > t = = NULL | | TA - > std = = NULL ) {
// TODO set values on error
return RPC_E_DISCONNECTED ;
}
2015-02-13 13:31:03 -06:00
return IAccessible_put_accValue ( TA - > std , varChild , szValue ) ;
2014-12-24 19:55:13 -06:00
}
2014-12-24 19:15:45 -06:00
static const IAccessibleVtbl tableAccVtbl = {
. QueryInterface = tableAccQueryInterface ,
. AddRef = tableAccAddRef ,
. Release = tableAccRelease ,
2014-12-24 19:55:13 -06:00
. GetTypeInfoCount = tableAccGetTypeInfoCount ,
. GetTypeInfo = tableAccGetTypeInfo ,
. GetIDsOfNames = tableAccGetIDsOfNames ,
. Invoke = tableAccInvoke ,
. get_accParent = tableAccget_accParent ,
. get_accChildCount = tableAccget_accChildCount ,
. get_accChild = tableAccget_accChild ,
. get_accName = tableAccget_accName ,
. get_accValue = tableAccget_accValue ,
. get_accDescription = tableAccget_accDescription ,
. get_accRole = tableAccget_accRole ,
. get_accState = tableAccget_accState ,
. get_accHelp = tableAccget_accHelp ,
. get_accHelpTopic = tableAccget_accHelpTopic ,
. get_accKeyboardShortcut = tableAccget_accKeyboardShortcut ,
. get_accFocus = tableAccget_accFocus ,
. get_accSelection = tableAccget_accSelection ,
. get_accDefaultAction = tableAccget_accDefaultAction ,
. accSelect = tableAccaccSelect ,
. accLocation = tableAccaccLocation ,
. accNavigate = tableAccaccNavigate ,
. accHitTest = tableAccaccHitTest ,
. accDoDefaultAction = tableAccaccDoDefaultAction ,
. put_accName = tableAccput_accName ,
. put_accValue = tableAccput_accValue ,
2014-12-24 19:15:45 -06:00
} ;
2015-02-14 13:15:51 -06:00
static struct tableAcc * newTableAcc ( struct table * t , LONG role , intptr_t row , intptr_t column )
2014-12-24 19:15:45 -06:00
{
2015-02-14 13:15:51 -06:00
struct tableAcc * ta ;
2015-01-04 00:13:35 -06:00
HRESULT hr ;
IAccessible * std ;
2014-12-24 19:15:45 -06:00
2015-02-14 13:15:51 -06:00
ta = ( struct tableAcc * ) tableAlloc ( sizeof ( struct tableAcc ) , " error creating Table accessibility object " ) ;
ta - > vtbl = & tableAccVtbl ;
ta - > refcount = 1 ;
ta - > t = t ;
2015-02-14 15:46:43 -06:00
// TODO adjust last argument
hr = CreateStdAccessibleObject ( t - > hwnd , OBJID_CLIENT , & IID_IAccessible , ( void * * ) ( & std ) ) ;
2015-01-04 00:13:35 -06:00
if ( hr ! = S_OK )
// TODO panichresult
panic ( " error creating standard accessible object for Table " ) ;
2015-02-14 13:15:51 -06:00
ta - > std = std ;
ta - > what . role = role ;
ta - > what . row = row ;
ta - > what . column = column ;
2015-02-14 09:39:26 -06:00
2015-02-14 15:46:43 -06:00
# ifdef TABLE_DEBUG_LINKEDLIST
printf ( " before add: " ) ; list ( t ) ;
# endif
2015-02-14 13:15:51 -06:00
ta - > next = t - > firstAcc ;
2015-02-14 16:31:36 -06:00
if ( t - > firstAcc ! = NULL )
t - > firstAcc - > prev = ta ;
2015-02-14 13:15:51 -06:00
t - > firstAcc = ta ;
2015-02-14 15:46:43 -06:00
# ifdef TABLE_DEBUG_LINKEDLIST
printf ( " after add: " ) ; list ( t ) ;
# endif
2015-02-14 09:39:26 -06:00
2014-12-24 19:15:45 -06:00
return ta ;
}
2015-02-14 13:15:51 -06:00
static void invalidateTableAccs ( struct table * t )
2014-12-24 19:15:45 -06:00
{
2015-02-14 13:15:51 -06:00
struct tableAcc * ta ;
for ( ta = t - > firstAcc ; ta ! = NULL ; ta = ta - > next ) {
ta - > t = NULL ;
IAccessible_Release ( ta - > std ) ;
ta - > std = NULL ;
}
t - > firstAcc = NULL ;
2014-12-24 19:15:45 -06:00
}
HANDLER ( accessibilityHandler )
{
2015-02-14 13:15:51 -06:00
struct tableAcc * ta ;
2014-12-24 19:15:45 -06:00
if ( uMsg ! = WM_GETOBJECT )
return FALSE ;
2015-02-13 15:19:54 -06:00
// OBJID_CLIENT evaluates to an expression of type LONG
// the documentation for WM_GETOBJECT says to cast "it" to a DWORD before comparing
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd373624%28v=vs.85%29.aspx casts them both to DWORDs; let's do that
// its two siblings only cast lParam, resulting in an erroneous DWORD to LONG comparison
// The Old New Thing book does not cast anything
// Microsoft's MSAA sample casts lParam to LONG instead!
2015-02-13 15:21:31 -06:00
// (As you can probably tell, the biggest problem with MSAA is that its documentation is ambiguous and/or self-contradictory...)
2015-02-13 15:19:54 -06:00
if ( ( ( DWORD ) lParam ) ! = ( ( DWORD ) OBJID_CLIENT ) )
2014-12-24 19:15:45 -06:00
return FALSE ;
2015-02-14 13:15:51 -06:00
ta = newTableAcc ( t , ROLE_SYSTEM_TABLE , - 1 , - 1 ) ;
* lResult = LresultFromObject ( & IID_IAccessible , wParam , ( LPUNKNOWN ) ( ta ) ) ;
2014-12-24 19:15:45 -06:00
// TODO check *lResult
2015-02-14 17:10:19 -06:00
// TODO adjust pointer
IAccessible_Release ( ( IAccessible * ) ta ) ;
2014-12-24 19:15:45 -06:00
return TRUE ;
}