
/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/STKVIEW.CPP   1.2.1.4   17 Apr 1997 16:02:14   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/STKVIEW.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 16:02:14   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:35:12   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:44:26   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:22:58   ZJRD
** 2.09E
** 
**    Rev 1.2.1.0   28 Mar 1997 10:26:58   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:36:46   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:50:50   ZJRD
** Initial revision.
** 
**    Rev 1.7.1.0.1.2   09 Dec 1996 10:17:24   ZJRD
** EasyPack/SLD Version 2.0P
** 
**    Rev 1.7.1.0.1.0   11 Nov 1996 13:00:40   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.7.1.4   09 Sep 1996 13:21:40   ZJRD
** No change.
** 
**    Rev 1.7.1.3   05 Sep 1996 11:33:08   ZJRD
** No change.
** 
**    Rev 1.7.1.2   02 Sep 1996 10:00:12   ZJRD
** No change.
** 
**    Rev 1.7.1.1   28 Aug 1996 15:50:00   ZJRD
** EasyPack/SLD Version 1.9b
** 
**    Rev 1.6.1.0   19 Jul 1996 09:58:04   ZJRD
** EasyPack/SLD Version 1.20b
** 
**    Rev 1.8   20 Jun 1996 09:30:30   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.7   11 Jun 1996 10:28:36   ZJRD
** EasyPack/SLD Version 1.97
** 
**    Rev 1.5   05 Jun 1996 14:57:14   ZJRD
** No change.
** 
**    Rev 1.4   29 May 1996 09:37:56   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:01:06   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:15:20   ZJRD
** EasyPack/SLD Version 1.93
** 
**    Rev 1.31   18 Apr 1996 13:02:06   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:41:00   Shirley
** No change.
** 
**    Rev 1.29   02 Apr 1996 09:29:56   Shirley
** No change.
** 
**    Rev 1.28   15 Feb 1996 08:56:00   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:07:18   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:33:46   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:47:40   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:18:54   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:14:08   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:14:02   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:35:22   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:26:08   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:14:48   Shirley
** No change.
** 
**    Rev 1.18   15 Jan 1996 16:16:54   Shirley
** No change.
** 
**    Rev 1.17   04 Jan 1996 11:13:58   Shirley
** EasyPack/SLD Version 0.34
** 
**    Rev 1.16   30 Nov 1995 09:14:14   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:33:08   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:19:04   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:23:18   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:34:12   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:32:10   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:46:02   Shirley
** No change.
** 
**    Rev 1.9   02 Nov 1995 10:07:06   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:49:14   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:43:50   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:26:54   Shirley
** EasyPack/SLD Version 0.1f
** 
**    Rev 1.5   18 Oct 1995 14:51:00   Shirley
** EasyPack/SLD Version 0.1e
** 
**    Rev 1.4   13 Oct 1995 13:19:08   Shirley
** EasyPack/SLD Version 0.1d
** 
**    Rev 1.3   29 Sep 1995 09:49:00   Shirley
** EasyPack/SLD Version 0.1c
** 
**    Rev 1.2   20 Sep 1995 10:57:26   Shirley
** EasyPack/SLD Version 0.1b
** 
**    Rev 1.1   15 Sep 1995 09:47:02   Shirley
** EasyPack/SLDV0.1a 
** 
**    Rev 1.0   07 Sep 1995 09:53:40   Shirley
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name: STKVIEW.CPP
//
//  Description: The implementation file for the class: CStackView.
//
//  Author: Chen Jun
//
//  Date: 07/29/95
//
//  Modification:
//      1. 07/29/95, Initial version of the class: CStackView.
//      2. 09/08/95, Fix bug 44, "UpdateGrid()".
//		3.    04/95, Modified by Jerry for replace Grid.VBX with CYYHGrid.
//
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// Include files.
#include "stdafx.h"
#include "resource.h"
#include "xview.h"

#include "symblsvr.h"
#include "stkinit.h"
#include "varinit.h"

#include "stkview.h"    



/////////////////////////////////////////////////////////////////////////////
// Debug flags.
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// Global variables.
CStackView* pStkView;

HHOOK hookStkKeyFilter = 0;


/////////////////////////////////////////////////////////////////////////////
// External variables.
extern class VarServer stkObject;

