/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

#include <cassert>

#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>

#include <oleacc.h>
#ifndef _SV_AccObjectWinManager_HXX
#include "AccObjectWinManager.hxx"
#endif
#include "AccEventListener.hxx"
#include "AccComponentEventListener.hxx"
#include "AccContainerEventListener.hxx"
#include "AccDialogEventListener.hxx"
#include "AccWindowEventListener.hxx"
#include "AccFrameEventListener.hxx"
#include "AccMenuEventListener.hxx"
#include "AccObjectContainerEventListener.hxx"
#include "AccParagraphEventListener.hxx"
#include "AccTextComponentEventListener.hxx"
#include "AccListEventListener.hxx"
#include "AccTreeEventListener.hxx"
#include "AccTableEventListener.hxx"
#include "AccObject.hxx"
#include "unomsaaevent.hxx"
#include "checkmt.hxx"

#define CHILDID_SELF             0


using namespace std;
using namespace com::sun::star::accessibility;
using namespace com::sun::star::uno;

AccObjectWinManager* g_acc_manager = NULL;
AccObjectWinManager* AccObjectWinManager::me = NULL;

/**
   * Implementation of interface XMSAAService's method getAccObjectPtr() that return the
   * corresponding com interface with the MS event.
   *
   * @param   
   * @return  Com interface.
   */
long GetMSComPtr(long hWnd, long lParam, long wParam)
{
    if( g_acc_manager )
        return (long)g_acc_manager->Get_ToATInterface(HWND((void*)hWnd),lParam,wParam );
    return NULL;
}

/**
   * constructor
   * @param   Agent The agent kept in all listeners,it's the sole interface by which
   *                listener communicate with windows manager.
   *          pEventAccObj The present event accobject.
   *          oldFocus     Last focused object.
   *          isSelectionChanged flag that identifies if there is selection changed.
   *		  selectionChildObj  Selected object.
   *          dChildID	Chile resource ID.
   *          hAcc TopWindowHWND
   * @return  
   */
AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ):
        pAgent( Agent ),
        oldFocus( NULL )
{
}

/**
   * Public method to produce manager
   * @param   Agent The agent kept in all listeners,it's the sole interface by which
   *          listener communicate with windows manager.
   * @return  
   */
AccObjectWinManager* AccObjectWinManager::CreateAccObjectWinManagerInstance( AccObjectManagerAgent* Agent )
{
    if( me == NULL )
    {
        me = new AccObjectWinManager( Agent );
        g_acc_manager = me;
        return me;
    }

    return me;
}


/**
   * Destructor,clear all resource.
   * @param   
   * @return  
   */
AccObjectWinManager::~AccObjectWinManager()
{
    XIdAccList.clear();
    HwndXAcc.clear();
    XResIdAccList.clear();
    XHWNDDocList.clear();
#ifdef ACC_DEBUG

    fclose( pFile );
#endif
}


/**
   * Get valid com object interface when notifying some MSAA event
   * @param pWND The top window handle that contains that event control.
   * @param wParam Windows system interface. 
   * @return Com interface with event. 
   */

long AccObjectWinManager::Get_ToATInterface( HWND hWnd, long lParam, long wParam)
{
    vos::OGuard localGuard(maATInterfaceMutex);//

    IMAccessible* pRetIMAcc = NULL;

    if(lParam == OBJID_CLIENT )
    {
        AccObject* topWindowAccObj = GetTopWindowAccObj(hWnd);
        if(topWindowAccObj)
        {
            pRetIMAcc = topWindowAccObj->GetIMAccessible();
            if(pRetIMAcc)
                pRetIMAcc->AddRef();//increase COM reference count
        }
    }

    if ( pRetIMAcc && lParam == OBJID_CLIENT )
    {
        IAccessible* pTemp = dynamic_cast<IAccessible*>( pRetIMAcc );
        HRESULT result = LresultFromObject(IID_IAccessible, wParam, pTemp);
        pTemp->Release();
        return result;
    }
    return 0;
}

/**
   * Search AccObject by XAccessible pointer from our container.
   * @param pXAcc XAccessible interface.
   * @return Pointer of accObject that is found. 
   */
AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
{
    if( pXAcc == NULL)
        return NULL;

    XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc );
    if ( pIndTemp == XIdAccList.end() )
        return NULL;

    return &(pIndTemp->second);
}

