/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.accessibility;

import java.net.*;
import java.util.*;
import java.util.List;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.cocoa.*;
import org.eclipse.swt.widgets.*;

/**
 * Instances of this class provide a bridge between application
 * code and assistive technology clients. Many platforms provide
 * default accessible behavior for most widgets, and this class
 * allows that default behavior to be overridden. Applications
 * can get the default Accessible object for a control by sending
 * it <code>getAccessible</code>, and then add an accessible listener
 * to override simple items like the name and help string, or they
 * can add an accessible control listener to override complex items.
 * As a rule of thumb, an application would only want to use the
 * accessible control listener to implement accessibility for a
 * custom control.
 *
 * @see Control#getAccessible
 * @see AccessibleListener
 * @see AccessibleEvent
 * @see AccessibleControlListener
 * @see AccessibleControlEvent
 * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 *
 * @since 2.0
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class Accessible {

	static boolean DEBUG = false;

	static final int MAX_RELATION_TYPES = 15;

	static NSString[] baseAttributes = {
		OS.NSAccessibilityRoleAttribute,
		OS.NSAccessibilitySubroleAttribute,
		OS.NSAccessibilityRoleDescriptionAttribute,
		OS.NSAccessibilityHelpAttribute,
		OS.NSAccessibilityFocusedAttribute,
		OS.NSAccessibilityParentAttribute,
		OS.NSAccessibilityChildrenAttribute,
		OS.NSAccessibilityPositionAttribute,
		OS.NSAccessibilitySizeAttribute,
		OS.NSAccessibilityWindowAttribute,
		OS.NSAccessibilityTopLevelUIElementAttribute,
	};

	NSMutableArray attributeNames = null;
	NSMutableArray parameterizedAttributeNames = null;
	NSMutableArray actionNames = null;

	List<AccessibleListener> accessibleListeners;
	List<AccessibleControlListener> accessibleControlListeners;
	List<AccessibleTextListener> accessibleTextListeners;
	List<AccessibleActionListener> accessibleActionListeners;
	List<AccessibleEditableTextListener> accessibleEditableTextListeners;
	List<AccessibleHyperlinkListener> accessibleHyperlinkListeners;
	List<AccessibleTableListener> accessibleTableListeners;
	List<AccessibleTableCellListener> accessibleTableCellListeners;
	List<AccessibleTextExtendedListener> accessibleTextExtendedListeners;
	List<AccessibleValueListener> accessibleValueListeners;
	List<AccessibleAttributeListener> accessibleAttributeListeners;

	Relation relations[] = new Relation[MAX_RELATION_TYPES];
	Accessible parent;
	Control control;
	int currentRole = -1;

	Map /*<Integer, SWTAccessibleDelegate>*/ childToIdMap = new HashMap();
	SWTAccessibleDelegate delegate;

	int index = -1;

	TableAccessibleDelegate tableDelegate;

	/**
	 * Constructs a new instance of this class given its parent.
	 *
	 * @param parent the Accessible parent, which must not be null
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
	 * </ul>
	 *
	 * @see #dispose
	 * @see Control#getAccessible
	 *
	 * @since 3.6
	 */
	public Accessible(Accessible parent) {
		if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
		this.parent = parent;
		this.control = parent.control;
		delegate = new SWTAccessibleDelegate(this, ACC.CHILDID_SELF);
	}

	/**
	 * @since 3.5
	 * @deprecated
	 */
	@Deprecated
	protected Accessible() {
	}

	Accessible(Control control) {
		this.control = control;
	}

	/**
	 * Invokes platform specific functionality to allocate a new accessible object.
	 * <p>
	 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
	 * API for <code>Accessible</code>. It is marked public only so that it
	 * can be shared within the packages provided by SWT. It is not
	 * available on all platforms, and should never be called from
	 * application code.
	 * </p>
	 *
	 * @param control the control to get the accessible object for
	 * @return the platform specific accessible object
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public static Accessible internal_new_Accessible(Control control) {
		return new Accessible(control);
	}

	id accessibleHandle(Accessible accessible) {
		if (accessible.delegate != null) return accessible.delegate;
		if (accessible.control != null) {
			NSView view = accessible.control.view;
			long /*int*/ handle = OS.objc_msgSend(view.id, OS.sel_accessibleHandle);
			return new id(handle);
		}
		return null;
	}

	/**
	 * Adds the listener to the collection of listeners who will
	 * be notified when an accessible client asks for certain strings,
	 * such as name, description, help, or keyboard shortcut. The
	 * listener is notified by sending it one of the messages defined
	 * in the <code>AccessibleListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for a name, description, help, or keyboard shortcut string
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleListener
	 * @see #removeAccessibleListener
	 */
	public void addAccessibleListener(AccessibleListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleListeners == null) accessibleListeners = new ArrayList<>();
		accessibleListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners who will
	 * be notified when an accessible client asks for custom control
	 * specific information. The listener is notified by sending it
	 * one of the messages defined in the <code>AccessibleControlListener</code>
	 * interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for custom control specific information
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleControlListener
	 * @see #removeAccessibleControlListener
	 */
	public void addAccessibleControlListener(AccessibleControlListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleControlListeners == null) accessibleControlListeners = new ArrayList<>();
		accessibleControlListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners who will
	 * be notified when an accessible client asks for custom text control
	 * specific information. The listener is notified by sending it
	 * one of the messages defined in the <code>AccessibleTextListener</code>
	 * and <code>AccessibleTextExtendedListener</code> interfaces.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for custom text control specific information
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTextListener
	 * @see AccessibleTextExtendedListener
	 * @see #removeAccessibleTextListener
	 *
	 * @since 3.0
	 */
	public void addAccessibleTextListener (AccessibleTextListener listener) {
		checkWidget ();
		if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
		if (listener instanceof AccessibleTextExtendedListener) {
			if (accessibleTextExtendedListeners == null) accessibleTextExtendedListeners = new ArrayList<>();
			accessibleTextExtendedListeners.add ((AccessibleTextExtendedListener) listener);
		} else {
			if (accessibleTextListeners == null) accessibleTextListeners = new ArrayList<>();
			accessibleTextListeners.add (listener);
		}
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleActionListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleActionListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleActionListener
	 * @see #removeAccessibleActionListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleActionListener(AccessibleActionListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleActionListeners == null) accessibleActionListeners = new ArrayList<>();
		accessibleActionListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleEditableTextListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleEditableTextListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleEditableTextListener
	 * @see #removeAccessibleEditableTextListener
	 *
	 * @since 3.7
	 */
	public void addAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
	    checkWidget();
	    if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleEditableTextListeners == null) accessibleEditableTextListeners = new ArrayList<>();
	    accessibleEditableTextListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleHyperlinkListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleHyperlinkListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleHyperlinkListener
	 * @see #removeAccessibleHyperlinkListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleHyperlinkListeners == null) accessibleHyperlinkListeners = new ArrayList<>();
		accessibleHyperlinkListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleTableListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleTableListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTableListener
	 * @see #removeAccessibleTableListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleTableListener(AccessibleTableListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleTableListeners == null) accessibleTableListeners = new ArrayList<>();
		accessibleTableListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleTableCellListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleTableCellListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTableCellListener
	 * @see #removeAccessibleTableCellListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleTableCellListener(AccessibleTableCellListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleTableCellListeners == null) accessibleTableCellListeners = new ArrayList<>();
		accessibleTableCellListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleValueListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleValueListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleValueListener
	 * @see #removeAccessibleValueListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleValueListener(AccessibleValueListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleValueListeners == null) accessibleValueListeners = new ArrayList<>();
		accessibleValueListeners.add(listener);
	}

	/**
	 * Adds the listener to the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleAttributeListener</code> interface.
	 *
	 * @param listener the listener that should be notified when the receiver
	 * is asked for <code>AccessibleAttributeListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleAttributeListener
	 * @see #removeAccessibleAttributeListener
	 *
	 * @since 3.6
	 */
	public void addAccessibleAttributeListener(AccessibleAttributeListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleAttributeListeners == null) accessibleAttributeListeners = new ArrayList<>();
		accessibleAttributeListeners.add(listener);
	}

	void addCGColor(double /*float*/ [] comps, NSMutableAttributedString inAttribString, NSString inAttribute, NSRange inRange) {
		long /*int*/ cgColorSpace = OS.CGColorSpaceCreateDeviceRGB();
		long /*int*/ cgColor = OS.CGColorCreate(cgColorSpace, comps);
		OS.CGColorSpaceRelease(cgColorSpace);
		inAttribString.addAttribute(inAttribute, new id(cgColor), inRange);
	    OS.CGColorRelease(cgColor);
	}

	/**
	 * Adds a relation with the specified type and target
	 * to the receiver's set of relations.
	 *
	 * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
	 * @param target the accessible that is the target for this relation
	 *
	 * @since 3.6
	 */
	public void addRelation(int type, Accessible target) {
		checkWidget();
		if (relations[type] == null) {
			relations[type] = new Relation(this, type);
		}
		relations[type].addTarget(target);
	}

	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();
	}

	void checkRole(int role) {
		// A lightweight control can change its role at any time, so track
		// the current role for the control.  If it changes, reset the attribute list.
		if (role != currentRole) {
			currentRole = role;

			if (attributeNames != null) {
				attributeNames.release();
				attributeNames = null;
			}

			if (parameterizedAttributeNames != null) {
				parameterizedAttributeNames.release();
				parameterizedAttributeNames = null;
			}

			if (actionNames != null) {
				actionNames.release();
				actionNames = null;
			}
		}
	}

	void createTableDelegate() {
		if (tableDelegate == null) {
			tableDelegate = new TableAccessibleDelegate(this);
		}
	}

	id getColumnIndexRangeAttribute(int childID) {
		AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
		for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
			AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
			listener.getColumnIndex(event);
			listener.getColumnSpan(event);
		}
		NSRange range = new NSRange();
		range.location = event.index;
		range.length = event.count;
		return NSValue.valueWithRange(range);
	}

	id getRowIndexRangeAttribute(int childID) {
		AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
		for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
			AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
			listener.getRowIndex(event);
			listener.getRowSpan(event);
		}
		NSRange range = new NSRange();
		range.location = event.index;
		range.length = event.count;
		return NSValue.valueWithRange(range);
	}

	id getSelectedAttribute(int childID) {
		if (accessibleTableListenersSize() > 0) {
			AccessibleTableEvent event = new AccessibleTableEvent(this);
			event.row = index;
			for (int i = 0; i < accessibleTableListenersSize(); i++) {
				AccessibleTableListener listener = accessibleTableListeners.get(i);
				if (currentRole == ACC.ROLE_ROW)
					listener.isRowSelected(event);
				else
					listener.isColumnSelected(event);
			}
			return NSNumber.numberWithBool(event.isSelected);
		}

		return NSNumber.numberWithBool(false);
	}

	id getIndexAttribute(int childID) {
		return NSNumber.numberWithInt(index);
	}

	id getHeaderAttribute(int childID) {
		id returnValue = null;
		AccessibleTableEvent tableEvent = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getColumnHeader(tableEvent);
		}
		if (tableEvent.accessible != null) returnValue = tableEvent.accessible.delegate;

		return returnValue;
	}

	id getVisibleColumnsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;
		id returnValue = null;
		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getVisibleColumns(event);
		}
		if (event.accessibles != null) {
			NSMutableArray array = NSMutableArray.arrayWithCapacity(event.accessibles.length);
			Accessible[] accessibles = event.accessibles;
			for (int i = 0; i < accessibles.length; i++) {
				Accessible acc = accessibles[i];
				array.addObject(acc.delegate);
			}
			returnValue = array;
		}
		return returnValue == null ? NSArray.array() : returnValue;
	}

	id getVisibleRowsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;
		id returnValue = null;
		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getVisibleRows(event);
		}
		if (event.accessibles != null) {
			NSMutableArray array = NSMutableArray.arrayWithCapacity(event.accessibles.length);
			Accessible[] accessibles = event.accessibles;
			for (int i = 0; i < accessibles.length; i++) {
				Accessible acc = accessibles[i];
				array.addObject(acc.delegate);
			}
			returnValue = array;
		}
		return returnValue == null ? NSArray.array() : returnValue;
	}

	id getSelectedRowsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;
		id returnValue = null;
		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getSelectedRows(event);
		}
		if (event.selected != null) {
			int[] selected = event.selected;
			NSMutableArray array = NSMutableArray.arrayWithCapacity(selected.length);
			for (int i = 0; i < selected.length; i++) {
				event.row = selected[i];
				for (int j = 0; j < accessibleTableListenersSize(); j++) {
					AccessibleTableListener listener = accessibleTableListeners.get(j);
					listener.getRow(event);
				}
				if (event.accessible != null) array.addObject(event.accessible.delegate);
			}
			returnValue = array;
		}
		return returnValue == null ? NSArray.array() : returnValue;
	}


	int getRowCount() {
		AccessibleTableEvent event = new AccessibleTableEvent(this);

		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getRowCount(event);
		}

		return event.count;
	}

	id getRowsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;

		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getRowCount(event);
			listener.getRows(event);
		}

		if (event.accessibles == null) event.accessibles = new Accessible[0];

		if (event.count != event.accessibles.length) {
			createTableDelegate();

			// Rerun the row query now that our accessible is in place.
			for (int i = 0; i < accessibleTableListenersSize(); i++) {
				AccessibleTableListener listener = accessibleTableListeners.get(i);
				listener.getRowCount(event);
				listener.getRows(event);
			}
		}

		NSMutableArray array = NSMutableArray.arrayWithCapacity(event.accessibles.length);
		Object[] rows = event.accessibles;
		for (int i = 0; i < rows.length; i++) {
			Accessible acc = (Accessible) rows[i];
			acc.index = i;
			array.addObject(acc.delegate);
		}
		return array;
	}

	id getSelectedColumnsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;

		id returnValue = null;
		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getSelectedColumns(event);
		}
		if (event.selected != null) {
			int[] selected = event.selected;
			NSMutableArray array = NSMutableArray.arrayWithCapacity(selected.length);
			for (int i = 0; i < selected.length; i++) {
				event.column = selected[i];
				for (int j = 0; j < accessibleTableListenersSize(); j++) {
					AccessibleTableListener listener = accessibleTableListeners.get(j);
					listener.getColumn(event);
				}
				if (event.accessible != null) array.addObject(event.accessible.delegate);
			}
			returnValue = array;
		}
		return returnValue == null ? NSArray.array() : returnValue;
	}

	int getColumnCount() {
		AccessibleTableEvent event = new AccessibleTableEvent(this);

		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getColumnCount(event);
		}

		return event.count;
	}

	id getColumnsAttribute(int childID) {
		if (accessibleTableListenersSize() == 0) return null;

		AccessibleTableEvent event = new AccessibleTableEvent(this);
		for (int i = 0; i < accessibleTableListenersSize(); i++) {
			AccessibleTableListener listener = accessibleTableListeners.get(i);
			listener.getColumnCount(event);
			listener.getColumns(event);
		}

		if (event.accessibles == null) event.accessibles = new Accessible[0];

		if (event.count != event.accessibles.length) {
			createTableDelegate();

			// Rerun the Column query, now that our adapter is in place.
			for (int i = 0; i < accessibleTableListenersSize(); i++) {
				AccessibleTableListener listener = accessibleTableListeners.get(i);
				listener.getColumnCount(event);
				listener.getColumns(event);
			}
		}

		NSMutableArray array = NSMutableArray.arrayWithCapacity(event.accessibles.length);
		Accessible[] accessibles = event.accessibles;
		for (int i = 0; i < accessibles.length; i++) {
			Accessible acc = accessibles[i];
			acc.index = i;
			array.addObject(acc.delegate);
		}
		return array;
	}

	/**
	 * Gets the human-readable description of an action.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public id internal_accessibilityActionDescription(NSString action, int childID) {
		NSString returnValue = NSString.string();
		String actionName = action.getString();
		if (accessibleActionListenersSize() > 0) {
			AccessibleActionEvent event = new AccessibleActionEvent(this);
			for (int i = 0; i < accessibleActionListenersSize(); i++) {
				AccessibleActionListener listener = accessibleActionListeners.get(i);
				listener.getActionCount(event);
			}
			int index = -1;
			for (int i = 0; i < event.count; i++) {
				event.index = i;
				for (int j = 0; j < accessibleActionListenersSize(); j++) {
					AccessibleActionListener listener = accessibleActionListeners.get(j);
					listener.getName(event);
				}
				if (actionName.equals(event.result)) {
					index = i;
					break;
				}
			}
			if (index != -1) {
				event.index = index;
				event.result = null;
				for (int i = 0; i < accessibleActionListenersSize(); i++) {
					AccessibleActionListener listener = accessibleActionListeners.get(i);
					listener.getDescription(event);
				}
				if (event.result != null) returnValue = NSString.stringWith(event.result);
			}
		}
		return returnValue;
	}

	/**
	 * Gets the array of action names that this object can perform.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public NSArray internal_accessibilityActionNames(int childID) {
		if (accessibleActionListenersSize() > 0) {
			AccessibleActionEvent event = new AccessibleActionEvent(this);
			for (int i = 0; i < accessibleActionListenersSize(); i++) {
				AccessibleActionListener listener = accessibleActionListeners.get(i);
				listener.getActionCount(event);
			}
			NSMutableArray array = NSMutableArray.arrayWithCapacity(event.count);
			for (int i = 0; i < event.count; i++) {
				event.index = i;
				for (int j = 0; j < accessibleActionListenersSize(); j++) {
					AccessibleActionListener listener = accessibleActionListeners.get(j);
					listener.getName(event);
				}
				array.addObject(NSString.stringWith(event.result));
			}
			return array;
		} else {
			// The supported action list depends on the role played by the control.
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.detail = -1;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getRole(event);
			}

			// No accessible listener is overriding the role of the control, so let Cocoa return the default set for the control.
			if (event.detail == -1) {
				return null;
			}

			checkRole(event.detail);

			if ((childID == ACC.CHILDID_SELF) && (actionNames != null)) {
				return retainedAutoreleased(actionNames);
			}

			NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(5);

			switch (event.detail) {
				case ACC.ROLE_PUSHBUTTON:
				case ACC.ROLE_RADIOBUTTON:
				case ACC.ROLE_CHECKBUTTON:
				case ACC.ROLE_TABITEM:
				case ACC.ROLE_LINK:
				case ACC.ROLE_CHECKMENUITEM:
				case ACC.ROLE_RADIOMENUITEM:
				case ACC.ROLE_SPLITBUTTON:
					returnValue.addObject(OS.NSAccessibilityPressAction);
					break;
				case ACC.ROLE_COMBOBOX:
					returnValue.addObject(OS.NSAccessibilityConfirmAction);
					break;
				case ACC.ROLE_WINDOW:
				case ACC.ROLE_DIALOG:
//					TODO
//					returnValue.addObject(OS.NSAccessibilityRaiseAction);
					break;
			}


			if (childID == ACC.CHILDID_SELF) {
				actionNames = returnValue;
				actionNames.retain();
				return retainedAutoreleased(actionNames);
			} else {
				// Caller must retain if they want to hold on to it.
				return returnValue;
			}
		}
	}

	/**
	 * Checks to see if the specified attribute can be set by a screen reader or other
	 * assistive service.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public boolean internal_accessibilityIsAttributeSettable(NSString attribute, int childID) {
		if (accessibleTextExtendedListenersSize() > 0) {
			if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangeAttribute)) return true;
			if (attribute.isEqualToString(OS.NSAccessibilityVisibleCharacterRangeAttribute)) return true;
		}
		if (accessibleEditableTextListenersSize() > 0) {
			if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextAttribute)) return true;
		}
		if (accessibleValueListenersSize() > 0) {
			if (attribute.isEqualToString(OS.NSAccessibilityValueAttribute)) return true;
		}
		return false;
	}

	/**
	 * Gets the array of attributes this object supports.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public NSArray internal_accessibilityAttributeNames(int childID) {
		// The supported attribute set depends on the role played by the control.
		// We may need to add or remove from the base set as needed.
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}

		// No accessible listener is overriding the role of the control, so let Cocoa
		// return the default set for the control.
		if (event.detail == -1)
			return null;

		checkRole(event.detail);

		// If the attributes haven't changed return the cached list.
		if (attributeNames != null) return retainedAutoreleased(attributeNames);

		// Set up the base set of attributes.
		NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(baseAttributes.length);

		for (int i = 0; i < baseAttributes.length; i++) {
			returnValue.addObject(baseAttributes[i]);
		}

		switch(event.detail) {
			case ACC.ROLE_CLIENT_AREA:
				break;
			case ACC.ROLE_WINDOW:
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
//				TODO
//				returnValue.addObject(OS.NSAccessibilityMainAttribute);
//				returnValue.addObject(OS.NSAccessibilityMinimizedAttribute);
				break;
			case ACC.ROLE_MENUBAR:
				returnValue.addObject(OS.NSAccessibilitySelectedChildrenAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleChildrenAttribute);
				break;
			case ACC.ROLE_MENU:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedChildrenAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleChildrenAttribute);
				break;
			case ACC.ROLE_MENUITEM:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				break;
			case ACC.ROLE_SEPARATOR:
				returnValue.addObject(OS.NSAccessibilityMaxValueAttribute);
				returnValue.addObject(OS.NSAccessibilityMinValueAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				//TODO
//				returnValue.addObject(OS.NSAccessibilityOrientationAttribute);
//				returnValue.addObject(OS.NSAccessibilityPreviousContentsAttribute);
//				returnValue.addObject(OS.NSAccessibilityNextContentsAttribute);
				break;
			case ACC.ROLE_TOOLTIP:
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
				break;
			case ACC.ROLE_SCROLLBAR:
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				//TODO
//				returnValue.addObject(OS.NSAccessibilityOrientationAttribute);
				break;
			case ACC.ROLE_DIALOG:
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
//				TODO
//				returnValue.addObject(OS.NSAccessibilityMainAttribute);
//				returnValue.addObject(OS.NSAccessibilityMinimizedAttribute);
				break;
			case ACC.ROLE_LABEL:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_PUSHBUTTON:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
				break;
			case ACC.ROLE_CHECKBUTTON:
			case ACC.ROLE_RADIOBUTTON:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
				break;
			case ACC.ROLE_SPLITBUTTON:
				break;
			case ACC.ROLE_COMBOBOX:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityExpandedAttribute);
				returnValue.addObject(OS.NSAccessibilityNumberOfCharactersAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedTextAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedTextRangeAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleCharacterRangeAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_TEXT:
			case ACC.ROLE_PARAGRAPH:
			case ACC.ROLE_HEADING:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityNumberOfCharactersAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedTextAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedTextRangeAttribute);
				returnValue.addObject(OS.NSAccessibilityInsertionPointLineNumberAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedTextRangesAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleCharacterRangeAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_TOOLBAR:
				break;
			case ACC.ROLE_LIST:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityRowsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityHeaderAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleChildrenAttribute);
				break;
			case ACC.ROLE_LISTITEM:
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_TABLE:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityRowsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityHeaderAttribute);
				break;
			case ACC.ROLE_TABLECELL:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_TREE:
				returnValue.addObject(OS.NSAccessibilityColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityRowsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityHeaderAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleColumnsAttribute);
				break;
			case ACC.ROLE_TREEITEM:
				returnValue.addObject(OS.NSAccessibilityColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedColumnsAttribute);
				returnValue.addObject(OS.NSAccessibilityRowsAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityHeaderAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleColumnsAttribute);
			case ACC.ROLE_TABFOLDER:
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				returnValue.addObject(OS.NSAccessibilityContentsAttribute);
				returnValue.addObject(OS.NSAccessibilityTabsAttribute);
				break;
			case ACC.ROLE_TABITEM:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
				break;
			case ACC.ROLE_PROGRESSBAR:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityMaxValueAttribute);
				returnValue.addObject(OS.NSAccessibilityMinValueAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				break;
			case ACC.ROLE_SLIDER:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityMaxValueAttribute);
				returnValue.addObject(OS.NSAccessibilityMinValueAttribute);
				returnValue.addObject(OS.NSAccessibilityValueAttribute);
				//TODO
//				returnValue.addObject(OS.NSAccessibilityOrientationAttribute);
//				increment
//				decrement
				break;
			case ACC.ROLE_LINK:
				//TODO
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
//				returnValue.addObject(OS.NSAccessibilityURLAttribute);
//				visited
				break;
			case ACC.ROLE_ALERT:
				break;
			case ACC.ROLE_ANIMATION:
				break;
			case ACC.ROLE_CANVAS:
				break;
			case ACC.ROLE_COLUMN:
				returnValue.removeObject(OS.NSAccessibilityChildrenAttribute);
				returnValue.removeObject(OS.NSAccessibilityFocusedAttribute);
				returnValue.addObject(OS.NSAccessibilityIndexAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedAttribute);
				returnValue.addObject(OS.NSAccessibilityRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityVisibleRowsAttribute);
				returnValue.addObject(OS.NSAccessibilityHeaderAttribute);
				break;
			case ACC.ROLE_DOCUMENT:
				break;
			case ACC.ROLE_GRAPHIC:
				returnValue.addObject(OS.NSAccessibilityEnabledAttribute);
				returnValue.addObject(OS.NSAccessibilityTitleAttribute);
				returnValue.addObject(OS.NSAccessibilityDescriptionAttribute);
				break;
			case ACC.ROLE_GROUP:
				break;
			case ACC.ROLE_ROW:
				returnValue.addObject(OS.NSAccessibilityVisibleChildrenAttribute);
				returnValue.addObject(OS.NSAccessibilityIndexAttribute);
				returnValue.addObject(OS.NSAccessibilitySelectedAttribute);
				break;
			case ACC.ROLE_SPINBUTTON:
				break;
			case ACC.ROLE_STATUSBAR:
				break;
			case ACC.ROLE_CHECKMENUITEM:
				break;
			case ACC.ROLE_RADIOMENUITEM:
				break;
			case ACC.ROLE_CLOCK:
				break;
			case ACC.ROLE_DATETIME:
				break;
			case ACC.ROLE_CALENDAR:
				break;
			case ACC.ROLE_FOOTER:
				break;
			case ACC.ROLE_HEADER:
				break;
			case ACC.ROLE_FORM:
				break;
			case ACC.ROLE_PAGE:
				break;
			case ACC.ROLE_SECTION:
				break;
		}


		/*
		 * Only report back sub-roles when the SWT role maps to a sub-role.
		 */
		if (event.detail != -1) {
			String osRole = roleToOs(event.detail);
			if (osRole.indexOf(':') == -1)
				returnValue.removeObject(OS.NSAccessibilitySubroleAttribute);
		}

		/*
		 * Children never return their own children, so remove that attribute.
		 */
		if (childID != ACC.CHILDID_SELF) {
			returnValue.removeObject(OS.NSAccessibilityChildrenAttribute);
		}

		if (childID == ACC.CHILDID_SELF) {
			attributeNames = returnValue;
			attributeNames.retain();
			return retainedAutoreleased(attributeNames);
		} else {
			// Caller must retain if necessary.
			return returnValue;
		}
	}

	/**
	 * Returns the value for the specified attribute. Return type depends on the attribute
	 * being queried; see the implementations of the accessor methods for details.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public id internal_accessibilityAttributeValue(NSString attribute, int childID) {
		if (attribute.isEqualToString(OS.NSAccessibilityRoleAttribute)) return getRoleAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySubroleAttribute)) return getSubroleAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityRoleDescriptionAttribute)) return getRoleDescriptionAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityExpandedAttribute)) return getExpandedAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityHelpAttribute)) return getHelpAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityTitleAttribute)) return getTitleAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityValueAttribute)) return getValueAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityMaxValueAttribute)) return getMaxValueAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityMinValueAttribute)) return getMinValueAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityEnabledAttribute)) return getEnabledAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityFocusedAttribute)) return getFocusedAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityParentAttribute)) return getParentAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityChildrenAttribute)) return getChildrenAttribute(childID, false);
		if (attribute.isEqualToString(OS.NSAccessibilityVisibleChildrenAttribute)) return getChildrenAttribute(childID, true);
		if (attribute.isEqualToString(OS.NSAccessibilityContentsAttribute)) return getChildrenAttribute(childID, false);
		// FIXME:  There's no specific API just for tabs, which won't include the buttons (if any.)
		if (attribute.isEqualToString(OS.NSAccessibilityTabsAttribute)) return getTabsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityWindowAttribute)) return getWindowAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityTopLevelUIElementAttribute)) return getTopLevelUIElementAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityPositionAttribute)) return getPositionAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySizeAttribute)) return getSizeAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityDescriptionAttribute)) return getDescriptionAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityNumberOfCharactersAttribute)) return getNumberOfCharactersAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextAttribute)) return getSelectedTextAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangeAttribute)) return getSelectedTextRangeAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityInsertionPointLineNumberAttribute)) return getInsertionPointLineNumberAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangesAttribute)) return getSelectedTextRangesAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityVisibleCharacterRangeAttribute)) return getVisibleCharacterRangeAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityServesAsTitleForUIElementsAttribute)) return getServesAsTitleForUIElementsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityTitleUIElementAttribute)) return getTitleUIElementAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityColumnsAttribute)) return getColumnsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedColumnsAttribute)) return getSelectedColumnsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityRowsAttribute)) return getRowsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedRowsAttribute)) return getSelectedRowsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityVisibleRowsAttribute)) return getVisibleRowsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityVisibleColumnsAttribute)) return getVisibleColumnsAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityHeaderAttribute)) return getHeaderAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilityIndexAttribute)) return getIndexAttribute(childID);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedAttribute)) return getSelectedAttribute(childID);
		if (OS.VERSION >= 0x1060 && attribute.isEqualToString(OS.NSAccessibilityRowIndexRangeAttribute)) return getRowIndexRangeAttribute(childID);
		if (OS.VERSION >= 0x1060 && attribute.isEqualToString(OS.NSAccessibilityColumnIndexRangeAttribute)) return getColumnIndexRangeAttribute(childID);

		// If this object don't know how to get the value it's up to the control itself to return an attribute value.
		return null;
	}

	/**
	 * Returns the value of the specified attribute, using the supplied parameter. Return
	 * and parameter types vary depending on the attribute being queried.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public id internal_accessibilityAttributeValue_forParameter(NSString attribute, id parameter, int childID) {
		if (attribute.isEqualToString(OS.NSAccessibilityStringForRangeParameterizedAttribute)) return getStringForRangeParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityRangeForLineParameterizedAttribute)) return getRangeForLineParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityRangeForIndexParameterizedAttribute)) return getRangeForIndexParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityLineForIndexParameterizedAttribute)) return getLineForIndexParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityBoundsForRangeParameterizedAttribute)) return getBoundsForRangeParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityRangeForPositionParameterizedAttribute)) return getRangeForPositionParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityAttributedStringForRangeParameterizedAttribute)) return getAttributedStringForRangeParameterizedAttribute(parameter, childID);
		if (attribute.isEqualToString(OS.NSAccessibilityStyleRangeForIndexParameterizedAttribute)) return getStyleRangeForIndexAttribute(parameter, childID);
		if (OS.VERSION >= 0x1060 && attribute.isEqualToString(OS.NSAccessibilityCellForColumnAndRowParameterizedAttribute)) return getCellForColumnAndRowParameter(parameter, childID);
		return null;
	}

	/**
	 * Returns the UI Element that has the focus. You can assume that the search
	 * for the focus has already been narrowed down to the receiver.
	 * Override this method to do a deeper search with a UIElement -
	 * e.g. a NSMatrix would determine if one of its cells has the focus.
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public id internal_accessibilityFocusedUIElement(int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = ACC.CHILDID_MULTIPLE; // set to invalid value, to test if the application sets it in getFocus()
		event.accessible = null;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getFocus(event);
		}

		// The listener did not respond, so let Cocoa figure it out.
		if (event.childID == ACC.CHILDID_MULTIPLE)
			return null;

		/* The application can optionally answer an accessible. */
		if (event.accessible != null) {
			return new id(OS.NSAccessibilityUnignoredAncestor(event.accessible.control.view.id));
		}

		/* Or the application can answer a valid child ID, including CHILDID_SELF and CHILDID_NONE. */
		if (event.childID == ACC.CHILDID_SELF || event.childID == ACC.CHILDID_NONE) {
			return new id(OS.NSAccessibilityUnignoredAncestor(control.view.id));
		}

		return new id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(event.childID).id));
	}

	/**
	 * Returns the deepest descendant of the UIElement hierarchy that contains the point.
	 * You can assume the point has already been determined to lie within the receiver.
	 * Override this method to do deeper hit testing within a UIElement - e.g. a NSMatrix
	 * would test its cells. The point is bottom-left relative screen coordinates.
	 *
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public id internal_accessibilityHitTest(NSPoint point, int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.x = (int) point.x;
		Monitor primaryMonitor = Display.getCurrent().getPrimaryMonitor();
		event.y = (int) (primaryMonitor.getBounds().height - point.y);

		// Set an impossible value to determine if anything responded to the event.
		event.childID = ACC.CHILDID_MULTIPLE;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getChildAtPoint(event);
		}

		// The listener did not respond, so let Cocoa figure it out.
		if (event.childID == ACC.CHILDID_MULTIPLE && event.accessible == null)
			return null;

		if (event.accessible != null) {
			return new id(OS.NSAccessibilityUnignoredAncestor(event.accessible.delegate.id));
		}

		if (event.childID == ACC.CHILDID_SELF || event.childID == ACC.CHILDID_NONE) {
			return new id(OS.NSAccessibilityUnignoredAncestor(control.view.id));
		}

		return new id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(event.childID).id));
	}

	/**
	 * Return YES if the UIElement doesn't show up to the outside world -
	 * i.e. its parent should return the UIElement's children as its own -
	 * cutting the UIElement out. E.g. NSControls are ignored when they are single-celled.
	 *
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public boolean internal_accessibilityIsIgnored(int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}

		boolean shouldIgnore = (event.detail == -1);

		if (shouldIgnore) {
			shouldIgnore = getTitleAttribute(childID) == null && getHelpAttribute(childID) == null && getDescriptionAttribute(childID) == null;
		}

		return shouldIgnore;
	}

	/**
	 * Return the array of supported attributes that take parameters.
	 *
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public NSArray internal_accessibilityParameterizedAttributeNames(int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}

		// No accessible listener is overriding the role of the control, so let Cocoa
		// return the default set for the control.
		if (event.detail == -1)
			return null;

		checkRole(event.detail);

		if ((childID == ACC.CHILDID_SELF) && (parameterizedAttributeNames != null)) {
			return retainedAutoreleased(parameterizedAttributeNames);
		}

		NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(4);

		switch(event.detail) {
			case ACC.ROLE_TEXT:
			case ACC.ROLE_PARAGRAPH:
			case ACC.ROLE_HEADING:
				returnValue.addObject(OS.NSAccessibilityStringForRangeParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityRangeForLineParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityRangeForIndexParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityLineForIndexParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityBoundsForRangeParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityRangeForPositionParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityAttributedStringForRangeParameterizedAttribute);
				returnValue.addObject(OS.NSAccessibilityStyleRangeForIndexParameterizedAttribute);
				break;
			case ACC.ROLE_TABLE:
				if (OS.VERSION >= 0x1060) returnValue.addObject(OS.NSAccessibilityCellForColumnAndRowParameterizedAttribute);
				break;
		}

		if (childID == ACC.CHILDID_SELF) {
			parameterizedAttributeNames = returnValue;
			parameterizedAttributeNames.retain();
			return retainedAutoreleased(parameterizedAttributeNames);
		} else {
			// Caller must retain if they want to keep it.
			return returnValue;
		}
	}

	/**
	 * Performs the specified action.
	 *
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public boolean internal_accessibilityPerformAction(NSString action, int childID) {
		String actionName = action.getString();
		if (accessibleActionListenersSize() > 0) {
			AccessibleActionEvent event = new AccessibleActionEvent(this);
			for (int i = 0; i < accessibleActionListenersSize(); i++) {
				AccessibleActionListener listener = accessibleActionListeners.get(i);
				listener.getActionCount(event);
			}
			int index = -1;
			for (int i = 0; i < event.count; i++) {
				event.index = i;
				for (int j = 0; j < accessibleActionListenersSize(); j++) {
					AccessibleActionListener listener = accessibleActionListeners.get(j);
					listener.getName(event);
				}
				if (actionName.equals(event.result)) {
					index = i;
					break;
				}
			}
			if (index != -1) {
				event.index = index;
				event.result = null;
				for (int i = 0; i < accessibleActionListenersSize(); i++) {
					AccessibleActionListener listener = accessibleActionListeners.get(i);
					listener.doAction(event);
				}
				return ACC.OK.equals(event.result);
			}
		}
		return false;
	}

	/**
	 * Set the value of the specified attribute to the given value.
	 * Unsupported attributes are ignored.
	 *
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public void internal_accessibilitySetValue_forAttribute(id value, NSString attribute, int childId) {
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangeAttribute)) setSelectedTextRangeAttribute(value, childId);
		if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextAttribute)) setSelectedTextAttribute(value, childId);
		if (attribute.isEqualToString(OS.NSAccessibilityVisibleCharacterRangeAttribute)) setVisibleCharacterRangeAttribute(value, childId);

		if (accessibleValueListenersSize() > 0) {
			AccessibleValueEvent event = new AccessibleValueEvent(this);
			NSNumber number = new NSNumber(value);
			event.value = new Double(number.doubleValue());
			for (int i = 0; i < accessibleValueListenersSize(); i++) {
				AccessibleValueListener listener = accessibleValueListeners.get(i);
				listener.setCurrentValue(event);
			}
		}
	}

	/**
	 * Disposes of the operating system resources associated with
	 * the receiver, and removes the receiver from its parent's
	 * list of children.
	 * <p>
	 * This method should be called when an accessible that was created
	 * with the public constructor <code>Accessible(Accessible parent)</code>
	 * is no longer needed. You do not need to call this when the receiver's
	 * control is disposed, because all <code>Accessible</code> instances
	 * associated with a control are released when the control is disposed.
	 * It is also not necessary to call this for instances of <code>Accessible</code>
	 * that were retrieved with <code>Control.getAccessible()</code>.
	 * </p>
	 *
	 * @since 3.6
	 */
	public void dispose () {
		if (parent == null) return;
		release(true);
		parent = null;
	}

	/**
	 * Returns the control for this Accessible object.
	 *
	 * @return the receiver's control
	 * @since 3.0
	 */
	public Control getControl() {
		return control;
	}

	/**
	 * Invokes platform specific functionality to dispose an accessible object.
	 * <p>
	 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
	 * API for <code>Accessible</code>. It is marked public only so that it
	 * can be shared within the packages provided by SWT. It is not
	 * available on all platforms, and should never be called from
	 * application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public void internal_dispose_Accessible() {
		release(true);
	}

	id getAttributedStringForRangeParameterizedAttribute(id parameter, int childID) {
		if (accessibleAttributeListenersSize() == 0) return null;

		id stringFragment = getStringForRangeParameterizedAttribute(parameter, childID);
		NSMutableAttributedString attribString = (NSMutableAttributedString)new NSMutableAttributedString().alloc();
		attribString.initWithString(new NSString(stringFragment), null);
		attribString.autorelease();

		// Parameter is an NSRange wrapped in an NSValue.
		NSValue parameterObject = new NSValue(parameter.id);
		NSRange range = parameterObject.rangeValue();

		AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);

		event.offset = (int) /*64*/ range.location;
		event.start = event.end = -1;

		NSRange attributeRange = new NSRange();

		while (event.offset < range.location + range.length) {
			for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
				AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
				listener.getTextAttributes(event);
			}

			if (event.start == -1 && event.end == -1) return stringFragment;

			// The returned attributed string must have zero-based attributes.
			attributeRange.location = event.start - range.location;
			attributeRange.length = event.end - event.start;

			// attributeRange.location can be negative if the start of the requested range falls in the middle of a style run.
			// If that happens, clamp to zero and adjust the length by the amount of adjustment.
			if (attributeRange.location < 0) {
				attributeRange.length -= -attributeRange.location;
				attributeRange.location = 0;
			}

			// Likewise, make sure the last attribute set does not run past the end of the requested range.
			if (attributeRange.location + attributeRange.length > range.length) {
				attributeRange.length = range.length - attributeRange.location;
			}

			// Reset the offset so we pick up the next set of attributes that change.
			event.offset = event.end;

			if (event.textStyle != null) {
				TextStyle ts = event.textStyle;
				if (ts.font != null) {
					NSMutableDictionary fontInfoDict = NSMutableDictionary.dictionaryWithCapacity(4);

					NSFont fontUsed = ts.font.handle;
					// Get font name and size from NSFont
					NSString fontName = fontUsed.fontName();
					fontInfoDict.setValue(fontName, OS.NSAccessibilityFontNameKey);
					NSString familyName = fontUsed.familyName();
					fontInfoDict.setValue(familyName, OS.NSAccessibilityFontFamilyKey);
					NSString displayName = fontUsed.displayName();
					fontInfoDict.setValue(displayName, OS.NSAccessibilityVisibleNameKey);
					double /*float*/ fontSize = fontUsed.pointSize();
					fontInfoDict.setValue(NSNumber.numberWithDouble(fontSize), OS.NSAccessibilityFontSizeKey);

					attribString.addAttribute(OS.NSAccessibilityFontTextAttribute, fontInfoDict, attributeRange);
				}

				if (ts.foreground != null) {
					addCGColor(ts.foreground.handle, attribString, OS.NSAccessibilityForegroundColorTextAttribute, attributeRange);
				}

				if (ts.background != null) {
					addCGColor(ts.background.handle, attribString, OS.NSAccessibilityBackgroundColorTextAttribute, attributeRange);
				}

				if (ts.underline) {
					int style = ts.underlineStyle;
					NSString attribute = OS.NSAccessibilityUnderlineTextAttribute;
					NSNumber styleObj = null;
					switch (style) {
					case SWT.UNDERLINE_SINGLE:
						styleObj = NSNumber.numberWithInt(OS.kAXUnderlineStyleSingle);
						break;
					case SWT.UNDERLINE_DOUBLE:
						styleObj = NSNumber.numberWithInt(OS.kAXUnderlineStyleDouble);
						break;
					case SWT.UNDERLINE_SQUIGGLE:
						attribute = OS.NSAccessibilityMisspelledTextAttribute;
						styleObj = NSNumber.numberWithBool(true);
						break;
					default:
						styleObj = NSNumber.numberWithInt(OS.kAXUnderlineStyleNone);
					}

					attribString.addAttribute(attribute, styleObj, attributeRange);
				}

				if (ts.underlineColor != null) {
					addCGColor(ts.underlineColor.handle, attribString, OS.NSAccessibilityUnderlineColorTextAttribute, attributeRange);
				}

				if (ts.strikeout) {
					attribString.addAttribute(OS.NSAccessibilityStrikethroughTextAttribute, NSNumber.numberWithBool(true), attributeRange);

					if (ts.strikeoutColor != null) {
						addCGColor(ts.strikeoutColor.handle, attribString, OS.NSAccessibilityStrikethroughColorTextAttribute, attributeRange);
					}
				}

				if (ts.data != null) {
					if (ts.data instanceof URL) {
						URL dataAsURL = (URL)ts.data;
						NSURL linkURL = NSURL.URLWithString(NSString.stringWith(dataAsURL.toExternalForm()));
						attribString.addAttribute(OS.NSAccessibilityLinkTextAttribute, linkURL, attributeRange);
					}
				}
			}
		}

		// Now add the alignment, justification, and indent, if available.
		AccessibleAttributeEvent docAttributes = new AccessibleAttributeEvent(this);
		docAttributes.indent = Integer.MAX_VALUE; // if unchanged no listener filled it in.
		for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
			AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
			listener.getAttributes(docAttributes);
		}

		if (docAttributes.indent != Integer.MAX_VALUE) {
			NSMutableDictionary paragraphDict = NSMutableDictionary.dictionaryWithCapacity(3);
			int osAlignment = 0;
			// FIXME: Doesn't account for right-to-left text?
			switch (docAttributes.alignment) {
			case SWT.CENTER:
				osAlignment = OS.NSCenterTextAlignment;
				break;
			case SWT.RIGHT:
				osAlignment = OS.NSRightTextAlignment;
				break;
			case SWT.LEFT:
			default:
				osAlignment = OS.NSLeftTextAlignment;
				break;
			}
			paragraphDict.setValue(NSNumber.numberWithInt(osAlignment), NSString.stringWith("AXTextAlignment"));
			range.location = 0;
			attribString.addAttribute(NSString.stringWith("AXParagraphStyle"), paragraphDict, range);
		}

		return attribString;
	}

	id getBoundsForRangeParameterizedAttribute(id parameter, int childID) {
		if (accessibleTextExtendedListenersSize() == 0) return null;

		id returnValue = null;
		NSValue parameterObject = new NSValue(parameter.id);
		NSRange range = parameterObject.rangeValue();
		NSRect rect = new NSRect();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event  = new AccessibleTextEvent(this);
			event.childID = childID;
			event.start = (int)/*64*/range.location;
			event.end = (int)/*64*/(range.location + range.length);
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getTextBounds(event);
			}
			rect.x = event.x;

			// Flip y coordinate for Cocoa.
			NSArray screens = NSScreen.screens();
			NSScreen screen = new NSScreen(screens.objectAtIndex(0));
			NSRect frame = screen.frame();
			rect.y = frame.height - event.y - event.height;

			rect.width = event.width;
			rect.height = event.height;
			returnValue = NSValue.valueWithRect(rect);
		} else {
			//FIXME???
			//how to implement with old listener
		}
		return returnValue;
	}

	id getExpandedAttribute(int childID) {
		// TODO: May need to expand the API so the combo box state can be reported.
		return NSNumber.numberWithBool(false);
	}

	id getHelpAttribute (int childID) {
		id returnValue = null;
		AccessibleEvent event = new AccessibleEvent(this);
		event.childID = childID;
		for (int i = 0; i < accessibleListenersSize(); i++) {
			AccessibleListener listener = accessibleListeners.get(i);
			listener.getHelp(event);
		}

		if (event.result != null) {
			returnValue = NSString.stringWith(event.result);
		}

		return returnValue;
	}

	id getRangeForPositionParameterizedAttribute(id parameter, int childID) {
		id returnValue = null;
		NSValue parameterObject = new NSValue(parameter.id);
		NSPoint point = parameterObject.pointValue();
		NSRange range = new NSRange();
		if (accessibleTextExtendedListenersSize() > 0) {
			NSArray screens = NSScreen.screens();
			NSScreen screen = new NSScreen(screens.objectAtIndex(0));
			NSRect frame = screen.frame();
			point.y = frame.height - point.y;
			AccessibleTextEvent event  = new AccessibleTextEvent(this);
			event.childID = childID;
			event.x = (int)point.x;
			event.y = (int)point.y;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getOffsetAtPoint(event);
			}
			range.location = event.offset;
			range.length = 1;
		} else {
			//FIXME???
			//how to implement with old listener
		}
		returnValue = NSValue.valueWithRange(range);
		return returnValue;
	}

	NSString getRoleAttribute(int childID) {
		NSString returnValue = null;
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}
		if (event.detail != -1) {
			String appRole = roleToOs (event.detail);
			int index = appRole.indexOf(':');
			if (index != -1) appRole = appRole.substring(0, index);
			returnValue = NSString.stringWith(appRole);
		}

		return returnValue;
	}

	id getSubroleAttribute (int childID) {
		id returnValue = null;
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}
		if (event.detail != -1) {
			String appRole = roleToOs (event.detail);
			int index = appRole.indexOf(':');
			if (index != -1) {
				appRole = appRole.substring(index + 1);
				returnValue = NSString.stringWith(appRole);
			}
		}
		return returnValue;
	}

	id getRoleDescriptionAttribute (int childID) {
		id returnValue = null;
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(event);
		}
		if (event.detail != -1) {
			if (event.detail == ACC.ROLE_TABITEM) {
				returnValue = new NSString(OS.NSAccessibilityRoleDescription (NSString.stringWith("AXTab").id, 0));
			} else {
				String appRole = roleToOs (event.detail);
				String appSubrole = null;
				int index = appRole.indexOf(':');
				if (index != -1) {
					appSubrole = appRole.substring(index + 1);
					appRole = appRole.substring(0, index);
				}
				NSString nsAppRole = NSString.stringWith(appRole);
				NSString nsAppSubrole = null;

				if (appSubrole != null) nsAppSubrole = NSString.stringWith(appSubrole);
				returnValue = new NSString(OS.NSAccessibilityRoleDescription (((nsAppRole != null) ? nsAppRole.id : 0), (nsAppSubrole != null) ? nsAppSubrole.id : 0));
			}
		}
		return returnValue;
	}

	id getTitleAttribute (int childID) {

		id returnValue = null;

		/*
		* Feature of the Macintosh.  The text of a Label is returned in its value,
		* not its title, so ensure that the role is not Label before asking for the title.
		*/
		AccessibleControlEvent roleEvent = new AccessibleControlEvent(this);
		roleEvent.childID = childID;
		roleEvent.detail = -1;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getRole(roleEvent);
		}
		if (roleEvent.detail != ACC.ROLE_LABEL) {
			AccessibleEvent event = new AccessibleEvent(this);
			event.childID = childID;
			event.result = null;
			for (int i = 0; i < accessibleListenersSize(); i++) {
				AccessibleListener listener = accessibleListeners.get(i);
				listener.getName(event);
			}

			if (event.result != null)
				returnValue = NSString.stringWith(event.result);
		}
		return returnValue;
	}

	id getTitleUIElementAttribute(int childID) {
		id returnValue = null;
		Relation relation = relations[ACC.RELATION_LABELLED_BY];
		if (relation != null) {
			returnValue = relation.getTitleUIElement();
		}
		return returnValue;
	}

	id getValueAttribute (int childID) {
		id returnValue = null;
		if (accessibleValueListenersSize() > 0) {
			AccessibleValueEvent event = new AccessibleValueEvent(this);
			for (int i = 0; i < accessibleValueListenersSize(); i++) {
				AccessibleValueListener listener = accessibleValueListeners.get(i);
				listener.getCurrentValue(event);
			}
			returnValue = NSNumber.numberWithDouble(event.value.doubleValue());
		} else {
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.detail = -1;
			event.result = null; //TODO: could pass the OS value to the app
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getRole(event);
				listener.getValue(event);
			}
			int role = event.detail;
			String value = event.result;

			switch (role) {
				case ACC.ROLE_RADIOBUTTON: // 1 = on, 0 = off
				case ACC.ROLE_CHECKBUTTON: // 1 = checked, 0 = unchecked, 2 = mixed
				case ACC.ROLE_SCROLLBAR: // numeric value representing the position of the scroller
				case ACC.ROLE_SLIDER: // the value associated with the position of the slider thumb
				case ACC.ROLE_PROGRESSBAR: // the value associated with the fill level of the progress bar
					if (value != null) {
						try {
							int number = Integer.parseInt(value);
							returnValue = NSNumber.numberWithBool(number == 0 ? false : true);
						} catch (NumberFormatException ex) {
							if (value.equalsIgnoreCase("true")) {
								returnValue = NSNumber.numberWithBool(true);
							} else if (value.equalsIgnoreCase("false")) {
								returnValue = NSNumber.numberWithBool(false);
							}
						}
					} else {
						returnValue = NSNumber.numberWithBool(false);
					}
					break;
				case ACC.ROLE_TABFOLDER: // the accessibility object representing the currently selected tab item
				case ACC.ROLE_TABITEM:  // 1 = selected, 0 = not selected
					AccessibleControlEvent ace = new AccessibleControlEvent(this);
					ace.childID = -4;
					for (int i = 0; i < accessibleControlListenersSize(); i++) {
						AccessibleControlListener listener = accessibleControlListeners.get(i);
						listener.getSelection(ace);
					}
					if (ace.childID >= ACC.CHILDID_SELF) {
						if (role == ACC.ROLE_TABITEM) {
					 		returnValue = NSNumber.numberWithBool(ace.childID == childID);
						} else {
							returnValue = new id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(ace.childID).id));
						}
					} else {
				 		returnValue = NSNumber.numberWithBool(false);
					}
					break;
				case ACC.ROLE_COMBOBOX: // text of the currently selected item
				case ACC.ROLE_TEXT: // text in the text field
				case ACC.ROLE_PARAGRAPH: // text in the text field
				case ACC.ROLE_HEADING: // text in the text field
					if (value != null) returnValue = NSString.stringWith(value);
					break;
				case ACC.ROLE_TABLECELL: // text in the cell
				case ACC.ROLE_LABEL: // text in the label
					/* On a Mac, the 'value' of a label is the same as the 'name' of the label. */
					AccessibleEvent e = new AccessibleEvent(this);
					e.childID = childID;
					e.result = null;
					for (int i = 0; i < accessibleListenersSize(); i++) {
						AccessibleListener listener = accessibleListeners.get(i);
						listener.getName(e);
					}
					if (e.result != null) {
						returnValue = NSString.stringWith(e.result);
					} else {
						if (value != null) returnValue = NSString.stringWith(value);
					}
					returnValue = returnValue == null ? NSString.string() : returnValue;
					break;
			}
		}
		return returnValue;
	}

	id getEnabledAttribute (int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.detail = ACC.STATE_NORMAL;
		event.childID = childID;
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getState(event);
		}
		boolean enabled = (event.detail & ACC.STATE_DISABLED) == 0;
		if (!enabled && delegate == null) enabled = control.isEnabled();
		return NSNumber.numberWithBool(enabled);
	}

	id getFocusedAttribute (int childID) {
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = ACC.CHILDID_MULTIPLE; // set to invalid value, to test if the application sets it in getFocus()
		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getFocus(event);
		}

		/* The application can optionally answer an accessible. */
		if (event.accessible != null) {
			boolean hasFocus = (event.accessible.index == childID) && (event.accessible.control == this.control);
			return NSNumber.numberWithBool(hasFocus);
		}

		/* Or the application can answer a valid child ID, including CHILDID_SELF and CHILDID_NONE. */
		if (event.childID == ACC.CHILDID_SELF) {
			return NSNumber.numberWithBool(true);
		}
		if (event.childID == ACC.CHILDID_NONE) {
			return NSNumber.numberWithBool(false);
		}
		if (event.childID != ACC.CHILDID_MULTIPLE) {
			/* Other valid childID. */
			return NSNumber.numberWithBool(event.childID == childID);
		}

		// Invalid childID at this point means the application did not implement getFocus, so
		// let the default handler return the native focus.
		return null;
	}

	id getParentAttribute (int childID) {
		id returnValue = null;
		if (childID == ACC.CHILDID_SELF) {
			if (parent != null) {
				if (parent.delegate != null) {
					returnValue = parent.delegate;
				} else {
					returnValue = new id(OS.NSAccessibilityUnignoredAncestor(accessibleHandle(parent).id));
				}
			} else {
				// Returning null here means 'let Cocoa figure it out.'
				returnValue = null;
			}
		} else {
			returnValue = new id(OS.NSAccessibilityUnignoredAncestor(accessibleHandle(this).id));
		}
		return returnValue;
	}

	id getChildrenAttribute (int childID, boolean visibleOnly) {
		id returnValue = null;
		if (childID == ACC.CHILDID_SELF) {
			// Test for a table first.
			if (currentRole == ACC.ROLE_TABLE) {
				// If the row count differs from the row elements returned,
				// we need to create our own adapter to map the cells onto
				// rows and columns.  The rows and columns attributes determine that for us.
				getRowsAttribute(childID);
				getColumnsAttribute(childID);
			}

			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.detail = -1; // set to impossible value to test if app resets
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getChildCount(event);
			}
			int childCount = event.detail;
			event.detail = (visibleOnly ? ACC.VISIBLE : 0);
			if (childCount >= 0) {
				for (int i = 0; i < accessibleControlListenersSize(); i++) {
					AccessibleControlListener listener = accessibleControlListeners.get(i);
					listener.getChildren(event);
				}
				Object[] children = event.children;
				childCount = children != null ? children.length : 0;
				NSMutableArray childArray = NSMutableArray.arrayWithCapacity(childCount);
				for (int i = 0; i < childCount; i++) {
					Object child = children[i];
					if (child instanceof Accessible) {
						Accessible accessible = (Accessible)child;
						if (accessible.delegate != null) {
							childArray.addObject(accessible.delegate);
						} else {
							childArray.addObject(accessibleHandle(accessible));
						}
					} else {
						if (child instanceof Integer) {
							id accChild = childIDToOs(((Integer)child).intValue());
							childArray.addObject(accChild);
						}
					}
				}
				returnValue = new id(OS.NSAccessibilityUnignoredChildren(childArray.id));
			}
		} else {
			// Lightweight children have no children of their own.
			// Don't return null if there are no children -- always return an empty array.
			returnValue = NSArray.array();
		}

		// Returning null here means we want the control itself to determine its children. If the accessible listener
		// implemented getChildCount/getChildren, references to those objects would have been returned above.
		return returnValue;
	}

	id getTabsAttribute (int childID) {
		id returnValue = null;
		if (childID == ACC.CHILDID_SELF) {
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.detail = -1; // set to impossible value to test if app resets
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getChildCount(event);
			}
			if (event.detail > 0) {
				for (int i = 0; i < accessibleControlListenersSize(); i++) {
					AccessibleControlListener listener = accessibleControlListeners.get(i);
					listener.getChildren(event);
				}
				Object [] appChildren = event.children;
				if (appChildren != null && appChildren.length > 0) {
					/* return an NSArray of NSAccessible objects. */
					NSMutableArray childArray = NSMutableArray.arrayWithCapacity(appChildren.length);

					for (int i = 0; i < appChildren.length; i++) {
						Object child = appChildren[i];
						if (child instanceof Integer) {
							int subChildID = ((Integer)child).intValue();
							event.childID = subChildID;
							event.detail = -1;
							for (int j = 0; j < accessibleControlListenersSize(); j++) {
								AccessibleControlListener listener = accessibleControlListeners.get(j);
								listener.getRole(event);
							}

							if (event.detail == ACC.ROLE_TABITEM) {
								id accChild = childIDToOs(((Integer)child).intValue());
								childArray.addObject(accChild);
							}
						} else {
							childArray.addObject(((Accessible)child).control.view);
						}
					}

					returnValue = new id(OS.NSAccessibilityUnignoredChildren(childArray.id));
				}
			}
		} else {
			// Lightweight children have no children of their own.
			// Don't return null if there are no children -- always return an empty array.
			returnValue = NSArray.array();
		}

		// Returning null here means we want the control itself to determine its children. If the accessible listener
		// implemented getChildCount/getChildren, references to those objects would have been returned above.
		return returnValue;
	}

	id getWindowAttribute (int childID) {
		return control.view.window();
	}

	id getTopLevelUIElementAttribute (int childID) {
		return control.view.window();
	}

	id getPositionAttribute (int childID) {
		id returnValue = null;
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.width = -1;

		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getLocation(event);
		}

		Monitor primaryMonitor = Display.getCurrent().getPrimaryMonitor();

		NSPoint osPositionAttribute = new NSPoint ();
		if (event.width != -1) {
			// The point returned is the lower-left coordinate of the widget in lower-left relative screen coordinates.
			osPositionAttribute.x = event.x;
			osPositionAttribute.y = primaryMonitor.getBounds().height - event.y - event.height;
			returnValue = NSValue.valueWithPoint(osPositionAttribute);
		} else {
			if (childID != ACC.CHILDID_SELF) {
				Point pt = null;
				Rectangle location = control.getBounds();

				if (control.getParent() != null)
					pt = control.getParent().toDisplay(location.x, location.y);
				else
					pt = ((Shell)control).toDisplay(location.x, location.y);

				osPositionAttribute.x = pt.x;
				osPositionAttribute.y = pt.y;
				returnValue = NSValue.valueWithPoint(osPositionAttribute);
			}
		}

		return returnValue;
	}

	id getSizeAttribute (int childID) {
		id returnValue = null;
		AccessibleControlEvent event = new AccessibleControlEvent(this);
		event.childID = childID;
		event.width = -1;

		for (int i = 0; i < accessibleControlListenersSize(); i++) {
			AccessibleControlListener listener = accessibleControlListeners.get(i);
			listener.getLocation(event);
		}

		NSSize controlSize = new NSSize ();
		if (event.width != -1) {
			controlSize.width = event.width;
			controlSize.height = event.height;
			returnValue = NSValue.valueWithSize(controlSize);
		} else {
			if (childID != ACC.CHILDID_SELF) {
				controlSize.width = controlSize.height = 0;
				returnValue = NSValue.valueWithSize(controlSize);
			}
		}

		return returnValue;
	}

	id getCellForColumnAndRowParameter(id parameter, int childID) {
		id returnValue = null;
		NSArray parameterObject = new NSArray(parameter.id);
		if (parameterObject.count() == 2) {
			AccessibleTableEvent event = new AccessibleTableEvent(this);
			event.column = new NSNumber(parameterObject.objectAtIndex(0)).intValue();
			event.row = new NSNumber(parameterObject.objectAtIndex(1)).intValue();
			for (int i = 0; i < accessibleTableListenersSize(); i++) {
				AccessibleTableListener listener = accessibleTableListeners.get(i);
				listener.getCell(event);
				returnValue = event.accessible.delegate;
			}
		}
		return returnValue;
	}

	id getDescriptionAttribute (int childID) {
		AccessibleEvent event = new AccessibleEvent(this);
		event.childID = childID;
		event.result = null;
		id returnValue = null;
		for (int i = 0; i < accessibleListenersSize(); i++) {
			AccessibleListener listener = accessibleListeners.get(i);
			listener.getDescription(event);
		}

		returnValue = (event.result != null ? NSString.stringWith(event.result) : null);

		// If no description was provided, and this is a composite or canvas, return a blank string
		// -- otherwise, let the Cocoa control handle it.
		if (returnValue == null) {
			if (control instanceof Composite) returnValue = NSString.string();
		}

		return returnValue;
	}

	id getInsertionPointLineNumberAttribute (int childID) {
		id returnValue = null;
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event  = new AccessibleTextEvent(this);
			event.childID = childID;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getCaretOffset(event);
			}
			int caretOffset = event.offset;
			event.start = caretOffset;
			event.end = caretOffset;
			event.count = Integer.MIN_VALUE;
			event.type = ACC.TEXT_BOUNDARY_LINE;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getText(event);
			}
			returnValue = NSNumber.numberWithInt(Math.max(0, -event.count));
		} else {
			AccessibleControlEvent controlEvent = new AccessibleControlEvent(this);
			controlEvent.childID = childID;
			controlEvent.result = null;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getValue(controlEvent);
			}
			AccessibleTextEvent textEvent = new AccessibleTextEvent(this);
			textEvent.childID = childID;
			textEvent.offset = -1;
			for (int i = 0; i < accessibleTextListenersSize(); i++) {
				AccessibleTextListener listener = accessibleTextListeners.get(i);
				listener.getCaretOffset(textEvent);
			}
			if (controlEvent.result != null && textEvent.offset != -1) {
				int lineNumber = lineNumberForOffset (controlEvent.result, textEvent.offset);
				returnValue = NSNumber.numberWithInt(lineNumber);
			}
		}
		return returnValue;
	}

	id getLineForIndexParameterizedAttribute (id parameter, int childID) {
		id returnValue = null;
		NSNumber charNumberObj = new NSNumber(parameter.id);
		int charNumber = charNumberObj.intValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.start = charNumber;
			event.end = charNumber;
			event.count = Integer.MIN_VALUE;
			event.type = ACC.TEXT_BOUNDARY_LINE;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getText(event);
			}
			returnValue = NSNumber.numberWithInt(Math.max(0, -event.count));
		} else {
			AccessibleControlEvent controlEvent = new AccessibleControlEvent(this);
			controlEvent.childID = childID;
			controlEvent.result = null;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getValue(controlEvent);
			}
			String text = controlEvent.result;
			if (text != null) returnValue = NSNumber.numberWithInt(lineNumberForOffset(text, charNumber));
		}
		return returnValue;
	}

	id getMaxValueAttribute(int childID) {
		id returnValue = null;
		if (accessibleValueListenersSize() > 0) {
			AccessibleValueEvent event = new AccessibleValueEvent(this);
			for (int i = 0; i < accessibleValueListenersSize(); i++) {
				AccessibleValueListener listener = accessibleValueListeners.get(i);
				listener.getMaximumValue(event);
			}
			returnValue = NSNumber.numberWithDouble(event.value.doubleValue());
		}
		return returnValue;
	}

	id getMinValueAttribute(int childID) {
		id returnValue = null;
		if (accessibleValueListenersSize() > 0) {
			AccessibleValueEvent event = new AccessibleValueEvent(this);
			for (int i = 0; i < accessibleValueListenersSize(); i++) {
				AccessibleValueListener listener = accessibleValueListeners.get(i);
				listener.getMinimumValue(event);
			}
			returnValue = NSNumber.numberWithDouble(event.value.doubleValue());
		}
		return returnValue;
	}

	id getNumberOfCharactersAttribute (int childID) {
		id returnValue = null;
		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;
			returnValue = NSNumber.numberWithInt(event.count);
		}
		return returnValue;
	}

	id getRangeForLineParameterizedAttribute (id parameter, int childID) {
		id returnValue = null;
		// The parameter is an NSNumber with the line number.
		NSNumber lineNumberObj = new NSNumber(parameter.id);
		int lineNumber = lineNumberObj.intValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.start = event.end = 0;
			event.count = lineNumber;
			event.type = ACC.TEXT_BOUNDARY_LINE;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getText(event);
			}
			NSRange range = new NSRange();
			range.location = event.start;
			range.length = event.end - event.start;
			returnValue = NSValue.valueWithRange(range);
		} else if (accessibleControlListenersSize() > 0){
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.result = null;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getValue(event);
			}
			if (event.result != null) {
				NSRange range = rangeForLineNumber (lineNumber, event.result);
				if (range.location != -1) {
					returnValue = NSValue.valueWithRange(range);
				}
			}
		}
		return returnValue;
	}

	id getRangeForIndexParameterizedAttribute (id parameter, int childID) {
		id returnValue = null;
		// The parameter is an NSNumber with the character number.
		NSNumber charNumberObj = new NSNumber(parameter.id);
		int charNumber = charNumberObj.intValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.start = event.end = 0;
			event.count = charNumber;
			event.type = ACC.TEXT_BOUNDARY_CHAR;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getText(event);
			}
			NSRange range = new NSRange();
			range.location = event.start;
			range.length = event.end - event.start;
			returnValue = NSValue.valueWithRange(range);
		} else if (accessibleControlListenersSize() > 0) {
//			AccessibleControlEvent event = new AccessibleControlEvent(this);
//			event.childID = childID;
//			event.result = null;
//			for (int i = 0; i < accessibleControlListenersSize(); i++) {
//				AccessibleControlListener listener = accessibleControlListeners.get(i);
//				listener.getValue(event);
//			}
//			if (event.result != null) {
//				NSRange range = rangeForLineNumber (lineNumber, event.result);
//				if (range.location != -1) {
//					returnValue = NSValue.valueWithRange(range);
//				}
//			}
		}
		return returnValue;
	}

	id getSelectedTextAttribute (int childID) {
		id returnValue = NSString.string();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.index = 0;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getSelection(event);
			}
			int start = event.start;
			int end = event.end;
			if (start != end) {
				event.type = ACC.TEXT_BOUNDARY_ALL;
				for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
					AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
					listener.getText(event);
				}
			}
			String text = event.result;
			if (text != null) returnValue = NSString.stringWith(text);
		} else if (accessibleTextListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.offset = -1;
			event.length = -1;
			for (int i = 0; i < accessibleTextListenersSize(); i++) {
				AccessibleTextListener listener = accessibleTextListeners.get(i);
				listener.getSelectionRange(event);
			}
			int offset = event.offset;
			int length = event.length;
			if (offset != -1 && length != -1 && length != 0) {  // TODO: do we need the && length != 0 ?
				AccessibleControlEvent event2 = new AccessibleControlEvent(this);
				event2.childID = event.childID;
				event2.result = null;
				for (int i = 0; i < accessibleControlListenersSize(); i++) {
					AccessibleControlListener listener = accessibleControlListeners.get(i);
					listener.getValue(event2);
				}
				String appValue = event2.result;
				if (appValue != null) {
					returnValue = NSString.stringWith(appValue.substring(offset, offset + length));
				}
			}
		}
		return returnValue;
	}

	id getSelectedTextRangeAttribute (int childID) {
		id returnValue = null;
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.index = 0;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getSelection(event);
			}
			NSRange range = new NSRange();
			range.location = event.start;
			range.length = event.end - event.start;
			returnValue = NSValue.valueWithRange(range);
		} else if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.offset = -1;
			event.length = 0;
			for (int i = 0; i < accessibleTextListenersSize(); i++) {
				AccessibleTextListener listener = accessibleTextListeners.get(i);
				listener.getSelectionRange(event);
			}
			if (event.offset != -1) {
				NSRange range = new NSRange();
				range.location = event.offset;
				range.length = event.length;
				returnValue = NSValue.valueWithRange(range);
			}
		}
		return returnValue;
	}

	id getServesAsTitleForUIElementsAttribute(int childID) {
		id returnValue = null;
		Relation relation = relations[ACC.RELATION_LABEL_FOR];
		if (relation != null) returnValue = relation.getServesAsTitleForUIElements();
		return returnValue;
	}

	id getStringForRangeParameterizedAttribute (id parameter, int childID) {
		id returnValue = null;

		// Parameter is an NSRange wrapped in an NSValue.
		NSValue parameterObject = new NSValue(parameter.id);
		NSRange range = parameterObject.rangeValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.start = (int) /*64*/ range.location;
			event.end = (int) /*64*/ (range.location + range.length);
			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) returnValue = NSString.stringWith(event.result);
		} else if (accessibleControlListenersSize() > 0) {
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.result = null;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getValue(event);
			}
			String appValue = event.result;

			if (appValue != null) {
				returnValue = NSString.stringWith(appValue.substring((int)/*64*/range.location, (int)/*64*/(range.location + range.length)));
			}
		}
		return returnValue;
	}

	id getSelectedTextRangesAttribute (int childID) {
		NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(3);
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getSelectionCount(event);
			}
			if (event.count > 0) {
				for (int i = 0; i < event.count; i++) {
					event.index = i;
					for (int j = 0; j < accessibleTextExtendedListenersSize(); j++) {
						AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(j);
						listener.getSelection(event);
					}
					NSRange range = new NSRange();
					range.location = event.start;
					range.length = event.end - event.start;
					returnValue.addObject(NSValue.valueWithRange(range));
				}
			}
		} else if (accessibleTextListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			event.offset = -1;
			event.length = 0;

			for (int i = 0; i < accessibleTextListenersSize(); i++) {
				AccessibleTextListener listener = accessibleTextListeners.get(i);
				listener.getSelectionRange(event);
			}

			if (event.offset != -1) {
				NSRange range = new NSRange();
				range.location = event.offset;
				range.length = event.length;
				returnValue.addObject(NSValue.valueWithRange(range));
			}
		}
		if (returnValue.count() == 0) {
			returnValue.addObject(NSValue.valueWithRange(new NSRange()));
		}
		return returnValue;
	}

	id getStyleRangeForIndexAttribute (id parameter, int childID) {
		if (accessibleAttributeListenersSize() == 0) return null;

		// Parameter is an NSRange wrapped in an NSValue.
		NSNumber parameterObject = new NSNumber(parameter.id);
		int index = parameterObject.intValue();

		AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);
		event.offset = (int) /*64*/ index;

		// Marker values -- if -1 after calling getTextAttributes, no one implemented it.
		event.start = event.end = -1;

		for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
			AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
			listener.getTextAttributes(event);
		}

		NSRange range = new NSRange();
		if (event.start == -1 && event.end == -1) {
			range.location = index;
			range.length = 0;
		} else {
			range.location = event.start;
			range.length = event.end - event.start;
		}

		return NSValue.valueWithRange(range);
	}

	id getVisibleCharacterRangeAttribute (int childID) {
		NSRange range = null;
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.childID = childID;
			for (int i=0; i<accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.getVisibleRanges(event);
			}
			range = new NSRange();
			range.location = event.start;
			range.length = event.end - event.start;
		} else if (accessibleControlListenersSize() > 0) {
			AccessibleControlEvent event = new AccessibleControlEvent(this);
			event.childID = childID;
			event.result = null;
			for (int i = 0; i < accessibleControlListenersSize(); i++) {
				AccessibleControlListener listener = accessibleControlListeners.get(i);
				listener.getValue(event);
			}
			if (event.result != null) {
				range = new NSRange();
				range.location = 0;
				range.length = event.result.length();
			}
		}

		return (range != null) ? NSValue.valueWithRange(range) : null;
	}

	int lineNumberForOffset (String text, int offset) {
		int lineNumber = 1;
		int length = text.length();
		for (int i = 0; i < offset; i++) {
			switch (text.charAt (i)) {
				case '\r':
					if (i + 1 < length) {
						if (text.charAt (i + 1) == '\n') ++i;
					}
					// FALL THROUGH
				case '\n':
					lineNumber++;
			}
		}
		return lineNumber;
	}

	NSRange rangeForLineNumber (int lineNumber, String text) {
		NSRange range = new NSRange();
		range.location = -1;
		int line = 1;
		int count = 0;
		int length = text.length ();
		for (int i = 0; i < length; i++) {
			if (line == lineNumber) {
				if (count == 0) {
					range.location = i;
				}
				count++;
			}
			if (line > lineNumber) break;
			switch (text.charAt (i)) {
				case '\r':
					if (i + 1 < length && text.charAt (i + 1) == '\n') i++;
					// FALL THROUGH
				case '\n':
					line++;
			}
		}
		range.length = count;
		return range;
	}

	/**
	 * Removes the listener from the collection of listeners who will
	 * be notified when an accessible client asks for certain strings,
	 * such as name, description, help, or keyboard shortcut.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for a name, description, help, or keyboard shortcut string
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleListener
	 * @see #addAccessibleListener
	 */
	public void removeAccessibleListener(AccessibleListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleListeners != null) {
			accessibleListeners.remove(listener);
			if (accessibleListeners.isEmpty()) accessibleListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners who will
	 * be notified when an accessible client asks for custom control
	 * specific information.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for custom control specific information
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleControlListener
	 * @see #addAccessibleControlListener
	 */
	public void removeAccessibleControlListener(AccessibleControlListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleControlListeners != null) {
			accessibleControlListeners.remove(listener);
			if (accessibleControlListeners.isEmpty()) accessibleControlListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners who will
	 * be notified when an accessible client asks for custom text control
	 * specific information.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for custom text control specific information
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTextListener
	 * @see AccessibleTextExtendedListener
	 * @see #addAccessibleTextListener
	 *
	 * @since 3.0
	 */
	public void removeAccessibleTextListener (AccessibleTextListener listener) {
		checkWidget ();
		if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
		if (listener instanceof AccessibleTextExtendedListener) {
			if (accessibleTextExtendedListeners != null) {
				accessibleTextExtendedListeners.remove(listener);
				if (accessibleTextExtendedListeners.isEmpty()) accessibleTextExtendedListeners = null;
			}
		} else {
			if (accessibleTextListeners != null) {
				accessibleTextListeners.remove(listener);
				if (accessibleTextListeners.isEmpty()) accessibleTextListeners = null;
			}
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleActionListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleActionListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleActionListener
	 * @see #addAccessibleActionListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleActionListener(AccessibleActionListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleActionListeners != null) {
			accessibleActionListeners.remove(listener);
			if (accessibleActionListeners.isEmpty()) accessibleActionListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleEditableTextListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleEditableTextListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleEditableTextListener
	 * @see #addAccessibleEditableTextListener
	 *
	 * @since 3.7
	 */
	public void removeAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
	    checkWidget();
	    if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleEditableTextListeners != null) {
			accessibleEditableTextListeners.remove(listener);
			if (accessibleEditableTextListeners.isEmpty()) accessibleEditableTextListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleHyperlinkListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleHyperlinkListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleHyperlinkListener
	 * @see #addAccessibleHyperlinkListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleHyperlinkListeners != null) {
			accessibleHyperlinkListeners.remove(listener);
			if (accessibleHyperlinkListeners.isEmpty()) accessibleHyperlinkListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleTableListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleTableListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTableListener
	 * @see #addAccessibleTableListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleTableListener(AccessibleTableListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleTableListeners != null) {
			accessibleTableListeners.remove(listener);
			if (accessibleTableListeners.isEmpty()) accessibleTableListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleTableCellListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleTableCellListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleTableCellListener
	 * @see #addAccessibleTableCellListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleTableCellListener(AccessibleTableCellListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleTableCellListeners != null) {
			accessibleTableCellListeners.remove(listener);
			if (accessibleTableCellListeners.isEmpty()) accessibleTableCellListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleValueListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleValueListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleValueListener
	 * @see #addAccessibleValueListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleValueListener(AccessibleValueListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleValueListeners != null) {
			accessibleValueListeners.remove(listener);
			if (accessibleValueListeners.isEmpty()) accessibleValueListeners = null;
		}
	}

	/**
	 * Removes the listener from the collection of listeners that will be
	 * notified when an accessible client asks for any of the properties
	 * defined in the <code>AccessibleAttributeListener</code> interface.
	 *
	 * @param listener the listener that should no longer be notified when the receiver
	 * is asked for <code>AccessibleAttributeListener</code> interface properties
	 *
	 * @exception IllegalArgumentException <ul>
	 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
	 * </ul>
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see AccessibleAttributeListener
	 * @see #addAccessibleAttributeListener
	 *
	 * @since 3.6
	 */
	public void removeAccessibleAttributeListener(AccessibleAttributeListener listener) {
		checkWidget();
		if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (accessibleAttributeListeners != null) {
			accessibleAttributeListeners.remove(listener);
			if (accessibleAttributeListeners.isEmpty()) accessibleAttributeListeners = null;
		}
	}

	/**
	 * Removes the relation with the specified type and target
	 * from the receiver's set of relations.
	 *
	 * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
	 * @param target the accessible that is the target for this relation
	 *
	 * @since 3.6
	 */
	public void removeRelation(int type, Accessible target) {
		checkWidget();
		if (relations[type] != null) {
			relations[type].removeTarget(target);
		}
	}

	void release(boolean destroy) {
		if (actionNames != null) actionNames.release();
		actionNames = null;
		if (attributeNames != null) attributeNames.release();
		attributeNames = null;
		if (parameterizedAttributeNames != null) parameterizedAttributeNames.release();
		parameterizedAttributeNames = null;
		if (delegate != null) {
			delegate.internal_dispose_SWTAccessibleDelegate();
			delegate.release();
		}
		delegate = null;
		relations = null;

		if (childToIdMap != null) {
			Collection delegates = childToIdMap.values();
			Iterator iter = delegates.iterator();
			while (iter.hasNext()) {
				SWTAccessibleDelegate childDelegate = (SWTAccessibleDelegate)iter.next();
				childDelegate.internal_dispose_SWTAccessibleDelegate();
				childDelegate.release();
			}
			childToIdMap.clear();
			childToIdMap = null;
		}

		if (tableDelegate != null) tableDelegate.release();
	}

	static NSArray retainedAutoreleased(NSArray inObject) {
		id temp = inObject.retain();
		id temp2 = new NSObject(temp.id).autorelease();
		return new NSArray(temp2.id);
	}

	/**
	 * Sends a message with event-specific data to accessible clients
	 * indicating that something has changed within a custom control.
	 *
	 * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
	 * @param eventData an object containing event-specific data, or null if there is no event-specific data
	 * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see ACC#EVENT_ACTION_CHANGED
	 * @see ACC#EVENT_ATTRIBUTE_CHANGED
	 * @see ACC#EVENT_DESCRIPTION_CHANGED
	 * @see ACC#EVENT_DOCUMENT_LOAD_COMPLETE
	 * @see ACC#EVENT_DOCUMENT_LOAD_STOPPED
	 * @see ACC#EVENT_DOCUMENT_RELOAD
	 * @see ACC#EVENT_HYPERLINK_ACTIVATED
	 * @see ACC#EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED
	 * @see ACC#EVENT_HYPERLINK_END_INDEX_CHANGED
	 * @see ACC#EVENT_HYPERLINK_SELECTED_LINK_CHANGED
	 * @see ACC#EVENT_HYPERLINK_START_INDEX_CHANGED
	 * @see ACC#EVENT_HYPERTEXT_LINK_COUNT_CHANGED
	 * @see ACC#EVENT_HYPERTEXT_LINK_SELECTED
	 * @see ACC#EVENT_LOCATION_CHANGED
	 * @see ACC#EVENT_NAME_CHANGED
	 * @see ACC#EVENT_PAGE_CHANGED
	 * @see ACC#EVENT_SECTION_CHANGED
	 * @see ACC#EVENT_SELECTION_CHANGED
	 * @see ACC#EVENT_STATE_CHANGED
	 * @see ACC#EVENT_TABLE_CAPTION_CHANGED
	 * @see ACC#EVENT_TABLE_CHANGED
	 * @see ACC#EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED
	 * @see ACC#EVENT_TABLE_COLUMN_HEADER_CHANGED
	 * @see ACC#EVENT_TABLE_ROW_DESCRIPTION_CHANGED
	 * @see ACC#EVENT_TABLE_ROW_HEADER_CHANGED
	 * @see ACC#EVENT_TABLE_SUMMARY_CHANGED
	 * @see ACC#EVENT_TEXT_ATTRIBUTE_CHANGED
	 * @see ACC#EVENT_TEXT_CARET_MOVED
	 * @see ACC#EVENT_TEXT_CHANGED
	 * @see ACC#EVENT_TEXT_COLUMN_CHANGED
	 * @see ACC#EVENT_TEXT_SELECTION_CHANGED
	 * @see ACC#EVENT_VALUE_CHANGED
	 *
	 * @since 3.6
	 */
	public void sendEvent(int event, Object eventData) {
		checkWidget();

		id eventSource = accessibleHandle(this);
		if (DEBUG) System.out.println("sendEvent: 0x" + Integer.toHexString(event) + ", data = " + eventData + ", source = " + eventSource);

		switch (event) {
		case ACC.EVENT_TEXT_CHANGED:
		case ACC.EVENT_VALUE_CHANGED:
		case ACC.EVENT_STATE_CHANGED:
		case ACC.EVENT_PAGE_CHANGED:
		case ACC.EVENT_SECTION_CHANGED:
		case ACC.EVENT_ACTION_CHANGED:
		case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED:
		case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED:
		case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED:
		case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED:
		case ACC.EVENT_HYPERLINK_ACTIVATED:
		case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED:
		case ACC.EVENT_ATTRIBUTE_CHANGED:
		case ACC.EVENT_TABLE_CAPTION_CHANGED:
		case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
		case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED:
		case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
		case ACC.EVENT_TABLE_ROW_HEADER_CHANGED:
		case ACC.EVENT_TABLE_SUMMARY_CHANGED:
		case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED:
		case ACC.EVENT_TEXT_COLUMN_CHANGED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityValueChangedNotification.id); break;

		case ACC.EVENT_SELECTION_CHANGED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedChildrenChangedNotification.id); break;
		case ACC.EVENT_TEXT_SELECTION_CHANGED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedTextChangedNotification.id); break;
		case ACC.EVENT_LOCATION_CHANGED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityMovedNotification.id); break;
		case ACC.EVENT_NAME_CHANGED:
		case ACC.EVENT_DESCRIPTION_CHANGED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityTitleChangedNotification.id); break;
		case ACC.EVENT_TEXT_CARET_MOVED:
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedTextChangedNotification.id); break;
		case ACC.EVENT_TABLE_CHANGED:
			if (tableDelegate != null) {
				tableDelegate.reset();
				getRowsAttribute(ACC.CHILDID_SELF);
				getColumnsAttribute(ACC.CHILDID_SELF);
			}
			if (eventData != null) {
				int[] eventParams = (int[])eventData;
				// Slot 2 of the array is the number of rows that were either added or deleted. If non-zero, fire a notification.
				// Cocoa doesn't have a notification for a change in the number of columns.
				if (eventParams[2] != 0) OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityRowCountChangedNotification.id);
			}
			break;

		// None of these correspond to anything in Cocoa.
		case ACC.EVENT_HYPERTEXT_LINK_SELECTED:
		case ACC.EVENT_DOCUMENT_LOAD_COMPLETE:
		case ACC.EVENT_DOCUMENT_LOAD_STOPPED:
		case ACC.EVENT_DOCUMENT_RELOAD:
			break;

		}
	}

	/**
	 * Sends a message with event-specific data and a childID
	 * to accessible clients, indicating that something has changed
	 * within a custom control.
	 *
	 * NOTE: This API is intended for applications that are still using childIDs.
	 * Moving forward, applications should use accessible objects instead of childIDs.
	 *
	 * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
	 * @param eventData an object containing event-specific data, or null if there is no event-specific data
	 * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
	 * @param childID an identifier specifying a child of the control
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see ACC#EVENT_DESCRIPTION_CHANGED
	 * @see ACC#EVENT_LOCATION_CHANGED
	 * @see ACC#EVENT_NAME_CHANGED
	 * @see ACC#EVENT_SELECTION_CHANGED
	 * @see ACC#EVENT_STATE_CHANGED
	 * @see ACC#EVENT_TEXT_SELECTION_CHANGED
	 * @see ACC#EVENT_VALUE_CHANGED
	 *
	 * @since 3.8
	 */
	public void sendEvent(int event, Object eventData, int childID) {
		checkWidget();

		id eventSource = childIDToOs(childID);
		if (DEBUG) System.out.println("sendEvent: 0x" + Integer.toHexString(event) + ", data = " + eventData + ", source = " + eventSource);

		switch (event) {
			case ACC.EVENT_VALUE_CHANGED:
			case ACC.EVENT_STATE_CHANGED:
			case ACC.EVENT_SELECTION_CHANGED:
				OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedChildrenChangedNotification.id); break;
			case ACC.EVENT_TEXT_SELECTION_CHANGED:
				OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedTextChangedNotification.id); break;
			case ACC.EVENT_LOCATION_CHANGED:
				OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityMovedNotification.id); break;
			case ACC.EVENT_NAME_CHANGED:
			case ACC.EVENT_DESCRIPTION_CHANGED:
				OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilityTitleChangedNotification.id); break;
		}
	}

	/**
	 * Sends a message to accessible clients that the child selection
	 * within a custom container control has changed.
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @since 3.0
	 */
	public void selectionChanged () {
		checkWidget();
		id eventSource = accessibleHandle(this);
		if (DEBUG) System.out.println("selectionChanged on " + eventSource);
		if (currentRole == ACC.ROLE_TABLE) {
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedRowsChangedNotification.id);
		} else {
			OS.NSAccessibilityPostNotification(eventSource.id, OS.NSAccessibilitySelectedChildrenChangedNotification.id);
		}
	}

	/**
	 * Sends a message to accessible clients indicating that the focus
	 * has changed within a custom control.
	 *
	 * @param childID an identifier specifying a child of the control
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 */
	public void setFocus(int childID) {
		checkWidget();
		id accessible = childIDToOs(childID);
		if (DEBUG) System.out.println("setFocus on " + accessible);
		OS.NSAccessibilityPostNotification(accessible.id, OS.NSAccessibilityFocusedUIElementChangedNotification.id);
	}

	void setSelectedTextAttribute(id value, int childId) {
		NSString newText = new NSString(value.id);
		int rangeStart = 0;
		id charsValue = getNumberOfCharactersAttribute(childId);
		int rangeEnd = new NSNumber(charsValue).intValue();
		id rangeObj = getSelectedTextRangeAttribute(childId);

		if (rangeObj != null) {
			NSRange range = new NSValue(rangeObj).rangeValue();
			rangeStart = (int)/*64*/range.location;
			rangeEnd = (int)/*64*/(range.location + range.length);
		}

		if (accessibleEditableTextListenersSize() > 0) {
			AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
			event.start = rangeStart;
			event.end = rangeEnd;
			event.string = newText.getString();

			for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
				AccessibleEditableTextListener listener = (AccessibleEditableTextListener) accessibleEditableTextListeners.get(i);
				listener.replaceText(event);
			}
		}
	}

	void setSelectedTextRangeAttribute(id value, int childId) {
		NSRange newRange = new NSValue(value.id).rangeValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.index = 0;
			event.start = (int)newRange.location;
			event.end = (int)(newRange.location + newRange.length);

			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.removeSelection(event);
				listener.addSelection(event);
			}
		}
	}

	void setVisibleCharacterRangeAttribute(id value, int childId) {
		NSRange newRange = new NSValue(value.id).rangeValue();
		if (accessibleTextExtendedListenersSize() > 0) {
			AccessibleTextEvent event = new AccessibleTextEvent(this);
			event.type = ACC.SCROLL_TYPE_TOP_LEFT;
			event.start = (int)newRange.location;
			event.end = (int)(newRange.location + newRange.length);

			for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
				AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
				listener.scrollText(event);
			}
		}
	}

	/**
	 * Sends a message to accessible clients that the text
	 * caret has moved within a custom control.
	 *
	 * @param index the new caret index within the control
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @since 3.0
	 */
	public void textCaretMoved (int index) {
		checkWidget();
		OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilitySelectedTextChangedNotification.id);
	}

	/**
	 * Sends a message to accessible clients that the text
	 * within a custom control has changed.
	 *
	 * @param type the type of change, one of <code>ACC.TEXT_INSERT</code>
	 * or <code>ACC.TEXT_DELETE</code>
	 * @param startIndex the text index within the control where the insertion or deletion begins
	 * @param length the non-negative length in characters of the insertion or deletion
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @see ACC#TEXT_INSERT
	 * @see ACC#TEXT_DELETE
	 *
	 * @since 3.0
	 */
	public void textChanged (int type, int startIndex, int length) {
		checkWidget();
		OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilityValueChangedNotification.id);
	}

	/**
	 * Sends a message to accessible clients that the text
	 * selection has changed within a custom control.
	 *
	 * @exception SWTException <ul>
	 *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
	 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
	 * </ul>
	 *
	 * @since 3.0
	 */
	public void textSelectionChanged () {
		checkWidget();
		OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilitySelectedTextChangedNotification.id);
	}

	id childIDToOs(int childID) {
		if (childID == ACC.CHILDID_SELF) {
			return control.view;
		}

		/* Check cache for childID, if found, return corresponding osChildID. */
		SWTAccessibleDelegate childRef = (SWTAccessibleDelegate) childToIdMap.get(Integer.valueOf(childID));

		if (childRef == null) {
			childRef = new SWTAccessibleDelegate(this, childID);
			childToIdMap.put(Integer.valueOf(childID), childRef);
		}

		return childRef;
	}

	NSString concatStringsAsRole(NSString str1, NSString str2) {
		NSString returnValue = str1;
		returnValue = returnValue.stringByAppendingString(NSString.stringWith(":"));
		returnValue = returnValue.stringByAppendingString(str2);
		return returnValue;
	}

	String roleToOs(int role) {
		NSString nsReturnValue = null; //OS.NSAccessibilityUnknownRole;

		switch (role) {
			case ACC.ROLE_CLIENT_AREA: nsReturnValue = OS.NSAccessibilityGroupRole; break;
			case ACC.ROLE_WINDOW: nsReturnValue = OS.NSAccessibilityWindowRole; break;
			case ACC.ROLE_MENUBAR: nsReturnValue = OS.NSAccessibilityMenuBarRole; break;
			case ACC.ROLE_MENU: nsReturnValue = OS.NSAccessibilityMenuRole; break;
			case ACC.ROLE_MENUITEM: nsReturnValue = OS.NSAccessibilityMenuItemRole; break;
			case ACC.ROLE_SEPARATOR: nsReturnValue = OS.NSAccessibilitySplitterRole; break;
			case ACC.ROLE_TOOLTIP: nsReturnValue = OS.NSAccessibilityHelpTagRole; break;
			case ACC.ROLE_SCROLLBAR: nsReturnValue = OS.NSAccessibilityScrollBarRole; break;
			case ACC.ROLE_DIALOG: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityWindowRole, OS.NSAccessibilityDialogSubrole); break;
			case ACC.ROLE_LABEL: nsReturnValue = OS.NSAccessibilityStaticTextRole; break;
			case ACC.ROLE_PUSHBUTTON: nsReturnValue = OS.NSAccessibilityButtonRole; break;
			case ACC.ROLE_CHECKBUTTON: nsReturnValue = OS.NSAccessibilityCheckBoxRole; break;
			case ACC.ROLE_RADIOBUTTON: nsReturnValue = OS.NSAccessibilityRadioButtonRole; break;
			case ACC.ROLE_SPLITBUTTON: nsReturnValue = OS.NSAccessibilityMenuButtonRole; break;
			case ACC.ROLE_COMBOBOX: nsReturnValue = OS.NSAccessibilityComboBoxRole; break;
			case ACC.ROLE_TEXT: {
				int style = control.getStyle();

				if ((style & SWT.MULTI) != 0) {
					nsReturnValue = OS.NSAccessibilityTextAreaRole;
				} else {
					nsReturnValue = OS.NSAccessibilityTextFieldRole;
				}

				break;
			}
			case ACC.ROLE_TOOLBAR: nsReturnValue = OS.NSAccessibilityToolbarRole; break;
			case ACC.ROLE_LIST: nsReturnValue = OS.NSAccessibilityOutlineRole; break;
			case ACC.ROLE_LISTITEM: nsReturnValue = OS.NSAccessibilityStaticTextRole; break;
			case ACC.ROLE_COLUMN: nsReturnValue =  OS.NSAccessibilityColumnRole; break;
			case ACC.ROLE_ROW: nsReturnValue =  concatStringsAsRole(OS.NSAccessibilityRowRole, OS.NSAccessibilityTableRowSubrole); break;
			case ACC.ROLE_TABLE: nsReturnValue = OS.NSAccessibilityTableRole; break;
			case ACC.ROLE_TABLECELL: nsReturnValue = OS.NSAccessibilityStaticTextRole; break;
			case ACC.ROLE_TABLECOLUMNHEADER: nsReturnValue = OS.NSAccessibilityGroupRole; break;
			case ACC.ROLE_TABLEROWHEADER: nsReturnValue = OS.NSAccessibilityGroupRole; break;
			case ACC.ROLE_TREE: nsReturnValue = OS.NSAccessibilityOutlineRole; break;
			case ACC.ROLE_TREEITEM: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityOutlineRole, OS.NSAccessibilityOutlineRowSubrole); break;
			case ACC.ROLE_TABFOLDER: nsReturnValue = OS.NSAccessibilityTabGroupRole; break;
			case ACC.ROLE_TABITEM: nsReturnValue = OS.NSAccessibilityRadioButtonRole; break;
			case ACC.ROLE_PROGRESSBAR: nsReturnValue = OS.NSAccessibilityProgressIndicatorRole; break;
			case ACC.ROLE_SLIDER: nsReturnValue = OS.NSAccessibilitySliderRole; break;
			case ACC.ROLE_LINK: nsReturnValue = OS.NSAccessibilityLinkRole; break;

			//10.6 only -> case ACC.ROLE_CANVAS: nsReturnValue = OS.NSAccessibilityLayoutAreaRole; break;
			case ACC.ROLE_CANVAS: nsReturnValue = OS.NSAccessibilityGroupRole; break;
			case ACC.ROLE_GRAPHIC: nsReturnValue = OS.NSAccessibilityImageRole; break;

			//CLIENT_AREA uses NSAccessibilityGroupRole already
			case ACC.ROLE_GROUP: nsReturnValue = OS.NSAccessibilityGroupRole; break;
			//SPLIT_BUTTON uses NSAccessibilityMenuButtonRole already
			case ACC.ROLE_CHECKMENUITEM: nsReturnValue = OS.NSAccessibilityMenuButtonRole; break;
			case ACC.ROLE_RADIOMENUITEM: nsReturnValue = OS.NSAccessibilityMenuButtonRole; break;
			//don't know the right answer for these:
			case ACC.ROLE_FOOTER:
			case ACC.ROLE_HEADER:
			case ACC.ROLE_FORM:
			case ACC.ROLE_PAGE:
			case ACC.ROLE_SECTION:
				nsReturnValue = OS.NSAccessibilityGroupRole;
				break;
			case ACC.ROLE_HEADING:
			case ACC.ROLE_PARAGRAPH:
				nsReturnValue = OS.NSAccessibilityTextAreaRole;
				break;
			case ACC.ROLE_CLOCK:
			case ACC.ROLE_DATETIME:
			case ACC.ROLE_CALENDAR:
			case ACC.ROLE_ALERT:
			case ACC.ROLE_ANIMATION:
			case ACC.ROLE_DOCUMENT:
			case ACC.ROLE_SPINBUTTON:
			case ACC.ROLE_STATUSBAR:
				nsReturnValue = OS.NSAccessibilityUnknownRole;
		}

		return nsReturnValue.getString();
	}

	/* 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);
	}

	/* isValidThread was copied from Widget, and rewritten to work in this package */
	boolean isValidThread () {
		return control.getDisplay ().getThread () == Thread.currentThread ();
	}

	/**
	 * Adds relationship attributes if needed to the property list.
	 * <p>
	 * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
	 * public API. 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 accessed from application code.
	 * </p>
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public long /*int*/ internal_addRelationAttributes(long /*int*/ defaultAttributes) {
		NSArray attributes = new NSArray(defaultAttributes);
		NSMutableArray returnArray = NSMutableArray.arrayWithCapacity(attributes.count());
		returnArray.addObjectsFromArray(attributes);

		if (getTitleAttribute(ACC.CHILDID_SELF) != null) {
			if (!returnArray.containsObject(OS.NSAccessibilityTitleAttribute)) returnArray.addObject(OS.NSAccessibilityTitleAttribute);
		}

		if (getDescriptionAttribute(ACC.CHILDID_SELF) != null) {
			if (!returnArray.containsObject(OS.NSAccessibilityDescriptionAttribute)) returnArray.addObject(OS.NSAccessibilityDescriptionAttribute);
		}

		// See if this object has a label or is a label for something else. If so, add that to the list.
		if (relations[ACC.RELATION_LABEL_FOR] != null) {
			if (!returnArray.containsObject(OS.NSAccessibilityServesAsTitleForUIElementsAttribute)) returnArray.addObject(OS.NSAccessibilityServesAsTitleForUIElementsAttribute);
			if (!returnArray.containsObject(OS.NSAccessibilityTitleAttribute)) returnArray.addObject(OS.NSAccessibilityTitleAttribute);
		} else {
			returnArray.removeObject(OS.NSAccessibilityServesAsTitleForUIElementsAttribute);
		}

		if (relations[ACC.RELATION_LABELLED_BY] != null) {
			if (!returnArray.containsObject(OS.NSAccessibilityTitleUIElementAttribute)) returnArray.addObject(OS.NSAccessibilityTitleUIElementAttribute);
		} else {
			returnArray.removeObject(OS.NSAccessibilityTitleUIElementAttribute);
		}

		return returnArray.id;
	}

}