extern BOOL bStkShowAddress;
extern BOOL bStkShowEntryPoint;
extern BOOL bStkShowModule;
extern BOOL bStkShowParameters;


/////////////////////////////////////////////////////////////////////////////
// Local define.
/*
#define AFX_NUM_EVENTPARAM(type, lpParams) (type FAR&)(**(type FAR* FAR*)lpParams)
#define AFX_HLSTR_EVENTPARAM(lpParams) (HLSTR FAR&)(*(HLSTR FAR*)lpParams)
#define AFX_NUM_EVENTPARAMINDEX(type, lpParams, index) (short FAR&)(**((type FAR* FAR*)(lpParams) + index))
#define AFX_HLSTR_EVENTPARAMINDEX(lpParams, index) (HLSTR FAR&)(*((HLSTR FAR*)(lpParams) + index))
*/


/////////////////////////////////////////////////////////////////////////////
// External function prototypes.

// Defined in Stack server: STKSVR.CPP
int StkGetStkLevelNum(int& num );
int StkGetStkFirstNode(STKNode* & node);
int StkGetStkNextNode(STKNode* & node, STKNode* & nextNode);
int StkGetNodeDisplayString(STKNode* node, CString& s1, CString& s2,
                                    CString& s3, CString& s4, CString& s5);
int StkLevelToNode(int nLevel , struct STKNode* &node);

// Defined in STKLOCAL.CPP
void StkUpdateLocalWindow(int nLevel);

// Defined in SRCWIN.CPP
void SrcShowSource(int nBank, unsigned short uAddr);
       
// Defined in BPTSERVE.CPP
BOOL BptAddBptfromWnd(BYTE nBank, unsigned short addr);

// Defined in EMUGO.CPP
void EmuServerGo(int nMode, int nBank, unsigned short uAddr);
void OnEmulation(void);


/////////////////////////////////////////////////////////////////////////////
// Global function prototypes.
void StkUpdateStackWindow(BOOL bUpdateStackOnly = FALSE);
void StkViewSource(void);
void StkRunUntil(void);
void StkSetBreakpoint(void);
int StkGetActiveLevel(void);

LRESULT CALLBACK StkKeyFilterHook(int nCode, WORD wParam, LPMSG /* lpMsg */);

IMPLEMENT_DYNCREATE(CStackView, CView)
/////////////////////////////////////////////////////////////////////////////
// Public functions.

// Filter the special key.
LRESULT CALLBACK StkKeyFilterHook(int nCode, WORD wParam, LPMSG /* lpMsg */)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );

    // Hook the special key.
    LRESULT lRetValue = 0;
    
    switch ( nCode ) {
        case HC_ACTION:
            switch ( wParam ) {
                case VK_HOME:
                    ::pStkView->GetDlgItem(IDC_YYHGRID)->SendMessage(WM_HSCROLL, SB_TOP);
                    lRetValue = 1;
                    break;
                case VK_END:
                    ::pStkView->GetDlgItem(IDC_YYHGRID)->SendMessage(WM_HSCROLL, SB_BOTTOM);
                    lRetValue = 1;
                    break;
                case VK_SPACE:
                    lRetValue = 1;
                    break;
                case VK_PRIOR:
                    if ( GetKeyState(VK_CONTROL) & 0x8000 ) {
                        lRetValue = 1;
                    }
                    break;
                case VK_NEXT:
                    if ( GetKeyState(VK_CONTROL) & 0x8000 ) {
                        lRetValue = 1;
                    }
                    break;
                case VK_LEFT:
                    ::pStkView->GetDlgItem(IDC_YYHGRID)->SendMessage(WM_HSCROLL, SB_LINELEFT);
                    lRetValue = 1;
                    break;
                case VK_RIGHT:
                    ::pStkView->GetDlgItem(IDC_YYHGRID)->SendMessage(WM_HSCROLL, SB_LINERIGHT);
                    lRetValue = 1;
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
    
    return (lRetValue);
}
    

// Update the stack view.
void StkUpdateStackWindow(BOOL bUpdateStackOnly)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );
    
    // Update the stack view.
    ::pStkView->UpdateStackWindow(bUpdateStackOnly);
}