/**
   * Search XAccessible by AccObject pointer from our container.
   * @param pAccObj AccObject pointer.
   * @return Pointer of XAccessible Interface. 
   */
XAccessible* AccObjectWinManager::GetXAccByAccObj(AccObject* pAccObj)
{
    XIdToAccObjHash::iterator iter = XIdAccList.begin();
    while(iter!=XIdAccList.end())
    {
        AccObject* tmp = &(iter->second);
        if(tmp== pAccObj)
            return (XAccessible*)(iter->first);
        iter++;
    }
    return NULL;
}

/**
   * get acc object of top window by its handle
   * @param hWnd, top window handle
   * @return pointer to AccObject
   */
AccObject* AccObjectWinManager::GetTopWindowAccObj(HWND hWnd)
{
    XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
    if(iterResult == HwndXAcc.end())
        return NULL;
    XAccessible* pXAcc = (XAccessible*)(iterResult->second);
    return GetAccObjByXAcc(pXAcc);
}

/**
   * Simulate MSAA event via XAccessible interface and event type.
   * @param pXAcc XAccessible interface.
   * @param state Customize Interface   
   * @return The terminate result that identifies if the call is successful. 
   */
sal_Bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc,short state)
{
    vos::OGuard aGuard(aNotifyMutex);

    if (!IsInMainThread())
    {
        return sal_False;
    }

    Reference< XAccessibleContext > pRContext;

    if( pXAcc == NULL)
        return sal_False;


    pRContext = pXAcc->getAccessibleContext();
    if( !pRContext.is() )
        return sal_False;


    AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);

    if(selfAccObj==NULL)
        return sal_False;

    int selectNum =0;

    long dChildID = selfAccObj->GetResID();
    HWND hAcc = selfAccObj->GetParentHWND();

    switch(state)
    {
    case UM_EVENT_STATE_FOCUSED:
        {
            UpdateAccFocus(pXAcc);
            if( selfAccObj )
                selfAccObj->UpdateDefaultAction( );
            UpdateValue(pXAcc);
            NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
            break;
        }
    case UM_EVENT_STATE_BUSY:
        NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_STATE_CHECKED:
        NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_STATE_PRESSED:
        NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;

    //Removed fire out selected event
    //case UM_EVENT_STATE_SELECTED:
    //	NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
    //	break;
    case UM_EVENT_STATE_ARMED:
        UpdateAccFocus(pXAcc);
        NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_MENU_START:
        NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_MENU_END:
        NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_MENUPOPUPSTART:
        NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_MENUPOPUPEND:
        NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_SELECTION_CHANGED:
        NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_SELECTION_CHANGED_ADD:
       	NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID  );
       	break;
    case UM_EVENT_SELECTION_CHANGED_REMOVE:
       	NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID  );
       	break;
    case UM_EVENT_SELECTION_CHANGED_WITHIN:
       	NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID  );
       	break;
    case UM_EVENT_OBJECT_VALUECHANGE:
        UpdateValue(pXAcc);
        NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_NAMECHANGE:
        NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_DESCRIPTIONCHANGE:
        NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_DEFACTIONCHANGE:
        NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_CARETCHANGE:
        NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_TEXTCHANGE:
        NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_ACTIVE_DESCENDANT_CHANGED:
        UpdateAccFocus(pXAcc);
        NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_BOUNDRECT_CHANGED:
        NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_VISIBLE_DATA_CHANGED:
        NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_SHOW :
        NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID  );
        NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID  );
	break;
    case UM_EVENT_TABLE_CAPTION_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_COLUMN_HEADER_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_MODEL_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_ROW_HEADER_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_SUMMARY_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
        NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_REORDER:
        NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_PAGE_CHANGED:
        NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_CHILD_REMOVED:
        NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_CHILD_ADDED:
        NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_OBJECT_PAGECHANGED:
        NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_TEXT_SELECTION_CHANGED:
        NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_SECTION_CHANGED:
        NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
        break;
    case UM_EVENT_COLUMN_CHANGED:
        NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
        break;
    default:
        break;
    }

    return sal_True;
}

/**
   * Get Parent XAccessible interface by XAccessible interface.
   * @param pXAcc XAccessible interface.
   * @return Parent XAccessible interface.
   */
XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
{
    AccObject* pObj= GetAccObjByXAcc(pXAcc);
    if( pObj ==NULL )
        return NULL;
    if(pObj->GetParentObj())
    {
        pObj = pObj->GetParentObj();
        return pObj->GetXAccessible().get();
    }
    return NULL;
}

/**
   * Get Parent role by XAccessible interface.
   * @param pXAcc XAccessible interface.
   * @return Parent role.
   */
short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
{
    AccObject* pObj= GetAccObjByXAcc(pXAcc);
    if( pObj ==NULL )
        return -1;
    if(pObj->GetParentObj())
    {
        pObj = pObj->GetParentObj();
        if(pObj->GetXAccessible().is())
        {
            XAccessible* pXAcc = pObj->GetXAccessible().get();
            Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
            if(pRContext.is())
                return pRContext->getAccessibleRole();
        }
    }
    return -1;
}

/**
   * Update focus objcet by new focused XAccessible interface.
   * @param newFocus New XAccessible interface that gets focus.
   * @return 
   */
void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
{
    AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
    if(pAccObjNew)
    {
        AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
        oldFocus = newFocus;
        pAccObjNew->setFocus();
        //if old == new, the pAccObjNew will be without focused state
        if (pAccObjOld && pAccObjOld != pAccObjNew)
            pAccObjOld->unsetFocus();
    }
}

/**
   * Update selected objcet by new focused XAccessible interface.
   * @param pXAcc XAccessible interface that has selected child changed.
   * @return Selected children count.
   */
int AccObjectWinManager::UpdateAccSelection(XAccessible* pXAcc)
{
    XAccessibleSelection* pSelection = NULL;
    Reference< XAccessibleContext > pRContext;

    if( pXAcc == NULL)
        return sal_False;

    pRContext = pXAcc->getAccessibleContext();
    if( !pRContext.is() )
        return sal_False;

    Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
    if( !pRSelection.is() )
        return sal_False;

    AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
    if(pAccObj==NULL)
        return sal_False;

    Reference<XAccessible> pRChild = NULL;
    AccObject* pAccChildObj = NULL;
    int selectNum= pRSelection->getSelectedAccessibleChildCount();

    IAccSelectionList oldSelection = pAccObj->GetSelection();

    if(selectNum > 4)//for selected.
        return selectNum;
    if(selectNum == 1 && oldSelection.size() == 0)
        return 1;

    for (int i=0;i<selectNum;i++)
    {
        pRChild = pRSelection->getSelectedAccessibleChild(i);
        if(!pRChild.is())
        {
            continue;
        }
        Reference<XAccessibleContext> pRChildContext = pRChild->getAccessibleContext();
        if(!pRChildContext.is())
        {
            continue;
        }
        long index = pRChildContext->getAccessibleIndexInParent();
        IAccSelectionList::iterator temp = oldSelection.find(index);
        if ( temp != oldSelection.end() )
        {
            oldSelection.erase(index);
            continue;
        }

        pAccChildObj = NULL;
        pAccChildObj = GetAccObjByXAcc(pRChild.get());
        if(!pAccChildObj)
        {
            InsertAccObj(pRChild.get(), pXAcc,pAccObj->GetParentHWND());
            pAccChildObj = GetAccObjByXAcc(pRChild.get());
        }

        pAccObj->AddSelect(index, pAccChildObj);

        if(pAccChildObj != NULL)
            NotifyWinEvent(EVENT_OBJECT_SELECTIONADD,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
    }

    IAccSelectionList::iterator iter = oldSelection.begin();
    while(iter!=oldSelection.end())
    {
        pAccObj->GetSelection().erase(iter->first);
        pAccChildObj = (AccObject*)(iter->second);
        if(pAccChildObj != NULL)
            NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
        iter++;
    }
    return 0;

}

/**
   * Delete child element from children list.
   * @param pObj Child element that should be removed from parant child list.
   * @return 
   */
void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
{
    AccObject *parentAccObj = pObj->GetParentObj();
    if( parentAccObj )
        parentAccObj->DeleteChild( pObj );
}

/**
   * Delete XAccessible items in top window handle hashtable
   * @param pXAcc XAccessible interface.
   * @return 
   */
void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible* pXAcc )
{
    XHWNDToXAccHash::iterator iter = HwndXAcc.begin();
    while(iter!=HwndXAcc.end())
    {
        if(iter->second == pXAcc )
        {
            HwndXAcc.erase(iter);
            return;
        }
        iter++;
    }
}

