X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Faccessibility%2FAccessible.java;fp=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Faccessibility%2FAccessible.java;h=05f69309b2277a917762fc50be6a66c807a12049;hb=6b98970d0458754dd67f789afbd0a39e1e7ac6eb;hp=0000000000000000000000000000000000000000;hpb=56a61575ce0d27b340cb12438c8a7f303842095e;p=simantics%2Fplatform.git diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java new file mode 100644 index 000000000..05f69309b --- /dev/null +++ b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java @@ -0,0 +1,5556 @@ +/******************************************************************************* + * 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 getAccessible, 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 Accessibility snippets + * @see Sample code and further information + * + * @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 accessibleListeners; + List accessibleControlListeners; + List accessibleTextListeners; + List accessibleActionListeners; + List accessibleEditableTextListeners; + List accessibleHyperlinkListeners; + List accessibleTableListeners; + List accessibleTableCellListeners; + List accessibleTextExtendedListeners; + List accessibleValueListeners; + List accessibleAttributeListeners; + Relation relations[] = new Relation[MAX_RELATION_TYPES]; + Object[] variants; + Accessible parent; + List 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
    + *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • + *
+ * + * @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,/*<>*/1,1,2,4,2,2,/*<>*/2,4,1,6,1,4,3,3,5,5,5,1,1,3,1,3,5,1,1,/*< + * IMPORTANT: This method is not part of the public + * API for Accessible. 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. + *

+ * + * @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 AccessibleListener 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
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleControlListener + * interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom control specific information + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleTextListener + * and AccessibleTextExtendedListener interfaces. + * + * @param listener the listener that should be notified when the receiver + * is asked for custom text control specific information + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleActionListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleActionListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleEditableTextListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleEditableTextListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleHyperlinkListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleHyperlinkListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleTableListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleTableListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleTableCellListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleTableCellListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleValueListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleValueListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleAttributeListener interface. + * + * @param listener the listener that should be notified when the receiver + * is asked for AccessibleAttributeListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 ACC 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. + *

+ * This method should be called when an accessible that was created + * with the public constructor Accessible(Accessible parent) + * is no longer needed. You do not need to call this when the receiver's + * control is disposed, because all Accessible instances + * associated with a control are released when the control is disposed. + * It is also not necessary to call this for instances of Accessible + * that were retrieved with Control.getAccessible(). + *

+ * + * @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. + *

+ * IMPORTANT: This method is not part of the public + * API for Accessible. 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. + *

+ * + * @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. + *

+ * IMPORTANT: This method is not part of the public + * API for Accessible. 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. + *

+ * + * @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
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleActionListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleActionListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleEditableTextListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleEditableTextListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleHyperlinkListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleHyperlinkListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleTableListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleTableListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleTableCellListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleTableCellListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleValueListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleValueListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 AccessibleAttributeListener interface. + * + * @param listener the listener that should no longer be notified when the receiver + * is asked for AccessibleAttributeListener interface properties + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 ACC 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 ACC 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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 ACC 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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ */ + 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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 ACC.TEXT_INSERT + * or ACC.TEXT_DELETE + * @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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
  • + *
+ * + * @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 +}