// Inspect the source line.
void StkInspectSource(void)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );
    
    // Inspect source line.
    ::pStkView->InspectSource();
}

// Set the breakpoint at the specific address.
void StkSetBreakpoint(void)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );
    
    // Set breakpoint.
    ::pStkView->SetBreakpoint();
}

// Run until the specific address.
void StkRunUntil(void)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );
    
    // Go till address.
    ::pStkView->RunUntil();
}

// Get the current active level.
int StkGetActiveLevel(void)
{
    // Assertion of the input parameters.
    ASSERT( ::pStkView );

    // Get the current active level.
    return (::pStkView->GetActiveLevel());
}


/////////////////////////////////////////////////////////////////////////////
// CStackView


void CStackView::InitialMember(void)
{
    // Depand on design.
    m_nMaxColumn = totalColumn;

    m_strLevel = " ";
    m_strAddress = " ";
    m_strEntryPoint = " ";
    m_strModule = " ";
    m_strFunction = " ";

    // Havn't initail grid.
    m_bUpdateStackOnly = FALSE;
    // Get the maximum level number.
    GetMaxLevel();
}

CStackView::CStackView():CView()
{
    //{{AFX_DATA_INIT(CStackView)
	//}}AFX_DATA_INIT
    
    // Initial.
    InitialMember();

    // Set the global pointer.
    ::pStkView = this;
}

CStackView::~CStackView()
{}  


void CStackView::OnDraw(CDC* pDC) 
{
   //CWnd::OnDraw(pDC);
}

void CStackView::DoDataExchange(CDataExchange* pDX)
{
    CView::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CStackView)
	//}}AFX_DATA_MAP
}

CStackDoc* CStackView::GetDocument() // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CStackDoc)));
    return (CStackDoc*)m_pDocument;
}


/////////////////////////////////////////////////////////////////////////////
// Public function.

// Update the whole stack pane.
void CStackView::UpdateStackWindow(BOOL bUpdateStackOnly)
{
    // Assertion of the input parameters.
    
    // Initial again.
    if ( !bUpdateStackOnly ) {
        GetMaxLevel();
    }
    
    // Refresh the grid.
    m_bUpdateStackOnly = bUpdateStackOnly;
    UpdateGrid();
}

// Inspect the source line.
extern void SymConvertToBank(U32& uAddr ,int& nBank);
void CStackView::InspectSource(void)
{
    // Assertion of the input parameters.

    // Get the entry point address.
    if ( 0 == ::StkLevelToNode((int)(m_Grid.m_nActiveRow-1), m_pStkNode) ) {
        // Call SRCWIN routine.
        int nBank;       
        U32 uAddr = m_pStkNode->addr;
        SymConvertToBank(uAddr,nBank);

        ::SrcShowSource(nBank, (unsigned short)(uAddr));
        //modify by chris for link success
        //::SrcShowSource((unsigned short)(m_pStkNode->addr));
    }
}

// Set the breakpoint at the specific address.
void CStackView::SetBreakpoint(void)
{
    // Assertion of the input parameters.

    // Get the entry point address.
    if ( 0 == ::StkLevelToNode((int)(m_Grid.m_nActiveRow-1), m_pStkNode) ) {
        // Call BPTSERVE routine.
        int nBank;       
        U32 uAddr = m_pStkNode->addr1;
        SymConvertToBank(uAddr,nBank);
//        ::BptAddBptfromWnd(1, (unsigned short)(m_pStkNode->addr1));
        ::BptAddBptfromWnd(nBank, (unsigned short)(uAddr));
        //modify by chris for link sucess
        //::BptAddBptfromWnd((unsigned short)(m_pStkNode->addr1));

        // Call SRCWIN routine.
        uAddr = m_pStkNode->addr;
        SymConvertToBank(uAddr,nBank);
//        ::SrcShowSource(1, (unsigned short)(m_pStkNode->addr));
        ::SrcShowSource(nBank, (unsigned short)(uAddr));
        //add by chris for link success
        //::SrcShowSource((unsigned short)(m_pStkNode->addr));
    }
}