/**
   * Delete Delete all children with the tree root of XAccessible pointer
   * @param pXAcc Tree root XAccessible interface.
   * @return 
   */
void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
{
    vos::OGuard aGuard( aDeleteMutex );
    AccObject* currentObj=NULL;
    AccObject* childObj=NULL;
    XAccessible* pTmpXAcc=NULL;

    currentObj =  GetAccObjByXAcc( pXAcc);
    if(currentObj)
    {
        childObj = currentObj->NextChild();
        while(childObj)
        {
            pTmpXAcc = GetXAccByAccObj(childObj);
            if(pTmpXAcc)
            {
                DeleteChildrenAccObj(pTmpXAcc);
                DeleteAccObj(pTmpXAcc);
            }
            childObj = currentObj->NextChild();
        }
    }
}

/**
   * Delete Delete Acc object self.
   * @param pXAcc The XAccessible interface.
   * @return 
   */
void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
{
    vos::OGuard aGuard( aDeleteMutex );
    if( pXAcc == NULL )
        return;
    XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
    if( temp != XIdAccList.end() )
    {
        ResIdGen.SetSub( temp->second.GetResID() );
    }
    else
    {
        return;
    }

    AccObject& accObj = temp->second;
    DeleteAccChildNode( &accObj );
    DeleteAccListener( &accObj );
    if( accObj.GetIMAccessible() )
    {
        accObj.GetIMAccessible()->Release();
    }
    XIdAccList.erase( pXAcc );
    XResIdAccList.erase( accObj.GetResID() );
    DeleteFromHwndXAcc(pXAcc);
}

/**
   * Delete listener that inspects some XAccessible object
   * @param pAccObj Accobject pointer.
   * @return 
   */
void AccObjectWinManager::DeleteAccListener( AccObject*  pAccObj )
{
    AccEventListener* listener = pAccObj->getListener();
    if( listener==NULL )
        return;
    listener->removeMeFromBroadcaster();
    pAccObj->SetListener(NULL);
}

/**
   * Generate a child ID, which is used for AT
   * @param 
   * @return New resource ID.
   */
inline long AccObjectWinManager::ImpleGenerateResID()
{
    return ResIdGen.GenerateNewResID();
}

/**
   * Insert all children of the current acc object
   * @param pXAcc XAccessible interface
   * @param pWnd  Top Window handle
   * @return The calling result.
   */
sal_Bool AccObjectWinManager::InsertChildrenAccObj( com::sun::star::accessibility::XAccessible* pXAcc,
        HWND pWnd)
{
    if(!IsContainer(pXAcc))
        return sal_False;

    Reference< XAccessibleContext > pRContext;

    if( pXAcc == NULL)
        return sal_False;
    pRContext = pXAcc->getAccessibleContext();
    if( !pRContext.is() )
        return sal_False;

    short role = pRContext->getAccessibleRole();

    if(com::sun::star::accessibility::AccessibleRole::DOCUMENT == role )
    {
        if(IsStateManageDescendant(pXAcc))
        {
            return sal_True;
        }
    }

    int count = pRContext->getAccessibleChildCount();
    for (int i=0;i<count;i++)
    {
        Reference<XAccessible> mxAccessible
        = pRContext->getAccessibleChild(i);
        XAccessible* mpAccessible = mxAccessible.get();
        if(mpAccessible != NULL)
        {
            InsertAccObj( mpAccessible,pXAcc,pWnd );
            InsertChildrenAccObj(mpAccessible,pWnd);
        }
    }

    return sal_True;
}

/**
   * Insert child object.
   * @param pCurObj The child object
   * @param pParentObj The parant object
   * @param pWnd Top window handle.
   * @return 
   */
void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
{
    if(pCurObj)
    {
        if(pParentObj)
        {
            pParentObj->InsertChild(pCurObj);
        }
        else
        {
            pCurObj->UpdateValidWindow();
        }
    }
}

/**
   * Insert child object.
   * @param pCurObj The child object
   * @param pParentObj The parant object
   * @param pWnd Top window handle.
   * @return 
   */
