blob: 00b05d53942501a80535ca9b797ca844bd44ea1e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 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.util.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.accessibility.gtk.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.widgets.*;
class AccessibleObject {
int /*long*/ handle;
int /*long*/ parentType;
int index = -1, id = ACC.CHILDID_SELF;
Accessible accessible;
AccessibleObject parent;
Hashtable children = new Hashtable (9);
/*
* a lightweight object does not correspond to a concrete gtk widget, but
* to a logical child of a widget (eg.- a CTabItem, which is simply drawn)
*/
boolean isLightweight = false;
static int /*long*/ actionNamePtr = -1;
static int /*long*/ descriptionPtr = -1;
static int /*long*/ keybindingPtr = -1;
static int /*long*/ namePtr = -1;
static final Hashtable AccessibleObjects = new Hashtable (9);
static final int /*long*/ ATK_ACTION_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkAction", true));
static final int /*long*/ ATK_COMPONENT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkComponent", true));
static final int /*long*/ ATK_HYPERTEXT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkHypertext", true));
static final int /*long*/ ATK_SELECTION_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkSelection", true));
static final int /*long*/ ATK_TEXT_TYPE = ATK.g_type_from_name (Converter.wcsToMbcs (null, "AtkText", true));
static final boolean DEBUG = Display.DEBUG;
AccessibleObject (int /*long*/ type, int /*long*/ widget, Accessible accessible, int /*long*/ parentType, boolean isLightweight) {
super ();
handle = ATK.g_object_new (type, 0);
this.parentType = parentType;
ATK.atk_object_initialize (handle, widget);
this.accessible = accessible;
this.isLightweight = isLightweight;
AccessibleObjects.put (new LONG (handle), this);
if (DEBUG) System.out.println("new AccessibleObject: " + handle);
}
void addChild (AccessibleObject child) {
children.put (new LONG (child.handle), child);
child.setParent (this);
}
static int /*long*/ atkAction_get_keybinding (int /*long*/ atkObject, int /*long*/ index) {
if (DEBUG) System.out.println ("-->atkAction_get_keybinding");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle));
AtkActionIface actionIface = new AtkActionIface ();
ATK.memmove (actionIface, superType);
if (actionIface.get_keybinding != 0) {
parentResult = ATK.call (actionIface.get_keybinding, object.handle, index);
}
}
AccessibleListener[] listeners = object.getAccessibleListeners ();
if (listeners.length == 0) return parentResult;
AccessibleEvent event = new AccessibleEvent (object.accessible);
event.childID = object.id;
if (parentResult != 0) {
int length = OS.strlen (parentResult);
byte [] buffer = new byte [length];
OS.memmove (buffer, parentResult, length);
event.result = new String (Converter.mbcsToWcs (null, buffer));
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getKeyboardShortcut (event);
}
if (event.result == null) return parentResult;
if (keybindingPtr != -1) OS.g_free (keybindingPtr);
byte[] name = Converter.wcsToMbcs (null, event.result, true);
keybindingPtr = OS.g_malloc (name.length);
OS.memmove (keybindingPtr, name, name.length);
return keybindingPtr;
}
static int /*long*/ atkAction_get_name (int /*long*/ atkObject, int /*long*/ index) {
if (DEBUG) System.out.println ("-->atkAction_get_name");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle));
AtkActionIface actionIface = new AtkActionIface ();
ATK.memmove (actionIface, superType);
if (actionIface.get_name != 0) {
parentResult = ATK.call (actionIface.get_name, object.handle, index);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
if (parentResult != 0) {
int length = OS.strlen (parentResult);
byte [] buffer = new byte [length];
OS.memmove (buffer, parentResult, length);
event.result = new String (Converter.mbcsToWcs (null, buffer));
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getDefaultAction (event);
}
if (event.result == null) return parentResult;
if (actionNamePtr != -1) OS.g_free (actionNamePtr);
byte[] name = Converter.wcsToMbcs (null, event.result, true);
actionNamePtr = OS.g_malloc (name.length);
OS.memmove (actionNamePtr, name, name.length);
return actionNamePtr;
}
static int /*long*/ atkComponent_get_extents (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ width, int /*long*/ height, int /*long*/ coord_type) {
if (DEBUG) System.out.println ("-->atkComponent_get_extents");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
OS.memmove (x, new int[] {0}, 4);
OS.memmove (y, new int[] {0}, 4);
OS.memmove (width, new int[] {0}, 4);
OS.memmove (height, new int[] {0}, 4);
if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
AtkComponentIface componentIface = new AtkComponentIface ();
ATK.memmove (componentIface, superType);
if (componentIface.get_extents != 0) {
ATK.call (componentIface.get_extents, object.handle, x, y, width, height, coord_type);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return 0;
int[] parentX = new int [1], parentY = new int [1];
int[] parentWidth = new int [1], parentHeight = new int [1];
OS.memmove (parentX, x, 4);
OS.memmove (parentY, y, 4);
OS.memmove (parentWidth, width, 4);
OS.memmove (parentHeight, height, 4);
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.x = parentX [0]; event.y = parentY [0];
event.width = parentWidth [0]; event.height = parentHeight [0];
if (coord_type == ATK.ATK_XY_WINDOW) {
/* translate control -> display, for filling in event to be dispatched */
int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle);
GtkAccessible gtkAccessible = new GtkAccessible ();
ATK.memmove (gtkAccessible, gtkAccessibleHandle);
int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel);
int[] topWindowX = new int [1], topWindowY = new int [1];
OS.gdk_window_get_origin (window, topWindowX, topWindowY);
event.x += topWindowX [0];
event.y += topWindowY [0];
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getLocation (event);
}
if (coord_type == ATK.ATK_XY_WINDOW) {
/* translate display -> control, for answering to the OS */
int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle);
GtkAccessible gtkAccessible = new GtkAccessible ();
ATK.memmove (gtkAccessible, gtkAccessibleHandle);
int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel);
int[] topWindowX = new int [1], topWindowY = new int [1];
OS.gdk_window_get_origin (window, topWindowX, topWindowY);
event.x -= topWindowX [0];
event.y -= topWindowY [0];
}
OS.memmove (x, new int[] {event.x}, 4);
OS.memmove (y, new int[] {event.y}, 4);
OS.memmove (width, new int[] {event.width}, 4);
OS.memmove (height, new int[] {event.height}, 4);
return 0;
}
static int /*long*/ atkComponent_get_position (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ coord_type) {
if (DEBUG) System.out.println ("-->atkComponent_get_position, object: " + atkObject + " x: " + x + " y: " + y + " coord: " + coord_type);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
OS.memmove (x, new int[] {0}, 4);
OS.memmove (y, new int[] {0}, 4);
if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
AtkComponentIface componentIface = new AtkComponentIface ();
ATK.memmove (componentIface, superType);
if (componentIface.get_extents != 0) {
ATK.call (componentIface.get_position, object.handle, x, y, coord_type);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return 0;
int[] parentX = new int [1], parentY = new int [1];
OS.memmove (parentX, x, 4);
OS.memmove (parentY, y, 4);
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.x = parentX [0]; event.y = parentY [0];
if (coord_type == ATK.ATK_XY_WINDOW) {
/* translate control -> display, for filling in event to be dispatched */
int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle);
GtkAccessible gtkAccessible = new GtkAccessible ();
ATK.memmove (gtkAccessible, gtkAccessibleHandle);
int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel);
int[] topWindowX = new int [1], topWindowY = new int [1];
OS.gdk_window_get_origin (window, topWindowX, topWindowY);
event.x += topWindowX [0];
event.y += topWindowY [0];
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getLocation (event);
}
if (coord_type == ATK.ATK_XY_WINDOW) {
/* translate display -> control, for answering to the OS */
int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle);
GtkAccessible gtkAccessible = new GtkAccessible ();
ATK.memmove (gtkAccessible, gtkAccessibleHandle);
int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel);
int[] topWindowX = new int [1], topWindowY = new int [1];
OS.gdk_window_get_origin (window, topWindowX, topWindowY);
event.x -= topWindowX [0];
event.y -= topWindowY [0];
}
OS.memmove (x, new int[] {event.x}, 4);
OS.memmove (y, new int[] {event.y}, 4);
return 0;
}
static int /*long*/ atkComponent_get_size (int /*long*/ atkObject, int /*long*/ width, int /*long*/ height, int /*long*/ coord_type) {
if (DEBUG) System.out.println ("-->atkComponent_get_size");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
OS.memmove (width, new int[] {0}, 4);
OS.memmove (height, new int[] {0}, 4);
if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
AtkComponentIface componentIface = new AtkComponentIface ();
ATK.memmove (componentIface, superType);
if (componentIface.get_extents != 0) {
ATK.call (componentIface.get_size, object.handle, width, height, coord_type);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return 0;
int[] parentWidth = new int [1], parentHeight = new int [1];
OS.memmove (parentWidth, width, 4);
OS.memmove (parentHeight, height, 4);
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.width = parentWidth [0]; event.height = parentHeight [0];
for (int i = 0; i < listeners.length; i++) {
listeners [i].getLocation (event);
}
OS.memmove (width, new int[] {event.width}, 4);
OS.memmove (height, new int[] {event.height}, 4);
return 0;
}
static int /*long*/ atkComponent_ref_accessible_at_point (int /*long*/ atkObject, int /*long*/ x, int /*long*/ y, int /*long*/ coord_type) {
if (DEBUG) System.out.println ("-->atkComponent_ref_accessible_at_point");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
AtkComponentIface componentIface = new AtkComponentIface ();
ATK.memmove (componentIface, superType);
if (componentIface.ref_accessible_at_point != 0) {
parentResult = ATK.call (componentIface.ref_accessible_at_point, object.handle, x, y, coord_type);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.x = (int)/*64*/x; event.y = (int)/*64*/y;
if (coord_type == ATK.ATK_XY_WINDOW) {
/* translate control -> display, for filling in the event to be dispatched */
int /*long*/ gtkAccessibleHandle = ATK.GTK_ACCESSIBLE (object.handle);
GtkAccessible gtkAccessible = new GtkAccessible ();
ATK.memmove (gtkAccessible, gtkAccessibleHandle);
int /*long*/ topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
int /*long*/ window = OS.GTK_WIDGET_WINDOW (topLevel);
int[] topWindowX = new int [1], topWindowY = new int [1];
OS.gdk_window_get_origin (window, topWindowX, topWindowY);
event.x += topWindowX [0];
event.y += topWindowY [0];
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getChildAtPoint (event);
}
if (event.childID == object.id) event.childID = ACC.CHILDID_SELF;
AccessibleObject accObj = object.getChildByID (event.childID);
if (accObj != null) {
if (parentResult > 0) OS.g_object_unref (parentResult);
OS.g_object_ref (accObj.handle);
return accObj.handle;
}
return parentResult;
}
static int /*long*/ atkHypertext_get_link (int /*long*/ atkObject, int /*long*/ link_index) {
if (DEBUG) System.out.println ("-->atkHypertext_get_link");
return 0;
}
static int /*long*/ atkHypertext_get_n_links (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkHypertext_get_n_links");
return 0; /* read hyperlink's name */
}
static int /*long*/ atkHypertext_get_link_index (int /*long*/ atkObject, int /*long*/ char_index) {
if (DEBUG) System.out.println ("-->atkHypertext_get_link_index");
return 0;
}
static int /*long*/ atkObject_get_description (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_get_description");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_description != 0) {
parentResult = ATK.call (objectClass.get_description, object.handle);
}
AccessibleListener[] listeners = object.getAccessibleListeners ();
if (listeners.length == 0) return parentResult;
AccessibleEvent event = new AccessibleEvent (object.accessible);
event.childID = object.id;
if (parentResult != 0) {
int length = OS.strlen (parentResult);
byte [] buffer = new byte [length];
OS.memmove (buffer, parentResult, length);
event.result = new String (Converter.mbcsToWcs (null, buffer));
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getDescription (event);
}
if (event.result == null) return parentResult;
if (descriptionPtr != -1) OS.g_free (descriptionPtr);
byte[] name = Converter.wcsToMbcs (null, event.result, true);
descriptionPtr = OS.g_malloc (name.length);
OS.memmove (descriptionPtr, name, name.length);
return descriptionPtr;
}
static int /*long*/ atkObject_get_name (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_get_name: " + atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_name != 0) {
parentResult = ATK.call (objectClass.get_name, object.handle);
}
AccessibleListener[] listeners = object.getAccessibleListeners ();
if (listeners.length == 0) return parentResult;
AccessibleEvent event = new AccessibleEvent (object.accessible);
event.childID = object.id;
if (parentResult != 0) {
int length = OS.strlen (parentResult);
byte [] buffer = new byte [length];
OS.memmove (buffer, parentResult, length);
event.result = new String (Converter.mbcsToWcs (null, buffer));
}
for (int i = 0; i < listeners.length; i++) {
listeners [i].getName (event);
}
if (event.result == null) return parentResult;
if (namePtr != -1) OS.g_free (namePtr);
byte[] name = Converter.wcsToMbcs (null, event.result, true);
namePtr = OS.g_malloc (name.length);
OS.memmove (namePtr, name, name.length);
return namePtr;
}
static int /*long*/ atkObject_get_n_children (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_get_n_children: " + atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_n_children != 0) {
parentResult = ATK.call (objectClass.get_n_children, object.handle);
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.detail = (int)/*64*/parentResult;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getChildCount (event);
}
return event.detail;
}
static int /*long*/ atkObject_get_index_in_parent (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObjectCB_get_index_in_parent. ");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
if (object.index != -1) return object.index;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_index_in_parent == 0) return 0;
return ATK.call (objectClass.get_index_in_parent,object. handle);
}
static int /*long*/ atkObject_get_parent (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_get_parent: " + atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
if (object.parent != null) return object.parent.handle;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_parent == 0) return 0;
return ATK.call (objectClass.get_parent, object.handle);
}
static int /*long*/ atkObject_get_role (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_get_role: " + atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
if (object.getAccessibleListeners ().length != 0) {
AccessibleControlListener[] listeners = object.getControlListeners ();
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.detail = -1;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getRole (event);
}
if (event.detail != -1) {
switch (event.detail) {
/* Convert from win32 role values to atk role values */
case ACC.ROLE_CHECKBUTTON: return ATK.ATK_ROLE_CHECK_BOX;
case ACC.ROLE_CLIENT_AREA: return ATK.ATK_ROLE_DRAWING_AREA;
case ACC.ROLE_COMBOBOX: return ATK.ATK_ROLE_COMBO_BOX;
case ACC.ROLE_DIALOG: return ATK.ATK_ROLE_DIALOG;
case ACC.ROLE_LABEL: return ATK.ATK_ROLE_LABEL;
case ACC.ROLE_LINK: return ATK.ATK_ROLE_TEXT;
case ACC.ROLE_LIST: return ATK.ATK_ROLE_LIST;
case ACC.ROLE_LISTITEM: return ATK.ATK_ROLE_LIST_ITEM;
case ACC.ROLE_MENU: return ATK.ATK_ROLE_MENU;
case ACC.ROLE_MENUBAR: return ATK.ATK_ROLE_MENU_BAR;
case ACC.ROLE_MENUITEM: return ATK.ATK_ROLE_MENU_ITEM;
case ACC.ROLE_PROGRESSBAR: return ATK.ATK_ROLE_PROGRESS_BAR;
case ACC.ROLE_PUSHBUTTON: return ATK.ATK_ROLE_PUSH_BUTTON;
case ACC.ROLE_SCROLLBAR: return ATK.ATK_ROLE_SCROLL_BAR;
case ACC.ROLE_SEPARATOR: return ATK.ATK_ROLE_SEPARATOR;
case ACC.ROLE_SLIDER: return ATK.ATK_ROLE_SLIDER;
case ACC.ROLE_TABLE: return ATK.ATK_ROLE_LIST;
case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_LIST_ITEM;
case ACC.ROLE_TABLECOLUMNHEADER: return ATK.ATK_ROLE_TABLE_COLUMN_HEADER;
case ACC.ROLE_TABLEROWHEADER: return ATK.ATK_ROLE_TABLE_ROW_HEADER;
case ACC.ROLE_TABFOLDER: return ATK.ATK_ROLE_PAGE_TAB_LIST;
case ACC.ROLE_TABITEM: return ATK.ATK_ROLE_PAGE_TAB;
case ACC.ROLE_TEXT: return ATK.ATK_ROLE_TEXT;
case ACC.ROLE_TOOLBAR: return ATK.ATK_ROLE_TOOL_BAR;
case ACC.ROLE_TOOLTIP: return ATK.ATK_ROLE_TOOL_TIP;
case ACC.ROLE_TREE: return ATK.ATK_ROLE_TREE;
case ACC.ROLE_TREEITEM: return ATK.ATK_ROLE_LIST_ITEM;
case ACC.ROLE_RADIOBUTTON: return ATK.ATK_ROLE_RADIO_BUTTON;
case ACC.ROLE_SPLITBUTTON: return ATK.ATK_ROLE_PUSH_BUTTON;
case ACC.ROLE_WINDOW: return ATK.ATK_ROLE_WINDOW;
}
}
}
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.get_role == 0) return 0;
return ATK.call (objectClass.get_role, object.handle);
}
static int /*long*/ atkObject_ref_child (int /*long*/ atkObject, int /*long*/ index) {
if (DEBUG) System.out.println ("-->atkObject_ref_child: " + index + " of: " + atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
object.updateChildren ();
AccessibleObject accObject = object.getChildByIndex ((int)/*64*/index);
if (accObject != null) {
OS.g_object_ref (accObject.handle);
return accObject.handle;
}
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.ref_child == 0) return 0;
return ATK.call (objectClass.ref_child, object.handle, index);
}
static int /*long*/ atkObject_ref_state_set (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkObject_ref_state_set");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkObjectClass objectClass = new AtkObjectClass ();
ATK.memmove (objectClass, superType);
if (objectClass.ref_state_set != 0) {
parentResult = ATK.call (objectClass.ref_state_set, object.handle);
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
int /*long*/ set = parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
event.detail = -1;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getState (event);
}
if (event.detail != -1) {
/* Convert from win32 state values to atk state values */
int state = event.detail;
if ((state & ACC.STATE_BUSY) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_BUSY);
if ((state & ACC.STATE_CHECKED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_CHECKED);
if ((state & ACC.STATE_EXPANDED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EXPANDED);
if ((state & ACC.STATE_FOCUSABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSABLE);
if ((state & ACC.STATE_FOCUSED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSED);
if ((state & ACC.STATE_HOTTRACKED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_ARMED);
if ((state & ACC.STATE_INVISIBLE) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_VISIBLE);
if ((state & ACC.STATE_MULTISELECTABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_MULTISELECTABLE);
if ((state & ACC.STATE_OFFSCREEN) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SHOWING);
if ((state & ACC.STATE_PRESSED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_PRESSED);
if ((state & ACC.STATE_READONLY) == 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EDITABLE);
if ((state & ACC.STATE_SELECTABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTABLE);
if ((state & ACC.STATE_SELECTED) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTED);
if ((state & ACC.STATE_SIZEABLE) != 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_RESIZABLE);
/* Note: STATE_COLLAPSED, STATE_LINKED and STATE_NORMAL have no ATK equivalents */
}
return set;
}
static int /*long*/ atkSelection_is_child_selected (int /*long*/ atkObject, int /*long*/ index) {
if (DEBUG) System.out.println ("-->atkSelection_is_child_selected");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle));
AtkSelectionIface selectionIface = new AtkSelectionIface ();
ATK.memmove (selectionIface, superType);
if (selectionIface.is_child_selected != 0) {
parentResult = ATK.call (selectionIface.is_child_selected, object.handle, index);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getSelection (event);
}
AccessibleObject accessibleObject = object.getChildByID (event.childID);
if (accessibleObject != null) {
return accessibleObject.index == index ? 1 : 0;
}
return parentResult;
}
static int /*long*/ atkSelection_ref_selection (int /*long*/ atkObject, int /*long*/ index) {
if (DEBUG) System.out.println ("-->atkSelection_ref_selection");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle));
AtkSelectionIface selectionIface = new AtkSelectionIface ();
ATK.memmove (selectionIface, superType);
if (selectionIface.ref_selection != 0) {
parentResult = ATK.call (selectionIface.ref_selection, object.handle, index);
}
}
AccessibleControlListener[] listeners = object.getControlListeners ();
if (listeners.length == 0) return parentResult;
AccessibleControlEvent event = new AccessibleControlEvent (object.accessible);
event.childID = object.id;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getSelection (event);
}
AccessibleObject accObj = object.getChildByID (event.childID);
if (accObj != null) {
if (parentResult > 0) OS.g_object_unref (parentResult);
OS.g_object_ref (accObj.handle);
return accObj.handle;
}
return parentResult;
}
static int /*long*/ atkText_get_caret_offset (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkText_get_caret_offset");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
if (textIface.get_caret_offset != 0) {
parentResult = ATK.call (textIface.get_caret_offset, object.handle);
}
}
AccessibleTextListener[] listeners = object.getTextListeners ();
if (listeners.length == 0) return parentResult;
AccessibleTextEvent event = new AccessibleTextEvent (object.accessible);
event.childID = object.id;
event.offset = (int)/*64*/parentResult;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getCaretOffset (event);
}
return event.offset;
}
static int /*long*/ atkText_get_character_at_offset (int /*long*/ atkObject, int /*long*/ offset) {
if (DEBUG) System.out.println ("-->atkText_get_character_at_offset");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
String text = object.getText ();
if (text != null) return text.charAt ((int)/*64*/offset); // TODO
if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
if (textIface.get_character_at_offset != 0) {
return ATK.call (textIface.get_character_at_offset, object.handle, offset);
}
}
return 0;
}
static int /*long*/ atkText_get_character_count (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkText_get_character_count");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
String text = object.getText ();
if (text != null) return text.length ();
if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_class_peek (object.parentType);
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
if (textIface.get_character_count != 0) {
return ATK.call (textIface.get_character_count, object.handle);
}
}
return 0;
}
static int /*long*/ atkText_get_n_selections (int /*long*/ atkObject) {
if (DEBUG) System.out.println ("-->atkText_get_n_selections");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int /*long*/ parentResult = 0;
if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
if (textIface.get_n_selections != 0) {
parentResult = ATK.call (textIface.get_n_selections, object.handle);
}
}
AccessibleTextListener[] listeners = object.getTextListeners ();
if (listeners.length == 0) return parentResult;
AccessibleTextEvent event = new AccessibleTextEvent (object.accessible);
event.childID = object.id;
for (int i = 0; i < listeners.length; i++) {
listeners [i].getSelectionRange (event);
}
return event.length == 0 ? parentResult : 1;
}
static int /*long*/ atkText_get_selection (int /*long*/ atkObject, int /*long*/ selection_num, int /*long*/ start_offset, int /*long*/ end_offset) {
if (DEBUG) System.out.println ("-->atkText_get_selection");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
OS.memmove (start_offset, new int[] {0}, 4);
OS.memmove (end_offset, new int[] {0}, 4);
if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
if (textIface.get_selection != 0) {
ATK.call (textIface.get_selection, object.handle, selection_num, start_offset, end_offset);
}
}
AccessibleTextListener[] listeners = object.getTextListeners ();
if (listeners.length == 0) return 0;
AccessibleTextEvent event = new AccessibleTextEvent (object.accessible);
event.childID = object.id;
int[] parentStart = new int [1];
int[] parentEnd = new int [1];
OS.memmove (parentStart, start_offset, 4);
OS.memmove (parentEnd, end_offset, 4);
event.offset = parentStart [0];
event.length = parentEnd [0] - parentStart [0];
for (int i = 0; i < listeners.length; i++) {
listeners [i].getSelectionRange (event);
}
OS.memmove (start_offset, new int[] {event.offset}, 4);
OS.memmove (end_offset, new int[] {event.offset + event.length}, 4);
return 0;
}
static int /*long*/ atkText_get_text (int /*long*/ atkObject, int /*long*/ start_offset, int /*long*/ end_offset) {
if (DEBUG) System.out.println ("-->atkText_get_text: " + start_offset + "," + end_offset);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
String text = object.getText ();
if (text.length () > 0) {
if (end_offset == -1) {
end_offset = text.length ();
} else {
end_offset = Math.min (end_offset, text.length ());
}
start_offset = Math.min (start_offset, end_offset);
text = text.substring ((int)/*64*/start_offset, (int)/*64*/end_offset);
byte[] bytes = Converter.wcsToMbcs (null, text, true);
int /*long*/ result = OS.g_malloc (bytes.length);
OS.memmove (result, bytes, bytes.length);
return result;
}
return 0;
}
static int /*long*/ atkText_get_text_after_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) {
if (DEBUG) System.out.println ("-->atkText_get_text_after_offset");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int offset = (int)/*64*/offset_value;
String text = object.getText ();
if (text.length () > 0) {
int length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)/*64*/boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length > offset) endBounds++;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = nextIndexOfChar (text, " !?.\n", offset - 1);
if (wordStart1 == -1) {
startBounds = endBounds = length;
break;
}
wordStart1 = nextIndexOfNotChar (text, " !?.\n", wordStart1);
if (wordStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = wordStart1;
int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
if (wordStart2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int previousWordEnd = previousIndexOfNotChar (text, " \n", offset);
if (previousWordEnd == -1 || previousWordEnd != offset - 1) {
offset = nextIndexOfNotChar (text, " \n", offset);
}
if (offset == -1) {
startBounds = endBounds = length;
break;
}
int wordEnd1 = nextIndexOfChar (text, " !?.\n", (int)/*64*/offset);
if (wordEnd1 == -1) {
startBounds = endBounds = length;
break;
}
wordEnd1 = nextIndexOfNotChar (text, "!?.", wordEnd1);
if (wordEnd1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = wordEnd1;
int wordEnd2 = nextIndexOfNotChar (text, " \n", wordEnd1);
if (wordEnd2 == length) {
startBounds = endBounds = length;
break;
}
wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int previousSentenceEnd = previousIndexOfChar (text, "!?.", offset);
int previousText = previousIndexOfNotChar (text, " !?.\n", offset);
int sentenceStart1 = 0;
if (previousSentenceEnd >= previousText) {
sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", offset);
} else {
sentenceStart1 = nextIndexOfChar (text, "!?.", offset);
if (sentenceStart1 == -1) {
startBounds = endBounds = length;
break;
}
sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", sentenceStart1);
}
if (sentenceStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = sentenceStart1;
int sentenceStart2 = nextIndexOfChar (text, "!?.", sentenceStart1);
if (sentenceStart2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = nextIndexOfChar (text, "!?.", offset);
if (sentenceEnd1 == -1) {
startBounds = endBounds = length;
break;
}
sentenceEnd1 = nextIndexOfNotChar (text, "!?.", sentenceEnd1);
if (sentenceEnd1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = sentenceEnd1;
int sentenceEnd2 = nextIndexOfNotChar (text, " \n", sentenceEnd1);
if (sentenceEnd2 == length) {
startBounds = endBounds = length;
break;
}
sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
endBounds = length;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
int lineStart1 = text.indexOf ('\n', offset - 1);
if (lineStart1 == -1) {
startBounds = endBounds = length;
break;
}
lineStart1 = nextIndexOfNotChar (text, "\n", lineStart1);
if (lineStart1 == length) {
startBounds = endBounds = length;
break;
}
startBounds = lineStart1;
int lineStart2 = text.indexOf ('\n', lineStart1);
if (lineStart2 == -1) {
endBounds = length;
break;
}
lineStart2 = nextIndexOfNotChar (text, "\n", lineStart2);
endBounds = lineStart2;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = nextIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = length;
break;
}
startBounds = lineEnd1;
if (startBounds == length) {
endBounds = length;
break;
}
int lineEnd2 = nextIndexOfChar (text, "\n", lineEnd1 + 1);
if (lineEnd2 == -1) {
endBounds = length;
break;
}
endBounds = lineEnd2;
break;
}
}
OS.memmove (start_offset, new int[] {startBounds}, 4);
OS.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
byte[] bytes = Converter.wcsToMbcs (null, text, true);
int /*long*/ result = OS.g_malloc (bytes.length);
OS.memmove (result, bytes, bytes.length);
return result;
}
return 0;
}
static int /*long*/ atkText_get_text_at_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) {
if (DEBUG) System.out.println ("-->atkText_get_text_at_offset: " + offset_value + " start: " + start_offset + " end: " + end_offset);
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int offset = (int)/*64*/offset_value;
String text = object.getText ();
if (text.length () > 0) {
int length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)/*64*/boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length > offset) endBounds++;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = previousIndexOfNotChar (text, " !?.\n", offset);
if (wordStart1 == -1) {
startBounds = endBounds = 0;
break;
}
wordStart1 = previousIndexOfChar (text, " !?.\n", wordStart1) + 1;
if (wordStart1 == -1) {
startBounds = 0;
break;
}
startBounds = wordStart1;
int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int wordEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
wordEnd1 = previousIndexOfChar (text, " !?.\n", wordEnd1);
wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = wordEnd1 + 1;
int wordEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
if (wordEnd2 == length) {
endBounds = startBounds;
break;
}
wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
endBounds = startBounds;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int sentenceStart1 = previousIndexOfNotChar (text, " !?.\n", offset + 1);
if (sentenceStart1 == -1) {
startBounds = endBounds = 0;
break;
}
sentenceStart1 = previousIndexOfChar (text, "!?.", sentenceStart1) + 1;
startBounds = nextIndexOfNotChar (text, " \n", sentenceStart1);
int sentenceStart2 = nextIndexOfChar (text, "!?.", startBounds);
endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
sentenceEnd1 = previousIndexOfChar (text, "!?.", sentenceEnd1);
sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = sentenceEnd1 + 1;
int sentenceEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
if (sentenceEnd2 == length) {
endBounds = startBounds;
break;
}
sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
endBounds = startBounds;
break;
}
endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
startBounds = previousIndexOfChar (text, "\n", offset) + 1;
int lineEnd2 = nextIndexOfChar (text, "\n", startBounds);
if (lineEnd2 < length) lineEnd2++;
endBounds = lineEnd2;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = previousIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
startBounds = lineEnd1;
endBounds = nextIndexOfChar (text, "\n", lineEnd1 + 1);
}
}
OS.memmove (start_offset, new int[] {startBounds}, 4);
OS.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
byte[] bytes = Converter.wcsToMbcs (null, text, true);
int /*long*/ result = OS.g_malloc (bytes.length);
OS.memmove (result, bytes, bytes.length);
return result;
}
return 0;
}
static int /*long*/ atkText_get_text_before_offset (int /*long*/ atkObject, int /*long*/ offset_value, int /*long*/ boundary_type, int /*long*/ start_offset, int /*long*/ end_offset) {
if (DEBUG) System.out.println ("-->atkText_get_text_before_offset");
AccessibleObject object = getAccessibleObject (atkObject);
if (object == null) return 0;
int offset = (int)/*64*/offset_value;
String text = object.getText ();
if (text.length () > 0) {
int length = text.length ();
offset = Math.min (offset, length - 1);
int startBounds = offset;
int endBounds = offset;
switch ((int)/*64*/boundary_type) {
case ATK.ATK_TEXT_BOUNDARY_CHAR: {
if (length >= offset && offset > 0) startBounds--;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
int wordStart1 = previousIndexOfChar (text, " !?.\n", offset - 1);
if (wordStart1 == -1) {
startBounds = endBounds = 0;
break;
}
int wordStart2 = previousIndexOfNotChar (text, " !?.\n", wordStart1);
if (wordStart2 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = wordStart1 + 1;
startBounds = previousIndexOfChar (text, " !?.\n", wordStart2) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
int wordEnd1 =previousIndexOfChar (text, " !?.\n", offset);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
if (wordEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = wordEnd1 + 1;
int wordEnd2 = previousIndexOfNotChar (text, " !?.\n", endBounds);
wordEnd2 = previousIndexOfChar (text, " !?.\n", wordEnd2);
if (wordEnd2 == -1) {
startBounds = 0;
break;
}
startBounds = previousIndexOfNotChar (text, " \n", wordEnd2 + 1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
int sentenceStart1 = previousIndexOfChar (text, "!?.", offset);
if (sentenceStart1 == -1) {
startBounds = endBounds = 0;
break;
}
int sentenceStart2 = previousIndexOfNotChar (text, "!?.", sentenceStart1);
if (sentenceStart2 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = sentenceStart1 + 1;
startBounds = previousIndexOfChar (text, "!?.", sentenceStart2) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
int sentenceEnd1 = previousIndexOfChar (text, "!?.", offset);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
if (sentenceEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = sentenceEnd1 + 1;
int sentenceEnd2 = previousIndexOfNotChar (text, "!?.", endBounds);
sentenceEnd2 = previousIndexOfChar (text, "!?.", sentenceEnd2);
if (sentenceEnd2 == -1) {
startBounds = 0;
break;
}
startBounds = previousIndexOfNotChar (text, " \n", sentenceEnd2 + 1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
int lineStart1 = previousIndexOfChar (text, "\n", offset);
if (lineStart1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = lineStart1 + 1;
startBounds = previousIndexOfChar (text, "\n", lineStart1) + 1;
break;
}
case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
int lineEnd1 = previousIndexOfChar (text, "\n", offset);
if (lineEnd1 == -1) {
startBounds = endBounds = 0;
break;
}
endBounds = lineEnd1;
startBounds = previousIndexOfChar (text, "\n", lineEnd1);
if (startBounds == -1) startBounds = 0;
break;
}
}
OS.memmove (start_offset, new int[] {startBounds}, 4);
OS.memmove (end_offset, new int[] {endBounds}, 4);
text = text.substring (startBounds, endBounds);
byte[] bytes = Converter.wcsToMbcs (null, text, true);
int /*long*/ result = OS.g_malloc (bytes.length);
OS.memmove (result, bytes, bytes.length);
return result;
}
return 0;
}
AccessibleListener[] getAccessibleListeners () {
if (accessible == null) return new AccessibleListener [0];
AccessibleListener[] result = accessible.getAccessibleListeners ();
return result != null ? result : new AccessibleListener [0];
}
static AccessibleObject getAccessibleObject (int /*long*/ atkObject) {
return (AccessibleObject)AccessibleObjects.get (new LONG (atkObject));
}
AccessibleObject getChildByHandle (int /*long*/ handle) {
return (AccessibleObject) children.get (new LONG (handle));
}
AccessibleObject getChildByID (int childId) {
if (childId == ACC.CHILDID_SELF) return this;
Enumeration elements = children.elements ();
while (elements.hasMoreElements ()) {
AccessibleObject object = (AccessibleObject) elements.nextElement ();
if (object.id == childId) return object;
}
return null;
}
AccessibleObject getChildByIndex (int childIndex) {
Enumeration elements = children.elements ();
while (elements.hasMoreElements ()) {
AccessibleObject object = (AccessibleObject) elements.nextElement ();
if (object.index == childIndex) return object;
}
return null;
}
AccessibleControlListener[] getControlListeners () {
if (accessible == null) return new AccessibleControlListener [0];
AccessibleControlListener[] result = accessible.getControlListeners ();
return result != null ? result : new AccessibleControlListener [0];
}
String getText () {
int /*long*/ parentResult = 0;
String parentText = ""; //$NON-NLS-1$
if (ATK.g_type_is_a (parentType, ATK_TEXT_TYPE)) {
int /*long*/ superType = ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (handle));
AtkTextIface textIface = new AtkTextIface ();
ATK.memmove (textIface, superType);
int /*long*/ characterCount = 0;
if (textIface.get_character_count != 0) {
characterCount = ATK.call (textIface.get_character_count, handle);
}
if (characterCount > 0 && textIface.get_text != 0) {
parentResult = ATK.call (textIface.get_text, handle, 0, characterCount);
if (parentResult != 0) {
int length = OS.strlen (parentResult);
byte [] buffer = new byte [length];
OS.memmove (buffer, parentResult, length);
parentText = new String (Converter.mbcsToWcs (null, buffer));
}
}
}
AccessibleControlListener[] controlListeners = getControlListeners ();
if (controlListeners.length == 0) return parentText;
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
event.childID = id;
event.result = parentText;
for (int i = 0; i < controlListeners.length; i++) {
controlListeners [i].getValue (event);
}
return event.result;
}
AccessibleTextListener[] getTextListeners () {
if (accessible == null) return new AccessibleTextListener [0];
AccessibleTextListener[] result = accessible.getTextListeners ();
return result != null ? result : new AccessibleTextListener [0];
}
static int /*long*/ gObjectClass_finalize (int /*long*/ atkObject) {
int /*long*/ superType = ATK.g_type_class_peek_parent (ATK.G_OBJECT_GET_CLASS (atkObject));
int /*long*/ gObjectClass = ATK.G_OBJECT_CLASS (superType);
GObjectClass objectClassStruct = new GObjectClass ();
ATK.memmove (objectClassStruct, gObjectClass);
ATK.call (objectClassStruct.finalize, atkObject);
AccessibleObject object = getAccessibleObject (atkObject);
if (object != null) {
AccessibleObjects.remove (new LONG (atkObject));
object.release ();
}
return 0;
}
static int nextIndexOfChar (String string, String searchChars, int startIndex) {
int result = string.length ();
for (int i = 0; i < searchChars.length (); i++) {
char current = searchChars.charAt (i);
int index = string.indexOf (current, startIndex);
if (index != -1) result = Math.min (result, index);
}
return result;
}
static int nextIndexOfNotChar (String string, String searchChars, int startIndex) {
int length = string.length ();
int index = startIndex;
while (index < length) {
char current = string.charAt (index);
if (searchChars.indexOf (current) == -1) break;
index++;
}
return index;
}
static int previousIndexOfChar (String string, String searchChars, int startIndex) {
int result = -1;
if (startIndex < 0) return result;
string = string.substring (0, startIndex);
for (int i = 0; i < searchChars.length (); i++) {
char current = searchChars.charAt (i);
int index = string.lastIndexOf (current);
if (index != -1) result = Math.max (result, index);
}
return result;
}
static int previousIndexOfNotChar (String string, String searchChars, int startIndex) {
if (startIndex < 0) return -1;
int index = startIndex - 1;
while (index >= 0) {
char current = string.charAt (index);
if (searchChars.indexOf (current) == -1) break;
index--;
}
return index;
}
void release () {
if (DEBUG) System.out.println("AccessibleObject.release: " + handle);
accessible = null;
Enumeration elements = children.elements ();
while (elements.hasMoreElements ()) {
AccessibleObject child = (AccessibleObject) elements.nextElement ();
if (child.isLightweight) OS.g_object_unref (child.handle);
}
if (parent != null) parent.removeChild (this, false);
}
void removeChild (AccessibleObject child, boolean unref) {
children.remove (new LONG (child.handle));
if (unref && child.isLightweight) OS.g_object_unref (child.handle);
}
void selectionChanged () {
OS.g_signal_emit_by_name (handle, ATK.selection_changed);
}
void setFocus (int childID) {
updateChildren ();
AccessibleObject accObject = getChildByID (childID);
if (accObject != null) {
ATK.atk_focus_tracker_notify (accObject.handle);
}
}
void setParent (AccessibleObject parent) {
this.parent = parent;
}
void textCaretMoved(int index) {
OS.g_signal_emit_by_name (handle, ATK.text_caret_moved, index);
}
void textChanged(int type, int startIndex, int length) {
if (type == ACC.TEXT_DELETE) {
OS.g_signal_emit_by_name (handle, ATK.text_changed_delete, startIndex, length);
} else {
OS.g_signal_emit_by_name (handle, ATK.text_changed_insert, startIndex, length);
}
}
void textSelectionChanged() {
OS.g_signal_emit_by_name (handle, ATK.text_selection_changed);
}
void updateChildren () {
if (isLightweight) return;
AccessibleControlListener[] listeners = getControlListeners ();
if (listeners.length == 0) return;
AccessibleControlEvent event = new AccessibleControlEvent (accessible);
for (int i = 0; i < listeners.length; i++) {
listeners [i].getChildren (event);
}
if (event.children != null && event.children.length > 0) {
Vector idsToKeep = new Vector (children.size ());
if (event.children [0] instanceof Integer) {
/* an array of child id's (Integers) was answered */
int /*long*/ parentType = AccessibleFactory.getDefaultParentType ();
for (int i = 0; i < event.children.length; i++) {
AccessibleObject object = getChildByIndex (i);
if (object == null) {
int /*long*/ childType = AccessibleFactory.getChildType (accessible, i);
object = new AccessibleObject (childType, 0, accessible, parentType, true);
AccessibleObjects.put (new LONG (object.handle), object);
addChild (object);
object.index = i;
}
try {
object.id = ((Integer)event.children[i]).intValue ();
} catch (ClassCastException e) {
/* a non-ID value was given so don't set the ID */
}
idsToKeep.addElement (new LONG (object.handle));
}
} else {
/* an array of Accessible children was answered */
int childIndex = 0;
for (int i = 0; i < event.children.length; i++) {
AccessibleObject object = null;
try {
object = ((Accessible)event.children [i]).accessibleObject;
} catch (ClassCastException e) {
/* a non-Accessible value was given so nothing to do here */
}
if (object != null) {
object.index = childIndex++;
idsToKeep.addElement (new LONG (object.handle));
}
}
}
/* remove old children that were not provided as children anymore */
Enumeration ids = children.keys ();
while (ids.hasMoreElements ()) {
LONG id = (LONG)ids.nextElement ();
if (!idsToKeep.contains (id)) {
AccessibleObject object = (AccessibleObject) children.get (id);
removeChild (object, true);
}
}
}
}
}