Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.accessibility; import java.util.*; import java.util.List; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.ole.win32.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.ole.win32.*; import org.eclipse.swt.widgets.*; /** * Instances of this class provide a bridge between application * code and assistive technology clients. Many platforms provide * default accessible behavior for most widgets, and this class * allows that default behavior to be overridden. Applications * can get the default Accessible object for a control by sending * it <code>getAccessible</code>, and then add an accessible listener * to override simple items like the name and help string, or they * can add an accessible control listener to override complex items. * As a rule of thumb, an application would only want to use the * accessible control listener to implement accessibility for a * custom control. * * @see Control#getAccessible * @see AccessibleListener * @see AccessibleEvent * @see AccessibleControlListener * @see AccessibleControlEvent * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a> * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> * * @since 2.0 */ public class Accessible { static final int MAX_RELATION_TYPES = 15; static final int TABLE_MODEL_CHANGE_SIZE = 5; static final int TEXT_CHANGE_SIZE = 4; static final int SCROLL_RATE = 100; static final boolean DEBUG = false; static final String PROPERTY_USEIA2 = "org.eclipse.swt.accessibility.UseIA2"; //$NON-NLS-1$ static boolean UseIA2 = true; static int UniqueID = -0x10; int refCount = 0, enumIndex = 0; Runnable timer; COMObject objIAccessible, objIEnumVARIANT, objIServiceProvider, objIAccessibleApplication, /*objIAccessibleComponent,*/ objIAccessibleEditableText, objIAccessibleHyperlink, objIAccessibleHypertext, /*objIAccessibleImage,*/ objIAccessibleTable2, objIAccessibleTableCell, objIAccessibleValue; /* objIAccessibleRelation is defined in Relation class */ IAccessible iaccessible; List<AccessibleListener> accessibleListeners; List<AccessibleControlListener> accessibleControlListeners; List<AccessibleTextListener> accessibleTextListeners; List<AccessibleActionListener> accessibleActionListeners; List<AccessibleEditableTextListener> accessibleEditableTextListeners; List<AccessibleHyperlinkListener> accessibleHyperlinkListeners; List<AccessibleTableListener> accessibleTableListeners; List<AccessibleTableCellListener> accessibleTableCellListeners; List<AccessibleTextExtendedListener> accessibleTextExtendedListeners; List<AccessibleValueListener> accessibleValueListeners; List<AccessibleAttributeListener> accessibleAttributeListeners; Relation relations[] = new Relation[MAX_RELATION_TYPES]; Object[] variants; Accessible parent; List<Accessible> children = new ArrayList<>(); Control control; int uniqueID = -1; int[] tableChange; // type, rowStart, rowCount, columnStart, columnCount Object[] textDeleted; // type, start, end, text Object[] textInserted; // type, start, end, text ToolItem item; static { String property = System.getProperty(PROPERTY_USEIA2); if (property != null && property.equalsIgnoreCase("false")) { //$NON-NLS-1$ UseIA2 = false; } } /** * Constructs a new instance of this class given its parent. * * @param parent the Accessible parent, which must not be null * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * </ul> * * @see #dispose * @see Control#getAccessible * * @since 3.6 */ public Accessible(Accessible parent) { this.parent = checkNull(parent); this.control = parent.control; parent.children.add(this); AddRef(); } /** * @since 3.5 * @deprecated */ @Deprecated protected Accessible() { } Accessible(Control control) { this.control = control; long[] ppvObject = new long[1]; /* CreateStdAccessibleObject([in] hwnd, [in] idObject, [in] riidInterface, [out] ppvObject). * AddRef has already been called on ppvObject by the callee and must be released by the caller. */ int result = (int) COM.CreateStdAccessibleObject(control.handle, OS.OBJID_CLIENT, COM.IIDIAccessible, ppvObject); /* The object needs to be checked, because if the CreateStdAccessibleObject() * symbol is not found, the return value is S_OK. */ if (ppvObject[0] == 0) return; if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result); iaccessible = new IAccessible(ppvObject[0]); createIAccessible(); AddRef(); } Accessible(Accessible parent, long iaccessible_address) { this(parent); iaccessible = new IAccessible(iaccessible_address); } static Accessible checkNull(Accessible parent) { if (parent == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); return parent; } void createIAccessible() { objIAccessible = new COMObject(new int[] { 2, 0, 0, /*IA>>*/1, 3, 5, 8, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 2, 2, 5, 3, 3, 1, 2, 2, /*<<IA*/1, 2, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } // method3 GetTypeInfoCount - not implemented // method4 GetTypeInfo - not implemented // method5 GetIDsOfNames - not implemented // method6 Invoke - not implemented @Override public long method7(long[] args) { return get_accParent(args[0]); } @Override public long method8(long[] args) { return get_accChildCount(args[0]); } @Override public long method9(long[] args) { return get_accChild(args[0], args[1]); } @Override public long method10(long[] args) { return get_accName(args[0], args[1]); } @Override public long method11(long[] args) { return get_accValue(args[0], args[1]); } @Override public long method12(long[] args) { return get_accDescription(args[0], args[1]); } @Override public long method13(long[] args) { return get_accRole(args[0], args[1]); } @Override public long method14(long[] args) { return get_accState(args[0], args[1]); } @Override public long method15(long[] args) { return get_accHelp(args[0], args[1]); } @Override public long method16(long[] args) { return get_accHelpTopic(args[0], args[1], args[2]); } @Override public long method17(long[] args) { return get_accKeyboardShortcut(args[0], args[1]); } @Override public long method18(long[] args) { return get_accFocus(args[0]); } @Override public long method19(long[] args) { return get_accSelection(args[0]); } @Override public long method20(long[] args) { return get_accDefaultAction(args[0], args[1]); } @Override public long method21(long[] args) { return accSelect((int) args[0], args[1]); } @Override public long method22(long[] args) { return accLocation(args[0], args[1], args[2], args[3], args[4]); } @Override public long method23(long[] args) { return accNavigate((int) args[0], args[1], args[2]); } @Override public long method24(long[] args) { return accHitTest((int) args[0], (int) args[1], args[2]); } @Override public long method25(long[] args) { return accDoDefaultAction(args[0]); } @Override public long method26(long[] args) { return put_accName(args[0], args[1]); } @Override public long method27(long[] args) { return put_accValue(args[0], args[1]); } // IAccessible2 methods @Override public long method28(long[] args) { return get_nRelations(args[0]); } @Override public long method29(long[] args) { return get_relation((int) args[0], args[1]); } @Override public long method30(long[] args) { return get_relations((int) args[0], args[1], args[2]); } @Override public long method31(long[] args) { return get_role(args[0]); } @Override public long method32(long[] args) { return scrollTo((int) args[0]); } @Override public long method33(long[] args) { return scrollToPoint((int) args[0], (int) args[1], (int) args[2]); } @Override public long method34(long[] args) { return get_groupPosition(args[0], args[1], args[2]); } @Override public long method35(long[] args) { return get_states(args[0]); } @Override public long method36(long[] args) { return get_extendedRole(args[0]); } @Override public long method37(long[] args) { return get_localizedExtendedRole(args[0]); } @Override public long method38(long[] args) { return get_nExtendedStates(args[0]); } @Override public long method39(long[] args) { return get_extendedStates((int) args[0], args[1], args[2]); } @Override public long method40(long[] args) { return get_localizedExtendedStates((int) args[0], args[1], args[2]); } @Override public long method41(long[] args) { return get_uniqueID(args[0]); } @Override public long method42(long[] args) { return get_windowHandle(args[0]); } @Override public long method43(long[] args) { return get_indexInParent(args[0]); } @Override public long method44(long[] args) { return get_locale(args[0]); } @Override public long method45(long[] args) { return get_attributes(args[0]); } }; } void createIAccessibleApplication() { objIAccessibleApplication = new COMObject(new int[] { 2, 0, 0, 1, 1, 1, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return get_appName(args[0]); } @Override public long method4(long[] args) { return get_appVersion(args[0]); } @Override public long method5(long[] args) { return get_toolkitName(args[0]); } @Override public long method6(long[] args) { return get_toolkitVersion(args[0]); } }; } // This method is intentionally commented. We are not providing IAccessibleComponent at this time. // void createIAccessibleComponent() { // objIAccessibleComponent = new COMObject(new int[] {2,0,0,2,1,1}) { // public long method0(long[] args) {return QueryInterface(args[0], args[1]);} // public long method1(long[] args) {return AddRef();} // public long method2(long[] args) {return Release();} // public long method3(long[] args) {return get_locationInParent(args[0], args[1]);} // public long method4(long[] args) {return get_foreground(args[0]);} // public long method5(long[] args) {return get_background(args[0]);} // }; // } void createIAccessibleEditableText() { objIAccessibleEditableText = new COMObject(new int[] { 2, 0, 0, 2, 2, 2, 2, 1, 3, 3 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return copyText((int) args[0], (int) args[1]); } @Override public long method4(long[] args) { return deleteText((int) args[0], (int) args[1]); } @Override public long method5(long[] args) { return insertText((int) args[0], args[1]); } @Override public long method6(long[] args) { return cutText((int) args[0], (int) args[1]); } @Override public long method7(long[] args) { return pasteText((int) args[0]); } @Override public long method8(long[] args) { return replaceText((int) args[0], (int) args[1], args[2]); } @Override public long method9(long[] args) { return setAttributes((int) args[0], (int) args[1], args[2]); } }; } void createIAccessibleHyperlink() { objIAccessibleHyperlink = new COMObject( new int[] { 2, 0, 0, /*IAA>>*/1, 1, 2, 4, 2, 2, /*<<IAA*/2, 2, 1, 1, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } // IAccessibleAction @Override public long method3(long[] args) { return get_nActions(args[0]); } @Override public long method4(long[] args) { return doAction((int) args[0]); } @Override public long method5(long[] args) { return get_description((int) args[0], args[1]); } @Override public long method6(long[] args) { return get_keyBinding((int) args[0], (int) args[1], args[2], args[3]); } @Override public long method7(long[] args) { return get_name((int) args[0], args[1]); } @Override public long method8(long[] args) { return get_localizedName((int) args[0], args[1]); } // IAccessibleHyperlink @Override public long method9(long[] args) { return get_anchor((int) args[0], args[1]); } @Override public long method10(long[] args) { return get_anchorTarget((int) args[0], args[1]); } @Override public long method11(long[] args) { return get_startIndex(args[0]); } @Override public long method12(long[] args) { return get_endIndex(args[0]); } @Override public long method13(long[] args) { return get_valid(args[0]); } }; } void createIAccessibleHypertext() { objIAccessibleHypertext = new COMObject(new int[] { 2, 0, 0, /*IAT>>*/2, 4, 1, 6, 1, 4, 3, 3, 5, 5, 5, 1, 1, 3, 1, 3, 5, 1, 1, /*<<IAT*/1, 2, 2 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } // IAccessibleText @Override public long method3(long[] args) { return addSelection((int) args[0], (int) args[1]); } @Override public long method4(long[] args) { return get_attributes((int) args[0], args[1], args[2], args[3]); } @Override public long method5(long[] args) { return get_caretOffset(args[0]); } @Override public long method6(long[] args) { return get_characterExtents((int) args[0], (int) args[1], args[2], args[3], args[4], args[5]); } @Override public long method7(long[] args) { return get_nSelections(args[0]); } @Override public long method8(long[] args) { return get_offsetAtPoint((int) args[0], (int) args[1], (int) args[2], args[3]); } @Override public long method9(long[] args) { return get_selection((int) args[0], args[1], args[2]); } @Override public long method10(long[] args) { return get_text((int) args[0], (int) args[1], args[2]); } @Override public long method11(long[] args) { return get_textBeforeOffset((int) args[0], (int) args[1], args[2], args[3], args[4]); } @Override public long method12(long[] args) { return get_textAfterOffset((int) args[0], (int) args[1], args[2], args[3], args[4]); } @Override public long method13(long[] args) { return get_textAtOffset((int) args[0], (int) args[1], args[2], args[3], args[4]); } @Override public long method14(long[] args) { return removeSelection((int) args[0]); } @Override public long method15(long[] args) { return setCaretOffset((int) args[0]); } @Override public long method16(long[] args) { return setSelection((int) args[0], (int) args[1], (int) args[2]); } @Override public long method17(long[] args) { return get_nCharacters(args[0]); } @Override public long method18(long[] args) { return scrollSubstringTo((int) args[0], (int) args[1], (int) args[2]); } @Override public long method19(long[] args) { return scrollSubstringToPoint((int) args[0], (int) args[1], (int) args[2], (int) args[3], (int) args[4]); } @Override public long method20(long[] args) { return get_newText(args[0]); } @Override public long method21(long[] args) { return get_oldText(args[0]); } // IAccessibleHypertext @Override public long method22(long[] args) { return get_nHyperlinks(args[0]); } @Override public long method23(long[] args) { return get_hyperlink((int) args[0], args[1]); } @Override public long method24(long[] args) { return get_hyperlinkIndex((int) args[0], args[1]); } }; } // This method is intentionally commented. We are not providing IAccessibleImage at this time. // void createIAccessibleImage() { // objIAccessibleImage = new COMObject(new int[] {2,0,0,1,3,2}) { // public long method0(long[] args) {return QueryInterface(args[0], args[1]);} // public long method1(long[] args) {return AddRef();} // public long method2(long[] args) {return Release();} // public long method3(long[] args) {return get_description(args[0]);} // public long method4(long[] args) {return get_imagePosition((int)args[0], args[1], args[2]);} // public long method5(long[] args) {return get_imageSize(args[0], args[1]);} // }; // } void createIAccessibleTable2() { objIAccessibleTable2 = new COMObject( new int[] { 2, 0, 0, 3, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return get_cellAt((int) args[0], (int) args[1], args[2]); } @Override public long method4(long[] args) { return get_caption(args[0]); } @Override public long method5(long[] args) { return get_columnDescription((int) args[0], args[1]); } @Override public long method6(long[] args) { return get_nColumns(args[0]); } @Override public long method7(long[] args) { return get_nRows(args[0]); } @Override public long method8(long[] args) { return get_nSelectedCells(args[0]); } @Override public long method9(long[] args) { return get_nSelectedColumns(args[0]); } @Override public long method10(long[] args) { return get_nSelectedRows(args[0]); } @Override public long method11(long[] args) { return get_rowDescription((int) args[0], args[1]); } @Override public long method12(long[] args) { return get_selectedCells(args[0], args[1]); } @Override public long method13(long[] args) { return get_selectedColumns(args[0], args[1]); } @Override public long method14(long[] args) { return get_selectedRows(args[0], args[1]); } @Override public long method15(long[] args) { return get_summary(args[0]); } @Override public long method16(long[] args) { return get_isColumnSelected((int) args[0], args[1]); } @Override public long method17(long[] args) { return get_isRowSelected((int) args[0], args[1]); } @Override public long method18(long[] args) { return selectRow((int) args[0]); } @Override public long method19(long[] args) { return selectColumn((int) args[0]); } @Override public long method20(long[] args) { return unselectRow((int) args[0]); } @Override public long method21(long[] args) { return unselectColumn((int) args[0]); } @Override public long method22(long[] args) { return get_modelChange(args[0]); } }; } void createIAccessibleTableCell() { objIAccessibleTableCell = new COMObject(new int[] { 2, 0, 0, 1, 2, 1, 1, 2, 1, 1, 5, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return get_columnExtent(args[0]); } @Override public long method4(long[] args) { return get_columnHeaderCells(args[0], args[1]); } @Override public long method5(long[] args) { return get_columnIndex(args[0]); } @Override public long method6(long[] args) { return get_rowExtent(args[0]); } @Override public long method7(long[] args) { return get_rowHeaderCells(args[0], args[1]); } @Override public long method8(long[] args) { return get_rowIndex(args[0]); } @Override public long method9(long[] args) { return get_isSelected(args[0]); } @Override public long method10(long[] args) { return get_rowColumnExtents(args[0], args[1], args[2], args[3], args[4]); } @Override public long method11(long[] args) { return get_table(args[0]); } }; } void createIAccessibleValue() { objIAccessibleValue = new COMObject(new int[] { 2, 0, 0, 1, 1, 1, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return get_currentValue(args[0]); } @Override public long method4(long[] args) { return setCurrentValue(args[0]); } @Override public long method5(long[] args) { return get_maximumValue(args[0]); } @Override public long method6(long[] args) { return get_minimumValue(args[0]); } }; } void createIEnumVARIANT() { objIEnumVARIANT = new COMObject(new int[] { 2, 0, 0, 3, 1, 0, 1 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return Next((int) args[0], args[1], args[2]); } @Override public long method4(long[] args) { return Skip((int) args[0]); } @Override public long method5(long[] args) { return Reset(); } @Override public long method6(long[] args) { return Clone(args[0]); } }; } void createIServiceProvider() { objIServiceProvider = new COMObject(new int[] { 2, 0, 0, 3 }) { @Override public long method0(long[] args) { return QueryInterface(args[0], args[1]); } @Override public long method1(long[] args) { return AddRef(); } @Override public long method2(long[] args) { return Release(); } @Override public long method3(long[] args) { return QueryService(args[0], args[1], args[2]); } }; } /** * Invokes platform specific functionality to allocate a new accessible object. * <p> * <b>IMPORTANT:</b> This method is <em>not</em> part of the public * API for <code>Accessible</code>. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. * </p> * * @param control the control to get the accessible object for * @return the platform specific accessible object * * @noreference This method is not intended to be referenced by clients. */ public static Accessible internal_new_Accessible(Control control) { return new Accessible(control); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for certain strings, * such as name, description, help, or keyboard shortcut. The * listener is notified by sending it one of the messages defined * in the <code>AccessibleListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for a name, description, help, or keyboard shortcut string * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleListener * @see #removeAccessibleListener */ public void addAccessibleListener(AccessibleListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleListeners == null) accessibleListeners = new ArrayList<>(); accessibleListeners.add(listener); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for custom control * specific information. The listener is notified by sending it * one of the messages defined in the <code>AccessibleControlListener</code> * interface. * * @param listener the listener that should be notified when the receiver * is asked for custom control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleControlListener * @see #removeAccessibleControlListener */ public void addAccessibleControlListener(AccessibleControlListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleControlListeners == null) accessibleControlListeners = new ArrayList<>(); accessibleControlListeners.add(listener); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for custom text control * specific information. The listener is notified by sending it * one of the messages defined in the <code>AccessibleTextListener</code> * and <code>AccessibleTextExtendedListener</code> interfaces. * * @param listener the listener that should be notified when the receiver * is asked for custom text control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTextListener * @see AccessibleTextExtendedListener * @see #removeAccessibleTextListener * * @since 3.0 */ public void addAccessibleTextListener(AccessibleTextListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (listener instanceof AccessibleTextExtendedListener) { if (accessibleTextExtendedListeners == null) accessibleTextExtendedListeners = new ArrayList<>(); accessibleTextExtendedListeners.add((AccessibleTextExtendedListener) listener); } else { if (accessibleTextListeners == null) accessibleTextListeners = new ArrayList<>(); accessibleTextListeners.add(listener); } } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleActionListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleActionListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleActionListener * @see #removeAccessibleActionListener * * @since 3.6 */ public void addAccessibleActionListener(AccessibleActionListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleActionListeners == null) accessibleActionListeners = new ArrayList<>(); accessibleActionListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleEditableTextListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleEditableTextListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleEditableTextListener * @see #removeAccessibleEditableTextListener * * @since 3.7 */ public void addAccessibleEditableTextListener(AccessibleEditableTextListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleEditableTextListeners == null) accessibleEditableTextListeners = new ArrayList<>(); accessibleEditableTextListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleHyperlinkListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleHyperlinkListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleHyperlinkListener * @see #removeAccessibleHyperlinkListener * * @since 3.6 */ public void addAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleHyperlinkListeners == null) accessibleHyperlinkListeners = new ArrayList<>(); accessibleHyperlinkListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleTableListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleTableListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTableListener * @see #removeAccessibleTableListener * * @since 3.6 */ public void addAccessibleTableListener(AccessibleTableListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleTableListeners == null) accessibleTableListeners = new ArrayList<>(); accessibleTableListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleTableCellListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleTableCellListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTableCellListener * @see #removeAccessibleTableCellListener * * @since 3.6 */ public void addAccessibleTableCellListener(AccessibleTableCellListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleTableCellListeners == null) accessibleTableCellListeners = new ArrayList<>(); accessibleTableCellListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleValueListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleValueListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleValueListener * @see #removeAccessibleValueListener * * @since 3.6 */ public void addAccessibleValueListener(AccessibleValueListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleValueListeners == null) accessibleValueListeners = new ArrayList<>(); accessibleValueListeners.add(listener); } /** * Adds the listener to the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleAttributeListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for <code>AccessibleAttributeListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleAttributeListener * @see #removeAccessibleAttributeListener * * @since 3.6 */ public void addAccessibleAttributeListener(AccessibleAttributeListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleAttributeListeners == null) accessibleAttributeListeners = new ArrayList<>(); accessibleAttributeListeners.add(listener); } /** * Adds a relation with the specified type and target * to the receiver's set of relations. * * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation * @param target the accessible that is the target for this relation * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null * @since 3.6 */ public void addRelation(int type, Accessible target) { checkWidget(); if (target == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (relations[type] == null) { relations[type] = new Relation(this, type); } relations[type].addTarget(target); } /** * Disposes of the operating system resources associated with * the receiver, and removes the receiver from its parent's * list of children. * <p> * This method should be called when an accessible that was created * with the public constructor <code>Accessible(Accessible parent)</code> * is no longer needed. You do not need to call this when the receiver's * control is disposed, because all <code>Accessible</code> instances * associated with a control are released when the control is disposed. * It is also not necessary to call this for instances of <code>Accessible</code> * that were retrieved with <code>Control.getAccessible()</code>. * </p> * * @since 3.6 */ public void dispose() { if (parent == null) return; Release(); parent.children.remove(this); parent = null; } long getAddress() { /* The address of an Accessible is the address of its IAccessible COMObject. */ if (objIAccessible == null) createIAccessible(); return objIAccessible.getAddress(); } /** * Returns the control for this Accessible object. * * @return the receiver's control * @since 3.0 */ public Control getControl() { return control; } /** * Invokes platform specific functionality to dispose an accessible object. * <p> * <b>IMPORTANT:</b> This method is <em>not</em> part of the public * API for <code>Accessible</code>. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. * </p> * * @noreference This method is not intended to be referenced by clients. */ public void internal_dispose_Accessible() { if (iaccessible != null) { iaccessible.Release(); } iaccessible = null; Release(); for (int i = 0; i < children.size(); i++) { Accessible child = children.get(i); child.dispose(); } } /** * Invokes platform specific functionality to handle a window message. * <p> * <b>IMPORTANT:</b> This method is <em>not</em> part of the public * API for <code>Accessible</code>. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. * </p> * * @noreference This method is not intended to be referenced by clients. */ public long internal_WM_GETOBJECT(long wParam, long lParam) { if (objIAccessible == null) return 0; if ((int) lParam == OS.OBJID_CLIENT) { /* LresultFromObject([in] riid, [in] wParam, [in] pAcc) * The argument pAcc is owned by the caller so reference count does not * need to be incremented. */ return COM.LresultFromObject(COM.IIDIAccessible, wParam, objIAccessible.getAddress()); } return 0; } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for certain strings, * such as name, description, help, or keyboard shortcut. * * @param listener the listener that should no longer be notified when the receiver * is asked for a name, description, help, or keyboard shortcut string * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleListener * @see #addAccessibleListener */ public void removeAccessibleListener(AccessibleListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleListeners != null) { accessibleListeners.remove(listener); if (accessibleListeners.isEmpty()) accessibleListeners = null; } } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for custom control * specific information. * * @param listener the listener that should no longer be notified when the receiver * is asked for custom control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleControlListener * @see #addAccessibleControlListener */ public void removeAccessibleControlListener(AccessibleControlListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleControlListeners != null) { accessibleControlListeners.remove(listener); if (accessibleControlListeners.isEmpty()) accessibleControlListeners = null; } } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for custom text control * specific information. * * @param listener the listener that should no longer be notified when the receiver * is asked for custom text control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTextListener * @see AccessibleTextExtendedListener * @see #addAccessibleTextListener * * @since 3.0 */ public void removeAccessibleTextListener(AccessibleTextListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (listener instanceof AccessibleTextExtendedListener) { if (accessibleTextExtendedListeners != null) { accessibleTextExtendedListeners.remove(listener); if (accessibleTextExtendedListeners.isEmpty()) accessibleTextExtendedListeners = null; } } else { if (accessibleTextListeners != null) { accessibleTextListeners.remove(listener); if (accessibleTextListeners.isEmpty()) accessibleTextListeners = null; } } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleActionListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleActionListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleActionListener * @see #addAccessibleActionListener * * @since 3.6 */ public void removeAccessibleActionListener(AccessibleActionListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleActionListeners != null) { accessibleActionListeners.remove(listener); if (accessibleActionListeners.isEmpty()) accessibleActionListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleEditableTextListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleEditableTextListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleEditableTextListener * @see #addAccessibleEditableTextListener * * @since 3.7 */ public void removeAccessibleEditableTextListener(AccessibleEditableTextListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleEditableTextListeners != null) { accessibleEditableTextListeners.remove(listener); if (accessibleEditableTextListeners.isEmpty()) accessibleEditableTextListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleHyperlinkListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleHyperlinkListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleHyperlinkListener * @see #addAccessibleHyperlinkListener * * @since 3.6 */ public void removeAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleHyperlinkListeners != null) { accessibleHyperlinkListeners.remove(listener); if (accessibleHyperlinkListeners.isEmpty()) accessibleHyperlinkListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleTableListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleTableListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTableListener * @see #addAccessibleTableListener * * @since 3.6 */ public void removeAccessibleTableListener(AccessibleTableListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleTableListeners != null) { accessibleTableListeners.remove(listener); if (accessibleTableListeners.isEmpty()) accessibleTableListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleTableCellListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleTableCellListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTableCellListener * @see #addAccessibleTableCellListener * * @since 3.6 */ public void removeAccessibleTableCellListener(AccessibleTableCellListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleTableCellListeners != null) { accessibleTableCellListeners.remove(listener); if (accessibleTableCellListeners.isEmpty()) accessibleTableCellListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleValueListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleValueListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleValueListener * @see #addAccessibleValueListener * * @since 3.6 */ public void removeAccessibleValueListener(AccessibleValueListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleValueListeners != null) { accessibleValueListeners.remove(listener); if (accessibleValueListeners.isEmpty()) accessibleValueListeners = null; } } /** * Removes the listener from the collection of listeners that will be * notified when an accessible client asks for any of the properties * defined in the <code>AccessibleAttributeListener</code> interface. * * @param listener the listener that should no longer be notified when the receiver * is asked for <code>AccessibleAttributeListener</code> interface properties * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleAttributeListener * @see #addAccessibleAttributeListener * * @since 3.6 */ public void removeAccessibleAttributeListener(AccessibleAttributeListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (accessibleAttributeListeners != null) { accessibleAttributeListeners.remove(listener); if (accessibleAttributeListeners.isEmpty()) accessibleAttributeListeners = null; } } /** * Removes the relation with the specified type and target * from the receiver's set of relations. * * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation * @param target the accessible that is the target for this relation * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null * @since 3.6 */ public void removeRelation(int type, Accessible target) { checkWidget(); if (target == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); Relation relation = relations[type]; if (relation != null) { relation.removeTarget(target); if (!relation.hasTargets()) { relations[type].Release(); relations[type] = null; } } } /** * Sends a message with event-specific data to accessible clients * indicating that something has changed within a custom control. * * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send * @param eventData an object containing event-specific data, or null if there is no event-specific data * (eventData is specified in the documentation for individual ACC.EVENT_* constants) * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see ACC#EVENT_ACTION_CHANGED * @see ACC#EVENT_ATTRIBUTE_CHANGED * @see ACC#EVENT_DESCRIPTION_CHANGED * @see ACC#EVENT_DOCUMENT_LOAD_COMPLETE * @see ACC#EVENT_DOCUMENT_LOAD_STOPPED * @see ACC#EVENT_DOCUMENT_RELOAD * @see ACC#EVENT_HYPERLINK_ACTIVATED * @see ACC#EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED * @see ACC#EVENT_HYPERLINK_END_INDEX_CHANGED * @see ACC#EVENT_HYPERLINK_SELECTED_LINK_CHANGED * @see ACC#EVENT_HYPERLINK_START_INDEX_CHANGED * @see ACC#EVENT_HYPERTEXT_LINK_COUNT_CHANGED * @see ACC#EVENT_HYPERTEXT_LINK_SELECTED * @see ACC#EVENT_LOCATION_CHANGED * @see ACC#EVENT_NAME_CHANGED * @see ACC#EVENT_PAGE_CHANGED * @see ACC#EVENT_SECTION_CHANGED * @see ACC#EVENT_SELECTION_CHANGED * @see ACC#EVENT_STATE_CHANGED * @see ACC#EVENT_TABLE_CAPTION_CHANGED * @see ACC#EVENT_TABLE_CHANGED * @see ACC#EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED * @see ACC#EVENT_TABLE_COLUMN_HEADER_CHANGED * @see ACC#EVENT_TABLE_ROW_DESCRIPTION_CHANGED * @see ACC#EVENT_TABLE_ROW_HEADER_CHANGED * @see ACC#EVENT_TABLE_SUMMARY_CHANGED * @see ACC#EVENT_TEXT_ATTRIBUTE_CHANGED * @see ACC#EVENT_TEXT_CARET_MOVED * @see ACC#EVENT_TEXT_CHANGED * @see ACC#EVENT_TEXT_COLUMN_CHANGED * @see ACC#EVENT_TEXT_SELECTION_CHANGED * @see ACC#EVENT_VALUE_CHANGED * * @since 3.6 */ public void sendEvent(int event, Object eventData) { checkWidget(); if (!isATRunning()) return; if (!UseIA2) return; if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + eventChildID()); switch (event) { case ACC.EVENT_TABLE_CHANGED: { if (!(eventData instanceof int[] && ((int[]) eventData).length == TABLE_MODEL_CHANGE_SIZE)) break; tableChange = (int[]) eventData; OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; } case ACC.EVENT_TEXT_CHANGED: { if (!(eventData instanceof Object[] && ((Object[]) eventData).length == TEXT_CHANGE_SIZE)) break; Object[] data = (Object[]) eventData; int type = ((Integer) data[0]).intValue(); switch (type) { case ACC.DELETE: textDeleted = (Object[]) eventData; OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_REMOVED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.INSERT: textInserted = (Object[]) eventData; OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_INSERTED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; } break; } case ACC.EVENT_HYPERTEXT_LINK_SELECTED: { if (!(eventData instanceof Integer)) break; // int index = ((Integer)eventData).intValue(); // TODO: IA2 currently does not use the index, however the plan is to use it in future OS.NotifyWinEvent(COM.IA2_EVENT_HYPERTEXT_LINK_SELECTED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; } case ACC.EVENT_VALUE_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_STATE_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_SELECTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TEXT_SELECTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_LOCATION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_NAME_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_DESCRIPTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_DOCUMENT_LOAD_COMPLETE: OS.NotifyWinEvent(COM.IA2_EVENT_DOCUMENT_LOAD_COMPLETE, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_DOCUMENT_LOAD_STOPPED: OS.NotifyWinEvent(COM.IA2_EVENT_DOCUMENT_LOAD_STOPPED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_DOCUMENT_RELOAD: OS.NotifyWinEvent(COM.IA2_EVENT_DOCUMENT_RELOAD, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_PAGE_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_PAGE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_SECTION_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_SECTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_ACTION_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_ACTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERLINK_START_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERLINK_END_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERLINK_ACTIVATED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERLINK_ACTIVATED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_ATTRIBUTE_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_CAPTION_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_CAPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_ROW_HEADER_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_ROW_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TABLE_SUMMARY_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TABLE_SUMMARY_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TEXT_CARET_MOVED: OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; case ACC.EVENT_TEXT_COLUMN_CHANGED: OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_COLUMN_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break; } } /** * Sends a message with event-specific data and a childID * to accessible clients, indicating that something has changed * within a custom control. * * NOTE: This API is intended for applications that are still using childIDs. * Moving forward, applications should use accessible objects instead of childIDs. * * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send * @param eventData an object containing event-specific data, or null if there is no event-specific data * (eventData is specified in the documentation for individual ACC.EVENT_* constants) * @param childID an identifier specifying a child of the control * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see ACC#EVENT_DESCRIPTION_CHANGED * @see ACC#EVENT_LOCATION_CHANGED * @see ACC#EVENT_NAME_CHANGED * @see ACC#EVENT_SELECTION_CHANGED * @see ACC#EVENT_STATE_CHANGED * @see ACC#EVENT_TEXT_SELECTION_CHANGED * @see ACC#EVENT_VALUE_CHANGED * * @since 3.8 */ public void sendEvent(int event, Object eventData, int childID) { checkWidget(); if (!isATRunning()) return; if (!UseIA2) return; int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID); if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + osChildID); switch (event) { case ACC.EVENT_STATE_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_NAME_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_VALUE_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_LOCATION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_SELECTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_TEXT_SELECTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, osChildID); break; case ACC.EVENT_DESCRIPTION_CHANGED: OS.NotifyWinEvent(COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break; } } /** * Sends a message to accessible clients that the child selection * within a custom container control has changed. * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void selectionChanged() { checkWidget(); if (!isATRunning()) return; if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_SELECTIONWITHIN hwnd=" + control.handle + " childID=" + eventChildID()); OS.NotifyWinEvent(COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID()); } /** * Sends a message to accessible clients indicating that the focus * has changed within a custom control. * * @param childID an identifier specifying a child of the control * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> */ public void setFocus(int childID) { checkWidget(); if (!isATRunning()) return; int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID); if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_FOCUS hwnd=" + control.handle + " childID=" + osChildID); OS.NotifyWinEvent(OS.EVENT_OBJECT_FOCUS, control.handle, OS.OBJID_CLIENT, osChildID); } /** * Sends a message to accessible clients that the text * caret has moved within a custom control. * * @param index the new caret index within the control * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void textCaretMoved(int index) { checkWidget(); if (timer == null) { timer = new Runnable() { @Override public void run() { if (!isATRunning()) return; if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_LOCATIONCHANGE hwnd=" + control.handle + " childID=" + eventChildID()); OS.NotifyWinEvent(COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CARET, eventChildID()); if (!UseIA2) return; if (DEBUG) print(this + ".NotifyWinEvent IA2_EVENT_TEXT_CARET_MOVED hwnd=" + control.handle + " childID=" + eventChildID()); OS.NotifyWinEvent(COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID()); } }; } control.getDisplay().timerExec(SCROLL_RATE, timer); } /** * Sends a message to accessible clients that the text * within a custom control has changed. * * @param type the type of change, one of <code>ACC.TEXT_INSERT</code> * or <code>ACC.TEXT_DELETE</code> * @param startIndex the text index within the control where the insertion or deletion begins * @param length the non-negative length in characters of the insertion or deletion * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see ACC#TEXT_INSERT * @see ACC#TEXT_DELETE * * @since 3.0 */ public void textChanged(int type, int startIndex, int length) { checkWidget(); if (!isATRunning()) return; AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = startIndex; event.end = startIndex + length; event.count = 0; event.type = ACC.TEXT_BOUNDARY_ALL; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } if (event.result != null) { Object[] eventData = new Object[] { Integer.valueOf(type), Integer.valueOf(startIndex), Integer.valueOf(startIndex + length), event.result }; sendEvent(ACC.EVENT_TEXT_CHANGED, eventData); return; } if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_VALUECHANGE hwnd=" + control.handle + " childID=" + eventChildID()); OS.NotifyWinEvent(COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); } /** * Sends a message to accessible clients that the text * selection has changed within a custom control. * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void textSelectionChanged() { checkWidget(); if (!isATRunning()) return; if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_TEXTSELECTIONCHANGED hwnd=" + control.handle + " childID=" + eventChildID()); OS.NotifyWinEvent(COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); } /* QueryInterface([in] iid, [out] ppvObject) * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject * must be incremented before returning. Caller is responsible for releasing ppvObject. */ int QueryInterface(long iid, long ppvObject) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF); GUID guid = new GUID(); COM.MoveMemory(guid, iid, GUID.sizeof); if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) { if (objIAccessible == null) createIAccessible(); OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF); AddRef(); if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK)); return COM.S_OK; } if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) { if (objIEnumVARIANT == null) createIEnumVARIANT(); OS.MoveMemory(ppvObject, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF); AddRef(); enumIndex = 0; if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIEnumVARIANT.getAddress() + hresult(COM.S_OK)); return COM.S_OK; } if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) { if (!UseIA2) return COM.E_NOINTERFACE; if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 || accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 || accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 || accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0 || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) { if (objIServiceProvider == null) createIServiceProvider(); OS.MoveMemory(ppvObject, new long[] { objIServiceProvider.getAddress() }, C.PTR_SIZEOF); AddRef(); if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIServiceProvider.getAddress() + hresult(COM.S_OK)); return COM.S_OK; } if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE)); return COM.E_NOINTERFACE; } int code = queryAccessible2Interfaces(guid, ppvObject); if (code != COM.S_FALSE) { if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning" + hresult(code)); return code; } if (iaccessible != null) { /* Forward any other GUIDs to the OS proxy. */ long[] ppv = new long[1]; code = iaccessible.QueryInterface(guid, ppv); OS.MoveMemory(ppvObject, ppv, C.PTR_SIZEOF); if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning super" + hresult(code)); return code; } if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE)); return COM.E_NOINTERFACE; } int accessibleListenersSize() { return accessibleListeners == null ? 0 : accessibleListeners.size(); } int accessibleControlListenersSize() { return accessibleControlListeners == null ? 0 : accessibleControlListeners.size(); } int accessibleValueListenersSize() { return accessibleValueListeners == null ? 0 : accessibleValueListeners.size(); } int accessibleTextExtendedListenersSize() { return accessibleTextExtendedListeners == null ? 0 : accessibleTextExtendedListeners.size(); } int accessibleTextListenersSize() { return accessibleTextListeners == null ? 0 : accessibleTextListeners.size(); } int accessibleTableCellListenersSize() { return accessibleTableCellListeners == null ? 0 : accessibleTableCellListeners.size(); } int accessibleTableListenersSize() { return accessibleTableListeners == null ? 0 : accessibleTableListeners.size(); } int accessibleHyperlinkListenersSize() { return accessibleHyperlinkListeners == null ? 0 : accessibleHyperlinkListeners.size(); } int accessibleEditableTextListenersSize() { return accessibleEditableTextListeners == null ? 0 : accessibleEditableTextListeners.size(); } int accessibleAttributeListenersSize() { return accessibleAttributeListeners == null ? 0 : accessibleAttributeListeners.size(); } int accessibleActionListenersSize() { return accessibleActionListeners == null ? 0 : accessibleActionListeners.size(); } int AddRef() { refCount++; return refCount; } int Release() { refCount--; if (refCount == 0) { if (objIAccessible != null) objIAccessible.dispose(); objIAccessible = null; if (objIEnumVARIANT != null) objIEnumVARIANT.dispose(); objIEnumVARIANT = null; if (objIServiceProvider != null) objIServiceProvider.dispose(); objIServiceProvider = null; if (objIAccessibleApplication != null) objIAccessibleApplication.dispose(); objIAccessibleApplication = null; // The following lines are intentionally commented. We are not providing IAccessibleComponent at this time. // if (objIAccessibleComponent != null) // objIAccessibleComponent.dispose(); // objIAccessibleComponent = null; if (objIAccessibleEditableText != null) objIAccessibleEditableText.dispose(); objIAccessibleEditableText = null; if (objIAccessibleHyperlink != null) objIAccessibleHyperlink.dispose(); objIAccessibleHyperlink = null; if (objIAccessibleHypertext != null) objIAccessibleHypertext.dispose(); objIAccessibleHypertext = null; // The following lines are intentionally commented. We are not providing IAccessibleImage at this time. // if (objIAccessibleImage != null) // objIAccessibleImage.dispose(); // objIAccessibleImage = null; if (objIAccessibleTable2 != null) objIAccessibleTable2.dispose(); objIAccessibleTable2 = null; if (objIAccessibleTableCell != null) objIAccessibleTableCell.dispose(); objIAccessibleTableCell = null; if (objIAccessibleValue != null) objIAccessibleValue.dispose(); objIAccessibleValue = null; for (int i = 0; i < relations.length; i++) { if (relations[i] != null) relations[i].Release(); } // TODO: also remove all relations for which 'this' is a target?? } return refCount; } /* QueryService([in] guidService, [in] riid, [out] ppvObject) */ int QueryService(long guidService, long riid, long ppvObject) { OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF); GUID service = new GUID(); COM.MoveMemory(service, guidService, GUID.sizeof); GUID guid = new GUID(); COM.MoveMemory(guid, riid, GUID.sizeof); if (COM.IsEqualGUID(service, COM.IIDIAccessible)) { if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) { if (objIAccessible == null) createIAccessible(); if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK)); OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } int code = queryAccessible2Interfaces(guid, ppvObject); if (code != COM.S_FALSE) { if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code)); return code; } } if (COM.IsEqualGUID(service, COM.IIDIAccessible2)) { int code = queryAccessible2Interfaces(guid, ppvObject); if (code != COM.S_FALSE) { if (DEBUG) print(this + ".*QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code)); return code; } } if (iaccessible != null) { /* Forward any other GUIDs to the OS proxy. */ long[] ppv = new long[1]; int code = iaccessible.QueryInterface(COM.IIDIServiceProvider, ppv); if (code == COM.S_OK) { IServiceProvider iserviceProvider = new IServiceProvider(ppv[0]); long[] ppvx = new long[1]; code = iserviceProvider.QueryService(service, guid, ppvx); OS.MoveMemory(ppvObject, ppvx, C.PTR_SIZEOF); if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning super" + hresult(code)); return code; } } if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE)); return COM.E_NOINTERFACE; } int queryAccessible2Interfaces(GUID guid, long ppvObject) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) { if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 || accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 || accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 || accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0 || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) { // NOTE: IAccessible2 vtable is shared with IAccessible if (objIAccessible == null) createIAccessible(); OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) { if (accessibleActionListenersSize() > 0) { // NOTE: IAccessibleAction vtable is shared with IAccessibleHyperlink if (objIAccessibleHyperlink == null) createIAccessibleHyperlink(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) { if (objIAccessibleApplication == null) createIAccessibleApplication(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleApplication.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) { // The following lines are intentionally commented. We are not supporting IAccessibleComponent at this time. // if (accessibleControlListenersSize() > 0) { // TO DO: can we reduce the scope of this somehow? // if (objIAccessibleComponent == null) createIAccessibleComponent(); // COM.MoveMemory(ppvObject, new long[] { objIAccessibleComponent.getAddress() }, OS.PTR_SIZEOF); // AddRef(); // return COM.S_OK; // } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) { if (accessibleEditableTextListenersSize() > 0) { if (objIAccessibleEditableText == null) createIAccessibleEditableText(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleEditableText.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) { if (accessibleHyperlinkListenersSize() > 0) { if (objIAccessibleHyperlink == null) createIAccessibleHyperlink(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) { if (accessibleTextExtendedListenersSize() > 0) { if (objIAccessibleHypertext == null) createIAccessibleHypertext(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) { // The following lines are intentionally commented. We are not supporting IAccessibleImage at this time. // if (getRole() == ACC.ROLE_GRAPHIC && (accessibleAccessibleListenersSize() > 0 || accessibleControlListenersSize() > 0)) { // if (objIAccessibleImage == null) createIAccessibleImage(); // COM.MoveMemory(ppvObject, new long[] { objIAccessibleImage.getAddress() }, OS.PTR_SIZEOF); // AddRef(); // return COM.S_OK; // } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) { // We are not supporting IAccessibleTable at this time. return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) { if (accessibleTableListenersSize() > 0) { if (objIAccessibleTable2 == null) createIAccessibleTable2(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleTable2.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) { if (accessibleTableCellListenersSize() > 0) { if (objIAccessibleTableCell == null) createIAccessibleTableCell(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleTableCell.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) { if (accessibleTextExtendedListenersSize() > 0 || accessibleAttributeListenersSize() > 0) { // NOTE: IAccessibleText vtable is shared with IAccessibleHypertext if (objIAccessibleHypertext == null) createIAccessibleHypertext(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) { if (accessibleValueListenersSize() > 0) { if (objIAccessibleValue == null) createIAccessibleValue(); OS.MoveMemory(ppvObject, new long[] { objIAccessibleValue.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } return COM.E_NOINTERFACE; } return COM.S_FALSE; } /* IAccessible::accDoDefaultAction([in] varChild) */ int accDoDefaultAction(long varChild) { if (DEBUG) print(this + ".IAccessible::accDoDefaultAction"); if (accessibleActionListenersSize() > 0) { VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; if (v.lVal == COM.CHILDID_SELF) return doAction(0); } int code = COM.DISP_E_MEMBERNOTFOUND; if (iaccessible != null) { /* If there were no action listeners, forward to the proxy. */ code = iaccessible.accDoDefaultAction(varChild); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID } return code; } /* IAccessible::accHitTest([in] xLeft, [in] yTop, [out] pvarChild) */ int accHitTest(int xLeft, int yTop, long pvarChild) { int osChild = ACC.CHILDID_NONE; long osChildObject = 0; if (iaccessible != null) { /* Get the default child at point (left, top) from the OS. */ int code = iaccessible.accHitTest(xLeft, yTop, pvarChild); if (code == COM.S_OK) { VARIANT v = getVARIANT(pvarChild); if (v.vt == COM.VT_I4) osChild = v.lVal; else if (v.vt == COM.VT_DISPATCH) { osChildObject = v.lVal; // TODO: don't use struct. lVal is an int. if (DEBUG) print(this + ".IAccessible::accHitTest() super returned VT_DISPATCH"); } } if (accessibleControlListenersSize() == 0) { if (DEBUG) print(this + ".IAccessible::accHitTest returning childID=" + osChild + " from super" + hresult(code)); return code; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild); // TODO: event.accessible = Accessible for osChildObject; event.x = xLeft; event.y = yTop; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getChildAtPoint(event); } Accessible accessible = event.accessible; if (accessible != null) { if (DEBUG) print(this + ".IAccessible::accHitTest returning " + accessible.getAddress() + hresult(COM.S_OK)); accessible.AddRef(); setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress()); return COM.S_OK; } int childID = event.childID; if (childID == ACC.CHILDID_NONE) { if (osChildObject != 0) { if (DEBUG) print(this + ".IAccessible::accHitTest returning osChildObject " + osChildObject + " from super" + hresult(COM.S_OK)); return COM.S_OK; } if (DEBUG) print(this + ".IAccessible::accHitTest returning VT_EMPTY" + hresult(COM.S_FALSE)); setIntVARIANT(pvarChild, COM.VT_EMPTY, 0); return COM.S_FALSE; } if (DEBUG) print(this + ".IAccessible::accHitTest returning " + childIDToOs(childID) + hresult(COM.S_OK)); setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID)); return COM.S_OK; } /* IAccessible::accLocation([out] pxLeft, [out] pyTop, [out] pcxWidth, [out] pcyHeight, [in] varChild) */ int accLocation(long pxLeft, long pyTop, long pcxWidth, long pcyHeight, long varChild) { VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0; if (iaccessible != null) { /* Get the default location from the OS. */ int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID if (accessibleControlListenersSize() == 0) { if (DEBUG) print(this + ".IAccessible::accLocation returning from super" + hresult(code)); return code; } if (code == COM.S_OK) { int[] pLeft = new int[1], pTop = new int[1], pWidth = new int[1], pHeight = new int[1]; OS.MoveMemory(pLeft, pxLeft, 4); OS.MoveMemory(pTop, pyTop, 4); OS.MoveMemory(pWidth, pcxWidth, 4); OS.MoveMemory(pHeight, pcyHeight, 4); osLeft = pLeft[0]; osTop = pTop[0]; osWidth = pWidth[0]; osHeight = pHeight[0]; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osToChildID(v.lVal); event.x = osLeft; event.y = osTop; event.width = osWidth; event.height = osHeight; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getLocation(event); } if (DEBUG) print(this + ".IAccessible::accLocation(" + v.lVal + ") returning x=" + event.x + " y=" + event.y + "w=" + event.width + "h=" + event.height + hresult(COM.S_OK)); OS.MoveMemory(pxLeft, new int[] { event.x }, 4); OS.MoveMemory(pyTop, new int[] { event.y }, 4); OS.MoveMemory(pcxWidth, new int[] { event.width }, 4); OS.MoveMemory(pcyHeight, new int[] { event.height }, 4); return COM.S_OK; } /* IAccessible::accNavigate([in] navDir, [in] varStart, [out] pvarEndUpAt) */ int accNavigate(int navDir, long varStart, long pvarEndUpAt) { if (DEBUG) print(this + ".IAccessible::accNavigate"); /* MSAA: "The accNavigate method is deprecated and should not be used." */ int code = COM.DISP_E_MEMBERNOTFOUND; if (iaccessible != null) { /* Since many of the native controls still handle accNavigate, * we will continue to send this through to the proxy. */ code = iaccessible.accNavigate(navDir, varStart, pvarEndUpAt); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID } return code; } // TODO: Consider supporting this in future. /* IAccessible::accSelect([in] flagsSelect, [in] varChild) */ int accSelect(int flagsSelect, long varChild) { int code = COM.DISP_E_MEMBERNOTFOUND; if (iaccessible != null) { /* Currently, we don't expose this as API. Forward to the proxy. */ code = iaccessible.accSelect(flagsSelect, varChild); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID } if (DEBUG) print(this + ".IAccessible::accSelect(" + flagsSelect + ") returning" + hresult(code)); return code; } /* IAccessible::get_accChild([in] varChild, [out] ppdispChild) * Ownership of ppdispChild transfers from callee to caller so reference count on ppdispChild * must be incremented before returning. The caller is responsible for releasing ppdispChild. */ int get_accChild(long varChild, long ppdispChild) { VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; if (v.lVal == COM.CHILDID_SELF) { if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + getAddress() + hresult(COM.S_OK)); AddRef(); OS.MoveMemory(ppdispChild, new long[] { getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } final int childID = osToChildID(v.lVal); int code = COM.S_FALSE; Accessible osAccessible = null; if (iaccessible != null) { /* Get the default child from the OS. */ code = iaccessible.get_accChild(varChild, ppdispChild); if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID if (code == COM.S_OK && control instanceof ToolBar) { ToolBar toolBar = (ToolBar) control; final ToolItem item = toolBar.getItem(childID); if (item != null && (item.getStyle() & SWT.DROP_DOWN) != 0) { long[] addr = new long[1]; OS.MoveMemory(addr, ppdispChild, C.PTR_SIZEOF); boolean found = false; for (int i = 0; i < children.size(); i++) { Accessible accChild = children.get(i); if (accChild.item == item) { /* * MSAA uses a new accessible for the child * so we dispose the old and use the new. */ accChild.dispose(); accChild.item = null; found = true; break; } } osAccessible = new Accessible(this, addr[0]); osAccessible.item = item; if (!found) { item.addListener(SWT.Dispose, e -> { for (int i = 0; i < children.size(); i++) { Accessible accChild = children.get(i); if (accChild.item == item) { accChild.dispose(); } } }); } osAccessible.addAccessibleListener(new AccessibleAdapter() { @Override public void getName(AccessibleEvent e) { if (e.childID == ACC.CHILDID_SELF) { AccessibleEvent event = new AccessibleEvent(Accessible.this); event.childID = childID; for (int i = 0; i < accessibleListenersSize(); i++) { AccessibleListener listener = accessibleListeners.get(i); listener.getName(event); } e.result = event.result; } } }); } } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getChild(event); } Accessible accessible = event.accessible; if (accessible == null) accessible = osAccessible; if (accessible != null) { if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + accessible.getAddress() + hresult(COM.S_OK)); accessible.AddRef(); OS.MoveMemory(ppdispChild, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning from super" + hresult(code)); return code; } /* IAccessible::get_accChildCount([out] pcountChildren) */ int get_accChildCount(long pcountChildren) { int osChildCount = 0; if (iaccessible != null) { /* Get the default child count from the OS. */ int code = iaccessible.get_accChildCount(pcountChildren); if (code == COM.S_OK) { int[] pChildCount = new int[1]; OS.MoveMemory(pChildCount, pcountChildren, 4); osChildCount = pChildCount[0]; } if (accessibleControlListenersSize() == 0) { if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + osChildCount + " from super" + hresult(code)); return code; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_SELF; event.detail = osChildCount; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getChildCount(event); } if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + event.detail + hresult(COM.S_OK)); OS.MoveMemory(pcountChildren, new int[] { event.detail }, 4); return COM.S_OK; } /* IAccessible::get_accDefaultAction([in] varChild, [out] pszDefaultAction) */ int get_accDefaultAction(long varChild, long pszDefaultAction) { if (DEBUG) print(this + ".IAccessible::get_accDefaultAction"); VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; String osDefaultAction = null; if (iaccessible != null) { /* Get the default defaultAction from the OS. */ code = iaccessible.get_accDefaultAction(varChild, pszDefaultAction); if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID if (accessibleControlListenersSize() == 0) return code; if (code == COM.S_OK) { long[] pDefaultAction = new long[1]; OS.MoveMemory(pDefaultAction, pszDefaultAction, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pDefaultAction[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pDefaultAction[0], size); osDefaultAction = new String(buffer); } } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osToChildID(v.lVal); event.result = osDefaultAction; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getDefaultAction(event); } if ((event.result == null || event.result.length() == 0) && v.lVal == COM.CHILDID_SELF) { code = get_name(0, pszDefaultAction); } if (event.result == null) return code; if (event.result.length() == 0) return COM.S_FALSE; setString(pszDefaultAction, event.result); return COM.S_OK; } /* IAccessible::get_accDescription([in] varChild, [out] pszDescription) */ int get_accDescription(long varChild, long pszDescription) { /* * MSAA: "The accDescription property is not supported in the transition to * UI Automation. MSAA servers and applications should not use it." * * TODO: Description was exposed as SWT API. We will need to either deprecate this (?), * or find a suitable replacement. Also, check description property on other platforms. * If it is truly deprecated for MSAA, then perhaps it can be reused for IAccessibleImage. * Note that the trick to expose tree columns (below) was not supported by screen readers, * so it should be replaced. */ VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; String osDescription = null; if (iaccessible != null) { /* Get the default description from the OS. */ code = iaccessible.get_accDescription(varChild, pszDescription); if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID // TEMPORARY CODE - process tree even if there are no apps listening if (accessibleListenersSize() == 0 && !(control instanceof Tree)) { if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning super" + hresult(code)); return code; } if (code == COM.S_OK) { long[] pDescription = new long[1]; OS.MoveMemory(pDescription, pszDescription, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pDescription[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pDescription[0], size); osDescription = new String(buffer); } } } AccessibleEvent event = new AccessibleEvent(this); event.childID = osToChildID(v.lVal); event.result = osDescription; // TEMPORARY CODE /* Currently our tree columns are emulated using custom draw, * so we need to create the description using the tree column * header text and tree item text. */ if (v.lVal != COM.CHILDID_SELF) { if (control instanceof Tree) { Tree tree = (Tree) control; int columnCount = tree.getColumnCount(); if (columnCount > 1) { long hwnd = control.handle, hItem = 0; hItem = OS.SendMessage(hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0); Widget widget = tree.getDisplay().findWidget(hwnd, hItem); event.result = ""; if (widget != null && widget instanceof TreeItem) { TreeItem item = (TreeItem) widget; for (int i = 1; i < columnCount; i++) { if (tree.isDisposed() || item.isDisposed()) { event.result = ""; return COM.S_OK; } event.result += tree.getColumn(i).getText() + ": " + item.getText(i); if (i + 1 < columnCount) event.result += ", "; } } } } } for (int i = 0; i < accessibleListenersSize(); i++) { AccessibleListener listener = accessibleListeners.get(i); listener.getDescription(event); } if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (event.result == null) return code; if (event.result.length() == 0) return COM.S_FALSE; setString(pszDescription, event.result); return COM.S_OK; } /* IAccessible::get_accFocus([out] pvarChild) * Ownership of pvarChild transfers from callee to caller so reference count on pvarChild * must be incremented before returning. The caller is responsible for releasing pvarChild. */ int get_accFocus(long pvarChild) { int osChild = ACC.CHILDID_NONE; if (iaccessible != null) { /* Get the default focus child from the OS. */ int code = iaccessible.get_accFocus(pvarChild); if (code == COM.S_OK) { VARIANT v = getVARIANT(pvarChild); if (v.vt == COM.VT_I4) osChild = v.lVal; // TODO: need to check VT_DISPATCH (don't use struct) if (DEBUG) if (v.vt == COM.VT_DISPATCH) print("IAccessible::get_accFocus() super returned VT_DISPATCH"); } if (accessibleControlListenersSize() == 0) { if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID=" + osChild + " from super" + hresult(code)); return code; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild); for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getFocus(event); } Accessible accessible = event.accessible; if (accessible != null) { if (DEBUG) print(this + ".IAccessible::get_accFocus() returning accessible " + accessible.getAddress() + hresult(COM.S_OK)); accessible.AddRef(); setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress()); return COM.S_OK; } int childID = event.childID; if (childID == ACC.CHILDID_NONE) { if (DEBUG) print(this + ".IAccessible::get_accFocus() returning VT_EMPTY" + hresult(COM.S_FALSE)); setIntVARIANT(pvarChild, COM.VT_EMPTY, 0); return COM.S_FALSE; } if (childID == ACC.CHILDID_SELF) { if (DEBUG) print(this + ".IAccessible::get_accFocus() returning CHILDID_SELF " + hresult(COM.S_OK)); AddRef(); setIntVARIANT(pvarChild, COM.VT_I4, COM.CHILDID_SELF); return COM.S_OK; } if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID " + childIDToOs(childID) + hresult(COM.S_OK)); setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID)); return COM.S_OK; } /* IAccessible::get_accHelp([in] varChild, [out] pszHelp) */ int get_accHelp(long varChild, long pszHelp) { if (DEBUG) print(this + ".IAccessible::get_accHelp"); VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; String osHelp = null; if (iaccessible != null) { /* Get the default help string from the OS. */ code = iaccessible.get_accHelp(varChild, pszHelp); if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID if (accessibleListenersSize() == 0) return code; if (code == COM.S_OK) { long[] pHelp = new long[1]; OS.MoveMemory(pHelp, pszHelp, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pHelp[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pHelp[0], size); osHelp = new String(buffer); } } } AccessibleEvent event = new AccessibleEvent(this); event.childID = osToChildID(v.lVal); event.result = osHelp; for (int i = 0; i < accessibleListenersSize(); i++) { AccessibleListener listener = accessibleListeners.get(i); listener.getHelp(event); } if (event.result == null) return code; if (event.result.length() == 0) return COM.S_FALSE; setString(pszHelp, event.result); return COM.S_OK; } /* IAccessible::get_accHelpTopic([out] pszHelpFile, [in] varChild, [out] pidTopic) */ int get_accHelpTopic(long pszHelpFile, long varChild, long pidTopic) { if (DEBUG) print(this + ".IAccessible::get_accHelpTopic"); /* MSAA: "The accHelpTopic property is deprecated and should not be used." */ int code = COM.DISP_E_MEMBERNOTFOUND; if (iaccessible != null) { /* Since it is possible that a native control might still handle get_accHelpTopic, * we will continue to send this through to the proxy. */ code = iaccessible.get_accHelpTopic(pszHelpFile, varChild, pidTopic); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID } return code; } /* IAccessible::get_accKeyboardShortcut([in] varChild, [out] pszKeyboardShortcut) */ int get_accKeyboardShortcut(long varChild, long pszKeyboardShortcut) { if (DEBUG) print(this + ".IAccessible::get_accKeyboardShortcut"); VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; String osKeyboardShortcut = null; if (iaccessible != null) { /* Get the default keyboard shortcut from the OS. */ code = iaccessible.get_accKeyboardShortcut(varChild, pszKeyboardShortcut); if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID /* Process TabFolder even if there are no apps listening. */ if (accessibleListenersSize() == 0 && !(control instanceof TabFolder)) return code; if (code == COM.S_OK) { long[] pKeyboardShortcut = new long[1]; OS.MoveMemory(pKeyboardShortcut, pszKeyboardShortcut, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pKeyboardShortcut[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pKeyboardShortcut[0], size); osKeyboardShortcut = new String(buffer); } } } AccessibleEvent event = new AccessibleEvent(this); event.childID = osToChildID(v.lVal); event.result = osKeyboardShortcut; /* SWT TabFolders use Ctrl+PageDown to switch pages (not Ctrl+Tab). */ if (v.lVal == COM.CHILDID_SELF && control instanceof TabFolder) { event.result = SWT.getMessage("SWT_SwitchPage_Shortcut"); //$NON-NLS-1$ } for (int i = 0; i < accessibleListenersSize(); i++) { AccessibleListener listener = accessibleListeners.get(i); listener.getKeyboardShortcut(event); } if (event.result == null) return code; if (event.result.length() == 0) return COM.S_FALSE; setString(pszKeyboardShortcut, event.result); return COM.S_OK; } /* IAccessible::get_accName([in] varChild, [out] pszName) */ int get_accName(long varChild, long pszName) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.S_FALSE; String osName = null; if (iaccessible != null) { /* Get the default name from the OS. */ code = iaccessible.get_accName(varChild, pszName); if (code == COM.S_OK) { long[] pName = new long[1]; OS.MoveMemory(pName, pszName, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pName[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pName[0], size); osName = new String(buffer); } } if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID /* Process Text even if there are no apps listening. */ if (accessibleListenersSize() == 0 && !(control instanceof Text)) { if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning name=" + osName + " from super" + hresult(code)); return code; } } AccessibleEvent event = new AccessibleEvent(this); event.childID = osToChildID(v.lVal); event.result = osName; /* * Bug in Windows: A Text with SWT.SEARCH style uses EM_SETCUEBANNER * to set the message text. This text should be used as the control's * accessible name, however it is not. The fix is to return the message * text here as the accName (unless there is a preceding label). */ if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && osName == null) { event.result = ((Text) control).getMessage(); } for (int i = 0; i < accessibleListenersSize(); i++) { AccessibleListener listener = accessibleListeners.get(i); listener.getName(event); } if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (event.result == null) return code; if (event.result.length() == 0) return COM.S_FALSE; setString(pszName, event.result); return COM.S_OK; } /* IAccessible::get_accParent([out] ppdispParent) * Ownership of ppdispParent transfers from callee to caller so reference count on ppdispParent * must be incremented before returning. The caller is responsible for releasing ppdispParent. */ int get_accParent(long ppdispParent) { int code = COM.DISP_E_MEMBERNOTFOUND; if (iaccessible != null) { /* Currently, we don't expose this as API. Forward to the proxy. */ code = iaccessible.get_accParent(ppdispParent); } if (parent != null) { /* For lightweight accessibles, return the accessible's parent. */ parent.AddRef(); OS.MoveMemory(ppdispParent, new long[] { parent.getAddress() }, C.PTR_SIZEOF); code = COM.S_OK; } if (DEBUG) print(this + ".IAccessible::get_accParent() returning" + (parent != null ? " " + parent.getAddress() : " from super") + hresult(code)); return code; } /* IAccessible::get_accRole([in] varChild, [out] pvarRole) */ int get_accRole(long varChild, long pvarRole) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int osRole = COM.ROLE_SYSTEM_CLIENT; if (iaccessible != null) { /* Get the default role from the OS. */ int code = iaccessible.get_accRole(varChild, pvarRole); if (code == COM.S_OK) { VARIANT v2 = getVARIANT(pvarRole); if (v2.vt == COM.VT_I4) osRole = v2.lVal; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osToChildID(v.lVal); event.detail = osToRole(osRole); // TEMPORARY CODE /* Currently our checkbox table and tree are emulated using state mask images, * so we need to specify 'checkbox' role for the items. */ if (control instanceof Tree || control instanceof Table) { if (v.lVal != COM.CHILDID_SELF && (control.getStyle() & SWT.CHECK) != 0) event.detail = ACC.ROLE_CHECKBUTTON; } for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getRole(event); } if (DEBUG) print(this + ".IAccessible::get_accRole(" + v.lVal + ") returning " + getRoleString(roleToOs(event.detail)) + hresult(COM.S_OK)); setIntVARIANT(pvarRole, COM.VT_I4, roleToOs(event.detail)); return COM.S_OK; } /* IAccessible::get_accSelection([out] pvarChildren) * Ownership of pvarChildren transfers from callee to caller so reference count on pvarChildren * must be incremented before returning. The caller is responsible for releasing pvarChildren. */ int get_accSelection(long pvarChildren) { if (DEBUG) print(this + ".IAccessible::get_accSelection"); int osChild = ACC.CHILDID_NONE; long osChildObject = 0; if (iaccessible != null) { /* Get the default selection from the OS. */ int code = iaccessible.get_accSelection(pvarChildren); if (accessibleControlListenersSize() == 0) return code; if (code == COM.S_OK) { VARIANT v = getVARIANT(pvarChildren); if (v.vt == COM.VT_I4) { osChild = osToChildID(v.lVal); } else if (v.vt == COM.VT_DISPATCH) { osChildObject = v.lVal; // TODO: don't use struct; lVal is an int } else if (v.vt == COM.VT_UNKNOWN) { osChild = ACC.CHILDID_MULTIPLE; // TODO: Should get IEnumVARIANT from punkVal field, and enumerate children... } } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osChild; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getSelection(event); } Accessible accessible = event.accessible; if (accessible != null) { accessible.AddRef(); setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, accessible.getAddress()); return COM.S_OK; } int childID = event.childID; if (childID == ACC.CHILDID_NONE) { if (osChildObject != 0) return COM.S_OK; setIntVARIANT(pvarChildren, COM.VT_EMPTY, 0); return COM.S_FALSE; } if (childID == ACC.CHILDID_MULTIPLE) { // TODO: return an enumeration for event.children (currently just returns enumeration from proxy) //AddRef(); //setPtrVARIANT(pvarChildren, COM.VT_UNKNOWN, getAddress()); return COM.S_OK; } if (childID == ACC.CHILDID_SELF) { AddRef(); setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, getAddress()); return COM.S_OK; } setIntVARIANT(pvarChildren, COM.VT_I4, childIDToOs(childID)); return COM.S_OK; } /* IAccessible::get_accState([in] varChild, [out] pvarState) */ int get_accState(long varChild, long pvarState) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int osState = 0; if (iaccessible != null) { /* Get the default state from the OS. */ int code = iaccessible.get_accState(varChild, pvarState); if (code == COM.S_OK) { VARIANT v2 = getVARIANT(pvarState); if (v2.vt == COM.VT_I4) osState = v2.lVal; } } boolean grayed = false; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osToChildID(v.lVal); event.detail = osToState(osState); // TEMPORARY CODE /* Currently our checkbox table and tree are emulated using state mask * images, so we need to determine if the item state is 'checked'. */ if (v.lVal != COM.CHILDID_SELF) { if (control instanceof Tree && (control.getStyle() & SWT.CHECK) != 0) { long hwnd = control.handle; TVITEM tvItem = new TVITEM(); tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; tvItem.stateMask = OS.TVIS_STATEIMAGEMASK; tvItem.hItem = OS.SendMessage(hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0); long result = OS.SendMessage(hwnd, OS.TVM_GETITEM, 0, tvItem); boolean checked = (result != 0) && (((tvItem.state >> 12) & 1) == 0); if (checked) event.detail |= ACC.STATE_CHECKED; grayed = tvItem.state >> 12 > 2; } else if (control instanceof Table && (control.getStyle() & SWT.CHECK) != 0) { Table table = (Table) control; int index = event.childID; if (0 <= index && index < table.getItemCount()) { TableItem item = table.getItem(index); if (item.getChecked()) event.detail |= ACC.STATE_CHECKED; if (item.getGrayed()) grayed = true; } } } for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getState(event); } int state = stateToOs(event.detail); if ((state & ACC.STATE_CHECKED) != 0 && grayed) { state &= ~COM.STATE_SYSTEM_CHECKED; state |= COM.STATE_SYSTEM_MIXED; } if (DEBUG) print(this + ".IAccessible::get_accState(" + v.lVal + ") returning" + getStateString(state) + hresult(COM.S_OK)); setIntVARIANT(pvarState, COM.VT_I4, state); return COM.S_OK; } /* IAccessible::get_accValue([in] varChild, [out] pszValue) */ int get_accValue(long varChild, long pszValue) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; String osValue = null; if (iaccessible != null) { /* Get the default value string from the OS. */ code = iaccessible.get_accValue(varChild, pszValue); if (code == COM.S_OK) { long[] pValue = new long[1]; OS.MoveMemory(pValue, pszValue, C.PTR_SIZEOF); int size = COM.SysStringByteLen(pValue[0]); if (size > 0) { char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, pValue[0], size); osValue = new String(buffer); } } if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID /* Process Text even if there are no apps listening. */ if (accessibleControlListenersSize() == 0 && !(control instanceof Text)) { if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning value=" + osValue + " from super" + hresult(code)); return code; } } AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = osToChildID(v.lVal); event.result = osValue; /* * Bug in Windows: A Text with SWT.SEARCH style uses EM_SETCUEBANNER * to set the message text. This text should be used as the control's * accessible value when the control does not have focus, however it * is not. The fix is to return the message text here as the accValue. */ if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && !control.isFocusControl()) { event.result = ((Text) control).getMessage(); } for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getValue(event); } if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : COM.S_OK)); if (event.result == null) return code; // empty string is a valid value, so do not test for it setString(pszValue, event.result); return COM.S_OK; } /* put_accName([in] varChild, [in] szName) */ int put_accName(long varChild, long szName) { /* MSAA: "The IAccessible::put_accName method is no longer supported. Servers should return E_NOTIMPL." */ return COM.E_NOTIMPL; } /* put_accValue([in] varChild, [in] szValue) */ int put_accValue(long varChild, long szValue) { /* MSAA: this method is supported for some UI elements (usually edit controls). */ VARIANT v = getVARIANT(varChild); if (v.vt != COM.VT_I4) return COM.E_INVALIDARG; int code = COM.DISP_E_MEMBERNOTFOUND; if (v.lVal == COM.CHILDID_SELF && accessibleEditableTextListenersSize() > 0) { /* * If the object supports AccessibleEditableTextListener.replaceText, * then give the object a chance to handle this event. */ AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = 0; event.end = getCharacterCount(); if (event.end >= 0) { int size = COM.SysStringByteLen(szValue); char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, szValue, size); event.string = new String(buffer); for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.replaceText(event); } if (event.result != null && event.result.equals(ACC.OK)) code = COM.S_OK; if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ", \"" + event.string + "\") returning " + hresult(code)); } } if (code != COM.S_OK && iaccessible != null) { /* If the object did not handle the event, then forward to the proxy. */ code = iaccessible.put_accValue(varChild, szValue); if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ") returning " + hresult(code) + " from proxy"); } return code; } /* IEnumVARIANT methods: Next, Skip, Reset, Clone */ /* Retrieve the next celt items in the enumeration sequence. * If there are fewer than the requested number of elements left * in the sequence, retrieve the remaining elements. * The number of elements actually retrieved is returned in pceltFetched * (unless the caller passed in NULL for that parameter). */ /* IEnumVARIANT::Next([in] celt, [out] rgvar, [in, out] pceltFetched) * Ownership of rgvar transfers from callee to caller so reference count on rgvar * must be incremented before returning. The caller is responsible for releasing rgvar. */ int Next(int celt, long rgvar, long pceltFetched) { if (DEBUG) print(this + ".IEnumVARIANT::Next"); /* If there are no listeners, query the proxy for * its IEnumVariant, and get the Next items from it. */ if (iaccessible != null && accessibleControlListenersSize() == 0) { long[] ppvObject = new long[1]; int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject); if (code != COM.S_OK) return code; IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]); int[] celtFetched = new int[1]; code = ienumvariant.Next(celt, rgvar, celtFetched); ienumvariant.Release(); OS.MoveMemory(pceltFetched, celtFetched, 4); return code; } if (rgvar == 0) return COM.E_INVALIDARG; if (pceltFetched == 0 && celt != 1) return COM.E_INVALIDARG; if (enumIndex == 0) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_SELF; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getChildren(event); } variants = event.children; } Object[] nextItems = null; if (variants != null && celt >= 1) { int endIndex = enumIndex + celt - 1; if (endIndex > (variants.length - 1)) endIndex = variants.length - 1; if (enumIndex <= endIndex) { nextItems = new Object[endIndex - enumIndex + 1]; for (int i = 0; i < nextItems.length; i++) { Object child = variants[enumIndex]; if (child instanceof Integer) { nextItems[i] = Integer.valueOf(childIDToOs(((Integer) child).intValue())); } else { nextItems[i] = child; } enumIndex++; } } } if (nextItems != null) { for (int i = 0; i < nextItems.length; i++) { Object nextItem = nextItems[i]; if (nextItem instanceof Integer) { int item = ((Integer) nextItem).intValue(); setIntVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_I4, item); } else { Accessible accessible = (Accessible) nextItem; accessible.AddRef(); setPtrVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_DISPATCH, accessible.getAddress()); } } if (pceltFetched != 0) OS.MoveMemory(pceltFetched, new int[] { nextItems.length }, 4); if (nextItems.length == celt) return COM.S_OK; } else { if (pceltFetched != 0) OS.MoveMemory(pceltFetched, new int[] { 0 }, 4); } return COM.S_FALSE; } /* IEnumVARIANT::Skip([in] celt) over the specified number of elements in the enumeration sequence. */ int Skip(int celt) { if (DEBUG) print(this + ".IEnumVARIANT::Skip"); /* If there are no listeners, query the proxy * for its IEnumVariant, and tell it to Skip. */ if (iaccessible != null && accessibleControlListenersSize() == 0) { long[] ppvObject = new long[1]; int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject); if (code != COM.S_OK) return code; IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]); code = ienumvariant.Skip(celt); ienumvariant.Release(); return code; } if (celt < 1) return COM.E_INVALIDARG; enumIndex += celt; if (enumIndex > (variants.length - 1)) { enumIndex = variants.length - 1; return COM.S_FALSE; } return COM.S_OK; } /* IEnumVARIANT::Reset() the enumeration sequence to the beginning. */ int Reset() { if (DEBUG) print(this + ".IEnumVARIANT::Reset"); /* If there are no listeners, query the proxy * for its IEnumVariant, and tell it to Reset. */ if (iaccessible != null && accessibleControlListenersSize() == 0) { long[] ppvObject = new long[1]; int code = (int) iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject); if (code != COM.S_OK) return code; IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]); code = ienumvariant.Reset(); ienumvariant.Release(); return code; } enumIndex = 0; return COM.S_OK; } /* IEnumVARIANT::Clone([out] ppEnum) * Ownership of ppEnum transfers from callee to caller so reference count on ppEnum * must be incremented before returning. The caller is responsible for releasing ppEnum. */ int Clone(long ppEnum) { if (DEBUG) print(this + ".IEnumVARIANT::Clone"); /* If there are no listeners, query the proxy for * its IEnumVariant, and get the Clone from it. */ if (iaccessible != null && accessibleControlListenersSize() == 0) { long[] ppvObject = new long[1]; int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject); if (code != COM.S_OK) return code; IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]); long[] pEnum = new long[1]; code = ienumvariant.Clone(pEnum); ienumvariant.Release(); OS.MoveMemory(ppEnum, pEnum, C.PTR_SIZEOF); return code; } if (ppEnum == 0) return COM.E_INVALIDARG; OS.MoveMemory(ppEnum, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF); AddRef(); return COM.S_OK; } /* IAccessible2::get_nRelations([out] pNRelations) */ int get_nRelations(long pNRelations) { int count = getRelationCount(); if (DEBUG) print(this + ".IAccessible2::get_nRelations returning " + count + hresult(COM.S_OK)); OS.MoveMemory(pNRelations, new int[] { count }, 4); return COM.S_OK; } /* IAccessible2::get_relation([in] relationIndex, [out] ppRelation) */ int get_relation(int relationIndex, long ppRelation) { int i = -1; for (int type = 0; type < MAX_RELATION_TYPES; type++) { Relation relation = relations[type]; if (relation != null) i++; if (i == relationIndex) { if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning " + relation.getAddress() + hresult(COM.S_OK)); relation.AddRef(); OS.MoveMemory(ppRelation, new long[] { relation.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } } if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning" + hresult(COM.E_INVALIDARG)); return COM.E_INVALIDARG; } /* IAccessible2::get_relations([in] maxRelations, [out] ppRelations, [out] pNRelations) */ int get_relations(int maxRelations, long ppRelations, long pNRelations) { int count = 0; for (int type = 0; type < MAX_RELATION_TYPES; type++) { if (count == maxRelations) break; Relation relation = relations[type]; if (relation != null) { relation.AddRef(); OS.MoveMemory(ppRelations + count * C.PTR_SIZEOF, new long[] { relation.getAddress() }, C.PTR_SIZEOF); count++; } } if (DEBUG) print(this + ".IAccessible2::get_relations(" + maxRelations + ") returning " + count + hresult(COM.S_OK)); OS.MoveMemory(pNRelations, new int[] { count }, 4); return COM.S_OK; } /* IAccessible2::get_role([out] pRole) */ int get_role(long pRole) { int role = getRole(); if (role == 0) role = getDefaultRole(); if (DEBUG) print(this + ".IAccessible2::get_role() returning " + getRoleString(role) + hresult(COM.S_OK)); OS.MoveMemory(pRole, new int[] { role }, 4); return COM.S_OK; } /* IAccessible2::scrollTo([in] scrollType) */ int scrollTo(int scrollType) { if (DEBUG) print(this + ".IAccessible2::scrollTo"); if (scrollType < ACC.SCROLL_TYPE_LEFT_EDGE || scrollType > ACC.SCROLL_TYPE_ANYWHERE) return COM.E_INVALIDARG; return COM.E_NOTIMPL; } /* IAccessible2::scrollToPoint([in] coordinateType, [in] x, [in] y) */ int scrollToPoint(int coordinateType, int x, int y) { if (DEBUG) print(this + ".IAccessible2::scrollToPoint"); if (coordinateType != COM.IA2_COORDTYPE_SCREEN_RELATIVE) return COM.E_INVALIDARG; return COM.E_NOTIMPL; } /* IAccessible2::get_groupPosition([out] pGroupLevel, [out] pSimilarItemsInGroup, [out] pPositionInGroup) */ int get_groupPosition(long pGroupLevel, long pSimilarItemsInGroup, long pPositionInGroup) { if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED; AccessibleAttributeEvent event = new AccessibleAttributeEvent(this); event.groupLevel = event.groupCount = event.groupIndex = -1; for (int i = 0; i < accessibleAttributeListenersSize(); i++) { AccessibleAttributeListener listener = accessibleAttributeListeners.get(i); listener.getAttributes(event); } int groupLevel = (event.groupLevel != -1) ? event.groupLevel : 0; int similarItemsInGroup = (event.groupCount != -1) ? event.groupCount : 0; int positionInGroup = (event.groupIndex != -1) ? event.groupIndex : 0; if (similarItemsInGroup == 0 && positionInGroup == 0) { /* Determine position and count for radio buttons. */ if (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) { Control[] children = control.getParent().getChildren(); positionInGroup = 1; similarItemsInGroup = 1; for (int i = 0; i < children.length; i++) { Control child = children[i]; if (child instanceof Button && ((child.getStyle() & SWT.RADIO) != 0)) { if (child == control) positionInGroup = similarItemsInGroup; else similarItemsInGroup++; } } } } OS.MoveMemory(pGroupLevel, new int[] { groupLevel }, 4); OS.MoveMemory(pSimilarItemsInGroup, new int[] { similarItemsInGroup }, 4); OS.MoveMemory(pPositionInGroup, new int[] { positionInGroup }, 4); if (DEBUG) print(this + ".IAccessible2::get_groupPosition() returning level=" + groupLevel + ", count=" + similarItemsInGroup + ", index=" + positionInGroup + hresult(groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0 ? COM.S_FALSE : COM.S_OK)); if (groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0) return COM.S_FALSE; return COM.S_OK; } /* IAccessible2::get_states([out] pStates) */ int get_states(long pStates) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_SELF; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getState(event); } int states = event.detail; int ia2States = 0; if ((states & ACC.STATE_ACTIVE) != 0) ia2States |= COM.IA2_STATE_ACTIVE; if ((states & ACC.STATE_SINGLELINE) != 0) ia2States |= COM.IA2_STATE_SINGLE_LINE; if ((states & ACC.STATE_MULTILINE) != 0) ia2States |= COM.IA2_STATE_MULTI_LINE; if ((states & ACC.STATE_REQUIRED) != 0) ia2States |= COM.IA2_STATE_REQUIRED; if ((states & ACC.STATE_INVALID_ENTRY) != 0) ia2States |= COM.IA2_STATE_INVALID_ENTRY; if ((states & ACC.STATE_SUPPORTS_AUTOCOMPLETION) != 0) ia2States |= COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION; /* If the role is text and there are TextExtendedListeners, then set IA2_STATE_EDITABLE. * Note that IA2_STATE_EDITABLE is not the opposite of STATE_READONLY. * Instead, it means: "has a caret, supports IAccessibleText, and is a text editing environment". */ if (getRole() == ACC.ROLE_TEXT && accessibleTextExtendedListenersSize() > 0) { ia2States |= COM.IA2_STATE_EDITABLE; } if (DEBUG) print(this + ".IAccessible2::get_states returning" + getIA2StatesString(ia2States) + hresult(COM.S_OK)); OS.MoveMemory(pStates, new int[] { ia2States }, 4); return COM.S_OK; } /* IAccessible2::get_extendedRole([out] pbstrExtendedRole) */ int get_extendedRole(long pbstrExtendedRole) { /* This feature is not supported. */ setString(pbstrExtendedRole, null); return COM.S_FALSE; } /* IAccessible2::get_localizedExtendedRole([out] pbstrLocalizedExtendedRole) */ int get_localizedExtendedRole(long pbstrLocalizedExtendedRole) { /* This feature is not supported. */ setString(pbstrLocalizedExtendedRole, null); return COM.S_FALSE; } /* IAccessible2::get_nExtendedStates([out] pNExtendedStates) */ int get_nExtendedStates(long pNExtendedStates) { /* This feature is not supported. */ OS.MoveMemory(pNExtendedStates, new int[] { 0 }, 4); return COM.S_OK; } /* IAccessible2::get_extendedStates([in] maxExtendedStates, [out] ppbstrExtendedStates, [out] pNExtendedStates) */ int get_extendedStates(int maxExtendedStates, long ppbstrExtendedStates, long pNExtendedStates) { /* This feature is not supported. */ setString(ppbstrExtendedStates, null); OS.MoveMemory(pNExtendedStates, new int[] { 0 }, 4); return COM.S_FALSE; } /* IAccessible2::get_localizedExtendedStates([in] maxLocalizedExtendedStates, [out] ppbstrLocalizedExtendedStates, [out] pNLocalizedExtendedStates) */ int get_localizedExtendedStates(int maxLocalizedExtendedStates, long ppbstrLocalizedExtendedStates, long pNLocalizedExtendedStates) { /* This feature is not supported. */ setString(ppbstrLocalizedExtendedStates, null); OS.MoveMemory(pNLocalizedExtendedStates, new int[] { 0 }, 4); return COM.S_FALSE; } /* IAccessible2::get_uniqueID([out] pUniqueID) */ int get_uniqueID(long pUniqueID) { if (uniqueID == -1) uniqueID = UniqueID--; if (DEBUG) print(this + ".IAccessible2::get_uniqueID returning " + uniqueID + hresult(COM.S_OK)); OS.MoveMemory(pUniqueID, new long[] { uniqueID }, 4); return COM.S_OK; } /* IAccessible2::get_windowHandle([out] pWindowHandle) */ int get_windowHandle(long pWindowHandle) { if (DEBUG) print(this + ".IAccessible2::get_windowHandle returning " + control.handle + hresult(COM.S_OK)); OS.MoveMemory(pWindowHandle, new long[] { control.handle }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessible2::get_indexInParent([out] pIndexInParent) */ int get_indexInParent(long pIndexInParent) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_CHILD_INDEX; event.detail = -1; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getChild(event); } int indexInParent = event.detail; if (indexInParent == -1) { // /* The application did not implement CHILDID_CHILD_INDEX, // * so determine the index by looping through the parent's // * children looking for this Accessible. This may be slow, // * so applications are strongly encouraged to implement // * getChild for CHILDID_CHILD_INDEX. // */ // // TODO: finish this. See also get_groupPosition // this won't work because VARIANT.sizeof isn't big enough on 64-bit machines. // just create an long [] ppdispParent - it's not a variant anyhow... // long ppdispParent = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof); // int code = get_accParent(ppdispParent); // if (code == COM.S_OK) { // VARIANT v = getVARIANT(ppdispParent); // if (v.vt == COM.VT_DISPATCH) { // IAccessible accParent = new IAccessible(v.lVal); // long pcountChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, 4); // code = accParent.get_accChildCount(pcountChildren); // if (code == COM.S_OK) { // int [] childCount = new int[1]; // OS.MoveMemory(childCount, pcountChildren, 4); // int[] pcObtained = new int[1]; // long rgVarChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof * childCount[0]); // System.out.println("Asking for AccessibleChildren"); // code = COM.AccessibleChildren(accParent.getAddress(), 0, childCount[0], rgVarChildren, pcObtained); // if (code == COM.S_OK) { // System.out.println("Got this far - now what?"); // } else { // System.out.println("AccessibleChildren failed? code=" + code); // } // OS.GlobalFree(rgVarChildren); // } else { // System.out.println("get_accChildCount failed? code=" + code); // } // OS.GlobalFree (pcountChildren); // } else { // System.out.println("get_accParent did not return VT_DISPATCH? It returned: " + v.vt); // } // COM.VariantClear(ppdispParent); // OS.GlobalFree (ppdispParent); // } else { // System.out.println("get_accParent failed? code=" + code); // } } if (DEBUG) print(this + ".IAccessible2::get_indexInParent returning " + indexInParent + hresult(indexInParent == -1 ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pIndexInParent, new int[] { indexInParent }, 4); return indexInParent == -1 ? COM.S_FALSE : COM.S_OK; } /* IAccessible2::get_locale([out] pLocale) */ int get_locale(long pLocale) { /* Return the default locale for the JVM. */ Locale locale = Locale.getDefault(); char[] data = (locale.getLanguage() + "\0").toCharArray(); long ptr = COM.SysAllocString(data); OS.MoveMemory(pLocale, new long[] { ptr }, C.PTR_SIZEOF); data = (locale.getCountry() + "\0").toCharArray(); ptr = COM.SysAllocString(data); OS.MoveMemory(pLocale + C.PTR_SIZEOF, new long[] { ptr }, C.PTR_SIZEOF); data = (locale.getVariant() + "\0").toCharArray(); ptr = COM.SysAllocString(data); OS.MoveMemory(pLocale + 2 * C.PTR_SIZEOF, new long[] { ptr }, C.PTR_SIZEOF); if (DEBUG) print(this + ".IAccessible2::get_locale() returning" + hresult(COM.S_OK)); return COM.S_OK; } /* IAccessible2::get_attributes([out] pbstrAttributes) */ int get_attributes(long pbstrAttributes) { AccessibleAttributeEvent event = new AccessibleAttributeEvent(this); for (int i = 0; i < accessibleAttributeListenersSize(); i++) { AccessibleAttributeListener listener = accessibleAttributeListeners.get(i); listener.getAttributes(event); } String attributes = ""; attributes += "margin-left:" + event.leftMargin + ";"; attributes += "margin-top:" + event.topMargin + ";"; attributes += "margin-right:" + event.rightMargin + ";"; attributes += "margin-bottom:" + event.bottomMargin + ";"; if (event.tabStops != null) { for (int i = 0; i < event.tabStops.length; i++) { attributes += "tab-stop:position=" + event.tabStops[i] + ";"; } } if (event.justify) attributes += "text-align:justify;"; attributes += "text-align:" + (event.alignment == SWT.LEFT ? "left" : event.alignment == SWT.RIGHT ? "right" : "center") + ";"; attributes += "text-indent:" + event.indent + ";"; if (event.attributes != null) { for (int i = 0; i + 1 < event.attributes.length; i += 2) { attributes += event.attributes[i] + ":" + event.attributes[i + 1] + ";"; } } /* If the role is text, then specify the text model for JAWS. */ if (getRole() == ACC.ROLE_TEXT) { attributes += "text-model:a1;"; } if (DEBUG) print(this + ".IAccessible2::get_attributes() returning " + attributes + hresult(attributes.length() == 0 ? COM.S_FALSE : COM.S_OK)); setString(pbstrAttributes, attributes); if (attributes.length() == 0) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleAction::get_nActions([out] pNActions) */ int get_nActions(long pNActions) { AccessibleActionEvent event = new AccessibleActionEvent(this); for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.getActionCount(event); } if (DEBUG) print(this + ".IAccessibleAction::get_nActions() returning " + event.count + hresult(COM.S_OK)); OS.MoveMemory(pNActions, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleAction::doAction([in] actionIndex) */ int doAction(int actionIndex) { AccessibleActionEvent event = new AccessibleActionEvent(this); event.index = actionIndex; for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.doAction(event); } if (DEBUG) print(this + ".IAccessibleAction::doAction(" + actionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleAction::get_description([in] actionIndex, [out] pbstrDescription) */ int get_description(int actionIndex, long pbstrDescription) { AccessibleActionEvent event = new AccessibleActionEvent(this); event.index = actionIndex; for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.getDescription(event); } if (DEBUG) print(this + ".IAccessibleAction::get_description(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK)); setString(pbstrDescription, event.result); if (event.result == null || event.result.length() == 0) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleAction::get_keyBinding([in] actionIndex, [in] nMaxBindings, [out] ppbstrKeyBindings, [out] pNBindings) */ int get_keyBinding(int actionIndex, int nMaxBindings, long ppbstrKeyBindings, long pNBindings) { AccessibleActionEvent event = new AccessibleActionEvent(this); event.index = actionIndex; for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.getKeyBinding(event); } String keyBindings = event.result; int length = 0; if (keyBindings != null) length = keyBindings.length(); int i = 0, count = 0; while (i < length) { if (count == nMaxBindings) break; int j = keyBindings.indexOf(';', i); if (j == -1) j = length; String keyBinding = keyBindings.substring(i, j); if (keyBinding.length() > 0) { setString(ppbstrKeyBindings + count * C.PTR_SIZEOF, keyBinding); count++; } i = j + 1; } if (DEBUG) print(this + ".IAccessibleAction::get_keyBinding(index=" + actionIndex + " max=" + nMaxBindings + ") returning count=" + count + hresult(count == 0 ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pNBindings, new int[] { count }, 4); if (count == 0) { setString(ppbstrKeyBindings, null); return COM.S_FALSE; } return COM.S_OK; } /* IAccessibleAction::get_name([in] actionIndex, [out] pbstrName) */ int get_name(int actionIndex, long pbstrName) { AccessibleActionEvent event = new AccessibleActionEvent(this); event.index = actionIndex; event.localized = false; for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.getName(event); } if (DEBUG) print(this + ".IAccessibleAction::get_name(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (event.result == null || event.result.length() == 0) { setString(pbstrName, null); return COM.S_FALSE; } setString(pbstrName, event.result); return COM.S_OK; } /* IAccessibleAction::get_localizedName([in] actionIndex, [out] pbstrLocalizedName) */ int get_localizedName(int actionIndex, long pbstrLocalizedName) { AccessibleActionEvent event = new AccessibleActionEvent(this); event.index = actionIndex; event.localized = true; for (int i = 0; i < accessibleActionListenersSize(); i++) { AccessibleActionListener listener = accessibleActionListeners.get(i); listener.getName(event); } if (DEBUG) print(this + ".IAccessibleAction::get_localizedName(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (event.result == null || event.result.length() == 0) { setString(pbstrLocalizedName, null); return COM.S_FALSE; } setString(pbstrLocalizedName, event.result); return COM.S_OK; } /* IAccessibleApplication::get_appName([out] pbstrName) */ int get_appName(long pbstrName) { String appName = Display.getAppName(); if (DEBUG) print(this + ".IAccessibleApplication::get_appName() returning " + appName + hresult(appName == null || appName.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (appName == null || appName.length() == 0) { setString(pbstrName, null); return COM.S_FALSE; } setString(pbstrName, appName); return COM.S_OK; } /* IAccessibleApplication::get_appVersion([out] pbstrVersion) */ int get_appVersion(long pbstrVersion) { String appVersion = Display.getAppVersion(); if (DEBUG) print(this + ".IAccessibleApplication::get_appVersion() returning" + appVersion + hresult(appVersion == null || appVersion.length() == 0 ? COM.S_FALSE : COM.S_OK)); if (appVersion == null || appVersion.length() == 0) { setString(pbstrVersion, null); return COM.S_FALSE; } setString(pbstrVersion, appVersion); return COM.S_OK; } /* IAccessibleApplication::get_toolkitName([out] pbstrName) */ int get_toolkitName(long pbstrName) { String toolkitName = "SWT"; if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitName() returning" + toolkitName + hresult(COM.S_OK)); setString(pbstrName, toolkitName); return COM.S_OK; } /* IAccessibleApplication::get_toolkitVersion([out] pbstrVersion) */ int get_toolkitVersion(long pbstrVersion) { String toolkitVersion = "" + SWT.getVersion(); //$NON-NLS-1$ if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitVersion() returning" + toolkitVersion + hresult(COM.S_OK)); setString(pbstrVersion, toolkitVersion); return COM.S_OK; } // The following 3 method are intentionally commented. We are not providing IAccessibleComponent at this time. // /* IAccessibleComponent::get_locationInParent([out] pX, [out] pY) */ // int get_locationInParent(long pX, long pY) { // if (DEBUG) print(this + ".IAccessibleComponent::get_locationInParent"); // // TO DO: support transparently (hard for lightweight parents - screen vs. parent coords) // AccessibleControlEvent event = new AccessibleControlEvent(this); // for (int i = 0; i < accessibleControlListenersSize(); i++) { // AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i); // listener.getLocation (event); // } // COM.MoveMemory(pX, new int [] { event.x }, 4); // COM.MoveMemory(pY, new int [] { event.y }, 4); // return COM.S_OK; // } // // /* IAccessibleComponent::get_foreground([out] pForeground) */ // int get_foreground(long pForeground) { // Color color = control.getForeground(); // if (DEBUG) print(this + ".IAccessibleComponent::get_foreground returning " + color.handle); // COM.MoveMemory(pForeground, new int [] { color.handle }, 4); // return COM.S_OK; // } // // /* IAccessibleComponent::get_background([out] pBackground) */ // int get_background(long pBackground) { // Color color = control.getBackground(); // if (DEBUG) print(this + ".IAccessibleComponent::get_background returning " + color.handle); // COM.MoveMemory(pBackground, new int [] { color.handle }, 4); // return COM.S_OK; // } /* IAccessibleEditableText::copyText([in] startOffset, [in] endOffset) */ int copyText(int startOffset, int endOffset) { if (DEBUG) print(this + ".IAccessibleEditableText::copyText, start=" + startOffset + ", end=" + endOffset); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.copyText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::deleteText([in] startOffset, [in] endOffset) */ int deleteText(int startOffset, int endOffset) { if (DEBUG) print(this + ".IAccessibleEditableText::deleteText, start=" + startOffset + ", end=" + endOffset); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; event.string = ""; for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.replaceText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::insertText([in] offset, [in] pbstrText) */ int insertText(int offset, long pbstrText) { if (DEBUG) print(this + ".IAccessibleEditableText::insertText, offset=" + offset + ", pbstrText=" + pbstrText); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset; event.end = event.start; event.string = getString(pbstrText); for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.replaceText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::cutText([in] startOffset, [in] endOffset) */ int cutText(int startOffset, int endOffset) { if (DEBUG) print(this + ".IAccessibleEditableText::cutText, start=" + startOffset + ", end=" + endOffset); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.cutText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::pasteText([in] offset) */ int pasteText(int offset) { if (DEBUG) print(this + ".IAccessibleEditableText::pasteText, offset=" + offset); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset; event.end = event.start; for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.pasteText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::replaceText([in] startOffset, [in] endOffset, [in] pbstrText) */ int replaceText(int startOffset, int endOffset, long pbstrText) { if (DEBUG) print(this + ".IAccessibleEditableText::replaceText, start=" + startOffset + ", end=" + endOffset + ", pbstrText=" + pbstrText); AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; event.string = getString(pbstrText); for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.replaceText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleEditableText::setAttributes([in] startOffset, [in] endOffset, [in] pbstrAttributes) */ int setAttributes(int startOffset, int endOffset, long pbstrAttributes) { if (DEBUG) print(this + ".IAccessibleEditableText::setAttributes, start=" + startOffset + ", end=" + endOffset + ", pbstrAttributes=" + pbstrAttributes); AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this); String string = getString(pbstrAttributes); if (string != null && string.length() > 0) { event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; TextStyle style = new TextStyle(); FontData fontData = null; int points = 10; // used for default rise String[] attributes = new String[0]; int begin = 0; int end = string.indexOf(';'); while (end != -1 && end < string.length()) { String keyValue = string.substring(begin, end).trim(); int colonIndex = keyValue.indexOf(':'); if (colonIndex != -1 && colonIndex + 1 < keyValue.length()) { String[] newAttributes = new String[attributes.length + 2]; System.arraycopy(attributes, 0, newAttributes, 0, attributes.length); newAttributes[attributes.length] = keyValue.substring(0, colonIndex).trim(); newAttributes[attributes.length + 1] = keyValue.substring(colonIndex + 1).trim(); attributes = newAttributes; } begin = end + 1; end = string.indexOf(';', begin); } for (int i = 0; i + 1 < attributes.length; i += 2) { String key = attributes[i]; String value = attributes[i + 1]; if (key.equals("text-position")) { if (value.equals("super")) style.rise = points / 2; else if (value.equals("sub")) style.rise = -points / 2; } else if (key.equals("text-underline-type")) { style.underline = true; if (value.equals("double")) style.underlineStyle = SWT.UNDERLINE_DOUBLE; else if (value.equals("single")) { if (style.underlineStyle != SWT.UNDERLINE_SQUIGGLE && style.underlineStyle != SWT.UNDERLINE_ERROR) { style.underlineStyle = SWT.UNDERLINE_SINGLE; } } } else if (key.equals("text-underline-style") && value.equals("wave")) { style.underline = true; style.underlineStyle = SWT.UNDERLINE_SQUIGGLE; } else if (key.equals("invalid") && value.equals("true")) { style.underline = true; style.underlineStyle = SWT.UNDERLINE_ERROR; } else if (key.equals("text-line-through-type")) { if (value.equals("single")) style.strikeout = true; } else if (key.equals("font-family")) { if (fontData == null) fontData = new FontData(); fontData.setName(value); } else if (key.equals("font-size")) { try { String pts = value.endsWith("pt") ? value.substring(0, value.length() - 2) : value; points = Integer.parseInt(pts); if (fontData == null) fontData = new FontData(); fontData.setHeight(points); if (style.rise > 0) style.rise = points / 2; else if (style.rise < 0) style.rise = -points / 2; } catch (NumberFormatException ex) { } } else if (key.equals("font-style")) { if (value.equals("italic")) { if (fontData == null) fontData = new FontData(); fontData.setStyle(fontData.getStyle() | SWT.ITALIC); } } else if (key.equals("font-weight")) { if (value.equals("bold")) { if (fontData == null) fontData = new FontData(); fontData.setStyle(fontData.getStyle() | SWT.BOLD); } else { try { int weight = Integer.parseInt(value); if (fontData == null) fontData = new FontData(); if (weight > 400) fontData.setStyle(fontData.getStyle() | SWT.BOLD); } catch (NumberFormatException ex) { } } } else if (key.equals("color")) { style.foreground = colorFromString(value); } else if (key.equals("background-color")) { style.background = colorFromString(value); } } if (attributes.length > 0) { event.attributes = attributes; if (fontData != null) { style.font = new Font(control.getDisplay(), fontData); } if (!style.equals(new TextStyle())) event.textStyle = style; } for (int i = 0; i < accessibleEditableTextListenersSize(); i++) { AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i); listener.setTextAttributes(event); } if (style.font != null) { style.font.dispose(); } if (style.foreground != null) { style.foreground.dispose(); } if (style.background != null) { style.background.dispose(); } } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleHyperlink::get_anchor([in] index, [out] pAnchor) */ int get_anchor(int index, long pAnchor) { if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchor"); AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this); event.index = index; for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) { AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i); listener.getAnchor(event); } Accessible accessible = event.accessible; if (accessible != null) { accessible.AddRef(); setPtrVARIANT(pAnchor, COM.VT_DISPATCH, accessible.getAddress()); return COM.S_OK; } setStringVARIANT(pAnchor, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleHyperlink::get_anchorTarget([in] index, [out] pAnchorTarget) */ int get_anchorTarget(int index, long pAnchorTarget) { if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchorTarget"); AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this); event.index = index; for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) { AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i); listener.getAnchorTarget(event); } Accessible accessible = event.accessible; if (accessible != null) { accessible.AddRef(); setPtrVARIANT(pAnchorTarget, COM.VT_DISPATCH, accessible.getAddress()); return COM.S_OK; } setStringVARIANT(pAnchorTarget, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleHyperlink::get_startIndex([out] pIndex) */ int get_startIndex(long pIndex) { if (DEBUG) print(this + ".IAccessibleHyperlink::get_startIndex"); AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this); for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) { AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i); listener.getStartIndex(event); } OS.MoveMemory(pIndex, new int[] { event.index }, 4); return COM.S_OK; } /* IAccessibleHyperlink::get_endIndex([out] pIndex) */ int get_endIndex(long pIndex) { if (DEBUG) print(this + ".IAccessibleHyperlink::get_endIndex"); AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this); for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) { AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i); listener.getEndIndex(event); } OS.MoveMemory(pIndex, new int[] { event.index }, 4); return COM.S_OK; } /* IAccessibleHyperlink::get_valid([out] pValid) */ int get_valid(long pValid) { /* Deprecated. */ return COM.E_NOTIMPL; } /* IAccessibleHypertext::get_nHyperlinks([out] pHyperlinkCount) */ int get_nHyperlinks(long pHyperlinkCount) { if (DEBUG) print(this + ".IAccessibleHypertext::get_nHyperlinks"); AccessibleTextEvent event = new AccessibleTextEvent(this); for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getHyperlinkCount(event); } OS.MoveMemory(pHyperlinkCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleHypertext::get_hyperlink([in] index, [out] ppHyperlink) */ int get_hyperlink(int index, long ppHyperlink) { if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlink"); AccessibleTextEvent event = new AccessibleTextEvent(this); event.index = index; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getHyperlink(event); } Accessible accessible = event.accessible; if (accessible == null) { setIntVARIANT(ppHyperlink, COM.VT_EMPTY, 0); return COM.E_INVALIDARG; } accessible.AddRef(); OS.MoveMemory(ppHyperlink, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessibleHypertext::get_hyperlinkIndex([in] charIndex, [out] pHyperlinkIndex) */ int get_hyperlinkIndex(int charIndex, long pHyperlinkIndex) { if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlinkIndex"); AccessibleTextEvent event = new AccessibleTextEvent(this); event.offset = charIndex; event.index = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getHyperlinkIndex(event); } OS.MoveMemory(pHyperlinkIndex, new int[] { event.index }, 4); if (event.index == -1) return COM.S_FALSE; return COM.S_OK; } // The following 3 method are intentionally commented. We are not providing IAccessibleImage at this time. // /* IAccessibleImage::get_description([out] pbstrDescription) */ // int get_description(long pbstrDescription) { // if (DEBUG) print(this + ".IAccessibleImage::get_description"); // // TO DO: Does it make sense to just reuse description? // AccessibleEvent event = new AccessibleEvent(this); // event.childID = ACC.CHILDID_SELF; // for (int i = 0; i < accessibleListenersSize(); i++) { // AccessibleListener listener = (AccessibleListener) accessibleListeners.get(i); // listener.getDescription(event); // } // setString(pbstrDescription, event.result); // if (event.result == null) return COM.S_FALSE; // return COM.S_OK; // } // // /* IAccessibleImage::get_imagePosition([in] coordinateType, [out] pX, [out] pY) */ // int get_imagePosition(int coordinateType, long pX, long pY) { // if (DEBUG) print(this + ".IAccessibleImage::get_imagePosition"); // // TO DO: does it make sense to just reuse getLocation? // AccessibleControlEvent event = new AccessibleControlEvent(this); // event.childID = ACC.CHILDID_SELF; // for (int i = 0; i < accessibleControlListenersSize(); i++) { // AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i); // listener.getLocation(event); // } // COM.MoveMemory(pX, new int [] { event.x }, 4); // COM.MoveMemory(pY, new int [] { event.y }, 4); // return COM.S_OK; // } // // /* IAccessibleImage::get_imageSize([out] pHeight, [out] pWidth) */ // int get_imageSize(long pHeight, long pWidth) { // if (DEBUG) print(this + ".IAccessibleImage::get_imageSize"); // // TO DO: does it make sense to just reuse getLocation? // AccessibleControlEvent event = new AccessibleControlEvent(this); // for (int i = 0; i < accessibleControlListenersSize(); i++) { // AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i); // listener.getLocation(event); // } // COM.MoveMemory(pHeight, new int [] { event.height }, 4); // COM.MoveMemory(pWidth, new int [] { event.width }, 4); // return COM.S_OK; // } /* IAccessibleTable2::get_cellAt([in] row, [in] column, [out] ppCell) */ int get_cellAt(int row, int column, long ppCell) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.row = row; event.column = column; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getCell(event); } Accessible accessible = event.accessible; if (DEBUG) print(this + ".IAccessibleTable2::get_cellAt(row=" + row + ", column=" + column + ") returning " + accessible); if (accessible == null) return COM.E_INVALIDARG; accessible.AddRef(); OS.MoveMemory(ppCell, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessibleTable2::get_caption([out] ppAccessible) */ int get_caption(long ppAccessible) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getCaption(event); } Accessible accessible = event.accessible; if (DEBUG) print(this + ".IAccessibleTable2::get_caption() returning " + accessible); if (accessible == null) { OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF); return COM.S_FALSE; } accessible.AddRef(); OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessibleTable2::get_columnDescription([in] column, [out] pbstrDescription) */ int get_columnDescription(int column, long pbstrDescription) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.column = column; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getColumnDescription(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_columnDescription(column=" + column + ") returning " + event.result); setString(pbstrDescription, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleTable2::get_nColumns([out] pColumnCount) */ int get_nColumns(long pColumnCount) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getColumnCount(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_nColumns() returning " + event.count); OS.MoveMemory(pColumnCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_nRows([out] pRowCount) */ int get_nRows(long pRowCount) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getRowCount(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_nRows() returning " + event.count); OS.MoveMemory(pRowCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_nSelectedCells([out] pCellCount) */ int get_nSelectedCells(long pCellCount) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedCellCount(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedCells() returning " + event.count); OS.MoveMemory(pCellCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_nSelectedColumns([out] pColumnCount) */ int get_nSelectedColumns(long pColumnCount) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedColumnCount(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedColumns() returning " + event.count); OS.MoveMemory(pColumnCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_nSelectedRows([out] pRowCount) */ int get_nSelectedRows(long pRowCount) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedRowCount(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedRows() returning " + event.count); OS.MoveMemory(pRowCount, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_rowDescription([in] row, [out] pbstrDescription) */ int get_rowDescription(int row, long pbstrDescription) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.row = row; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getRowDescription(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_rowDescription(row=" + row + ") returning " + event.result); setString(pbstrDescription, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleTable2::get_selectedCells([out] ppCells, [out] pNSelectedCells) */ int get_selectedCells(long ppCells, long pNSelectedCells) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedCells(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_selectedCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]")); if (event.accessibles == null || event.accessibles.length == 0) { OS.MoveMemory(ppCells, new long[] { 0 }, C.PTR_SIZEOF); OS.MoveMemory(pNSelectedCells, new int[] { 0 }, 4); return COM.S_FALSE; } int length = event.accessibles.length; long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF); int count = 0; for (int i = 0; i < length; i++) { Accessible accessible = event.accessibles[i]; if (accessible != null) { accessible.AddRef(); OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); count++; } } OS.MoveMemory(ppCells, new long[] { pv }, C.PTR_SIZEOF); OS.MoveMemory(pNSelectedCells, new int[] { count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_selectedColumns([out] ppSelectedColumns, [out] pNColumns) */ int get_selectedColumns(long ppSelectedColumns, long pNColumns) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedColumns(event); } int count = event.selected == null ? 0 : event.selected.length; if (DEBUG) print(this + ".IAccessibleTable2::get_selectedColumns() returning " + (count == 0 ? "null" : "selected[" + count + "]")); if (count == 0) { OS.MoveMemory(ppSelectedColumns, new long[] { 0 }, C.PTR_SIZEOF); OS.MoveMemory(pNColumns, new int[] { 0 }, 4); return COM.S_FALSE; } long pv = OS.CoTaskMemAlloc(count * 4); OS.MoveMemory(pv, event.selected, count * 4); OS.MoveMemory(ppSelectedColumns, new long[] { pv }, C.PTR_SIZEOF); OS.MoveMemory(pNColumns, new int[] { count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_selectedRows([out] ppSelectedRows, [out] pNRows) */ int get_selectedRows(long ppSelectedRows, long pNRows) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSelectedRows(event); } int count = event.selected == null ? 0 : event.selected.length; if (DEBUG) print(this + ".IAccessibleTable2::get_selectedRows() returning " + (count == 0 ? "null" : "selected[" + count + "]")); if (count == 0) { OS.MoveMemory(ppSelectedRows, new long[] { 0 }, C.PTR_SIZEOF); OS.MoveMemory(pNRows, new int[] { 0 }, 4); return COM.S_FALSE; } long pv = OS.CoTaskMemAlloc(count * 4); OS.MoveMemory(pv, event.selected, count * 4); OS.MoveMemory(ppSelectedRows, new long[] { pv }, C.PTR_SIZEOF); OS.MoveMemory(pNRows, new int[] { count }, 4); return COM.S_OK; } /* IAccessibleTable2::get_summary([out] ppAccessible) */ int get_summary(long ppAccessible) { AccessibleTableEvent event = new AccessibleTableEvent(this); for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.getSummary(event); } Accessible accessible = event.accessible; if (DEBUG) print(this + ".IAccessibleTable2::get_summary() returning " + accessible); if (accessible == null) { OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF); return COM.S_FALSE; } accessible.AddRef(); OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessibleTable2::get_isColumnSelected([in] column, [out] pIsSelected) */ int get_isColumnSelected(int column, long pIsSelected) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.column = column; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.isColumnSelected(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_isColumnSelected() returning " + event.isSelected); OS.MoveMemory(pIsSelected, new int[] { event.isSelected ? 1 : 0 }, 4); return COM.S_OK; } /* IAccessibleTable2::get_isRowSelected([in] row, [out] pIsSelected) */ int get_isRowSelected(int row, long pIsSelected) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.row = row; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.isRowSelected(event); } if (DEBUG) print(this + ".IAccessibleTable2::get_isRowSelected() returning " + event.isSelected); OS.MoveMemory(pIsSelected, new int[] { event.isSelected ? 1 : 0 }, 4); return COM.S_OK; } /* IAccessibleTable2::selectRow([in] row) */ int selectRow(int row) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.row = row; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.setSelectedRow(event); } if (DEBUG) print(this + ".IAccessibleTable2::selectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleTable2::selectColumn([in] column) */ int selectColumn(int column) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.column = column; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.setSelectedColumn(event); } if (DEBUG) print(this + ".IAccessibleTable2::selectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleTable2::unselectRow([in] row) */ int unselectRow(int row) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.row = row; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.deselectRow(event); } if (DEBUG) print(this + ".IAccessibleTable2::unselectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleTable2::unselectColumn([in] column) */ int unselectColumn(int column) { AccessibleTableEvent event = new AccessibleTableEvent(this); event.column = column; for (int i = 0; i < accessibleTableListenersSize(); i++) { AccessibleTableListener listener = accessibleTableListeners.get(i); listener.deselectColumn(event); } if (DEBUG) print(this + ".IAccessibleTable2::unselectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleTable2::get_modelChange([out] pModelChange) */ int get_modelChange(long pModelChange) { if (DEBUG) print(this + ".IAccessibleTable2::get_modelChange() returning " + (tableChange == null ? "null" : "tableChange=" + tableChange[0] + ", " + tableChange[1] + ", " + tableChange[2] + ", " + tableChange[3])); if (tableChange == null) { OS.MoveMemory(pModelChange, new long[] { 0 }, C.PTR_SIZEOF); return COM.S_FALSE; } OS.MoveMemory(pModelChange, tableChange, tableChange.length * 4); return COM.S_OK; } /* IAccessibleTableCell::get_columnExtent([out] pNColumnsSpanned) */ int get_columnExtent(long pNColumnsSpanned) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getColumnSpan(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_columnExtent() returning " + event.count); OS.MoveMemory(pNColumnsSpanned, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_columnHeaderCells([out] ppCellAccessibles, [out] pNColumnHeaderCells) */ int get_columnHeaderCells(long ppCellAccessibles, long pNColumnHeaderCells) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getColumnHeaders(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_columnHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]")); if (event.accessibles == null || event.accessibles.length == 0) { OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF); OS.MoveMemory(pNColumnHeaderCells, new int[] { 0 }, 4); return COM.S_FALSE; } int length = event.accessibles.length; long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF); int count = 0; for (int i = 0; i < length; i++) { Accessible accessible = event.accessibles[i]; if (accessible != null) { accessible.AddRef(); OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); count++; } } OS.MoveMemory(ppCellAccessibles, new long[] { pv }, C.PTR_SIZEOF); OS.MoveMemory(pNColumnHeaderCells, new int[] { count }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_columnIndex([out] pColumnIndex) */ int get_columnIndex(long pColumnIndex) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getColumnIndex(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_columnIndex() returning " + event.index); OS.MoveMemory(pColumnIndex, new int[] { event.index }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_rowExtent([out] pNRowsSpanned) */ int get_rowExtent(long pNRowsSpanned) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getRowSpan(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_rowExtent() returning " + event.count); OS.MoveMemory(pNRowsSpanned, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_rowHeaderCells([out] ppCellAccessibles, [out] pNRowHeaderCells) */ int get_rowHeaderCells(long ppCellAccessibles, long pNRowHeaderCells) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getRowHeaders(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_rowHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]")); if (event.accessibles == null || event.accessibles.length == 0) { OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF); OS.MoveMemory(pNRowHeaderCells, new int[] { 0 }, 4); return COM.S_FALSE; } int length = event.accessibles.length; long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF); int count = 0; for (int i = 0; i < length; i++) { Accessible accessible = event.accessibles[i]; if (accessible != null) { accessible.AddRef(); OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); count++; } } OS.MoveMemory(ppCellAccessibles, new long[] { pv }, C.PTR_SIZEOF); OS.MoveMemory(pNRowHeaderCells, new int[] { count }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_rowIndex([out] pRowIndex) */ int get_rowIndex(long pRowIndex) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getRowIndex(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_rowIndex() returning " + event.index); OS.MoveMemory(pRowIndex, new int[] { event.index }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_isSelected([out] pIsSelected) */ int get_isSelected(long pIsSelected) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.isSelected(event); } if (DEBUG) print(this + ".IAccessibleTableCell::get_isSelected() returning " + event.isSelected); OS.MoveMemory(pIsSelected, new int[] { event.isSelected ? 1 : 0 }, 4); return COM.S_OK; } /* IAccessibleTableCell::get_rowColumnExtents([out] pRow, [out] pColumn, [out] pRowExtents, [out] pColumnExtents, [out] pIsSelected) */ int get_rowColumnExtents(long pRow, long pColumn, long pRowExtents, long pColumnExtents, long pIsSelected) { if (DEBUG) print(this + ".IAccessibleTableCell::get_rowColumnExtents"); // TODO: should we implement this? It is just a convenience function. return COM.DISP_E_MEMBERNOTFOUND; // AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); // for (int i = 0; i < accessibleTableCellListenersSize(); i++) { // AccessibleTableCellListener listener = (AccessibleTableCellListener) accessibleTableCellListeners.get(i); // listener.getRowColumnExtents(event); // } // COM.MoveMemory(pRow, new int [] { event.row }, 4); // COM.MoveMemory(pColumn, new int [] { event.column }, 4); // COM.MoveMemory(pRowExtents, new int [] { event.rowExtents }, 4); // COM.MoveMemory(pColumnExtents, new int [] { event.columnExtents }, 4); // return COM.S_OK; } /* IAccessibleTableCell::get_table([out] ppTable) */ int get_table(long ppTable) { AccessibleTableCellEvent event = new AccessibleTableCellEvent(this); for (int i = 0; i < accessibleTableCellListenersSize(); i++) { AccessibleTableCellListener listener = accessibleTableCellListeners.get(i); listener.getTable(event); } Accessible accessible = event.accessible; if (DEBUG) print(this + ".IAccessibleTableCell::get_table() returning " + accessible); if (accessible == null) { // TODO: This is not supposed to return S_FALSE. We need to lookup the table role parent and return that. OS.MoveMemory(ppTable, new long[] { 0 }, C.PTR_SIZEOF); return COM.S_FALSE; } accessible.AddRef(); OS.MoveMemory(ppTable, new long[] { accessible.getAddress() }, C.PTR_SIZEOF); return COM.S_OK; } /* IAccessibleText::addSelection([in] startOffset, [in] endOffset) */ int addSelection(int startOffset, int endOffset) { if (DEBUG) print(this + ".IAccessibleText::addSelection(" + startOffset + ", " + endOffset + ")"); AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.addSelection(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::get_attributes([in] offset, [out] pStartOffset, [out] pEndOffset, [out] pbstrTextAttributes) */ int get_attributes(int offset, long pStartOffset, long pEndOffset, long pbstrTextAttributes) { AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this); event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset; for (int i = 0; i < accessibleAttributeListenersSize(); i++) { AccessibleAttributeListener listener = accessibleAttributeListeners.get(i); listener.getTextAttributes(event); } String textAttributes = ""; TextStyle style = event.textStyle; if (style != null) { if (style.rise != 0) { textAttributes += "text-position:"; if (style.rise > 0) textAttributes += "super"; else textAttributes += "sub"; } if (style.underline) { textAttributes += "text-underline-type:"; switch (style.underlineStyle) { case SWT.UNDERLINE_SINGLE: textAttributes += "single;"; break; case SWT.UNDERLINE_DOUBLE: textAttributes += "double;"; break; case SWT.UNDERLINE_SQUIGGLE: textAttributes += "single;text-underline-style:wave;"; break; case SWT.UNDERLINE_ERROR: textAttributes += "single;text-underline-style:wave;invalid:true;"; break; default: textAttributes += "none;"; break; } // style.underlineColor is not currently part of the IA2 spec. If provided, it would be "text-underline-color:rgb(n,n,n);" } if (style.strikeout) { textAttributes += "text-line-through-type:single;"; // style.strikeoutColor is not currently part of the IA2 spec. If provided, it would be "text-line-through-color:rgb(n,n,n);" } Font font = style.font; if (font != null && !font.isDisposed()) { FontData fontData = font.getFontData()[0]; textAttributes += "font-family:" + fontData.getName() + ";"; textAttributes += "font-size:" + fontData.getHeight() + "pt;"; textAttributes += "font-style:" + (fontData.data.lfItalic != 0 ? "italic" : "normal") + ";"; textAttributes += "font-weight:" + fontData.data.lfWeight + ";"; } Color color = style.foreground; if (color != null && !color.isDisposed()) { textAttributes += "color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");"; } color = style.background; if (color != null && !color.isDisposed()) { textAttributes += "background-color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");"; } } if (event.attributes != null) { for (int i = 0; i + 1 < event.attributes.length; i += 2) { textAttributes += event.attributes[i] + ":" + event.attributes[i + 1] + ";"; } } if (DEBUG) print(this + ".IAccessibleText::get_attributes(" + offset + ") returning start = " + event.start + ", end = " + event.end + ", attributes = " + textAttributes); OS.MoveMemory(pStartOffset, new int[] { event.start }, 4); OS.MoveMemory(pEndOffset, new int[] { event.end }, 4); setString(pbstrTextAttributes, textAttributes); if (textAttributes.length() == 0) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_caretOffset([out] pOffset) */ int get_caretOffset(long pOffset) { int offset = getCaretOffset(); if (DEBUG) print(this + ".IAccessibleText::get_caretOffset returning " + offset + hresult(offset == -1 ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pOffset, new int[] { offset }, 4); if (offset == -1) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_characterExtents([in] offset, [in] coordType, [out] pX, [out] pY, [out] pWidth, [out] pHeight) */ int get_characterExtents(int offset, int coordType, long pX, long pY, long pWidth, long pHeight) { int length = getCharacterCount(); AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? length : offset < 0 ? 0 : offset; event.end = offset == COM.IA2_TEXT_OFFSET_LENGTH || offset >= length ? length : offset + 1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getTextBounds(event); } /* Note: event.rectangles is not used here, because IAccessibleText::get_characterExtents is just for one character. */ if (DEBUG) print(this + ".IAccessibleText::get_characterExtents(" + offset + ") returning " + event.x + ", " + event.y + ", " + event.width + ", " + event.height); OS.MoveMemory(pX, new int[] { event.x }, 4); OS.MoveMemory(pY, new int[] { event.y }, 4); OS.MoveMemory(pWidth, new int[] { event.width }, 4); OS.MoveMemory(pHeight, new int[] { event.height }, 4); if (event.width == 0 && event.height == 0) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::get_nSelections([out] pNSelections) */ int get_nSelections(long pNSelections) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.count = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getSelectionCount(event); } if (event.count == -1) { event.childID = ACC.CHILDID_SELF; event.offset = -1; event.length = 0; for (int i = 0; i < accessibleTextListenersSize(); i++) { AccessibleTextListener listener = accessibleTextListeners.get(i); listener.getSelectionRange(event); } event.count = event.offset != -1 && event.length > 0 ? 1 : 0; } if (DEBUG) print(this + ".IAccessibleText::get_nSelections returning " + event.count); OS.MoveMemory(pNSelections, new int[] { event.count }, 4); return COM.S_OK; } /* IAccessibleText::get_offsetAtPoint([in] x, [in] y, [in] coordType, [out] pOffset) */ int get_offsetAtPoint(int x, int y, int coordType, long pOffset) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.x = x; event.y = y; event.offset = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getOffsetAtPoint(event); } if (DEBUG) print(this + ".IAccessibleText::get_offsetAtPoint(" + x + ", " + y + ") returning " + event.offset + hresult(event.offset == -1 ? COM.S_FALSE : COM.S_OK)); /* * Note that the current IA2 spec says to return 0 when there's nothing to return, * but since 0 is a valid return value, the spec is going to be updated to return -1. */ OS.MoveMemory(pOffset, new int[] { event.offset }, 4); if (event.offset == -1) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_selection([in] selectionIndex, [out] pStartOffset, [out] pEndOffset) */ int get_selection(int selectionIndex, long pStartOffset, long pEndOffset) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.index = selectionIndex; event.start = -1; event.end = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getSelection(event); } if (event.start == -1 && selectionIndex == 0) { event.childID = ACC.CHILDID_SELF; event.offset = -1; event.length = 0; for (int i = 0; i < accessibleTextListenersSize(); i++) { AccessibleTextListener listener = accessibleTextListeners.get(i); listener.getSelectionRange(event); } event.start = event.offset; event.end = event.offset + event.length; } if (DEBUG) print(this + ".IAccessibleText::get_selection(" + selectionIndex + ") returning " + event.start + ", " + event.end); OS.MoveMemory(pStartOffset, new int[] { event.start }, 4); OS.MoveMemory(pEndOffset, new int[] { event.end }, 4); /* * Note that the current IA2 spec says to return 0,0 when there's nothing to return, * but since 0 is a valid return value, the spec is going to be updated to return -1,-1. */ if (event.start == -1) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_text([in] startOffset, [in] endOffset, [out] pbstrText) */ int get_text(int startOffset, int endOffset, long pbstrText) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; if (event.start > event.end) { /* IA2 spec says that indices can be exchanged. */ int temp = event.start; event.start = event.end; event.end = temp; } event.count = 0; event.type = ACC.TEXT_BOUNDARY_ALL; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } if (event.result == null) { AccessibleControlEvent e = new AccessibleControlEvent(this); e.childID = ACC.CHILDID_SELF; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getRole(e); listener.getValue(e); } // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_nCharacters. if (e.detail == ACC.ROLE_TEXT) { event.result = e.result; } } if (DEBUG) print(this + ".IAccessibleText::get_text(" + startOffset + ", " + endOffset + ") returning " + event.result + hresult(event.result == null ? COM.E_INVALIDARG : COM.S_OK)); setString(pbstrText, event.result); if (event.result == null) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::get_textBeforeOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */ int get_textBeforeOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) { AccessibleTextEvent event = new AccessibleTextEvent(this); int charCount = getCharacterCount(); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset; event.end = event.start; event.count = -1; switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break; case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break; case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break; case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break; case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break; default: return COM.E_INVALIDARG; } int eventStart = event.start; int eventEnd = event.end; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } if (event.end < charCount) { switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_WORD: case COM.IA2_TEXT_BOUNDARY_SENTENCE: case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: case COM.IA2_TEXT_BOUNDARY_LINE: int start = event.start; event.start = eventStart; event.end = eventEnd; event.count = 0; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } event.end = event.start; event.start = start; event.type = ACC.TEXT_BOUNDARY_ALL; event.count = 0; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } } } if (DEBUG) print(this + ".IAccessibleText::get_textBeforeOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pStartOffset, new int[] { event.start }, 4); OS.MoveMemory(pEndOffset, new int[] { event.end }, 4); setString(pbstrText, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_textAfterOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */ int get_textAfterOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) { AccessibleTextEvent event = new AccessibleTextEvent(this); int charCount = getCharacterCount(); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset; event.end = event.start; event.count = 1; switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break; case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break; case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break; case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break; case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break; default: return COM.E_INVALIDARG; } int eventStart = event.start; int eventEnd = event.end; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } if (event.end < charCount) { switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_WORD: case COM.IA2_TEXT_BOUNDARY_SENTENCE: case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: case COM.IA2_TEXT_BOUNDARY_LINE: int start = event.start; event.start = eventStart; event.end = eventEnd; event.count = 2; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } event.end = event.start; event.start = start; event.type = ACC.TEXT_BOUNDARY_ALL; event.count = 0; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } } } if (DEBUG) print(this + ".IAccessibleText::get_textAfterOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pStartOffset, new int[] { event.start }, 4); OS.MoveMemory(pEndOffset, new int[] { event.end }, 4); setString(pbstrText, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_textAtOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */ int get_textAtOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) { AccessibleTextEvent event = new AccessibleTextEvent(this); int charCount = getCharacterCount(); event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset; event.end = event.start; event.count = 0; switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break; case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break; case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break; case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break; case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break; case COM.IA2_TEXT_BOUNDARY_ALL: { event.type = ACC.TEXT_BOUNDARY_ALL; event.start = 0; event.end = charCount; event.count = 0; break; } default: return COM.E_INVALIDARG; } int eventStart = event.start; int eventEnd = event.end; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } if (event.end < charCount) { switch (boundaryType) { case COM.IA2_TEXT_BOUNDARY_WORD: case COM.IA2_TEXT_BOUNDARY_SENTENCE: case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: case COM.IA2_TEXT_BOUNDARY_LINE: int start = event.start; event.start = eventStart; event.end = eventEnd; event.count = 1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } event.end = event.start; event.start = start; event.type = ACC.TEXT_BOUNDARY_ALL; event.count = 0; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getText(event); } } } if (DEBUG) print(this + ".IAccessibleText::get_textAtOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK)); OS.MoveMemory(pStartOffset, new int[] { event.start }, 4); OS.MoveMemory(pEndOffset, new int[] { event.end }, 4); setString(pbstrText, event.result); if (event.result == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::removeSelection([in] selectionIndex) */ int removeSelection(int selectionIndex) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.index = selectionIndex; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.removeSelection(event); } if (DEBUG) print(this + ".IAccessibleText::removeSelection(" + selectionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::setCaretOffset([in] offset) */ int setCaretOffset(int offset) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.setCaretOffset(event); } if (DEBUG) print(this + ".IAccessibleText::setCaretOffset(" + offset + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK)); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval E_FAIL if the caret cannot be set ? return COM.S_OK; } /* IAccessibleText::setSelection([in] selectionIndex, [in] startOffset, [in] endOffset) */ int setSelection(int selectionIndex, int startOffset, int endOffset) { AccessibleTextEvent event = new AccessibleTextEvent(this); event.index = selectionIndex; event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset; event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.setSelection(event); } if (DEBUG) print(this + ".IAccessibleText::setSelection(index=" + selectionIndex + ", start=" + event.start + ", end=" + event.end + ") returning " + (event.result.equals(ACC.OK) ? "OK" : "INVALIDARG")); if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::get_nCharacters([out] pNCharacters) */ int get_nCharacters(long pNCharacters) { int count = getCharacterCount(); OS.MoveMemory(pNCharacters, new int[] { count }, 4); if (DEBUG) print(this + ".IAccessibleText::get_nCharacters returning " + count); return COM.S_OK; } /* IAccessibleText::scrollSubstringTo([in] startIndex, [in] endIndex, [in] scrollType) */ int scrollSubstringTo(int startIndex, int endIndex, int scrollType) { if (DEBUG) print(this + ".IAccessibleText::scrollSubstringTo"); AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = startIndex; event.end = endIndex; switch (scrollType) { case COM.IA2_SCROLL_TYPE_TOP_LEFT: event.type = ACC.SCROLL_TYPE_TOP_LEFT; break; case COM.IA2_SCROLL_TYPE_BOTTOM_RIGHT: event.type = ACC.SCROLL_TYPE_BOTTOM_RIGHT; break; case COM.IA2_SCROLL_TYPE_TOP_EDGE: event.type = ACC.SCROLL_TYPE_TOP_EDGE; break; case COM.IA2_SCROLL_TYPE_BOTTOM_EDGE: event.type = ACC.SCROLL_TYPE_BOTTOM_EDGE; break; case COM.IA2_SCROLL_TYPE_LEFT_EDGE: event.type = ACC.SCROLL_TYPE_LEFT_EDGE; break; case COM.IA2_SCROLL_TYPE_RIGHT_EDGE: event.type = ACC.SCROLL_TYPE_RIGHT_EDGE; break; case COM.IA2_SCROLL_TYPE_ANYWHERE: event.type = ACC.SCROLL_TYPE_ANYWHERE; break; } for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.scrollText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; return COM.S_OK; } /* IAccessibleText::scrollSubstringToPoint([in] startIndex, [in] endIndex, [in] coordinateType, [in] x, [in] y) */ int scrollSubstringToPoint(int startIndex, int endIndex, int coordinateType, int x, int y) { if (DEBUG) print(this + ".IAccessibleText::scrollSubstringToPoint"); AccessibleTextEvent event = new AccessibleTextEvent(this); event.start = startIndex; event.end = endIndex; event.type = ACC.SCROLL_TYPE_POINT; event.x = x; event.y = y; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.scrollText(event); } if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval S_FALSE if the object is already at the specified location. return COM.S_OK; } /* IAccessibleText::get_newText([out] pNewText) */ int get_newText(long pNewText) { if (DEBUG) print(this + ".IAccessibleText::get_newText"); String text = null; int start = 0; int end = 0; if (textInserted != null) { text = (String) textInserted[3]; start = ((Integer) textInserted[1]).intValue(); end = ((Integer) textInserted[2]).intValue(); } setString(pNewText, text); OS.MoveMemory(pNewText + C.PTR_SIZEOF, new int[] { start }, 4); OS.MoveMemory(pNewText + C.PTR_SIZEOF + 4, new int[] { end }, 4); if (textInserted == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleText::get_oldText([out] pOldText) */ int get_oldText(long pOldText) { if (DEBUG) print(this + ".IAccessibleText::get_oldText"); String text = null; int start = 0; int end = 0; if (textDeleted != null) { text = (String) textDeleted[3]; start = ((Integer) textDeleted[1]).intValue(); end = ((Integer) textDeleted[2]).intValue(); } setString(pOldText, text); OS.MoveMemory(pOldText + C.PTR_SIZEOF, new int[] { start }, 4); OS.MoveMemory(pOldText + C.PTR_SIZEOF + 4, new int[] { end }, 4); if (textDeleted == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleValue::get_currentValue([out] pCurrentValue) */ int get_currentValue(long pCurrentValue) { AccessibleValueEvent event = new AccessibleValueEvent(this); for (int i = 0; i < accessibleValueListenersSize(); i++) { AccessibleValueListener listener = accessibleValueListeners.get(i); listener.getCurrentValue(event); } if (DEBUG) print(this + ".IAccessibleValue::get_currentValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK)); setNumberVARIANT(pCurrentValue, event.value); return COM.S_OK; } /* IAccessibleValue::setCurrentValue([in] value) */ int setCurrentValue(long value) { if (DEBUG) print(this + ".IAccessibleValue::setCurrentValue"); AccessibleValueEvent event = new AccessibleValueEvent(this); event.value = getNumberVARIANT(value); for (int i = 0; i < accessibleValueListenersSize(); i++) { AccessibleValueListener listener = accessibleValueListeners.get(i); listener.setCurrentValue(event); } //if (event.value == null) return COM.S_FALSE; return COM.S_OK; } /* IAccessibleValue::get_maximumValue([out] pMaximumValue) */ int get_maximumValue(long pMaximumValue) { AccessibleValueEvent event = new AccessibleValueEvent(this); for (int i = 0; i < accessibleValueListenersSize(); i++) { AccessibleValueListener listener = accessibleValueListeners.get(i); listener.getMaximumValue(event); } if (DEBUG) print(this + ".IAccessibleValue::get_maximumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK)); setNumberVARIANT(pMaximumValue, event.value); return COM.S_OK; } /* IAccessibleValue::get_minimumValue([out] pMinimumValue) */ int get_minimumValue(long pMinimumValue) { AccessibleValueEvent event = new AccessibleValueEvent(this); for (int i = 0; i < accessibleValueListenersSize(); i++) { AccessibleValueListener listener = accessibleValueListeners.get(i); listener.getMinimumValue(event); } if (DEBUG) print(this + ".IAccessibleValue::get_minimumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK)); setNumberVARIANT(pMinimumValue, event.value); return COM.S_OK; } int eventChildID() { if (parent == null) return COM.CHILDID_SELF; if (uniqueID == -1) uniqueID = UniqueID--; return uniqueID; } void checkUniqueID(int childID) { /* If the application is using child ids, check whether there's a corresponding * accessible, and if so, use the child id as that accessible's unique id. */ AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; for (int l = 0; l < accessibleControlListenersSize(); l++) { AccessibleControlListener listener = accessibleControlListeners.get(l); listener.getChild(event); } Accessible accessible = event.accessible; if (accessible != null && accessible.uniqueID == -1) { accessible.uniqueID = childID; } } int childIDToOs(int childID) { if (childID == ACC.CHILDID_SELF) return COM.CHILDID_SELF; /* ChildIDs are 1-based indices. */ int osChildID = childID + 1; if (control instanceof Tree) { osChildID = (int) OS.SendMessage(control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0); } checkUniqueID(osChildID); return osChildID; } int osToChildID(int osChildID) { if (osChildID == COM.CHILDID_SELF) return ACC.CHILDID_SELF; /* * Feature of Windows: * Before Windows XP, tree item ids were 1-based indices. * Windows XP and later use the tree item handle for the * accessible child ID. For backward compatibility, we still * take 1-based childIDs for tree items prior to Windows XP. * All other childIDs are 1-based indices. */ if (!(control instanceof Tree)) return osChildID - 1; return (int) OS.SendMessage(control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0); } int stateToOs(int state) { int osState = 0; if ((state & ACC.STATE_SELECTED) != 0) osState |= COM.STATE_SYSTEM_SELECTED; if ((state & ACC.STATE_SELECTABLE) != 0) osState |= COM.STATE_SYSTEM_SELECTABLE; if ((state & ACC.STATE_MULTISELECTABLE) != 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE; if ((state & ACC.STATE_FOCUSED) != 0) osState |= COM.STATE_SYSTEM_FOCUSED; if ((state & ACC.STATE_FOCUSABLE) != 0) osState |= COM.STATE_SYSTEM_FOCUSABLE; if ((state & ACC.STATE_PRESSED) != 0) osState |= COM.STATE_SYSTEM_PRESSED; if ((state & ACC.STATE_CHECKED) != 0) osState |= COM.STATE_SYSTEM_CHECKED; if ((state & ACC.STATE_EXPANDED) != 0) osState |= COM.STATE_SYSTEM_EXPANDED; if ((state & ACC.STATE_COLLAPSED) != 0) osState |= COM.STATE_SYSTEM_COLLAPSED; if ((state & ACC.STATE_HOTTRACKED) != 0) osState |= COM.STATE_SYSTEM_HOTTRACKED; if ((state & ACC.STATE_BUSY) != 0) osState |= COM.STATE_SYSTEM_BUSY; if ((state & ACC.STATE_READONLY) != 0) osState |= COM.STATE_SYSTEM_READONLY; if ((state & ACC.STATE_INVISIBLE) != 0) osState |= COM.STATE_SYSTEM_INVISIBLE; if ((state & ACC.STATE_OFFSCREEN) != 0) osState |= COM.STATE_SYSTEM_OFFSCREEN; if ((state & ACC.STATE_SIZEABLE) != 0) osState |= COM.STATE_SYSTEM_SIZEABLE; if ((state & ACC.STATE_LINKED) != 0) osState |= COM.STATE_SYSTEM_LINKED; if ((state & ACC.STATE_DISABLED) != 0) osState |= COM.STATE_SYSTEM_UNAVAILABLE; return osState; } int osToState(int osState) { int state = ACC.STATE_NORMAL; if ((osState & COM.STATE_SYSTEM_SELECTED) != 0) state |= ACC.STATE_SELECTED; if ((osState & COM.STATE_SYSTEM_SELECTABLE) != 0) state |= ACC.STATE_SELECTABLE; if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) state |= ACC.STATE_MULTISELECTABLE; if ((osState & COM.STATE_SYSTEM_FOCUSED) != 0) state |= ACC.STATE_FOCUSED; if ((osState & COM.STATE_SYSTEM_FOCUSABLE) != 0) state |= ACC.STATE_FOCUSABLE; if ((osState & COM.STATE_SYSTEM_PRESSED) != 0) state |= ACC.STATE_PRESSED; if ((osState & COM.STATE_SYSTEM_CHECKED) != 0) state |= ACC.STATE_CHECKED; if ((osState & COM.STATE_SYSTEM_EXPANDED) != 0) state |= ACC.STATE_EXPANDED; if ((osState & COM.STATE_SYSTEM_COLLAPSED) != 0) state |= ACC.STATE_COLLAPSED; if ((osState & COM.STATE_SYSTEM_HOTTRACKED) != 0) state |= ACC.STATE_HOTTRACKED; if ((osState & COM.STATE_SYSTEM_BUSY) != 0) state |= ACC.STATE_BUSY; if ((osState & COM.STATE_SYSTEM_READONLY) != 0) state |= ACC.STATE_READONLY; if ((osState & COM.STATE_SYSTEM_INVISIBLE) != 0) state |= ACC.STATE_INVISIBLE; if ((osState & COM.STATE_SYSTEM_OFFSCREEN) != 0) state |= ACC.STATE_OFFSCREEN; if ((osState & COM.STATE_SYSTEM_SIZEABLE) != 0) state |= ACC.STATE_SIZEABLE; if ((osState & COM.STATE_SYSTEM_LINKED) != 0) state |= ACC.STATE_LINKED; if ((osState & COM.STATE_SYSTEM_UNAVAILABLE) != 0) state |= ACC.STATE_DISABLED; return state; } int roleToOs(int role) { switch (role) { case ACC.ROLE_CLIENT_AREA: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_WINDOW: return COM.ROLE_SYSTEM_WINDOW; case ACC.ROLE_MENUBAR: return COM.ROLE_SYSTEM_MENUBAR; case ACC.ROLE_MENU: return COM.ROLE_SYSTEM_MENUPOPUP; case ACC.ROLE_MENUITEM: return COM.ROLE_SYSTEM_MENUITEM; case ACC.ROLE_SEPARATOR: return COM.ROLE_SYSTEM_SEPARATOR; case ACC.ROLE_TOOLTIP: return COM.ROLE_SYSTEM_TOOLTIP; case ACC.ROLE_SCROLLBAR: return COM.ROLE_SYSTEM_SCROLLBAR; case ACC.ROLE_DIALOG: return COM.ROLE_SYSTEM_DIALOG; case ACC.ROLE_LABEL: return COM.ROLE_SYSTEM_STATICTEXT; case ACC.ROLE_PUSHBUTTON: return COM.ROLE_SYSTEM_PUSHBUTTON; case ACC.ROLE_CHECKBUTTON: return COM.ROLE_SYSTEM_CHECKBUTTON; case ACC.ROLE_RADIOBUTTON: return COM.ROLE_SYSTEM_RADIOBUTTON; case ACC.ROLE_SPLITBUTTON: return COM.ROLE_SYSTEM_SPLITBUTTON; case ACC.ROLE_COMBOBOX: return COM.ROLE_SYSTEM_COMBOBOX; case ACC.ROLE_TEXT: return COM.ROLE_SYSTEM_TEXT; case ACC.ROLE_TOOLBAR: return COM.ROLE_SYSTEM_TOOLBAR; case ACC.ROLE_LIST: return COM.ROLE_SYSTEM_LIST; case ACC.ROLE_LISTITEM: return COM.ROLE_SYSTEM_LISTITEM; case ACC.ROLE_TABLE: return COM.ROLE_SYSTEM_TABLE; case ACC.ROLE_TABLECELL: return COM.ROLE_SYSTEM_CELL; case ACC.ROLE_TABLECOLUMNHEADER: return COM.ROLE_SYSTEM_COLUMNHEADER; case ACC.ROLE_TABLEROWHEADER: return COM.ROLE_SYSTEM_ROWHEADER; case ACC.ROLE_TREE: return COM.ROLE_SYSTEM_OUTLINE; case ACC.ROLE_TREEITEM: return COM.ROLE_SYSTEM_OUTLINEITEM; case ACC.ROLE_TABFOLDER: return COM.ROLE_SYSTEM_PAGETABLIST; case ACC.ROLE_TABITEM: return COM.ROLE_SYSTEM_PAGETAB; case ACC.ROLE_PROGRESSBAR: return COM.ROLE_SYSTEM_PROGRESSBAR; case ACC.ROLE_SLIDER: return COM.ROLE_SYSTEM_SLIDER; case ACC.ROLE_LINK: return COM.ROLE_SYSTEM_LINK; case ACC.ROLE_ALERT: return COM.ROLE_SYSTEM_ALERT; case ACC.ROLE_ANIMATION: return COM.ROLE_SYSTEM_ANIMATION; case ACC.ROLE_COLUMN: return COM.ROLE_SYSTEM_COLUMN; case ACC.ROLE_DOCUMENT: return COM.ROLE_SYSTEM_DOCUMENT; case ACC.ROLE_GRAPHIC: return COM.ROLE_SYSTEM_GRAPHIC; case ACC.ROLE_GROUP: return COM.ROLE_SYSTEM_GROUPING; case ACC.ROLE_ROW: return COM.ROLE_SYSTEM_ROW; case ACC.ROLE_SPINBUTTON: return COM.ROLE_SYSTEM_SPINBUTTON; case ACC.ROLE_STATUSBAR: return COM.ROLE_SYSTEM_STATUSBAR; case ACC.ROLE_CLOCK: return COM.ROLE_SYSTEM_CLOCK; case ACC.ROLE_CALENDAR: return COM.ROLE_SYSTEM_DROPLIST; /* The rest are IA2 roles, so return the closest match. */ case ACC.ROLE_CANVAS: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_CHECKMENUITEM: return COM.ROLE_SYSTEM_MENUITEM; case ACC.ROLE_RADIOMENUITEM: return COM.ROLE_SYSTEM_MENUITEM; case ACC.ROLE_DATETIME: return COM.ROLE_SYSTEM_DROPLIST; case ACC.ROLE_FOOTER: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_FORM: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_HEADER: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_HEADING: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_PAGE: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_PARAGRAPH: return COM.ROLE_SYSTEM_CLIENT; case ACC.ROLE_SECTION: return COM.ROLE_SYSTEM_CLIENT; } return COM.ROLE_SYSTEM_CLIENT; } int osToRole(int osRole) { switch (osRole) { case COM.ROLE_SYSTEM_CLIENT: return ACC.ROLE_CLIENT_AREA; case COM.ROLE_SYSTEM_WINDOW: return ACC.ROLE_WINDOW; case COM.ROLE_SYSTEM_MENUBAR: return ACC.ROLE_MENUBAR; case COM.ROLE_SYSTEM_MENUPOPUP: return ACC.ROLE_MENU; case COM.ROLE_SYSTEM_MENUITEM: return ACC.ROLE_MENUITEM; case COM.ROLE_SYSTEM_SEPARATOR: return ACC.ROLE_SEPARATOR; case COM.ROLE_SYSTEM_TOOLTIP: return ACC.ROLE_TOOLTIP; case COM.ROLE_SYSTEM_SCROLLBAR: return ACC.ROLE_SCROLLBAR; case COM.ROLE_SYSTEM_DIALOG: return ACC.ROLE_DIALOG; case COM.ROLE_SYSTEM_STATICTEXT: return ACC.ROLE_LABEL; case COM.ROLE_SYSTEM_PUSHBUTTON: return ACC.ROLE_PUSHBUTTON; case COM.ROLE_SYSTEM_CHECKBUTTON: return ACC.ROLE_CHECKBUTTON; case COM.ROLE_SYSTEM_RADIOBUTTON: return ACC.ROLE_RADIOBUTTON; case COM.ROLE_SYSTEM_SPLITBUTTON: return ACC.ROLE_SPLITBUTTON; case COM.ROLE_SYSTEM_COMBOBOX: return ACC.ROLE_COMBOBOX; case COM.ROLE_SYSTEM_TEXT: return ACC.ROLE_TEXT; case COM.ROLE_SYSTEM_TOOLBAR: return ACC.ROLE_TOOLBAR; case COM.ROLE_SYSTEM_LIST: return ACC.ROLE_LIST; case COM.ROLE_SYSTEM_LISTITEM: return ACC.ROLE_LISTITEM; case COM.ROLE_SYSTEM_TABLE: return ACC.ROLE_TABLE; case COM.ROLE_SYSTEM_CELL: return ACC.ROLE_TABLECELL; case COM.ROLE_SYSTEM_COLUMNHEADER: return ACC.ROLE_TABLECOLUMNHEADER; case COM.ROLE_SYSTEM_ROWHEADER: return ACC.ROLE_TABLEROWHEADER; case COM.ROLE_SYSTEM_OUTLINE: return ACC.ROLE_TREE; case COM.ROLE_SYSTEM_OUTLINEITEM: return ACC.ROLE_TREEITEM; case COM.ROLE_SYSTEM_PAGETABLIST: return ACC.ROLE_TABFOLDER; case COM.ROLE_SYSTEM_PAGETAB: return ACC.ROLE_TABITEM; case COM.ROLE_SYSTEM_PROGRESSBAR: return ACC.ROLE_PROGRESSBAR; case COM.ROLE_SYSTEM_SLIDER: return ACC.ROLE_SLIDER; case COM.ROLE_SYSTEM_LINK: return ACC.ROLE_LINK; case COM.ROLE_SYSTEM_ALERT: return ACC.ROLE_ALERT; case COM.ROLE_SYSTEM_ANIMATION: return ACC.ROLE_ANIMATION; case COM.ROLE_SYSTEM_COLUMN: return ACC.ROLE_COLUMN; case COM.ROLE_SYSTEM_DOCUMENT: return ACC.ROLE_DOCUMENT; case COM.ROLE_SYSTEM_GRAPHIC: return ACC.ROLE_GRAPHIC; case COM.ROLE_SYSTEM_GROUPING: return ACC.ROLE_GROUP; case COM.ROLE_SYSTEM_ROW: return ACC.ROLE_ROW; case COM.ROLE_SYSTEM_SPINBUTTON: return ACC.ROLE_SPINBUTTON; case COM.ROLE_SYSTEM_STATUSBAR: return ACC.ROLE_STATUSBAR; case COM.ROLE_SYSTEM_CLOCK: return ACC.ROLE_CLOCK; case COM.ROLE_SYSTEM_DROPLIST: return ACC.ROLE_CALENDAR; } return ACC.ROLE_CLIENT_AREA; } /* * Return a Color given a string of the form "rgb(n,n,n)". */ Color colorFromString(String rgbString) { try { int open = rgbString.indexOf('('); int comma1 = rgbString.indexOf(','); int comma2 = rgbString.indexOf(',', comma1 + 1); int close = rgbString.indexOf(')'); int r = Integer.parseInt(rgbString.substring(open + 1, comma1)); int g = Integer.parseInt(rgbString.substring(comma1 + 1, comma2)); int b = Integer.parseInt(rgbString.substring(comma2 + 1, close)); return new Color(control.getDisplay(), r, g, b); } catch (NumberFormatException ex) { } return null; } int getCaretOffset() { AccessibleTextEvent event = new AccessibleTextEvent(this); event.offset = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextListener listener = accessibleTextExtendedListeners.get(i); listener.getCaretOffset(event); } if (event.offset == -1) { for (int i = 0; i < accessibleTextListenersSize(); i++) { event.childID = ACC.CHILDID_SELF; AccessibleTextListener listener = accessibleTextListeners.get(i); listener.getCaretOffset(event); } } return event.offset; } int getCharacterCount() { AccessibleTextEvent event = new AccessibleTextEvent(this); event.count = -1; for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) { AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i); listener.getCharacterCount(event); } if (event.count == -1) { AccessibleControlEvent e = new AccessibleControlEvent(this); e.childID = ACC.CHILDID_SELF; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getRole(e); listener.getValue(e); } // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_text. event.count = e.detail == ACC.ROLE_TEXT && e.result != null ? e.result.length() : 0; } return event.count; } int getRelationCount() { int count = 0; for (int type = 0; type < MAX_RELATION_TYPES; type++) { if (relations[type] != null) count++; } return count; } int getRole() { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_SELF; for (int i = 0; i < accessibleControlListenersSize(); i++) { AccessibleControlListener listener = accessibleControlListeners.get(i); listener.getRole(event); } return event.detail; } int getDefaultRole() { int role; role = COM.ROLE_SYSTEM_CLIENT; if (iaccessible != null) { /* Get the default role from the OS. */ long varChild = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof); setIntVARIANT(varChild, COM.VT_I4, COM.CHILDID_SELF); long pvarRole = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof); int code = iaccessible.get_accRole(varChild, pvarRole); if (code == COM.S_OK) { VARIANT v = getVARIANT(pvarRole); if (v.vt == COM.VT_I4) role = v.lVal; } OS.GlobalFree(varChild); OS.GlobalFree(pvarRole); } return role; } String getString(long psz) { long[] ptr = new long[1]; OS.MoveMemory(ptr, psz, C.PTR_SIZEOF); int size = COM.SysStringByteLen(ptr[0]); if (size == 0) return ""; char[] buffer = new char[(size + 1) / 2]; OS.MoveMemory(buffer, ptr[0], size); return new String(buffer); } VARIANT getVARIANT(long variant) { VARIANT v = new VARIANT(); COM.MoveMemory(v, variant, VARIANT.sizeof); return v; } Number getNumberVARIANT(long variant) { VARIANT v = new VARIANT(); COM.MoveMemory(v, variant, VARIANT.sizeof); if (v.vt == COM.VT_I8) return Long.valueOf(v.lVal); // TODO: Fix this - v.lVal is an int - don't use struct return Integer.valueOf(v.lVal); } void setIntVARIANT(long variant, short vt, int lVal) { if (vt == COM.VT_I4 || vt == COM.VT_EMPTY) { OS.MoveMemory(variant, new short[] { vt }, 2); OS.MoveMemory(variant + 8, new int[] { lVal }, 4); } } void setPtrVARIANT(long variant, short vt, long lVal) { if (vt == COM.VT_DISPATCH || vt == COM.VT_UNKNOWN) { OS.MoveMemory(variant, new short[] { vt }, 2); OS.MoveMemory(variant + 8, new long[] { lVal }, C.PTR_SIZEOF); } } void setNumberVARIANT(long variant, Number number) { if (number == null) { OS.MoveMemory(variant, new short[] { COM.VT_EMPTY }, 2); OS.MoveMemory(variant + 8, new int[] { 0 }, 4); } else if (number instanceof Double) { OS.MoveMemory(variant, new short[] { COM.VT_R8 }, 2); OS.MoveMemory(variant + 8, new double[] { number.doubleValue() }, 8); } else if (number instanceof Float) { OS.MoveMemory(variant, new short[] { COM.VT_R4 }, 2); OS.MoveMemory(variant + 8, new float[] { number.floatValue() }, 4); } else if (number instanceof Long) { OS.MoveMemory(variant, new short[] { COM.VT_I8 }, 2); OS.MoveMemory(variant + 8, new long[] { number.longValue() }, 8); } else { OS.MoveMemory(variant, new short[] { COM.VT_I4 }, 2); OS.MoveMemory(variant + 8, new int[] { number.intValue() }, 4); } } void setString(long psz, String string) { long ptr = 0; if (string != null) { char[] data = (string + "\0").toCharArray(); ptr = COM.SysAllocString(data); } OS.MoveMemory(psz, new long[] { ptr }, C.PTR_SIZEOF); } void setStringVARIANT(long variant, String string) { long ptr = 0; if (string != null) { char[] data = (string + "\0").toCharArray(); ptr = COM.SysAllocString(data); } OS.MoveMemory(variant, new short[] { ptr == 0 ? COM.VT_EMPTY : COM.VT_BSTR }, 2); OS.MoveMemory(variant + 8, new long[] { ptr }, C.PTR_SIZEOF); } /* checkWidget was copied from Widget, and rewritten to work in this package */ void checkWidget() { if (!isValidThread()) SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS); if (control.isDisposed()) SWT.error(SWT.ERROR_WIDGET_DISPOSED); } boolean isATRunning() { /* * Currently there is no accurate way to check if AT is running from 'refCount'. * JAWS screen reader cannot be detected using 'refCount' approach, * because 'refCount' continues to be 1 even when JAWS is running. */ // if (refCount <= 1) return false; return true; } /* isValidThread was copied from Widget, and rewritten to work in this package */ boolean isValidThread() { return control.getDisplay().getThread() == Thread.currentThread(); } // START DEBUG CODE static void print(String str) { if (DEBUG) System.out.println(str); } String getRoleString(int role) { if (DEBUG) switch (role) { case COM.ROLE_SYSTEM_CLIENT: return "ROLE_SYSTEM_CLIENT"; case COM.ROLE_SYSTEM_WINDOW: return "ROLE_SYSTEM_WINDOW"; case COM.ROLE_SYSTEM_MENUBAR: return "ROLE_SYSTEM_MENUBAR"; case COM.ROLE_SYSTEM_MENUPOPUP: return "ROLE_SYSTEM_MENUPOPUP"; case COM.ROLE_SYSTEM_MENUITEM: return "ROLE_SYSTEM_MENUITEM"; case COM.ROLE_SYSTEM_SEPARATOR: return "ROLE_SYSTEM_SEPARATOR"; case COM.ROLE_SYSTEM_TOOLTIP: return "ROLE_SYSTEM_TOOLTIP"; case COM.ROLE_SYSTEM_SCROLLBAR: return "ROLE_SYSTEM_SCROLLBAR"; case COM.ROLE_SYSTEM_DIALOG: return "ROLE_SYSTEM_DIALOG"; case COM.ROLE_SYSTEM_STATICTEXT: return "ROLE_SYSTEM_STATICTEXT"; case COM.ROLE_SYSTEM_PUSHBUTTON: return "ROLE_SYSTEM_PUSHBUTTON"; case COM.ROLE_SYSTEM_CHECKBUTTON: return "ROLE_SYSTEM_CHECKBUTTON"; case COM.ROLE_SYSTEM_RADIOBUTTON: return "ROLE_SYSTEM_RADIOBUTTON"; case COM.ROLE_SYSTEM_SPLITBUTTON: return "ROLE_SYSTEM_SPLITBUTTON"; case COM.ROLE_SYSTEM_COMBOBOX: return "ROLE_SYSTEM_COMBOBOX"; case COM.ROLE_SYSTEM_TEXT: return "ROLE_SYSTEM_TEXT"; case COM.ROLE_SYSTEM_TOOLBAR: return "ROLE_SYSTEM_TOOLBAR"; case COM.ROLE_SYSTEM_LIST: return "ROLE_SYSTEM_LIST"; case COM.ROLE_SYSTEM_LISTITEM: return "ROLE_SYSTEM_LISTITEM"; case COM.ROLE_SYSTEM_TABLE: return "ROLE_SYSTEM_TABLE"; case COM.ROLE_SYSTEM_CELL: return "ROLE_SYSTEM_CELL"; case COM.ROLE_SYSTEM_COLUMNHEADER: return "ROLE_SYSTEM_COLUMNHEADER"; case COM.ROLE_SYSTEM_ROWHEADER: return "ROLE_SYSTEM_ROWHEADER"; case COM.ROLE_SYSTEM_OUTLINE: return "ROLE_SYSTEM_OUTLINE"; case COM.ROLE_SYSTEM_OUTLINEITEM: return "ROLE_SYSTEM_OUTLINEITEM"; case COM.ROLE_SYSTEM_PAGETABLIST: return "ROLE_SYSTEM_PAGETABLIST"; case COM.ROLE_SYSTEM_PAGETAB: return "ROLE_SYSTEM_PAGETAB"; case COM.ROLE_SYSTEM_PROGRESSBAR: return "ROLE_SYSTEM_PROGRESSBAR"; case COM.ROLE_SYSTEM_SLIDER: return "ROLE_SYSTEM_SLIDER"; case COM.ROLE_SYSTEM_LINK: return "ROLE_SYSTEM_LINK"; case COM.ROLE_SYSTEM_ALERT: return "ROLE_SYSTEM_ALERT"; case COM.ROLE_SYSTEM_ANIMATION: return "ROLE_SYSTEM_ANIMATION"; case COM.ROLE_SYSTEM_COLUMN: return "ROLE_SYSTEM_COLUMN"; case COM.ROLE_SYSTEM_DOCUMENT: return "ROLE_SYSTEM_DOCUMENT"; case COM.ROLE_SYSTEM_GRAPHIC: return "ROLE_SYSTEM_GRAPHIC"; case COM.ROLE_SYSTEM_GROUPING: return "ROLE_SYSTEM_GROUPING"; case COM.ROLE_SYSTEM_ROW: return "ROLE_SYSTEM_ROW"; case COM.ROLE_SYSTEM_SPINBUTTON: return "ROLE_SYSTEM_SPINBUTTON"; case COM.ROLE_SYSTEM_STATUSBAR: return "ROLE_SYSTEM_STATUSBAR"; case COM.ROLE_SYSTEM_CLOCK: return "ROLE_SYSTEM_CLOCK"; case COM.ROLE_SYSTEM_DROPLIST: return "ROLE_SYSTEM_DROPLIST"; // IA2 roles case ACC.ROLE_CANVAS: return "IA2_ROLE_CANVAS"; case ACC.ROLE_CHECKMENUITEM: return "IA2_ROLE_CHECKMENUITEM"; case ACC.ROLE_RADIOMENUITEM: return "IA2_ROLE_RADIOMENUITEM"; case ACC.ROLE_DATETIME: return "IA2_ROLE_DATETIME"; case ACC.ROLE_FOOTER: return "IA2_ROLE_FOOTER"; case ACC.ROLE_FORM: return "IA2_ROLE_FORM"; case ACC.ROLE_HEADER: return "IA2_ROLE_HEADER"; case ACC.ROLE_HEADING: return "IA2_ROLE_HEADING"; case ACC.ROLE_PAGE: return "IA2_ROLE_PAGE"; case ACC.ROLE_PARAGRAPH: return "IA2_ROLE_PARAGRAPH"; case ACC.ROLE_SECTION: return "IA2_ROLE_SECTION"; } return "Unknown role (" + role + ")"; } String getStateString(int state) { if (state == 0) return " no state bits set"; StringBuilder stateString = new StringBuilder(); if (DEBUG) { if ((state & COM.STATE_SYSTEM_SELECTED) != 0) stateString.append(" STATE_SYSTEM_SELECTED"); if ((state & COM.STATE_SYSTEM_SELECTABLE) != 0) stateString.append(" STATE_SYSTEM_SELECTABLE"); if ((state & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) stateString.append(" STATE_SYSTEM_MULTISELECTABLE"); if ((state & COM.STATE_SYSTEM_FOCUSED) != 0) stateString.append(" STATE_SYSTEM_FOCUSED"); if ((state & COM.STATE_SYSTEM_FOCUSABLE) != 0) stateString.append(" STATE_SYSTEM_FOCUSABLE"); if ((state & COM.STATE_SYSTEM_PRESSED) != 0) stateString.append(" STATE_SYSTEM_PRESSED"); if ((state & COM.STATE_SYSTEM_CHECKED) != 0) stateString.append(" STATE_SYSTEM_CHECKED"); if ((state & COM.STATE_SYSTEM_EXPANDED) != 0) stateString.append(" STATE_SYSTEM_EXPANDED"); if ((state & COM.STATE_SYSTEM_COLLAPSED) != 0) stateString.append(" STATE_SYSTEM_COLLAPSED"); if ((state & COM.STATE_SYSTEM_HOTTRACKED) != 0) stateString.append(" STATE_SYSTEM_HOTTRACKED"); if ((state & COM.STATE_SYSTEM_BUSY) != 0) stateString.append(" STATE_SYSTEM_BUSY"); if ((state & COM.STATE_SYSTEM_READONLY) != 0) stateString.append(" STATE_SYSTEM_READONLY"); if ((state & COM.STATE_SYSTEM_INVISIBLE) != 0) stateString.append(" STATE_SYSTEM_INVISIBLE"); if ((state & COM.STATE_SYSTEM_OFFSCREEN) != 0) stateString.append(" STATE_SYSTEM_OFFSCREEN"); if ((state & COM.STATE_SYSTEM_SIZEABLE) != 0) stateString.append(" STATE_SYSTEM_SIZEABLE"); if ((state & COM.STATE_SYSTEM_LINKED) != 0) stateString.append(" STATE_SYSTEM_LINKED"); if ((state & COM.STATE_SYSTEM_UNAVAILABLE) != 0) stateString.append(" STATE_SYSTEM_UNAVAILABLE"); if (stateString.length() == 0) stateString.append(" Unknown state[s] (" + Integer.toHexString(state) + ")"); } return stateString.toString(); } String getIA2StatesString(int ia2States) { if (ia2States == 0) return " no state bits set"; StringBuilder stateString = new StringBuilder(); if (DEBUG) { if ((ia2States & COM.IA2_STATE_ACTIVE) != 0) stateString.append(" IA2_STATE_ACTIVE"); if ((ia2States & COM.IA2_STATE_EDITABLE) != 0) stateString.append(" IA2_STATE_EDITABLE"); if ((ia2States & COM.IA2_STATE_SINGLE_LINE) != 0) stateString.append(" IA2_STATE_SINGLE_LINE"); if ((ia2States & COM.IA2_STATE_MULTI_LINE) != 0) stateString.append(" IA2_STATE_MULTI_LINE"); if ((ia2States & COM.IA2_STATE_REQUIRED) != 0) stateString.append(" IA2_STATE_REQUIRED"); if ((ia2States & COM.IA2_STATE_INVALID_ENTRY) != 0) stateString.append(" IA2_STATE_INVALID_ENTRY"); if ((ia2States & COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION) != 0) stateString.append(" IA2_STATE_SUPPORTS_AUTOCOMPLETION"); if (stateString.length() == 0) stateString.append(" Unknown IA2 state[s] (" + ia2States + ")"); } return stateString.toString(); } String getEventString(int event) { if (DEBUG) switch (event) { case ACC.EVENT_TABLE_CHANGED: return "IA2_EVENT_TABLE_CHANGED"; case ACC.EVENT_TEXT_CHANGED: return "IA2_EVENT_TEXT_REMOVED or IA2_EVENT_TEXT_INSERTED"; case ACC.EVENT_HYPERTEXT_LINK_SELECTED: return "IA2_EVENT_HYPERTEXT_LINK_SELECTED"; case ACC.EVENT_VALUE_CHANGED: return "EVENT_OBJECT_VALUECHANGE"; case ACC.EVENT_STATE_CHANGED: return "EVENT_OBJECT_STATECHANGE"; case ACC.EVENT_SELECTION_CHANGED: return "EVENT_OBJECT_SELECTIONWITHIN"; case ACC.EVENT_TEXT_SELECTION_CHANGED: return "EVENT_OBJECT_TEXTSELECTIONCHANGED"; case ACC.EVENT_LOCATION_CHANGED: return "EVENT_OBJECT_LOCATIONCHANGE"; case ACC.EVENT_NAME_CHANGED: return "EVENT_OBJECT_NAMECHANGE"; case ACC.EVENT_DESCRIPTION_CHANGED: return "EVENT_OBJECT_DESCRIPTIONCHANGE"; case ACC.EVENT_DOCUMENT_LOAD_COMPLETE: return "IA2_EVENT_DOCUMENT_LOAD_COMPLETE"; case ACC.EVENT_DOCUMENT_LOAD_STOPPED: return "IA2_EVENT_DOCUMENT_LOAD_STOPPED"; case ACC.EVENT_DOCUMENT_RELOAD: return "IA2_EVENT_DOCUMENT_RELOAD"; case ACC.EVENT_PAGE_CHANGED: return "IA2_EVENT_PAGE_CHANGED"; case ACC.EVENT_SECTION_CHANGED: return "IA2_EVENT_SECTION_CHANGED"; case ACC.EVENT_ACTION_CHANGED: return "IA2_EVENT_ACTION_CHANGED"; case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_START_INDEX_CHANGED"; case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_END_INDEX_CHANGED"; case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED: return "IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED"; case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED: return "IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED"; case ACC.EVENT_HYPERLINK_ACTIVATED: return "IA2_EVENT_HYPERLINK_ACTIVATED"; case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED: return "IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED"; case ACC.EVENT_ATTRIBUTE_CHANGED: return "IA2_EVENT_ATTRIBUTE_CHANGED"; case ACC.EVENT_TABLE_CAPTION_CHANGED: return "IA2_EVENT_TABLE_CAPTION_CHANGED"; case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED"; case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED: return "IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED"; case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED"; case ACC.EVENT_TABLE_ROW_HEADER_CHANGED: return "IA2_EVENT_TABLE_ROW_HEADER_CHANGED"; case ACC.EVENT_TABLE_SUMMARY_CHANGED: return "IA2_EVENT_TABLE_SUMMARY_CHANGED"; case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED: return "IA2_EVENT_TEXT_ATTRIBUTE_CHANGED"; case ACC.EVENT_TEXT_CARET_MOVED: return "IA2_EVENT_TEXT_CARET_MOVED"; case ACC.EVENT_TEXT_COLUMN_CHANGED: return "IA2_EVENT_TEXT_COLUMN_CHANGED"; } return "Unknown event (" + event + ")"; } private String hresult(int code) { if (DEBUG) switch (code) { case COM.S_OK: return " S_OK"; case COM.S_FALSE: return " S_FALSE"; case COM.E_ACCESSDENIED: return " E_ACCESSDENIED"; case COM.E_FAIL: return " E_FAIL"; case COM.E_INVALIDARG: return " E_INVALIDARG"; case COM.E_NOINTERFACE: return " E_NOINTERFACE"; case COM.E_NOTIMPL: return " E_NOTIMPL"; case COM.E_NOTSUPPORTED: return " E_NOTSUPPORTED"; case COM.E_OUTOFMEMORY: return " E_OUTOFMEMORY"; case OS.E_POINTER: return " E_POINTER"; case COM.DISP_E_EXCEPTION: return " DISP_E_EXCEPTION"; case COM.DISP_E_MEMBERNOTFOUND: return " DISP_E_MEMBERNOTFOUND"; case COM.DISP_E_UNKNOWNINTERFACE: return " DISP_E_UNKNOWNINTERFACE"; case COM.DISP_E_UNKNOWNNAME: return " DISP_E_UNKNOWNNAME"; } return " HRESULT=" + code; } boolean interesting(GUID guid) { if (DEBUG) { if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return true; if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return true; if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return true; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return true; } return false; } String guidString(GUID guid) { if (DEBUG) { final GUID IIDIAccessibleHandler = IIDFromString("{03022430-ABC4-11D0-BDE2-00AA001A1953}"); //$NON-NLS-1$ final GUID IIDIAccessor = IIDFromString("{0C733A8C-2A1C-11CE-ADE5-00AA0044773D}"); //$NON-NLS-1$ final GUID IIDIAdviseSink2 = IIDFromString("{00000125-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIBindCtx = IIDFromString("{0000000E-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDICreateErrorInfo = IIDFromString("{22F03340-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$ final GUID IIDICreateTypeInfo = IIDFromString("{00020405-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDICreateTypeLib = IIDFromString("{00020406-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIDataAdviseHolder = IIDFromString("{00000110-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumConnectionPoints = IIDFromString("{B196B285-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ final GUID IIDIEnumConnections = IIDFromString("{B196B287-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ final GUID IIDIEnumMoniker = IIDFromString("{00000102-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumOLEVERB = IIDFromString("{00000104-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumSTATDATA = IIDFromString("{00000105-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumSTATSTG = IIDFromString("{0000000D-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumString = IIDFromString("{00000101-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIEnumUnknown = IIDFromString("{00000100-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIErrorInfo = IIDFromString("{1CF2B120-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$ final GUID IIDIErrorLog = IIDFromString("{3127CA40-446E-11CE-8135-00AA004BB851}"); //$NON-NLS-1$ final GUID IIDIExternalConnection = IIDFromString("{00000019-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIFontDisp = IIDFromString("{BEF6E003-A874-101A-8BBA-00AA00300CAB}"); //$NON-NLS-1$ final GUID IIDILockBytes = IIDFromString("{0000000A-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIMalloc = IIDFromString("{00000002-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIMallocSpy = IIDFromString("{0000001D-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIMarshal = IIDFromString("{00000003-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIMessageFilter = IIDFromString("{00000016-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIMoniker = IIDFromString("{0000000F-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIOleAdviseHolder = IIDFromString("{00000111-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIOleCache = IIDFromString("{0000011E-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIOleCache2 = IIDFromString("{00000128-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIOleCacheControl = IIDFromString("{00000129-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIOleItemContainer = IIDFromString("{0000011C-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIParseDisplayName = IIDFromString("{0000011A-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIPerPropertyBrowsing = IIDFromString("{376BD3AA-3845-101B-84ED-08002B2EC713}"); //$NON-NLS-1$ final GUID IIDIPersistMemory = IIDFromString("{BD1AE5E0-A6AE-11CE-BD37-504200C10000}"); //$NON-NLS-1$ final GUID IIDIPersistPropertyBag = IIDFromString("{37D84F60-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$ final GUID IIDIPicture = IIDFromString("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$ final GUID IIDIPictureDisp = IIDFromString("{7BF80981-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$ final GUID IIDIPropertyBag = IIDFromString("{55272A00-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$ final GUID IIDIPropertyPage = IIDFromString("{B196B28D-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ final GUID IIDIPropertyPage2 = IIDFromString("{01E44665-24AC-101B-84ED-08002B2EC713}"); //$NON-NLS-1$ final GUID IIDIPropertyPageSite = IIDFromString("{B196B28C-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ final GUID IIDIPSFactoryBuffer = IIDFromString("{D5F569D0-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$ final GUID IIDIRootStorage = IIDFromString("{00000012-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIROTData = IIDFromString("{F29F6BC0-5021-11CE-AA15-00006901293F}"); //$NON-NLS-1$ final GUID IIDIRpcChannelBuffer = IIDFromString("{D5F56B60-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$ final GUID IIDIRpcProxyBuffer = IIDFromString("{D5F56A34-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$ final GUID IIDIRpcStubBuffer = IIDFromString("{D5F56AFC-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$ final GUID IIDIRunnableObject = IIDFromString("{00000126-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIRunningObjectTable = IIDFromString("{00000010-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDISimpleFrameSite = IIDFromString("{742B0E01-14E6-101B-914E-00AA00300CAB}"); //$NON-NLS-1$ final GUID IIDIStdMarshalInfo = IIDFromString("{00000018-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDISupportErrorInfo = IIDFromString("{DF0B3D60-548F-101B-8E65-08002B2BD119}"); //$NON-NLS-1$ final GUID IIDITypeComp = IIDFromString("{00020403-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDITypeLib = IIDFromString("{00020402-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIViewObject = IIDFromString("{0000010D-0000-0000-C000-000000000046}"); //$NON-NLS-1$ final GUID IIDIdentityUnmarshal = IIDFromString("{0000001b-0000-0000-c000-000000000046}"); //$NON-NLS-1$ final GUID IIDInternalMSMarshaller = IIDFromString("{4c1e39e1-e3e3-4296-aa86-ec938d896e92}"); //$NON-NLS-1$ final GUID IIDIAccIdentity = IIDFromString("{7852B78D-1CFD-41C1-A615-9C0C85960B5F}"); //$NON-NLS-1$ final GUID IIDIAccPropServer = IIDFromString("{76C0DBBB-15E0-4E7B-B61B-20EEEA2001E0}"); //$NON-NLS-1$ final GUID IIDIAccPropServices = IIDFromString("{6E26E776-04F0-495D-80E4-3330352E3169}"); //$NON-NLS-1$ if (COM.IsEqualGUID(guid, COM.IID_IDropTargetHelper)) return "IID_IDropTargetHelper"; if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge)) return "IIDJavaBeansBridge"; if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) return "IIDShockwaveActiveXControl"; if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return "IIDIAccessible"; if (COM.IsEqualGUID(guid, IIDIAccessibleHandler)) return "IIDIAccessibleHandler"; if (COM.IsEqualGUID(guid, IIDIAccessor)) return "IIDIAccessor"; if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) return "IIDIAdviseSink"; if (COM.IsEqualGUID(guid, IIDIAdviseSink2)) return "IIDIAdviseSink2"; if (COM.IsEqualGUID(guid, IIDIBindCtx)) return "IIDIBindCtx"; if (COM.IsEqualGUID(guid, COM.IIDIClassFactory)) return "IIDIClassFactory"; if (COM.IsEqualGUID(guid, COM.IIDIClassFactory2)) return "IIDIClassFactory2"; if (COM.IsEqualGUID(guid, COM.IIDIConnectionPointContainer)) return "IIDIConnectionPointContainer"; if (COM.IsEqualGUID(guid, IIDICreateErrorInfo)) return "IIDICreateErrorInfo"; if (COM.IsEqualGUID(guid, IIDICreateTypeInfo)) return "IIDICreateTypeInfo"; if (COM.IsEqualGUID(guid, IIDICreateTypeLib)) return "IIDICreateTypeLib"; if (COM.IsEqualGUID(guid, IIDIDataAdviseHolder)) return "IIDIDataAdviseHolder"; if (COM.IsEqualGUID(guid, COM.IIDIDataObject)) return "IIDIDataObject"; if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) return "IIDIDispatch"; if (COM.IsEqualGUID(guid, COM.IIDIDispatchEx)) return "IIDIDispatchEx"; if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) return "IIDIDocHostUIHandler"; if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) return "IIDIDocHostShowUI"; if (COM.IsEqualGUID(guid, COM.IIDIDropSource)) return "IIDIDropSource"; if (COM.IsEqualGUID(guid, COM.IIDIDropTarget)) return "IIDIDropTarget"; if (COM.IsEqualGUID(guid, IIDIEnumConnectionPoints)) return "IIDIEnumConnectionPoints"; if (COM.IsEqualGUID(guid, IIDIEnumConnections)) return "IIDIEnumConnections"; if (COM.IsEqualGUID(guid, COM.IIDIEnumFORMATETC)) return "IIDIEnumFORMATETC"; if (COM.IsEqualGUID(guid, IIDIEnumMoniker)) return "IIDIEnumMoniker"; if (COM.IsEqualGUID(guid, IIDIEnumOLEVERB)) return "IIDIEnumOLEVERB"; if (COM.IsEqualGUID(guid, IIDIEnumSTATDATA)) return "IIDIEnumSTATDATA"; if (COM.IsEqualGUID(guid, IIDIEnumSTATSTG)) return "IIDIEnumSTATSTG"; if (COM.IsEqualGUID(guid, IIDIEnumString)) return "IIDIEnumString"; if (COM.IsEqualGUID(guid, IIDIEnumUnknown)) return "IIDIEnumUnknown"; if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return "IIDIEnumVARIANT"; if (COM.IsEqualGUID(guid, IIDIErrorInfo)) return "IIDIErrorInfo"; if (COM.IsEqualGUID(guid, IIDIErrorLog)) return "IIDIErrorLog"; if (COM.IsEqualGUID(guid, IIDIExternalConnection)) return "IIDIExternalConnection"; if (COM.IsEqualGUID(guid, IIDIFontDisp)) return "IIDIFontDisp"; // if (COM.IsEqualGUID(guid, COM.IIDIHTMLDocumentEvents2)) return "IIDIHTMLDocumentEvents2"; if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) return "IIDIInternetSecurityManager"; if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) return "IIDIAuthenticate"; if (COM.IsEqualGUID(guid, COM.IIDIJScriptTypeInfo)) return "IIDIJScriptTypeInfo"; if (COM.IsEqualGUID(guid, IIDILockBytes)) return "IIDILockBytes"; if (COM.IsEqualGUID(guid, IIDIMalloc)) return "IIDIMalloc"; if (COM.IsEqualGUID(guid, IIDIMallocSpy)) return "IIDIMallocSpy"; if (COM.IsEqualGUID(guid, IIDIMarshal)) return "IIDIMarshal"; if (COM.IsEqualGUID(guid, IIDIMessageFilter)) return "IIDIMessageFilter"; if (COM.IsEqualGUID(guid, IIDIMoniker)) return "IIDIMoniker"; if (COM.IsEqualGUID(guid, IIDIOleAdviseHolder)) return "IIDIOleAdviseHolder"; if (COM.IsEqualGUID(guid, IIDIOleCache)) return "IIDIOleCache"; if (COM.IsEqualGUID(guid, IIDIOleCache2)) return "IIDIOleCache2"; if (COM.IsEqualGUID(guid, IIDIOleCacheControl)) return "IIDIOleCacheControl"; if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) return "IIDIOleClientSite"; if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) return "IIDIOleCommandTarget"; if (COM.IsEqualGUID(guid, COM.IIDIOleControl)) return "IIDIOleControl"; if (COM.IsEqualGUID(guid, COM.IIDIOleControlSite)) return "IIDIOleControlSite"; if (COM.IsEqualGUID(guid, COM.IIDIOleDocument)) return "IIDIOleDocument"; if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite)) return "IIDIOleDocumentSite"; if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame)) return "IIDIOleInPlaceFrame"; if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceObject)) return "IIDIOleInPlaceObject"; if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) return "IIDIOleInPlaceSite"; if (COM.IsEqualGUID(guid, IIDIOleItemContainer)) return "IIDIOleItemContainer"; if (COM.IsEqualGUID(guid, COM.IIDIOleLink)) return "IIDIOleLink"; if (COM.IsEqualGUID(guid, COM.IIDIOleObject)) return "IIDIOleObject"; if (COM.IsEqualGUID(guid, IIDIParseDisplayName)) return "IIDIParseDisplayName"; if (COM.IsEqualGUID(guid, IIDIPerPropertyBrowsing)) return "IIDIPerPropertyBrowsing"; if (COM.IsEqualGUID(guid, COM.IIDIPersist)) return "IIDIPersist"; if (COM.IsEqualGUID(guid, COM.IIDIPersistFile)) return "IIDIPersistFile"; if (COM.IsEqualGUID(guid, IIDIPersistMemory)) return "IIDIPersistMemory"; if (COM.IsEqualGUID(guid, IIDIPersistPropertyBag)) return "IIDIPersistPropertyBag"; if (COM.IsEqualGUID(guid, COM.IIDIPersistStorage)) return "IIDIPersistStorage"; if (COM.IsEqualGUID(guid, COM.IIDIPersistStreamInit)) return "IIDIPersistStreamInit"; if (COM.IsEqualGUID(guid, IIDIPicture)) return "IIDIPicture"; if (COM.IsEqualGUID(guid, IIDIPictureDisp)) return "IIDIPictureDisp"; if (COM.IsEqualGUID(guid, IIDIPropertyBag)) return "IIDIPropertyBag"; if (COM.IsEqualGUID(guid, COM.IIDIPropertyNotifySink)) return "IIDIPropertyNotifySink"; if (COM.IsEqualGUID(guid, IIDIPropertyPage)) return "IIDIPropertyPage"; if (COM.IsEqualGUID(guid, IIDIPropertyPage2)) return "IIDIPropertyPage2"; if (COM.IsEqualGUID(guid, IIDIPropertyPageSite)) return "IIDIPropertyPageSite"; if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo)) return "IIDIProvideClassInfo"; if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo2)) return "IIDIProvideClassInfo2"; if (COM.IsEqualGUID(guid, IIDIPSFactoryBuffer)) return "IIDIPSFactoryBuffer"; if (COM.IsEqualGUID(guid, IIDIRootStorage)) return "IIDIRootStorage"; if (COM.IsEqualGUID(guid, IIDIROTData)) return "IIDIROTData"; if (COM.IsEqualGUID(guid, IIDIRpcChannelBuffer)) return "IIDIRpcChannelBuffer"; if (COM.IsEqualGUID(guid, IIDIRpcProxyBuffer)) return "IIDIRpcProxyBuffer"; if (COM.IsEqualGUID(guid, IIDIRpcStubBuffer)) return "IIDIRpcStubBuffer"; if (COM.IsEqualGUID(guid, IIDIRunnableObject)) return "IIDIRunnableObject"; if (COM.IsEqualGUID(guid, IIDIRunningObjectTable)) return "IIDIRunningObjectTable"; if (COM.IsEqualGUID(guid, IIDISimpleFrameSite)) return "IIDISimpleFrameSite"; if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return "IIDIServiceProvider"; if (COM.IsEqualGUID(guid, COM.IIDISpecifyPropertyPages)) return "IIDISpecifyPropertyPages"; if (COM.IsEqualGUID(guid, IIDIStdMarshalInfo)) return "IIDIStdMarshalInfo"; if (COM.IsEqualGUID(guid, IIDISupportErrorInfo)) return "IIDISupportErrorInfo"; if (COM.IsEqualGUID(guid, IIDITypeComp)) return "IIDITypeComp"; if (COM.IsEqualGUID(guid, IIDITypeLib)) return "IIDITypeLib"; if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return "IIDIUnknown"; if (COM.IsEqualGUID(guid, IIDIViewObject)) return "IIDIViewObject"; if (COM.IsEqualGUID(guid, COM.IIDIViewObject2)) return "IIDIViewObject2"; if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) return "CGID_DocHostCommandHandler"; if (COM.IsEqualGUID(guid, COM.CGID_Explorer)) return "CGID_Explorer"; if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return "IIDIAccessible2"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return "IIDIAccessibleRelation"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return "IIDIAccessibleAction"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return "IIDIAccessibleComponent"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return "IIDIAccessibleValue"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return "IIDIAccessibleText"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return "IIDIAccessibleEditableText"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return "IIDIAccessibleHyperlink"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return "IIDIAccessibleHypertext"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return "IIDIAccessibleTable"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return "IIDIAccessibleTable2"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return "IIDIAccessibleTableCell"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return "IIDIAccessibleImage"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return "IIDIAccessibleApplication"; if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return "IIDIAccessibleContext"; if (COM.IsEqualGUID(guid, IIDIdentityUnmarshal)) return "IIDIdentityUnmarshal"; if (COM.IsEqualGUID(guid, IIDInternalMSMarshaller)) return "IIDInternalMSMarshaller"; if (COM.IsEqualGUID(guid, IIDIAccIdentity)) return "IIDIAccIdentity"; if (COM.IsEqualGUID(guid, IIDIAccPropServer)) return "IIDIAccPropServer"; if (COM.IsEqualGUID(guid, IIDIAccPropServices)) return "IIDIAccPropServices"; } return guid.toString(); } static GUID IIDFromString(String lpsz) { if (DEBUG) { int length = lpsz.length(); char[] buffer = new char[length + 1]; lpsz.getChars(0, length, buffer, 0); GUID lpiid = new GUID(); if (COM.IIDFromString(buffer, lpiid) == COM.S_OK) return lpiid; } return null; } @Override public String toString() { String toString = super.toString(); if (DEBUG) { int role = getRole(); if (role == 0) role = getDefaultRole(); return toString.substring(toString.lastIndexOf('.') + 1) + "(" + getRoleString(role) + ")"; } return toString; } // END DEBUG CODE }