// Run until the specific address.
void CStackView::RunUntil(void)
{
    // Assertion of the input parameters.

    // Get the entry point address.
    if ( 0 == ::StkLevelToNode((int)(m_Grid.m_nActiveRow-1), m_pStkNode) ) {
        // Call EMUGO routine.
        int nBank;       
        U32 uAddr = m_pStkNode->addr1;
        SymConvertToBank(uAddr,nBank);
        
//        ::EmuServerGo(3, 1, (unsigned short)(m_pStkNode->addr1));
        ::EmuServerGo(3, nBank, (unsigned short)(uAddr));
        //modify by chris for link success. 
        //Note: set parameter2 to space of m_pStkNode->addr1.
        //::EmuServerGo(3, (unsigned short)(m_pStkNode->addr1));

        // Call SRCWIN routine.
        uAddr = m_pStkNode->addr;
        SymConvertToBank(uAddr,nBank);
//        ::SrcShowSource(1, (unsigned short)(m_pStkNode->addr));
        ::SrcShowSource(nBank, (unsigned short)(uAddr));
        //add by chris for link success
        //::SrcShowSource((unsigned short)(m_pStkNode->addr));

        ::OnEmulation();
    }
}

// Get the active level.
int CStackView::GetActiveLevel(void)
{
    // Assertion of the input parameters.

    // Get the maximum level.
    if ( m_nMaxLevel < 1 ) {
        return (-1);
    }
    else {
        return m_Grid.m_nActiveRow-1;
    }
}


/////////////////////////////////////////////////////////////////////////////
// Common function.

// Get the maximum stack level.
void CStackView::GetMaxLevel(void)
{
    // Assertion of the input parameters.
    
    // Delete all the local variables & stack information.
    ::stkObject.VarDeleteAll();

    // Get from Stack server.
    if ( -1 == ::StkGetStkLevelNum(m_nMaxLevel) ) {
        m_nMaxLevel = 0;
    }
}

// Get the information from Stack server.
void CStackView::GetStackInfo(void)
{
    // Assertion of the input parameters.
    ASSERT( m_nMaxLevel > 0 );

    // Get the first node.
    if ( -1 == ::StkGetStkFirstNode(m_pStkNode) ) {
        return;
    }
        
    // Get the detail information by referring to m_pStkNode.
    m_nCurRow = 0;
    do {
        int nRetValue = ::StkGetNodeDisplayString(m_pStkNode, m_strLevel,
                m_strAddress, m_strEntryPoint, m_strModule, m_strFunction);
        if ( -1 == nRetValue ) {
            return;
        }
        else if ( 0 == nRetValue ) {
            m_nCurRow++;
            //SetColumnWidth();
			HideColumn();
            ShowStackInfo();
        }
        else {
            ASSERT( FALSE );
        }
    } while ( 0 == ::StkGetStkNextNode(m_pStkNode, m_pStkNode) );
    m_Grid.UpdateWindow();
}


/////////////////////////////////////////////////////////////////////////////
// Grid operation.

// Update grid.
void CStackView::UpdateGrid(void)
{

    int nMaxRow ;//= (int)
	m_Grid.ResetContent(m_nMaxLevel+1);  
    if ( 0 == m_nMaxLevel ) {
        // Clear the Local window when reset to no stack information.
        //m_Grid.ResetContent(m_nMaxLevel+1);
        ::StkUpdateLocalWindow(-1);
        return;
    }
    // Get the Stack information from server.
    if ( m_nMaxLevel > 0 ) {     
        
        GetStackInfo();
    }
    
    m_Grid.ResizeCell(0,0);     // added by Jamoon for Format Function List
    // Reset the active row.
//    ResetRow();
}