sal_Bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
{
    XIdToAccObjHash::iterator itXacc = XIdAccList.find( (void*)pXAcc );
    if (itXacc != XIdAccList.end() )
    {
        short nCurRole =GetRole(pXAcc);
        if (AccessibleRole::SHAPE == nCurRole)
        {
            AccObject &objXacc = itXacc->second;
            AccObject *pObjParent = objXacc.GetParentObj();
            if (pObjParent &&
                    pObjParent->GetXAccessible().is() &&
                    pObjParent->GetXAccessible().get() != pParentXAcc)
            {
                XIdToAccObjHash::iterator itXaccParent  = XIdAccList.find( (void*)pParentXAcc );
                if(itXaccParent != XIdAccList.end())
                {
                    objXacc.SetParentObj(&(itXaccParent->second));
                }
            }
        }
        return sal_False;
    }


    Reference< XAccessibleContext > pRContext;

    if( pXAcc == NULL)
        return sal_False;

    pRContext = pXAcc->getAccessibleContext();
    if( !pRContext.is() )
        return sal_False;

    if( pWnd == NULL )
    {
        if(pParentXAcc)
        {
            AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
            if(pObj)
                pWnd = pObj->GetParentHWND();
        }
        if( pWnd == NULL )
            return sal_False;
    }

    AccObject pObj( pXAcc,pAgent );
    if( pObj.GetIMAccessible() == NULL )
        return sal_False;
    pObj.SetResID( this->ImpleGenerateResID());
    pObj.SetParentHWND( pWnd );

    //for file name support
    if ( pObj.GetRole() == DOCUMENT )
    {
        XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find( (long)pWnd );
        if ( aIter != XHWNDDocList.end() )
        {
            XHWNDDocList.erase( aIter );
        }
        XHWNDDocList.insert( XHWNDToDocumentHash::value_type( (long)pWnd, pXAcc ) );

    }
    //end of file name

    AccEventListener* listener = createAccEventListener(pXAcc, pAgent);
    if(listener==NULL)
        return sal_False;
    Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
    Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
    if (broadcaster.is())
    {
        Reference <XAccessibleEventListener> pp (
            static_cast< XAccessibleEventListener* >(listener),UNO_QUERY );
        if(pp.is())
        {
            broadcaster->addEventListener(pp);
        }
        else
        {
            delete listener;
            return sal_False;
        }
    }
    else
        return sal_False;

    XIdAccList.insert( XIdToAccObjHash::value_type( (void*)pXAcc, pObj ));
    XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc );
    XResIdAccList.insert(XResIdToAccObjHash::value_type(pObj.GetResID(),&(pIndTemp->second)));

    AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
    if( pCurObj )
    {
        pCurObj->SetListener( listener );
        if(listener != NULL)
            listener->acquire();
    }

    AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
    InsertAccChildNode(pCurObj,pParentObj,pWnd);
    if( pCurObj )
        pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
    return sal_True;
}


/**
   * save the pair <topwindowhandle, XAccessible>
   * @param hWnd, top window handle
   * @param pXAcc XAccessible interface for top window
   * @return void
   */
void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, com::sun::star::accessibility::XAccessible* pXAcc)
{
    HwndXAcc.insert( XHWNDToXAccHash::value_type( hWnd,(void*)pXAcc ) );
}


/**
   * create the corresponding listener.
   * @param pXAcc XAccessible interface.
   * @param Agent The agent kept in all listeners,it's the sole interface by which
   *        listener communicate with windows manager.
   * @return 
   */
