PRUint32 nsAccessibleWrap::mAtkTypeNameIndex = 0;
static void finalizeCB(GObject *aObj);/* callbacks for AtkObject virtual functions */static const gchar*        getNameCB (AtkObject *aAtkObj);static const gchar*        getDescriptionCB (AtkObject *aAtkObj);static AtkRole             getRoleCB(AtkObject *aAtkObj);static AtkObject*          getParentCB(AtkObject *aAtkObj);static gint                getChildCountCB(AtkObject *aAtkObj);static AtkObject*          refChildCB(AtkObject *aAtkObj, gint aChildIndex);static gint                getIndexInParentCB(AtkObject *aAtkObj);static AtkStateSet*        refStateSetCB(AtkObject *aAtkObj);/* the missing atkobject virtual functions *//*  static AtkRelationSet*     refRelationSetCB(AtkObject *aAtkObj);  static AtkLayer            getLayerCB(AtkObject *aAtkObj);  static gint                getMdiZorderCB(AtkObject *aAtkObj);  static void                SetNameCB(AtkObject *aAtkObj,  const gchar *name);  static void                SetDescriptionCB(AtkObject *aAtkObj,  const gchar *description);  static void                SetParentCB(AtkObject *aAtkObj,  AtkObject *parent);  static void                SetRoleCB(AtkObject *aAtkObj,  AtkRole role);  static guint               ConnectPropertyChangeHandlerCB(  AtkObject  *aObj,  AtkPropertyChangeHandler *handler);  static void                RemovePropertyChangeHandlerCB(  AtkObject *aAtkObj,  guint handler_id);  static void                InitializeCB(AtkObject *aAtkObj,  gpointer data);  static void                ChildrenChangedCB(AtkObject *aAtkObj,  guint change_index,  gpointer changed_child);  static void                FocusEventCB(AtkObject *aAtkObj,  gboolean focus_in);  static void                PropertyChangeCB(AtkObject *aAtkObj,  AtkPropertyValues *values);  static void                StateChangeCB(AtkObject *aAtkObj,  const gchar *name,  gboolean state_set);  static void                VisibleDataChangedCB(AtkObject *aAtkObj);*/G_END_DECLSstatic gpointer parent_class = NULL;GTypemai_atk_object_get_type(void){    static GType type = 0;    if (!type) {        static const GTypeInfo tinfo = {            sizeof(MaiAtkObjectClass),            (GBaseInitFunc)NULL,            (GBaseFinalizeFunc)NULL,            (GClassInitFunc)classInitCB,            (GClassFinalizeFunc)NULL,            NULL, /* class data */            sizeof(MaiAtkObject), /* instance size */            0, /* nb preallocs */            (GInstanceInitFunc)NULL,            NULL /* value table */        };        type = g_type_register_static(ATK_TYPE_OBJECT,                                      "MaiAtkObject", &tinfo, GTypeFlags(0));    }    return type;}#ifdef MAI_LOGGINGPRInt32 nsAccessibleWrap::mAccWrapCreated = 0;PRInt32 nsAccessibleWrap::mAccWrapDeleted = 0;#endifPRUint32 nsAccessibleWrap::mAtkTypeNameIndex = 0;nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode,                                   nsIWeakReference *aShell)    : nsAccessible(aNode, aShell),      mMaiAtkObject(nsnull),      mInterfaces(nsnull),      mInterfaceCount(0){#ifdef MAI_LOGGING    ++mAccWrapCreated;#endif    MAI_LOG_DEBUG(("==nsAccessibleWrap creating: this=%p,total=%d left=%d\n",                   (void*)this, mAccWrapCreated,                  (mAccWrapCreated-mAccWrapDeleted)));}nsAccessibleWrap::~nsAccessibleWrap(){#ifdef MAI_LOGGING    ++mAccWrapDeleted;#endif    MAI_LOG_DEBUG(("==nsAccessibleWrap deleting: this=%p,total=%d left=%d\n",                   (void*)this, mAccWrapDeleted,                   (mAccWrapCreated-mAccWrapDeleted)));    if (mMaiAtkObject) {        MAI_ATK_OBJECT(mMaiAtkObject)->accWrap = nsnull;        g_object_unref(mMaiAtkObject);    }    if (mInterfaces) {        for (int index = 0; index < MAI_INTERFACE_NUM; ++index)            delete mInterfaces[index];        delete [] mInterfaces;    }}NS_IMETHODIMP nsAccessibleWrap::GetExtState(PRUint32 *aState){    PRUint32 state;    nsAccessible::GetState(&state);    if (!(state & STATE_INVISIBLE))      *aState |= STATE_SHOWING;    return NS_OK;}NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible){    *aOutAccessible = nsnull;    if (!mMaiAtkObject) {        CreateMaiInterfaces();        mMaiAtkObject =            NS_REINTERPRET_CAST(AtkObject *,                                g_object_new(GetMaiAtkType(), NULL));        NS_ENSURE_TRUE(mMaiAtkObject, NS_ERROR_OUT_OF_MEMORY);        atk_object_initialize(mMaiAtkObject, this);        mMaiAtkObject->role = ATK_ROLE_INVALID;        mMaiAtkObject->layer = ATK_LAYER_INVALID;    }    *aOutAccessible = mMaiAtkObject;    return NS_OK;}AtkObject *nsAccessibleWrap::GetAtkObject(void){    void *atkObj = nsnull;    GetNativeInterface(&atkObj);    return NS_STATIC_CAST(AtkObject *, atkObj);}/* private */nsresultnsAccessibleWrap::CreateMaiInterfaces(void){    typedef MaiInterface * MaiInterfacePointer;    if (!mInterfaces) {        mInterfaces = new MaiInterfacePointer[MAI_INTERFACE_NUM];        for (PRUint16 index = 0; index < MAI_INTERFACE_NUM; ++index) {            mInterfaces[index] = nsnull;        }        NS_ENSURE_TRUE(mInterfaces, NS_ERROR_OUT_OF_MEMORY);    }    // Add Interfaces for each nsIAccessible.ext interfaces    nsresult rv;    // the Component interface are supported by all nsIAccessible    MaiInterfaceComponent *maiInterfaceComponent =        new MaiInterfaceComponent(this);    NS_ENSURE_TRUE(maiInterfaceComponent, NS_ERROR_OUT_OF_MEMORY);    rv = AddMaiInterface(maiInterfaceComponent);    NS_ENSURE_SUCCESS(rv, rv);    // Add Action interface if the action count is more than zero.    PRUint8 actionCount = 0;    rv = GetNumActions(&actionCount);    if (NS_SUCCEEDED(rv) && actionCount > 0) {        MaiInterfaceAction *maiInterfaceAction = new MaiInterfaceAction(this);        NS_ENSURE_TRUE(maiInterfaceAction, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceAction);        NS_ENSURE_SUCCESS(rv, rv);    }    //nsIAccessibleText    nsCOMPtr<nsIAccessibleText> accessInterfaceText;    QueryInterface(NS_GET_IID(nsIAccessibleText),                   getter_AddRefs(accessInterfaceText));    if (accessInterfaceText) {        MaiInterfaceText *maiInterfaceText = new MaiInterfaceText(this);        NS_ENSURE_TRUE(maiInterfaceText, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceText);        NS_ENSURE_SUCCESS(rv, rv);    }    //nsIAccessibleEditableText    nsCOMPtr<nsIAccessibleEditableText> accessInterfaceEditableText;    QueryInterface(NS_GET_IID(nsIAccessibleEditableText),                   getter_AddRefs(accessInterfaceEditableText));    if (accessInterfaceEditableText) {        MaiInterfaceEditableText *maiInterfaceEditableText =            new MaiInterfaceEditableText(this);        NS_ENSURE_TRUE(maiInterfaceEditableText, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceEditableText);        NS_ENSURE_SUCCESS(rv, rv);    }    //nsIAccessibleSelection    nsCOMPtr<nsIAccessibleSelectable> accessInterfaceSelection;    QueryInterface(NS_GET_IID(nsIAccessibleSelectable),                   getter_AddRefs(accessInterfaceSelection));    if (accessInterfaceSelection) {        MaiInterfaceSelection *maiInterfaceSelection =            new MaiInterfaceSelection(this);        NS_ENSURE_TRUE(maiInterfaceSelection, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceSelection);        NS_ENSURE_SUCCESS(rv, rv);    }    //nsIAccessibleValue    nsCOMPtr<nsIAccessibleValue> accessInterfaceValue;    QueryInterface(NS_GET_IID(nsIAccessibleValue),                   getter_AddRefs(accessInterfaceValue));    if (accessInterfaceValue) {        MaiInterfaceValue *maiInterfaceValue = new MaiInterfaceValue(this);        NS_ENSURE_TRUE(maiInterfaceValue, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceValue);        NS_ENSURE_SUCCESS(rv, rv);    }    //nsIAccessibleHypertext    PRInt32 linkCount = 0;    nsCOMPtr<nsIAccessibleHyperText> accessInterfaceHypertext;    QueryInterface(NS_GET_IID(nsIAccessibleHyperText),                   getter_AddRefs(accessInterfaceHypertext));    if (accessInterfaceHypertext) {        rv = accessInterfaceHypertext->GetLinks(&linkCount);        if (NS_SUCCEEDED(rv) && (linkCount > 0)) {            MaiInterfaceHypertext *maiInterfaceHypertext =                new MaiInterfaceHypertext(this, mWeakShell);            NS_ENSURE_TRUE(maiInterfaceHypertext, NS_ERROR_OUT_OF_MEMORY);            rv = AddMaiInterface(maiInterfaceHypertext);            NS_ENSURE_SUCCESS(rv, rv);        }    }    //nsIAccessibleTable    nsCOMPtr<nsIAccessibleTable> accessInterfaceTable;    QueryInterface(NS_GET_IID(nsIAccessibleTable),                   getter_AddRefs(accessInterfaceTable));    if (accessInterfaceTable) {        MaiInterfaceTable *maiInterfaceTable = new MaiInterfaceTable(this);        NS_ENSURE_TRUE(maiInterfaceTable, NS_ERROR_OUT_OF_MEMORY);        rv = AddMaiInterface(maiInterfaceTable);        NS_ENSURE_SUCCESS(rv, rv);    }    return rv;}nsresultnsAccessibleWrap::AddMaiInterface(MaiInterface *aMaiIface){    NS_ENSURE_ARG_POINTER(aMaiIface);    MaiInterfaceType aMaiIfaceType = aMaiIface->GetType();    if ((aMaiIfaceType <= MAI_INTERFACE_INVALID) ||        (aMaiIfaceType >= MAI_INTERFACE_NUM))        return NS_ERROR_FAILURE;    // if same type of If has been added, release previous one    if (mInterfaces[aMaiIfaceType]) {        delete mInterfaces[aMaiIfaceType];    }    mInterfaces[aMaiIfaceType] = aMaiIface;    mInterfaceCount++;    return NS_OK;}MaiInterface *nsAccessibleWrap::GetMaiInterface(PRInt16 aIfaceType){    NS_ENSURE_TRUE(aIfaceType > MAI_INTERFACE_INVALID, nsnull);    NS_ENSURE_TRUE(aIfaceType < MAI_INTERFACE_NUM, nsnull);    return mInterfaces[aIfaceType];}PRUint32nsAccessibleWrap::GetMaiAtkType(void){    GType type;    static const GTypeInfo tinfo = {        sizeof(MaiAtkObjectClass),        (GBaseInitFunc) NULL,        (GBaseFinalizeFunc) NULL,        (GClassInitFunc) NULL,        (GClassFinalizeFunc) NULL,        NULL, /* class data */        sizeof(MaiAtkObject), /* instance size */        0, /* nb preallocs */        (GInstanceInitFunc) NULL,        NULL /* value table */    };    if (mInterfaceCount == 0)        return MAI_TYPE_ATK_OBJECT;    type = g_type_register_static(MAI_TYPE_ATK_OBJECT,                                  nsAccessibleWrap::GetUniqueMaiAtkTypeName(),                                  &tinfo, GTypeFlags(0));    for (int index = 0; index < MAI_INTERFACE_NUM; index++) {        if (!mInterfaces[index])            continue;        g_type_add_interface_static(type,                                    mInterfaces[index]->GetAtkType(),                                    mInterfaces[index]->GetInterfaceInfo());    }    return type;}const char *nsAccessibleWrap::GetUniqueMaiAtkTypeName(void){#define MAI_ATK_TYPE_NAME_LEN (30)     /* 10+sizeof(gulong)*8/4+1 < 30 */    static gchar namePrefix[] = "MaiAtkType";   /* size = 10 */    static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];    sprintf(name, "%s%lx", namePrefix, mAtkTypeNameIndex++);    name[MAI_ATK_TYPE_NAME_LEN] = '\0';    MAI_LOG_DEBUG(("MaiWidget::LastedTypeName=%s\n", name));    return name;}/******************************************************************************The following nsIAccessible states aren't translated, just ignored.  STATE_MIXED:         For a three-state check box.  STATE_READONLY:      The object is designated read-only.  STATE_HOTTRACKED:    Means its appearance has changed to indicate mouse                       over it.  STATE_DEFAULT:       Represents the default button in a window.  STATE_FLOATING:      Not supported yet.  STATE_MARQUEED:      Indicate scrolling or moving text or graphics.  STATE_ANIMATED:  STATE_OFFSCREEN:     Has no on-screen representation.  STATE_MOVEABLE:  STATE_SELFVOICING:   The object has self-TTS.  STATE_LINKED:        The object is formatted as a hyperlink.  STATE_TRAVERSE:      The object is a hyperlink that has been visited.  STATE_EXTSELECTABLE: Indicates that an object extends its selectioin.  STATE_ALERT_LOW:     Not supported yet.  STATE_ALERT_MEDIUM:  Not supported yet.  STATE_ALERT_HIGH:    Not supported yet.  STATE_PROTECTED:     The object is a password-protected edit control.  STATE_HASPOPUP:      Object displays a pop-up menu or window when invoked.Returned AtkStatusSet never contain the following AtkStates.  ATK_STATE_ARMED:     Indicates that the object is armed.  ATK_STATE_DEFUNCT:   Indicates the user interface object corresponding to                       thus object no longer exists.  ATK_STATE_EDITABLE:  Indicates the user can change the contents of the object.  ATK_STATE_HORIZONTAL:Indicates the orientation of this object is horizontal.  ATK_STATE_ICONIFIED:  ATK_STATE_OPAQUE:     Indicates the object paints every pixel within its                        rectangular region  ATK_STATE_STALE:      The index associated with this object has changed since                        the user accessed the object******************************************************************************/voidnsAccessibleWrap::TranslateStates(PRUint32 aState, void *aAtkStateSet){    if (!aAtkStateSet)        return;    AtkStateSet *state_set = NS_STATIC_CAST(AtkStateSet *, aAtkStateSet);    if (aState & nsIAccessible::STATE_SELECTED)        atk_state_set_add_state (state_set, ATK_STATE_SELECTED);    if (aState & nsIAccessible::STATE_FOCUSED)        atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);    if (aState & nsIAccessible::STATE_PRESSED)        atk_state_set_add_state (state_set, ATK_STATE_PRESSED);    if (aState & nsIAccessible::STATE_CHECKED)        atk_state_set_add_state (state_set, ATK_STATE_CHECKED);    if (aState & nsIAccessible::STATE_EXPANDED)        atk_state_set_add_state (state_set, ATK_STATE_EXPANDED);    if (aState & nsIAccessible::STATE_COLLAPSED)        atk_state_set_add_state (state_set, ATK_STATE_EXPANDABLE);                       // The control can't accept input at this time    if (aState & nsIAccessible::STATE_BUSY)        atk_state_set_add_state (state_set, ATK_STATE_BUSY);    if (aState & nsIAccessible::STATE_FOCUSABLE)        atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);    if (!(aState & nsIAccessible::STATE_INVISIBLE))        atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);    if (aState & nsIAccessible::STATE_SELECTABLE)        atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE);    if (aState & nsIAccessible::STATE_SIZEABLE)        atk_state_set_add_state (state_set, ATK_STATE_RESIZABLE);    if (aState & nsIAccessible::STATE_MULTISELECTABLE)        atk_state_set_add_state (state_set, ATK_STATE_MULTISELECTABLE);    if (!(aState & nsIAccessible::STATE_UNAVAILABLE)) {        atk_state_set_add_state (state_set, ATK_STATE_ENABLED);        atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);    }    // The following state is    // Extended state flags (for now non-MSAA, for Java and Gnome/ATK support)    // This is only the states that there isn't already a mapping for in MSAA    // See www.accessmozilla.org/article.php?sid=11 for information on the    // mappings between accessibility API state    if (aState & nsIAccessible::STATE_INVALID)        atk_state_set_add_state (state_set, ATK_STATE_INVALID);    if (aState & nsIAccessible::STATE_ACTIVE)        atk_state_set_add_state (state_set, ATK_STATE_ACTIVE);    if (aState & nsIAccessible::STATE_EXPANDABLE)        atk_state_set_add_state (state_set, ATK_STATE_EXPANDABLE);    if (aState & nsIAccessible::STATE_MODAL)        atk_state_set_add_state (state_set, ATK_STATE_MODAL);    if (aState & nsIAccessible::STATE_MULTI_LINE)        atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);    if (aState & nsIAccessible::STATE_SENSITIVE)        atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);    if (aState & nsIAccessible::STATE_SHOWING)        atk_state_set_add_state (state_set, ATK_STATE_SHOWING);    if (aState & nsIAccessible::STATE_SINGLE_LINE)        atk_state_set_add_state (state_set, ATK_STATE_SINGLE_LINE);    if (aState & nsIAccessible::STATE_TRANSIENT)        atk_state_set_add_state (state_set, ATK_STATE_TRANSIENT);    if (aState & nsIAccessible::STATE_VERTICAL)        atk_state_set_add_state (state_set, ATK_STATE_VERTICAL);}PRBool nsAccessibleWrap::IsValidObject(){    // to ensure we are not shut down    return (mDOMNode != nsnull);}/* static functions for ATK callbacks */voidclassInitCB(AtkObjectClass *aClass){    GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);    parent_class = g_type_class_peek_parent(aClass);    aClass->get_name = getNameCB;    aClass->get_description = getDescriptionCB;    aClass->get_parent = getParentCB;    aClass->get_n_children = getChildCountCB;    aClass->ref_child = refChildCB;    aClass->get_index_in_parent = getIndexInParentCB;    aClass->get_role = getRoleCB;    aClass->ref_state_set = refStateSetCB;    aClass->initialize = initializeCB;    gobject_class->finalize = finalizeCB;    mai_atk_object_signals [ACTIVATE] =    g_signal_new ("activate",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [CREATE] =    g_signal_new ("create",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [DEACTIVATE] =    g_signal_new ("deactivate",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [DESTROY] =    g_signal_new ("destroy",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [MAXIMIZE] =    g_signal_new ("maximize",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [MINIMIZE] =    g_signal_new ("minimize",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [RESIZE] =    g_signal_new ("resize",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);    mai_atk_object_signals [RESTORE] =    g_signal_new ("restore",                  MAI_TYPE_ATK_OBJECT,                  G_SIGNAL_RUN_LAST,                  0, /* default signal handler */                  NULL, NULL,                  g_cclosure_marshal_VOID__VOID,                  G_TYPE_NONE, 0);}voidinitializeCB(AtkObject *aAtkObj, gpointer aData){    NS_ASSERTION((MAI_IS_ATK_OBJECT(aAtkObj)), "Invalid AtkObject");    NS_ASSERTION(aData, "Invalid Data to init AtkObject");    if (!aAtkObj || !aData)        return;    /* call parent init function */    /* AtkObjectClass has not a "initialize" function now,     * maybe it has later     */    if (ATK_OBJECT_CLASS(parent_class)->initialize)        ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);    /* initialize object */    MAI_ATK_OBJECT(aAtkObj)->accWrap =        NS_STATIC_CAST(nsAccessibleWrap*, aData);#ifdef MAI_LOGGING    ++sMaiAtkObjCreated;#endif    MAI_LOG_DEBUG(("MaiAtkObj Create obj=%p for AccWrap=%p, all=%d, left=%d\n",                   (void*)aAtkObj, (void*)aData, sMaiAtkObjCreated,                   (sMaiAtkObjCreated-sMaiAtkObjDeleted)));}voidfinalizeCB(GObject *aObj){    if (!MAI_IS_ATK_OBJECT(aObj))        return;    NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == nsnull, "AccWrap NOT null");#ifdef MAI_LOGGING    ++sMaiAtkObjDeleted;#endif    MAI_LOG_DEBUG(("MaiAtkObj Delete obj=%p, all=%d, left=%d\n",                   (void*)aObj, sMaiAtkObjCreated,                   (sMaiAtkObjCreated-sMaiAtkObjDeleted)));    // call parent finalize function    // finalize of GObjectClass will unref the accessible parent if has    if (G_OBJECT_CLASS (parent_class)->finalize)        G_OBJECT_CLASS (parent_class)->finalize(aObj);}