// Hide the special columns.
void CStackView::HideColumn(void)
{
    // Assertion of the input parameters.

    // Hide or show address.
    BOOL bInvalidate=0;
    if(!::bStkShowAddress)
    {	m_Grid.m_nColWidth[addressColumn]=0; bInvalidate=1;}
    else if(m_Grid.m_nColWidth[addressColumn]==0)
         { m_Grid.m_nColWidth[addressColumn]=m_Grid.m_nDefColWidth;
           bInvalidate=1; 	   
         }  
    // Hide or show entry point.                
    if(!::bStkShowEntryPoint)
    {	m_Grid.m_nColWidth[entryPointColumn]=0;    
    	bInvalidate=1;
    }	
    else if(m_Grid.m_nColWidth[entryPointColumn]==0)
         {
             m_Grid.m_nColWidth[entryPointColumn]=m_Grid.m_nDefColWidth;
             bInvalidate=1;
         }    
    // Hide or show module.
    if(!::bStkShowModule)
    {	m_Grid.m_nColWidth[moduleColumn]=0;    
    	bInvalidate=1;
    }	
    else if(m_Grid.m_nColWidth[moduleColumn]==0)  
         {
            m_Grid.m_nColWidth[moduleColumn]=m_Grid.m_nDefColWidth;
            bInvalidate=1;
         }   
    // Hide or show function parameters.
    if ( ::bStkShowParameters ) {
        m_Grid.SetCellText(functionColumn,m_nCurRow,m_strFunction.GetBuffer(24));
        m_Grid.UpdateWindow();
        m_strFunction.ReleaseBuffer();
    }
    else {
        int i = m_strFunction.Find('(');
        if ( -1 != i && ')' != m_strFunction[i+1] ) {
            CString str = m_strFunction.Left(i);
            str += "(...)";   
            
            m_Grid.SetCellText(functionColumn,m_nCurRow,str.GetBuffer(24));
            m_Grid.UpdateWindow();
            str.ReleaseBuffer();
        }
// Update Stack function name error when no parameters
		else {
	        m_Grid.SetCellText(functionColumn,m_nCurRow,m_strFunction.GetBuffer(24));
            m_Grid.UpdateWindow();
        }        
    } 
    if(bInvalidate){
    	m_Grid.Invalidate();
    	m_Grid.UpdateWindow();
    }	
}                                       


// Show stack information in the grid.
void CStackView::ShowStackInfo(void)
{
    // Assertion of the input parameters.
                         
    // Set the current row.
//    m_pGrid->SetNumProperty("Row", m_nCurRow);
      
    // Show level number.
//    m_pGrid->SetNumProperty("Col", levelColumn);
//    m_pGrid->SetStrProperty("Text", m_strLevel);
      m_Grid.SetCellText(levelColumn,m_nCurRow,(m_strLevel.GetBuffer(24)));  
      m_strLevel.ReleaseBuffer();
    // Show address.
//    m_pGrid->SetNumProperty("Col", addressColumn);
//    m_pGrid->SetStrProperty("Text", "0x" + m_strAddress);

// Modified by Gates Hua , --- for display 0xP0:1212
//      CString s=("0x" + m_strAddress);            
	  CString s = m_strAddress;
// Modified finished	  
      m_Grid.SetCellText(addressColumn,m_nCurRow,s.GetBuffer(24));
      s.ReleaseBuffer();
    // Show entry point.
//    m_pGrid->SetNumProperty("Col", entryPointColumn);
//    m_pGrid->SetStrProperty("Text", m_strEntryPoint);
      m_Grid.SetCellText(entryPointColumn,m_nCurRow,(m_strEntryPoint.GetBuffer(24)));
	m_strEntryPoint.ReleaseBuffer();
    // Show module.
//    m_pGrid->SetNumProperty("Col", moduleColumn);
//    m_pGrid->SetStrProperty("Text", m_strModule);
     m_Grid.SetCellText(moduleColumn,m_nCurRow,(m_strModule.GetBuffer(24)));
     m_strModule.ReleaseBuffer();
    // Show function.
//    m_pGrid->SetNumProperty("Col", functionColumn);
//    m_pGrid->SetStrProperty("Text", m_strFunction); 
   	 if ( ::bStkShowParameters ) {
        m_Grid.SetCellText(functionColumn,m_nCurRow,m_strFunction.GetBuffer(24));
        m_Grid.UpdateWindow();
        m_strFunction.ReleaseBuffer();
     }
     else {
        int i = m_strFunction.Find('(');
        if ( -1 != i && ')' != m_strFunction[i+1] ) {
            CString str = m_strFunction.Left(i);
            str += "(...)";   
            m_Grid.SetCellText(functionColumn,m_nCurRow,str.GetBuffer(24));
            m_Grid.UpdateWindow();
            str.ReleaseBuffer();
        }
// Update Stack function name error when no parameters
		else {
	        m_Grid.SetCellText(functionColumn,m_nCurRow,m_strFunction.GetBuffer(24));
            m_Grid.UpdateWindow();
        }        
     } 

//	m_Grid.SetCellText(functionColumn,m_nCurRow,m_str.GetBuffer(24));
//	m_strFunction.ReleaseBuffer();
}