AccEventListener* AccObjectWinManager::createAccEventListener(XAccessible* pXAcc, AccObjectManagerAgent* /* Agent */ )
{
    AccEventListener* listener = NULL;
    Reference<XAccessibleContext> xContext(pXAcc->getAccessibleContext(),UNO_QUERY);
    if(xContext.is())
    {
        switch( xContext->getAccessibleRole() )
        {
        case /*AccessibleRole::*/DIALOG:
            listener = new AccDialogEventListener(pXAcc,pAgent);
            break;
        case /*AccessibleRole::*/FRAME:
            listener = new AccFrameEventListener(pXAcc,pAgent);
            break;
        case /*AccessibleRole::*/WINDOW:
            listener = new AccWindowEventListener(pXAcc,pAgent);
            break;
        case /*AccessibleRole::*/ROOT_PANE:
            listener = new AccFrameEventListener(pXAcc,pAgent);
            break;
            //Container
        case /*AccessibleRole::*/CANVAS:
        case /*AccessibleRole::*/COMBO_BOX:
        case /*AccessibleRole::*/DOCUMENT:
        case /*AccessibleRole::*/END_NOTE:
        case /*AccessibleRole::*/FILLER:
        case /*AccessibleRole::*/FOOTNOTE:
        case /*AccessibleRole::*/FOOTER:
        case /*AccessibleRole::*/HEADER:
        case /*AccessibleRole::*/LAYERED_PANE:
        case /*AccessibleRole::*/MENU_BAR:
        case /*AccessibleRole::*/POPUP_MENU:
        case /*AccessibleRole::*/OPTION_PANE:
        case /*AccessibleRole::*/PAGE_TAB:
        case /*AccessibleRole::*/PAGE_TAB_LIST:
        case /*AccessibleRole::*/PANEL:
        case /*AccessibleRole::*/SCROLL_PANE:
        case /*AccessibleRole::*/SPLIT_PANE:
        case /*AccessibleRole::*/STATUS_BAR:
        case /*AccessibleRole::*/TABLE_CELL:
        case /*AccessibleRole::*/TOOL_BAR:
        case /*AccessibleRole::*/VIEW_PORT:
            listener = new AccContainerEventListener(pXAcc,pAgent);
            break;
        case /*AccessibleRole::*/PARAGRAPH:
        case /*AccessibleRole::*/HEADING:
            listener = new AccParagraphEventListener(pXAcc,pAgent);
            break;
            //Component
        case /*AccessibleRole::*/CHECK_BOX:
        case /*AccessibleRole::*/ICON:
        case /*AccessibleRole::*/LABEL:
        case /*AccessibleRole::*/MENU_ITEM:
        case /*AccessibleRole::*/CHECK_MENU_ITEM:
        case /*AccessibleRole::*/RADIO_MENU_ITEM:
        case /*AccessibleRole::*/PUSH_BUTTON:
        case /*AccessibleRole::*/RADIO_BUTTON:
        case /*AccessibleRole::*/SCROLL_BAR:
        case /*AccessibleRole::*/SEPARATOR:
        case /*AccessibleRole::*/TOGGLE_BUTTON:
        case /*AccessibleRole::*/BUTTON_DROPDOWN:
        case /*AccessibleRole::*/TOOL_TIP:
        case /*AccessibleRole::*/SPIN_BOX:
        case DATE_EDITOR:
            listener = new AccComponentEventListener(pXAcc,pAgent);
            break;
            //text component
        case /*AccessibleRole::*/TEXT:
            listener = new AccTextComponentEventListener(pXAcc,pAgent);
            break;
            //menu
        case /*AccessibleRole::*/MENU:
            listener = new AccMenuEventListener(pXAcc,pAgent);
            break;
            //object container
        case /*AccessibleRole::*/SHAPE:

        case /*AccessibleRole::*/EMBEDDED_OBJECT:
        case /*AccessibleRole::*/GRAPHIC:
        case /*AccessibleRole::*/TEXT_FRAME:
            listener = new AccObjectContainerEventListener(pXAcc,pAgent);
            break;
            //descendmanager
        case /*AccessibleRole::*/LIST:
            listener = new AccListEventListener(pXAcc,pAgent);
            break;
        case /*AccessibleRole::*/TREE:
            listener = new AccTreeEventListener(pXAcc,pAgent);
            break;
            //special
        case /*AccessibleRole::*/COLUMN_HEADER:
        case /*AccessibleRole::*/TABLE:
            listener = new AccTableEventListener(pXAcc,pAgent);
            break;
        default:
            listener = new AccContainerEventListener(pXAcc,pAgent);
            break;
        }
    }

    return listener;
}

/**
   * state is a combination integer, each bit of which represents a single state,
   * such as focused,1 for the state on,0 for the state off. Here call COM interface
   * to modify the state value, including DecreaseState.
   * @param pXAcc XAccessible interface.
   * @param pState Changed state.
   * @return 
   */
void AccObjectWinManager::DecreaseState( XAccessible* pXAcc,unsigned short pState )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->DecreaseState( pState );
}

/**
   * state is a combination integer, each bit of which represents a single state,such as focused,1 for
   * the state on,0 for the state off. Here call COM interface to modify the state value, including 
   * IncreaseState.
   * @param pXAcc XAccessible interface.
   * @param pState Changed state.
   * @return 
   */
