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