// Hihglight the active row.
LONG CStackView::OnUpdateLocal(UINT,LONG)
{
    // Assertion of the input parameters.
    
        // Update the local variables.
        if ( !m_bUpdateStackOnly ) {
            ::StkUpdateLocalWindow((int)(m_Grid.m_nActiveRow-1));
        }
        else {
            m_bUpdateStackOnly = FALSE;
        }                         
        return 1;
}

/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CStackView, CView)
    //{{AFX_MSG_MAP(CStackView)
    ON_WM_SIZE()
    ON_WM_SETCURSOR()
    ON_WM_DESTROY()
    ON_WM_RBUTTONDOWN()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()                
	ON_MESSAGE(SM_UPDATELOCAL,OnUpdateLocal)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CStackView message handlers



void CStackView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here

    // Get the client area size.
    GetClientRect(m_rectClient);
    m_Grid.MoveWindow(&m_rectClient);
    // Update grid contents.
}

BOOL CStackView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    // TODO: Add your message handler code here and/or call default

    // Send the WM_RBUTTONDOWN message to implement local menu.
    if( HTCLIENT == nHitTest && WM_RBUTTONDOWN == message ) {
        return FALSE;
    }

    return CView::OnSetCursor(pWnd, nHitTest, message);
}



void CStackView::OnDestroy()
{
    CView::OnDestroy();
    
    // TODO: Add your message handler code here
    
    // Remove the hook function from the hook chain.
    if ( ::hookStkKeyFilter ) {
        UnhookWindowsHookEx(::hookStkKeyFilter);
        ::hookStkKeyFilter = 0;
    }
}

void CStackView::OnRButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    
    // Create the local menu.
    CMenu* pLocalMenu = new CMenu;
    ASSERT( NULL != pLocalMenu );
    if ( !pLocalMenu ) {
        AfxMessageBox("Insufficient memory.");
        return;
    }
    pLocalMenu->CreatePopupMenu();
    
    // Define the local menu.
    pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_INSPECTSOURCE, "&Inspect Source");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SETBREAKPOINT, "Set &Breakpoint");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_RUNUNTIL, "&Run Until");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_FORMATFUNCTIONLIST, "For&mat Function List...");
    
    // Adjust the cursor location.
    CPoint pt(m_rectClient.Width()/2, m_rectClient.Height()/2);
    
    // Display the local menu.
    ClientToScreen(&pt);
    
    // Active the local menu.
    pLocalMenu->TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, GetParent()->GetParent());
    
    // Release the allocated buffer.
    delete pLocalMenu;

    CView::OnRButtonDown(nFlags, point);
}

void CStackView::OnSetFocus(CWnd* pOldWnd)
{
	CView::OnSetFocus(pOldWnd);
	
	m_Grid.SetFocus(); 
/*	   if ( !::hookStkKeyFilter ) {
        ::hookStkKeyFilter = 
            SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)::StkKeyFilterHook,
                             AfxGetApp()->m_hInstance, GetCurrentTask());
    }
*/	
}

void CStackView::OnKillFocus(CWnd* pNewWnd)
{
	CView::OnKillFocus(pNewWnd);
	
	    if ( ::hookStkKeyFilter ) {
        UnhookWindowsHookEx(::hookStkKeyFilter);
        ::hookStkKeyFilter = 0;
    }
	
}

int CStackView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1; 
    DWORD dwStyle=WS_HSCROLL|WS_VSCROLL|WS_VISIBLE;
	
	CRect rect;
	GetClientRect(&rect);
	if(!m_Grid.Create(this,dwStyle,rect,IDC_YYHGRID) ) 
	     return -1;
	m_Grid.SetCellText(0,0,"Level");     
	m_Grid.SetCellText(1,0,"Address");     
	m_Grid.SetCellText(2,0,"Entry Point");     
    m_Grid.SetCellText(3,0,"Module");     
	m_Grid.SetCellText(4,0,"Function");        
	// TODO: Add your specialized creation code here
	return 0;
}