void AccObjectWinManager::IncreaseState( XAccessible* pXAcc,unsigned short pState )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->IncreaseState( pState );
}

void  AccObjectWinManager::UpdateState( com::sun::star::accessibility::XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->UpdateState( );
}

/**
   * Set corresponding com object's accessible name via XAccessilbe interface and new
   * name
   * @param pXAcc XAccessible interface.
   * @return 
   */
void  AccObjectWinManager::UpdateAccName( XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->UpdateName();
}

void  AccObjectWinManager::UpdateAction( XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->UpdateAction();
}

void AccObjectWinManager::UpdateDescription( XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if ( pAccObj )
        pAccObj->UpdateDescription();
}

/**
   * Set corresponding com object's accessible location via XAccessilbe interface and new
   * location.
   * @param pXAcc XAccessible interface.
   * @return 
   */
void  AccObjectWinManager::SetLocation( XAccessible* pXAcc, long /*top*/, long /*left*/, long /*width*/, long /*height*/ )
{
    AccObject* pObj = GetAccObjByXAcc( pXAcc );
    //get the location from XComponent.
    Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
    if( pObj )
        pObj->UpdateLocation();
}

/**
   * Set corresponding com object's value  via XAccessilbe interface and new value.
   * @param pXAcc XAccessible interface.
   * @param pAny new value.
   * @return 
   */
void  AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->SetValue( pAny );
}

/**
   * Set corresponding com object's value  via XAccessilbe interface.
   * @param pXAcc XAccessible interface.
   * @return 
   */
void  AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->UpdateValue();
}

/**
   * Set corresponding com object's name via XAccessilbe interface and new name.
   * @param pXAcc XAccessible interface.
   * @param newName new name
   * @return 
   */
void  AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName)
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->SetName( newName );
}

/**
   * Set corresponding com object's description via XAccessilbe interface and new description.
   * @param pXAcc XAccessible interface.
   * @param newDesc new description
   * @return 
   */
void  AccObjectWinManager::SetDescription( XAccessible* pXAcc, Any newDesc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->SetDescription( newDesc );
}

/**
   * Set corresponding com object's role via XAccessilbe interface and new role.
   * @param pXAcc XAccessible interface.
   * @param Role new role
   * @return 
   */
void  AccObjectWinManager::SetRole( XAccessible* pXAcc, long Role )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if( pAccObj )
        pAccObj->SetRole( (short)Role );
}

/**
   * Judge if a XAccessible object is a container object.
   * @param pAccessible XAccessible interface.
   * @return If XAccessible object is container.
   */
sal_Bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
{
    try
    {
        if(pAccessible)
        {
            Reference<XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
            if(xContext.is())
            {
                switch( xContext->getAccessibleRole() )
                {
                case /*AccessibleRole::*/DIALOG:
                case /*AccessibleRole::*/FRAME:
                case /*AccessibleRole::*/WINDOW:
                case /*AccessibleRole::*/ROOT_PANE:
                case /*AccessibleRole::*/CANVAS:
                case /*AccessibleRole::*/COMBO_BOX:
                case /*AccessibleRole::*/DOCUMENT:
                case /*AccessibleRole::*/EMBEDDED_OBJECT:
                case /*AccessibleRole::*/END_NOTE:
                case /*AccessibleRole::*/FILLER:
                case /*AccessibleRole::*/FOOTNOTE:
                case /*AccessibleRole::*/FOOTER:
                case /*AccessibleRole::*/GRAPHIC:
                case /*AccessibleRole::*/GROUP_BOX:
                case /*AccessibleRole::*/HEADER:
                case /*AccessibleRole::*/LAYERED_PANE:
                case /*AccessibleRole::*/MENU_BAR:
                case /*AccessibleRole::*/POPUP_MENU:
                case /*AccessibleRole::*/OPTION_PANE:
                case /*AccessibleRole::*/PAGE_TAB:
                case /*AccessibleRole::*/PAGE_TAB_LIST:
                case /*AccessibleRole::*/PANEL:
                case /*AccessibleRole::*/SCROLL_PANE:
                case /*AccessibleRole::*/SPLIT_PANE:
                case /*AccessibleRole::*/STATUS_BAR:
                case /*AccessibleRole::*/TABLE_CELL:
                case /*AccessibleRole::*/TEXT_FRAME:
                case /*AccessibleRole::*/TOOL_BAR:
                case /*AccessibleRole::*/VIEW_PORT:
                case /*AccessibleRole::*/SHAPE:
                    return sal_True;
                    break;
                case /*AccessibleRole::*/COLUMN_HEADER:
                case /*AccessibleRole::*/TABLE:
                    if(!IsStateManageDescendant(pAccessible))
                        return sal_True;
                    break;
                case /*AccessibleRole::*/MENU:
                    return sal_True;
                    break;
                default:
                    return sal_False;
                }
            }
        }
    }
    catch(...)
    {
        return sal_False;
    }
    return sal_False;
}

/**
   * Judge if a XAccessible object has ManageDescendant event.
   * @param pAccessible XAccessible interface.
   * @return If XAccessible object is managedescendant.
   */
bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
{
    if(pAccessible)
    {
        Reference<XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
        if(xContext.is())
        {
            Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
            if( !pRState.is() )
                return sal_False;

            Sequence<short> pStates = pRState->getStates();
            int count = pStates.getLength();
            for( int iIndex = 0;iIndex < count;iIndex++ )
            {
                if(pStates[iIndex] == /*AccessibleStateType::*/MANAGES_DESCENDANTS)
                    return sal_True;
            }
        }
    }
    return sal_False;
}

/**
   * Query and get IAccessible interface by XAccessible interface from list.
   * @param pXAcc XAccessible interface.
   * @return Com accobject interface.
   */
IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc)
{
    AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
    if(pAccObj)
    {
        return pAccObj->GetIMAccessible();
    }
    else
    {
        return NULL;
    }
}

/**
   * Query and get IAccessible interface by child id from list.
   * @param resID, childID.
   * @return Com accobject interface.
   */
IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
{
    XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
    if ( pIndTemp == XResIdAccList.end() )
        return NULL;

    AccObject* pObj = pIndTemp->second;

    if(pObj->GetIMAccessible())
        return pObj->GetIMAccessible();
    return NULL;
}
/**
   * Notify some object will be destroyed.
   * @param pXAcc XAccessible interface.
   * @return Com accobject interface.
   */
void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
{
    AccObject* accObj = GetAccObjByXAcc(pXAcc);
    if(accObj)
    {
        accObj->NotifyDestroy(sal_True);
    }
}


void AccObjectWinManager::UpdateChildState(com::sun::star::accessibility::XAccessible* pAccSubMenu)
{
    Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
    if (!xContext.is())
    {
        return;
    }
    sal_Int32 nCount = xContext->getAccessibleChildCount();
    for (sal_Int32 i = 0 ; i < nCount ; ++i)
    {
        Reference<com::sun::star::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
        if (xChild.is())
        {
            AccObject *pObj =  GetAccObjByXAcc(xChild.get());
            if (pObj)
            {
                pObj->UpdateState();
            }
        }
    }
}


bool AccObjectWinManager::IsSpecialToolboItem(com::sun::star::accessibility::XAccessible* pXAcc)
{
    if (pXAcc && oldFocus != pXAcc)
    {
        if(GetParentRole(pXAcc) == TOOL_BAR)
        {
            Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext());
            if (pRContext.is())
            {
                if(pRContext->getAccessibleRole() == TOGGLE_BUTTON)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

short AccObjectWinManager::GetRole(com::sun::star::accessibility::XAccessible* pXAcc)
{
    assert(pXAcc != NULL);
    Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pXAcc->getAccessibleContext(),UNO_QUERY);
    if(xContext.is())
    {
        return xContext->getAccessibleRole();
    }
    return -1;
}

XAccessible* AccObjectWinManager::GetAccDocByHWND( long pWnd )
{
    XHWNDToDocumentHash::iterator aIter;
    aIter = XHWNDDocList.find( pWnd );
    if ( aIter != XHWNDDocList.end() )
    {
        return aIter->second;
    }

    return NULL;
}

XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
{
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    long pWnd = (long)( pAccObj->GetParentHWND() );
    return GetAccDocByHWND( pWnd );
}

bool AccObjectWinManager::IsTopWinAcc( com::sun::star::accessibility::XAccessible* pXAcc )
{
    bool bRet = false;
    AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
    if ( pAccObj )
    {
        bRet = ( pAccObj->GetParentObj() == NULL );
    }
    return bRet;
}