/***********************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/MEMPAGE.CPP   1.8   20 Jun 1996 09:25:44   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/MEMPAGE.CPP  $
** 
**    Rev 1.8   20 Jun 1996 09:25:44   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.7   11 Jun 1996 10:28:00   ZJRD
** EasyPack/SLD Version 1.97
** 
**    Rev 1.5   05 Jun 1996 14:56:38   ZJRD
** No change.
** 
**    Rev 1.4   29 May 1996 09:29:56   ZJRD
** EasyPack/SLD Version 1.95
** 
**    Rev 1.3   16 May 1996 09:07:14   ZJRD
** EasyPack/SLD Version 1.94
** 
**    Rev 1.2   10 May 1996 09:10:14   ZJRD
** EasyPack/SLD Version 1.93
** 
**    Rev 1.1   02 May 1996 10:26:50   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.0   12 Apr 1996 10:36:36   Shirley
** Initial revision.
** 
************************************************************************/

//
// mempage.cpp : implementation file of the memory page dialog
//       Copy, Compare, Checksum, Test, Search, Fill, (Total is six)
//
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#include "stdafx.h"
#include "resource.h"
#include "uicom.h"
#include "mempage.h"
#include "memdlg.h"
   
// Use ABI
//
#include "ctype.h"
#include "abibase.h"
#include "abitype.h"
#include "basictyp.h"   

// Use address server
//
#include "address.h"
#include "addrapi.h"

// include error handling head file
//
#include "errcodea.h"
#include "errcodec.h"                   

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern ADDR_SIZE  dwpMax;        // program  max address
extern ADDR_SIZE  dwpMin;        // program  min address
extern ADDR_SIZE  dwxMax;        // external max address
extern ADDR_SIZE  dwxMin;        // external min address
extern ADDR_SIZE  dwiMax;        // external max address
extern ADDR_SIZE  dwiMin;        // external min address


extern BOOL MemServerTest(unsigned short uStartAddr,
                          unsigned short uEndAddr,
                          unsigned char uchType,
                          unsigned short& uBadAddr);

extern BOOL MemServerSearch(unsigned short uStart,
                            unsigned short uEnd,
                            unsigned char uchType,
                            char* pszPattern,
                            int nInsensitive,
                            unsigned short& uRetAddr);

extern void MemServerCopy(unsigned short uStart,
                          unsigned short uEnd,
                          unsigned short uTarget,
                          unsigned char uchType1,
                          unsigned char uchType2);
                          
extern void MemServerFill(const unsigned short uStart,
                          const unsigned short uEnd,
                          const unsigned char uchType,
                          char* szPattern);

extern BOOL MemServerCompare(unsigned short uStart,
                             unsigned short uEnd,
                             unsigned short uTarget,
                             unsigned char uchStartType,
                             unsigned char uchEndType,
                             unsigned short& uSource,
                             char* pszResult);

extern long MemServerChecksum(const unsigned short uStart,
                              const unsigned short uEnd,
                              unsigned char uchType);

extern int GetTokenNum(char* string);
RETCODE EXPORT ErrGetErrorText(U32 errorCode, LPSTR lpszError ...);
RETCODE EXPORT ErrGetErrorText(U32 errorCode, CString& strError ...);


                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
long   lErrorID;
                       /****************************
                        *                          *
                        *       GLOBAL VARS        *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/**---------------------------------------------------------------------**
 ** Error handling routine
 **
 **---------------------------------------------------------------------**/
void
DisplayError(long lErrorID)
{
   CString errormsg;
   
   ::ErrGetErrorText(lErrorID, errormsg);
   AfxMessageBox(errormsg, MB_OK|MB_ICONEXCLAMATION);
}

void
DisplayAddrError(ADDR_RETCODE  retCode)
{
   CString errormsg;
   
   ::AdrErrorDeal(retCode, errormsg);
   AfxMessageBox(errormsg, MB_OK|MB_ICONEXCLAMATION);
}   

/**--------------------------------------------------------------------**
 **  DetectSpace                                                       **
 **     Change the space determine the actural memory space            **
 **                                                                    **
 **--------------------------------------------------------------------**/

void DetectSpace(unsigned char &uchSpace)
{
   if (dwpMin == dwpMax) {                // no code area
      switch (uchSpace) {
        case   1:
               uchSpace = 2;
               break;
               
        case   2:
               uchSpace = 3;
               break;

        case   3:
               break;
      }
   }
   
   if (dwxMin == dwxMax) {                // no data area
      switch (uchSpace) {
        case   1:
               break;
               
        case   2:
               uchSpace = 3;
               break;

        case   3:
               break;
      }
   }
   
   if (dwiMin == dwiMax) {                // no internal area
      switch (uchSpace) {
        case   1:
               break;
               
        case   2:
               break;

        case   3:
               break;
      }
   }
   
   return;         
}

/**--------------------------------------------------------------------**
 **                                                                    **
 **  CMemSearch dialog                                                 **
 **                                                                    **
 **   The memory search page dialog                                    **
 **                                                                    **
 **--------------------------------------------------------------------**/
 
//
// CMemSearchPage dialog
//

CMemSearchPage::CMemSearchPage()
   : CPropertyPage(CMemSearchPage::IDD)
{
   //{{AFX_DATA_INIT(CMemSearchPage)
   m_strSearchData = "";
   m_strSearchEndAddr = "";
   m_strSearchEndSelect = "EndAddress";
   m_strSearchStartAddr = "";
   m_nSearchSpace = 0;
   //}}AFX_DATA_INIT
}

void CMemSearchPage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMemSearchPage)
   DDX_Control(pDX, IDC_SEARCH_STARTADDR, m_ctrlSearchStartAddr);
   DDX_Control(pDX, IDC_SEARCH_ENDADDR, m_ctrlSearchEndAddr);
   DDX_Control(pDX, IDC_SEARCH_DATA, m_ctrlSearchData);
   DDX_Text(pDX, IDC_SEARCH_DATA, m_strSearchData);
   DDV_MaxChars(pDX, m_strSearchData, 50);
   DDX_Text(pDX, IDC_SEARCH_ENDADDR, m_strSearchEndAddr);
   DDV_MaxChars(pDX, m_strSearchEndAddr, 50);
   DDX_CBString(pDX, IDC_SEARCH_ENDSELECT, m_strSearchEndSelect);
   DDV_MaxChars(pDX, m_strSearchEndSelect, 15);
   DDX_Text(pDX, IDC_SEARCH_STARTADDR, m_strSearchStartAddr);
   DDV_MaxChars(pDX, m_strSearchStartAddr, 50);
   DDX_Radio(pDX, IDC_SEARCH_SPACE, m_nSearchSpace);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMemSearchPage, CPropertyPage)
   //{{AFX_MSG_MAP(CMemSearchPage)
   ON_BN_CLICKED(IDB_SEARCH_CANCEL, OnSearchCancel)
   ON_BN_CLICKED(IDB_SEARCH_HELP, OnSearchHelp)
   ON_BN_CLICKED(IDB_SEARCH_SEARCH, OnSearchSearch)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//
// CMemSearchPage message handlers
//
/////////////////////////////////////////////////////////////////////
// DoSearch
//
//    Do the memory search
//
/////////////////////////////////////////////////////////////////////
void CMemSearchPage::DoSearch()
{
   // TODO: Add your control notification handler code here
   BOOL          bIsOk = TRUE;
   unsigned char uchMemSpace = 0;
   char          *chFind;
   BOOL          bFindOk;
   unsigned short retAddress = 0;   
   
   CString       text;
   ADDRESS       startAddress, endAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   chFind = new char[4096];
   ASSERT (NULL != chFind);
   if (NULL == chFind) {
      // Call Error handle
      // Insufficient memory
      //
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);
      
      return;
   }
   
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchMemSpace = (unsigned char)(m_nSearchSpace+1);
   ::DetectSpace(uchMemSpace);
   
   // Convert the start address
   //      
   retCode = ::AdrTextToAddr(m_strSearchStartAddr, startAddress);
   if (::ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlSearchStartAddr.SetFocus();
      m_ctrlSearchStartAddr.SetSel(0, -1);            
      
      return;
   }

   int nSelect = ((CComboBox *)GetDlgItem(IDC_SEARCH_ENDSELECT))->GetCurSel();   
   
   if ( 0 == nSelect ) {         // End address select
      // Convert the end address data
      //
      retCode = ::AdrTextToAddr(m_strSearchEndAddr, endAddress);
   }      
   else {
      // Convert the length as data
      //
      retCode = ::AdrTextToAddr(m_strSearchEndAddr, endAddress, 0);
   }      
      
   if (::ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlSearchEndAddr.SetFocus();
      m_ctrlSearchEndAddr.SetSel(0, -1);            
         
      return;
   }      

   // Get the end select(End address or length)   
   //
   if (0 == nSelect) {          // End address select
     //
     // If the start address's space is different to end address's space
     // It's error!!!
     //
     if (::SPACE_UNDEFINE != endAddress.adrSpace) {
         if (endAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
            MessageBeep(-1);         
            AfxMessageBox("Space define error.");
            m_ctrlSearchEndAddr.SetFocus();
            m_ctrlSearchEndAddr.SetSel(0, -1);            
         
            return;
         }
     }
   }    
   else {                  // Length select
     if (::SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);         
         lErrorID = ER_MEMDLG_LENGTH;
         ::DisplayError(lErrorID);
         m_ctrlSearchEndAddr.SetFocus();
         m_ctrlSearchEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (::SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
         // Call error handling
         // Msg = "Space define error"               
         AfxMessageBox("Space define error.");
         m_ctrlSearchStartAddr.SetFocus();
         m_ctrlSearchStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchMemSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchMemSpace;                  
   }
   
   // Check the two addrss
   //                 
   retCode = ::AdrCheck2Addr(startAddress, endAddress);
   if (::ADR_OK != retCode) {
      // Call error handling
      // Msg = "Two address comapre error"
      //
      lErrorID = ER_ADDR_COMPARE;
      ::DisplayError(lErrorID);
      m_ctrlSearchEndAddr.SetFocus();
      m_ctrlSearchEndAddr.SetSel(0, -1);            
       
      return;
   }
   
   // Convert the input data
   //
   int   len = 0;
   char  separation[3];
   char* temp;
   int   i = 0;
   BOOL  space = FALSE;
   UINT  findAddress = 0;
   int   line = 0;
   char* ptrNewLine;
   int   nLen;
   
   // Get search token
   //
   //
   strcpy(chFind, m_strSearchData.GetBuffer(m_strSearchData.GetLength()));
   char *input = new char[201];
   ASSERT(NULL != input);
   if (NULL == input) {
      // Call Error handing
      //
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);

      return;
   }

   char strToken[6];

   char *str1 = new char[201];
   ASSERT(NULL != str1);
   if (NULL == str1) {
      // Call error handling
      //
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);
      delete []input;

      return;
   }

   i = strlen(chFind) - 1;
   // Filter the tail white space
   while(chFind[i] == ' ') {
      i--;
      space = TRUE;
   }
   chFind[i+1] = '\0';

   len = strlen(chFind);
   if (len <= 0) bIsOk = FALSE;

   if (bIsOk) {
     if ('"' == chFind[0]) {
        if ('"' == chFind[len-1]) {
           if ((len > 34) || (len < 3))
              bIsOk=FALSE;
           else {
              strncpy(input, chFind, 200);
              input[200]='\0';
           }
        }
        else
           bIsOk=FALSE;
     }
     else {
         len = GetTokenNum(chFind);
         if ((len <= 0) || (len > 32))
           bIsOk=FALSE;
         else {
           separation[0]=' ';
           separation[1]=',';
           separation[2]='\0';

           strncpy(str1, chFind, 200);

           //
           // The tokens is by hexdecimal(default)
           // No leading '0x'
           // In the input radix is changed to the hexidecimal must have
           // leading '0x', the following statment must change
           //

           temp = strtok(str1, separation);
           i = strlen(temp);

           /* For have leading '0x'*/
           if (i > 4)
              bIsOk = FALSE;
           else {
              ADDRESS  token;
              if (::ADR_OK != ::AdrTextToAddr(temp, token, 0)) {  // For data
                 bIsOk = FALSE;
                 goto Faile1;
              }
              token.adrSpace = SPACE_UNDEFINE;
              if (::ADR_OK != ::AdrAddrToHex(token, strToken)) {
                 bIsOk = FALSE;
                 goto Faile1;
              }
           }
           strcpy(input, strToken + 2);
           i = strlen(input);
           input[i]=' ';
           input[i+1]='\0';

           while(NULL != temp) {
             temp = strtok(NULL, separation);
             if (NULL == temp) break;
             i = strlen(temp);
             if (i > 4)
                bIsOk = FALSE;
             else {
               ADDRESS  token;
               if (ADR_OK != ::AdrTextToAddr(temp, token, 0)) {   // For data
                 bIsOk = FALSE;
                 goto Faile1;
               }
               token.adrSpace = SPACE_UNDEFINE;
               if (ADR_OK != ::AdrAddrToHex(token, strToken)) {
                 bIsOk = FALSE;
                 goto Faile1;
               }
             }

             strcat(input, strToken + 2);  // Skip head leading '0x'
             i = strlen(input);
             input[i]=' ';
             input[i+1]='\0';
           }
         }
     }
   }

   Faile1:
   if (!bIsOk) { 
       // Call Erroe handing
       // Msg = "Data input error"
       //
       MessageBeep(-1);
       MessageBox("Input Error",NULL,MB_OK|MB_ICONEXCLAMATION);
       
       m_ctrlSearchData.SetFocus();
       m_ctrlSearchData.SetSel(0, -1);            
       
       return;
   }
                        
   findAddress = (UINT)startAddress.adrAddress;
   line = 0;
   memset(chFind, 0, 4096);
   ptrNewLine = chFind;

   // Call memory server. Do search processing
   //
   BeginWaitCursor();
   do {
       bFindOk = FALSE;
       line++;
#ifndef _NOABI
       // Has ABI
       strcpy(str1, input);
       
       bFindOk = ::MemServerSearch((unsigned short)findAddress,
                                   (unsigned short)endAddress.adrAddress,
                                   uchMemSpace,// mem space
                                   str1,       // pattern
                                   0,          // Insensitive
                                   retAddress);

       if (bFindOk) {
           findAddress = retAddress;
           sprintf(str1, "%d>Find At %04X", line, findAddress);
           findAddress++;
       }
#else
       // No ABI  
       findAddress = 0;
       sprintf(str1, "%d>Find At %04X", line, findAddress);
       break;
#endif   // _NOABI       

       if (!bFindOk)
          break;

       nLen = strlen(str1);
       strncpy(ptrNewLine, str1, nLen);
       ptrNewLine += nLen;
       *(ptrNewLine++) = (BYTE)0xd;
       *(ptrNewLine++) = (BYTE)0xa;
       if (line >= 50) {
           strncpy(ptrNewLine, "***", 3);
           ptrNewLine += 3;
           strncpy(ptrNewLine, "Find Limitation : 50", 21);
           ptrNewLine += 21;
           strncpy(ptrNewLine, "***", 3);
           ptrNewLine += 3;
           *ptrNewLine = (BYTE)0;
           break;
       }
       *ptrNewLine = (BYTE)0;
   }while(findAddress <= (UINT)(endAddress.adrAddress));
   EndWaitCursor();

   if ((line == 1) && !bFindOk)
       SetDlgItemText(IDC_SEARCH_LIST, "Not Found");
   else
       SetDlgItemText(IDC_SEARCH_LIST, chFind);
   
   if (NULL != str1) delete []str1;
   if (NULL != input) delete []input;
   if (NULL != chFind) delete []chFind;
   
   return;
}

/////////////////////////////////////////////////////////////////////
// OnInitDialog
//
//    Initialize the dialog   
//
////////////////////////////////////////////////////////////////////
BOOL CMemSearchPage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_SEARCH_SPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_SEARCH_SPACE_DATA);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}

/////////////////////////////////////////////////////////////////////
// OnOk
//
//    Do the memory search.
//    The dialog will close if the focus does not on the search button when 
//    you press the 'Enter'.
//    Overide the OnOK from the class CPropertyPage to process the search
//
////////////////////////////////////////////////////////////////////
void CMemSearchPage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoSearch();
   ((CMemDlg*)GetParent())->SetModal(TRUE);   
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CMemSearchPage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}

////////////////////////////////////////////////////////////////////
// OnSearchSearch
//
//    Do the memory search
//
////////////////////////////////////////////////////////////////////
void CMemSearchPage::OnSearchSearch()
{
   // TODO: Add your control notification handler code here
   DoSearch();
}

////////////////////////////////////////////////////////////////////
// OnSearchCancel
//
//    Quit the memory dialog
//
////////////////////////////////////////////////////////////////////
void CMemSearchPage::OnSearchCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}

////////////////////////////////////////////////////////////////////
// OnSearchHelp
//
//    Do the memory search help
//
////////////////////////////////////////////////////////////////////
void CMemSearchPage::OnSearchHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   OnCommandHelp(0, 0);
}     

BOOL  CMemSearchPage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_SEARCH;

   return CPropertyPage::OnSetActive();
}
/**-------------------------------------------------------------------**
 **
 **  CMemComparePage dialog
 **   
 **   The memory compare page dialog   
 **
 **-------------------------------------------------------------------**/
 
//
// CMemComparePage dialog
//

CMemComparePage::CMemComparePage()
   : CPropertyPage(CMemComparePage::IDD)
{
   //{{AFX_DATA_INIT(CMemComparePage)
   m_strCompDestAddr = "";
   m_strCompEndAddr = "";
   m_strCompEndSelect = "EndAddress";
   m_strCompStartAddr = "";
   m_bCompCheckStop = TRUE;      //FASLE
   m_nCompSrcSpace = 0;
   m_nCompDestSpace = 0;
   //}}AFX_DATA_INIT
}

void CMemComparePage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMemComparePage)
   DDX_Control(pDX, IDC_COMP_STARTADDR, m_ctrlCompStartAddr);
   DDX_Control(pDX, IDC_COMP_ENDADDR, m_ctrlCompEndAddr);
   DDX_Control(pDX, IDC_COMP_DESTADDR, m_ctrlCompDestAddr);
   DDX_Text(pDX, IDC_COMP_DESTADDR, m_strCompDestAddr);
   DDV_MaxChars(pDX, m_strCompDestAddr, 50);
   DDX_Text(pDX, IDC_COMP_ENDADDR, m_strCompEndAddr);
   DDV_MaxChars(pDX, m_strCompEndAddr, 50);
   DDX_CBString(pDX, IDC_COMP_ENDSELECT, m_strCompEndSelect);
   DDV_MaxChars(pDX, m_strCompEndSelect, 15);
   DDX_Text(pDX, IDC_COMP_STARTADDR, m_strCompStartAddr);
   DDV_MaxChars(pDX, m_strCompStartAddr, 50);
   DDX_Check(pDX, IDC_COMP_CHECKSTOP, m_bCompCheckStop);
   DDX_Radio(pDX, IDC_COMP_SRCSPACE, m_nCompSrcSpace);
   DDX_Radio(pDX, IDC_COMP_DESTSPACE, m_nCompDestSpace);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMemComparePage, CPropertyPage)
   //{{AFX_MSG_MAP(CMemComparePage)
   ON_BN_CLICKED(IDB_COMP_CANCEL, OnCompCancel)
   ON_BN_CLICKED(IDB_COMP_COMP, OnCompComp)
   ON_BN_CLICKED(IDB_COMP_HELP, OnCompHelp)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//
// CMemComparePage message handlers
//
///////////////////////////////////////////////////////////////////////
// DoCompare
//
//    Do the memory compare
//
//
///////////////////////////////////////////////////////////////////////
void CMemComparePage::DoCompare()
{
   // TODO: Add your control notification handler code here
   unsigned char uchSrcSpace = 0, uchDestSpace = 0;
   char          *chFind;
   BOOL          bFindOk;
   
   CString       text;
   ADDRESS       startAddress, endAddress, destAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   chFind = new char[4096];
   ASSERT (NULL != chFind);
   if (NULL == chFind) {
      // Call Error handle
      // Msg = "Insufficient memory"
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);
      return;
   }
   
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchSrcSpace = (unsigned char)(m_nCompSrcSpace+1);
   DetectSpace(uchSrcSpace);
   uchDestSpace = (unsigned char)(m_nCompDestSpace+1);
   DetectSpace(uchDestSpace);
   
   // Convert the start address
   //      
   retCode = AdrTextToAddr(m_strCompStartAddr, startAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      // AdrErrorDeal();
      //
      ::DisplayAddrError(retCode);
      m_ctrlCompStartAddr.SetFocus();
      m_ctrlCompStartAddr.SetSel(0, -1);            
      
      return;
   }
   
   // Get the end select(End address or length)   
   int nSelect = ((CComboBox *)GetDlgItem(IDC_COMP_ENDSELECT))->GetCurSel();
   
   if ( 0 == nSelect ) {
      // Convert the end address
      //
      retCode = AdrTextToAddr(m_strCompEndAddr, endAddress);
   }
   else {      
      // Convert the length( for data )
      //
      retCode = AdrTextToAddr(m_strCompEndAddr, endAddress, 0);
   }
      
   if (ADR_OK != retCode) {
      // Call Error handling
      // AdrErrorDeal()
      //
      ::DisplayAddrError(retCode);
      m_ctrlCompEndAddr.SetFocus();
      m_ctrlCompEndAddr.SetSel(0, -1);            
         
      return;
   }      
   

   if (0 == nSelect) {          // End address select
     //
     // If the start address's space is different to end address's space
     // It's error!!!
     //
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         if (endAddress.adrSpace != (ADDR_SPACE)uchSrcSpace) {
           MessageBeep(-1);
           AfxMessageBox("Space define error.");
           m_ctrlCompEndAddr.SetFocus();
           m_ctrlCompEndAddr.SetSel(0, -1);            
         
           return;
         }
     }
       
   }    
   else {                  // Length select
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);
         lErrorID = ER_MEMDLG_LENGTH;
         ::DisplayError(lErrorID);
         m_ctrlCompEndAddr.SetFocus();
         m_ctrlCompEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchSrcSpace) {
         // Call error handling
         //
         AfxMessageBox("Space define error.");
         m_ctrlCompStartAddr.SetFocus();
         m_ctrlCompStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchSrcSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchSrcSpace;
   }
   
   // Check the two addrss
   //
   retCode = ::AdrCheck2Addr(startAddress, endAddress);
   if (ADR_OK != retCode) {
       // Call error handling
       //
       lErrorID = ER_ADDR_COMPARE;
       ::DisplayError(lErrorID);
       m_ctrlCompEndAddr.SetFocus();
       m_ctrlCompEndAddr.SetSel(0, -1);
       
       return;
   }

   // Convert the dest address
   //
   retCode = AdrTextToAddr(m_strCompDestAddr, destAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      DisplayAddrError(retCode);
      m_ctrlCompDestAddr.SetFocus();
      m_ctrlCompDestAddr.SetSel(0, -1);
      
      return;
   }
   
   if (SPACE_UNDEFINE != destAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (destAddress.adrSpace != (ADDR_SPACE)uchDestSpace) {
         // Call error handling
         //
         //AfxMessageBox("Input error!");
         lErrorID = ER_MEMDLG_INPUT;
         ::DisplayError(lErrorID);
         m_ctrlCompDestAddr.SetFocus();
         m_ctrlCompDestAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      destAddress.adrSpace = (ADDR_SPACE)uchDestSpace;
   }

   ADDRESS tempAddress;
   tempAddress.adrAddress = destAddress.adrAddress+
                            (endAddress.adrAddress - startAddress.adrAddress);
   tempAddress.adrSpace   = destAddress.adrSpace;
   if (!AdrCheckAddrRange(tempAddress)) {         
      // Call error handling
      //
      ::DisplayError(ER_ADDR_COMPARE);
      m_ctrlCompDestAddr.SetFocus();
      m_ctrlCompDestAddr.SetSel(0, -1);            
      
      return;
   }

   BOOL  bStop = TRUE;   
   if (m_bCompCheckStop) bStop = TRUE;
   else bStop = FALSE;

   unsigned short retAddress = 0;
   UINT findAddress = 0;
   int line = 0;   
   char* ptrNewLine;   
   int nLen = 0;   
   
   findAddress  = (UINT)startAddress.adrAddress;
   DWORD dwdestAddress  = destAddress.adrAddress;
   line = 0;
   memset(chFind, 0, 4096);
   ptrNewLine = chFind;
    
   char* temptext = new char [200];
   ASSERT(NULL != temptext);
   if (NULL == temptext) {
      MessageBox("Insufficient memory",
                 NULL,
                 MB_OK|MB_ICONEXCLAMATION);
      return;
   }                  

   // Call memory server
   //
    
   BeginWaitCursor();
   do {
      bFindOk = FALSE;
      line++;
#ifndef _NOABI
      //Has ABI
      //
      bFindOk = ::MemServerCompare((unsigned short)findAddress,
                                   (unsigned short)endAddress.adrAddress,
                                   (unsigned short)dwdestAddress,
                                   uchSrcSpace,
                                   uchDestSpace,
                                   retAddress,
                                   temptext);
          
        
      if (bFindOk) {
         findAddress = retAddress + 1;
         dwdestAddress = destAddress.adrAddress + 
                         (findAddress - startAddress.adrAddress);
      }
#else
      // No ABI
      //
      findAddress = 0;
      dwdestAddress = destAddress.adrAddress + 
                      (findAddress - startAddress.adrAddress);
      
#endif   // _NOABI
      if (!bFindOk) break;

      nLen = strlen(temptext);
      strncpy(ptrNewLine, temptext, nLen);
      ptrNewLine += nLen;
      *(ptrNewLine++) = (BYTE)0xd;
      *(ptrNewLine++) = (BYTE)0xa;
      if (line >= 50) {
         strncpy(ptrNewLine, "***", 3);
         ptrNewLine += 3;
         strncpy(ptrNewLine, "Compare Limitation : 50", 23);
         ptrNewLine+=23;
         strncpy(ptrNewLine, "***", 3);
         ptrNewLine += 3;
         *(ptrNewLine++) = (BYTE)0xd;
         *(ptrNewLine++) = (BYTE)0xa;
         *ptrNewLine = (BYTE)0;
         break;
      }
      *ptrNewLine = (BYTE)0;

      // If set stop, break out;
      if (bStop) break;
           
   }while(findAddress <= endAddress.adrAddress);
    
   EndWaitCursor();

   strncpy(ptrNewLine, "Compare Finished.", 17);
   ptrNewLine += 17;
   *ptrNewLine = (BYTE)0;
   SetDlgItemText(IDC_COMP_LIST, chFind);
   if (NULL != temptext)  delete []temptext;
   if (NULL != chFind)  delete []chFind;
   
   return;
}

//////////////////////////////////////////////////////////////////////////
// OnOK
//
//    Do the memory compare
//    The dialog will close if the focus does not on the compare button when 
//    you press the 'Enter'.
//    Overide the OnOK from the class CPropertyPage to process the compare
//
//////////////////////////////////////////////////////////////////////////
void CMemComparePage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoCompare();
   ((CMemDlg*)GetParent())->SetModal(TRUE);
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CMemComparePage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}

//////////////////////////////////////////////////////////////////////////
// OnCompComp
//
//    Do the memory compare
//
//////////////////////////////////////////////////////////////////////////
void CMemComparePage::OnCompComp()
{
   // TODO: Add your control notification handler code here
   DoCompare();
}

//////////////////////////////////////////////////////////////////////////
// OnCompCancel
//
//    Quit the memory window
//
/////////////////////////////////////////////////////////////////////////////
void CMemComparePage::OnCompCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}

/////////////////////////////////////////////////////////////////////////////
// OnCompHelp
//
//    Help
//
/////////////////////////////////////////////////////////////////////////////
void CMemComparePage::OnCompHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   //AfxGetApp()->WinHelp(IDD_MEMCOMP_PAGE);
   OnCommandHelp(0, 0);
} 

BOOL  CMemComparePage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_COMPARE;

   return CPropertyPage::OnSetActive();
}

/////////////////////////////////////////////////////////////////////////////
// OnInitDialog
//
//    Initialize the dialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMemComparePage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_COMP_SRCSPACE);
      ctrl->EnableWindow(FALSE);
      ctrl = GetDlgItem(IDC_COMP_DESTSPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_COMP_SRCDATA);
      ctrl->EnableWindow(FALSE);
      ctrl = GetDlgItem(IDC_COMP_DESTDATA);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
} // End of CMemComparePage



/**-----------------------------------------------------------------------**
 **
 **  CMemCopyPage dialog
 **   
 **   The memory copy page dialog   
 **
 **-----------------------------------------------------------------------**/
 
//
// CMemCopyPage dialog
//

CMemCopyPage::CMemCopyPage()
   : CPropertyPage(CMemCopyPage::IDD)
{
   //{{AFX_DATA_INIT(CMemCopyPage)
   m_strCopyDestAddr = "";
   m_strCopyEndAddr = "";
   m_strCopyEndSelect = "EndAddress";
   m_strCopyStartAddr = "";
   m_nCopyDestSpace = 0;
   m_nCopySrcSpace = 0;
   //}}AFX_DATA_INIT
}

void CMemCopyPage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMemCopyPage)
   DDX_Control(pDX, IDC_COPY_ENDADDR, m_ctrlCopyEndAddr);
   DDX_Control(pDX, IDC_COPY_STARTADDR, m_ctrlCopyStartAddr);
   DDX_Control(pDX, IDC_COPY_DESTADDR, m_ctrlCopyDestAddr);
   DDX_Text(pDX, IDC_COPY_DESTADDR, m_strCopyDestAddr);
   DDV_MaxChars(pDX, m_strCopyDestAddr, 50);
   DDX_Text(pDX, IDC_COPY_ENDADDR, m_strCopyEndAddr);
   DDX_CBString(pDX, IDC_COPY_ENDSELECT, m_strCopyEndSelect);
   DDV_MaxChars(pDX, m_strCopyEndSelect, 15);
   DDX_Text(pDX, IDC_COPY_STARTADDR, m_strCopyStartAddr);
   DDV_MaxChars(pDX, m_strCopyStartAddr, 50);
   DDX_Radio(pDX, IDC_COPY_DESTSPACE, m_nCopyDestSpace);
   DDX_Radio(pDX, IDC_COPY_SRCSPACE, m_nCopySrcSpace);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMemCopyPage, CPropertyPage)
   //{{AFX_MSG_MAP(CMemCopyPage)
   ON_BN_CLICKED(IDB_COPY_CANCEL, OnCopyCancel)
   ON_BN_CLICKED(IDB_COPY_COPY, OnCopyCopy)
   ON_BN_CLICKED(IDB_COPY_HELP, OnCopyHelp)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//
// CMemCopyPage message handlers
//
////////////////////////////////////////////////////////////////////////
// DoCopy
//
//    Do the memory copy
//
////////////////////////////////////////////////////////////////////////
void CMemCopyPage::DoCopy()
{
   // TODO: Add your control notification handler code here
   unsigned char uchSrcSpace = 0, uchDestSpace = 0;
   
   ADDRESS       startAddress, endAddress, destAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchSrcSpace = (unsigned char)(m_nCopySrcSpace+1);
   DetectSpace(uchSrcSpace);
   uchDestSpace = (unsigned char)(m_nCopyDestSpace+1);
   DetectSpace(uchDestSpace);
   
   // Convert the start address
   //      
   retCode = ::AdrTextToAddr(m_strCopyStartAddr, startAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      DisplayAddrError(retCode);
      m_ctrlCopyStartAddr.SetFocus();
      m_ctrlCopyStartAddr.SetSel(0, -1);            
      
      return;
   }

   // Get the end select(End address or length)   
   int nSelect = ((CComboBox *)GetDlgItem(IDC_COPY_ENDSELECT))->GetCurSel();
   
   if ( 0 == nSelect ) {
      // Convert the end address
      //
      retCode = ::AdrTextToAddr(m_strCopyEndAddr, endAddress);
   }
   else {
      // Convert the length
      //
      retCode = ::AdrTextToAddr(m_strCopyEndAddr, endAddress, 0);
   }      
         
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlCopyEndAddr.SetFocus();
      m_ctrlCopyEndAddr.SetSel(0, -1);            
      
      return;
   }      

                              
   if (0 == nSelect) {          // End address select
      //
      // If the start address's space is different to end address's space
      // It's error!!!
      //
      if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         if (endAddress.adrSpace != (ADDR_SPACE)uchSrcSpace) {
            // Call error handling
            //
            MessageBeep(-1);
            AfxMessageBox("Space define error.");
            m_ctrlCopyEndAddr.SetFocus();
            m_ctrlCopyEndAddr.SetSel(0, -1);            
         
            return;
         }
      }
   }    
   else {                  // Length select
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);
         ::DisplayError(ER_MEMDLG_LENGTH);
         m_ctrlCopyEndAddr.SetFocus();
         m_ctrlCopyEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchSrcSpace) {
         // Call error handling
         //
         MessageBeep(-1);
         AfxMessageBox("Space define error.");
         //::DisplayError(ER_MEMDLG_INPUT);
         m_ctrlCopyStartAddr.SetFocus();
         m_ctrlCopyStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchSrcSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchSrcSpace;
   }
   
   // Check the two addrss
   //
   retCode = ::AdrCheck2Addr(startAddress, endAddress);
   if (ADR_OK != retCode) {
       // Call error handling
       //
       ::DisplayAddrError(retCode);
       m_ctrlCopyEndAddr.SetFocus();
       m_ctrlCopyEndAddr.SetSel(0, -1);
       
       return;
   }

   retCode = ::AdrTextToAddr(m_strCopyDestAddr, destAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlCopyDestAddr.SetFocus();
      m_ctrlCopyDestAddr.SetSel(0, -1);
      
      return;
   }
   
   if (SPACE_UNDEFINE != destAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (destAddress.adrSpace != (ADDR_SPACE)uchDestSpace) {
         // Call error handling
         //
         //::DisplayError(ER_MEMDLG_INPUT);
         MessageBeep(-1);
         AfxMessageBox("Space define error!");
         m_ctrlCopyDestAddr.SetFocus();
         m_ctrlCopyDestAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      destAddress.adrSpace = (ADDR_SPACE)uchDestSpace;
   }
   

   ADDRESS tempAddress;
   tempAddress.adrAddress = destAddress.adrAddress+
                            (endAddress.adrAddress - startAddress.adrAddress);
   tempAddress.adrSpace   = destAddress.adrSpace;
   if (!AdrCheckAddrRange(tempAddress)) {         
      // Call error handling
      //
      MessageBeep(-1);
      ::DisplayError(ER_MEMDLG_COPYOVER);                  
      m_ctrlCopyDestAddr.SetFocus();
      m_ctrlCopyDestAddr.SetSel(0, -1);            
      
      return;
   }
   
   BeginWaitCursor();
   
#ifndef _NOABI
   // Has ABI
   MemServerCopy((unsigned short)startAddress.adrAddress,
                 (unsigned short)endAddress.adrAddress,
                 (unsigned short)destAddress.adrAddress,
                 uchSrcSpace,
                 uchDestSpace);

#endif   // _NOABI

   for (int no = 0; no < 3; no ++ ){
     if (isMemOn[no])
        pMemWnd[no] -> InvalidateRect(NULL,FALSE);
   } 
   ::RepaintStack();
   ::RepaintVariable();

   EndWaitCursor();
   
   return;
}

////////////////////////////////////////////////////////////////////////
// OnOK
//
//    Do the memory copy
//
////////////////////////////////////////////////////////////////////////
void CMemCopyPage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoCopy();
   ((CMemDlg*)GetParent())->SetModal(TRUE);   
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CMemCopyPage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}

/////////////////////////////////////////////////////////////////////////////
// OnCopyCopy
//
//    Do the memory copy
//
/////////////////////////////////////////////////////////////////////////////
void CMemCopyPage::OnCopyCopy()
{
   // TODO: Add your control notification handler code here
   DoCopy();
}

/////////////////////////////////////////////////////////////////////////////
// OnCopyCancel
//
//    Quit the memory dialog
//
/////////////////////////////////////////////////////////////////////////////
void CMemCopyPage::OnCopyCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}

/////////////////////////////////////////////////////////////////////////////
// OnCopyHelp
//
//    Do the memory copy help
//
/////////////////////////////////////////////////////////////////////////////
void CMemCopyPage::OnCopyHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   //AfxGetApp()->WinHelp(IDD_MEMCOPY_PAGE);
   OnCommandHelp(0, 0);
}     // End of copy page dialog

BOOL CMemCopyPage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_COPY;

   return CPropertyPage::OnSetActive();
}

/////////////////////////////////////////////////////////////////////////////
// OnInitDialog
//
//    Initialize the dialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMemCopyPage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_COPY_SRCSPACE);
      ctrl->EnableWindow(FALSE);
      ctrl = GetDlgItem(IDC_COPY_DESTSPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_COPY_SRCDATA);
      ctrl->EnableWindow(FALSE);
      ctrl = GetDlgItem(IDC_COPY_DESTDATA);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}  // End of copy page dialog


/**-----------------------------------------------------------------------**
 **
 **  CMemFillPage dialog
 **   
 **   The memory fill page dialog   
 **
 **-----------------------------------------------------------------------**/

//
// CMemFillPage dialog
//

CMemFillPage::CMemFillPage()
   : CPropertyPage(CMemFillPage::IDD)
{
   //{{AFX_DATA_INIT(CMemFillPage)
   m_strFillData = "";
   m_strFillEndAddr = "";
   m_strFillEndSelect = "EndAddress";
   m_strFillStartAddr = "";
   m_nFillSpace = 0;
   //}}AFX_DATA_INIT
}

void CMemFillPage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMemFillPage)
   DDX_Control(pDX, IDC_FILL_STARTADDR, m_ctrlFillStartAddr);
   DDX_Control(pDX, IDC_FILL_ENDADDR, m_ctrlFillEndAddr);
   DDX_Control(pDX, IDC_FILL_DATA, m_ctrlFillData);
   DDX_Text(pDX, IDC_FILL_DATA, m_strFillData);
   DDV_MaxChars(pDX, m_strFillData, 50);
   DDX_Text(pDX, IDC_FILL_ENDADDR, m_strFillEndAddr);
   DDV_MaxChars(pDX, m_strFillEndAddr, 50);
   DDX_CBString(pDX, IDC_FILL_ENDSELECT, m_strFillEndSelect);
   DDV_MaxChars(pDX, m_strFillEndSelect, 15);
   DDX_Text(pDX, IDC_FILL_STARTADDR, m_strFillStartAddr);
   DDV_MaxChars(pDX, m_strFillStartAddr, 50);
   DDX_Radio(pDX, IDC_FILL_SPACE, m_nFillSpace);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMemFillPage, CPropertyPage)
   //{{AFX_MSG_MAP(CMemFillPage)
   ON_BN_CLICKED(IDB_FILL_CANCEL, OnFillCancel)
   ON_BN_CLICKED(IDB_FILL_FILL, OnFillFill)
   ON_BN_CLICKED(IDB_FILL_HELP, OnFillHelp)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//
// CMemFillPage message handlers
//
///////////////////////////////////////////////////////////////////////
// DoFill
//
//    Do the memory fill
//
///////////////////////////////////////////////////////////////////////
void CMemFillPage::DoFill()
{
   // TODO: Add your control notification handler code here
   BOOL          bIsOk = TRUE;
   char*         chFind;
   unsigned char uchMemSpace = 0;
   unsigned short retAddress = 0;   
   
   CString       text;
   ADDRESS       startAddress, endAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   chFind = new char[512];
   ASSERT (NULL != chFind);
   if (NULL == chFind) {
      // Call Error handle
      return;
   }
   
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchMemSpace = (unsigned char)(m_nFillSpace+1);
   ::DetectSpace(uchMemSpace);
   
   // Convert the start address
   //      
   retCode = ::AdrTextToAddr(m_strFillStartAddr, startAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      MessageBeep(-1);
      ::DisplayAddrError(retCode);
      m_ctrlFillStartAddr.SetFocus();
      m_ctrlFillStartAddr.SetSel(0, -1);            
      
      return;
   }

   // Get the end select(End address or length)   
   int nSelect = ((CComboBox *)GetDlgItem(IDC_FILL_ENDSELECT))->GetCurSel();

   if ( 0 == nSelect ) {   
      // Convert the end address
      //
      retCode = ::AdrTextToAddr(m_strFillEndAddr, endAddress);
   }
   else {      
      // Convert the length
      //
      retCode = ::AdrTextToAddr(m_strFillEndAddr, endAddress, 0);
   }
      
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      MessageBeep(-1);
      ::DisplayAddrError(retCode);
      m_ctrlFillEndAddr.SetFocus();
      m_ctrlFillEndAddr.SetSel(0, -1);            
      
      return;
   }      

                              
   if (0 == nSelect) {          // End address select
       //
       // If the start address's space is different to end address's space
       // It's error!!!
       //
      if (SPACE_UNDEFINE != endAddress.adrSpace) {
         if (endAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
            MessageBeep(-1);
            AfxMessageBox("Space define error.");
            m_ctrlFillEndAddr.SetFocus();
            m_ctrlFillEndAddr.SetSel(0, -1);            
         
            return;
         }
      }
   }    
   else {                  // Length select
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);
         ::DisplayError(ER_MEMDLG_LENGTH);
         m_ctrlFillEndAddr.SetFocus();
         m_ctrlFillEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
         // Call error handling
         //      
         MessageBeep(-1);
         AfxMessageBox("Space define error");
         m_ctrlFillStartAddr.SetFocus();
         m_ctrlFillStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchMemSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchMemSpace;                  
   }
   
   // Check the two addrss
   //                 
   retCode = ::AdrCheck2Addr(startAddress, endAddress);
   if (ADR_OK != retCode) {
       // Call error handling
       //
       MessageBeep(-1);
       ::DisplayAddrError(retCode);
       m_ctrlFillEndAddr.SetFocus();
       m_ctrlFillEndAddr.SetSel(0, -1);            
       
       return;
   }
   
   // Convert the input data
   //
   int   len = 0;
   char  separation[3];
   char* temp;
   int   i = 0;
   BOOL  space = FALSE;
   UINT  findAddress = 0;
   int   line = 0;
   
   // Get search token
   //
   //
   strcpy(chFind, m_strFillData.GetBuffer(m_strFillData.GetLength()));
   char *input = new char[201];
   ASSERT(NULL != input);
   if (NULL == input) {
      // Call Error handing
      //
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);

      return;
   }

   char *str1 = new char[201];
   char strToken[6];

   ASSERT(NULL != str1);
   if (NULL == str1) {
      // Call error handling
      //
      MessageBox("Insufficient memory", "Alloc memory error",
                 MB_OK|MB_ICONEXCLAMATION);
      delete []input;

      return;
   }

   i = strlen(chFind) - 1;
   // Filter the tail white space
   while(chFind[i] == ' ') {
      i--;
      space = TRUE;
   }
   chFind[i+1] = '\0';

   len = strlen(chFind);
   if (len <= 0) bIsOk = FALSE;

   if (bIsOk) {
     if ('"' == chFind[0]) {
        if ('"' == chFind[len-1]) {
           if ((len > 34) || (len < 3))
              bIsOk=FALSE;
           else {
              strncpy(input, chFind, 200);
              input[200]='\0';
           }
        }
        else
           bIsOk=FALSE;
     }
     else {
         len = GetTokenNum(chFind);
         if ((len <= 0) || (len > 32))
           bIsOk=FALSE;
         else {
           separation[0]=' ';
           separation[1]=',';
           separation[2]='\0';

           strncpy(str1, chFind, 200);

           //
           // The tokens is by hexdecimal(default)
           // No leading '0x'
           // In the input radix is changed to the hexidecimal must have
           // leading '0x', the following statment must change
           //

           temp = strtok(str1, separation);
           i = strlen(temp);

           /* For have leading '0x'*/
           if (i > 4)
              bIsOk = FALSE;
           else {
              ADDRESS  token;
              if (ADR_OK != ::AdrTextToAddr(temp, token, 0)) {
                 bIsOk = FALSE;
                 goto Faile;
              }   
              token.adrSpace = SPACE_UNDEFINE;
              if (ADR_OK != ::AdrAddrToHex(token, strToken)) {
                 bIsOk = FALSE;
                 goto Faile;
              }   
           }
           strcpy(input, strToken + 2);
           i = strlen(input);
           input[i]=' ';
           input[i+1]='\0';

           while(NULL != temp) {
             temp = strtok(NULL, separation);
             if (NULL == temp) break;
             i = strlen(temp);
             if (i > 4)
                bIsOk = FALSE;
             else {
               ADDRESS  token;
               if (ADR_OK != ::AdrTextToAddr(temp, token, 0)) {
                 bIsOk = FALSE;
                 goto Faile;
               }
               token.adrSpace = SPACE_UNDEFINE;
               if (ADR_OK != ::AdrAddrToHex(token, strToken)) {
                 bIsOk = FALSE;
                 goto Faile;
               }
             }

             strcat(input, strToken + 2);  // Skip head leading '0x'
             i = strlen(input);
             input[i]=' ';
             input[i+1]='\0';
           }
         }
     }
   }
   
   Faile:
   if (!bIsOk) { 
       // Call Erroe handing
       //
       MessageBeep(-1);
       ::DisplayError(ER_MEMDLG_INPUT);
       
       m_ctrlFillData.SetFocus();
       m_ctrlFillData.SetSel(0, -1);            
       
       return;
   }
   
   // Call memory server
   // 
   BeginWaitCursor();
    
#ifndef _NOABI
   // Has ABI
   MemServerFill((const unsigned short)startAddress.adrAddress,
                 (const unsigned short)endAddress.adrAddress,
                 uchMemSpace,
                 input);
#endif   // _NOABI

   for (int no = 0; no < 3; no ++ ){
     if (isMemOn[no])
        pMemWnd[no] -> InvalidateRect(NULL,FALSE);
   } 
    
   ::RepaintStack();
   ::RepaintVariable();
    
   EndWaitCursor();
    
   if (NULL != str1) delete []str1;
   if (NULL != input) delete []input;
   if (NULL != chFind) delete []chFind;
   
   return;
}

///////////////////////////////////////////////////////////////////////
// OnOK
//
//    Do the memory fill
//
///////////////////////////////////////////////////////////////////////
void CMemFillPage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoFill();
   ((CMemDlg*)GetParent())->SetModal(TRUE);      
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CMemFillPage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}

/////////////////////////////////////////////////////////////////////////////
// OnFillFill
//
//    Do the memory fill
//
/////////////////////////////////////////////////////////////////////////////
void CMemFillPage::OnFillFill()
{
   // TODO: Add your control notification handler code here
   DoFill();
}

/////////////////////////////////////////////////////////////////////////////
// OnFillCancel
//
//    Do the memory dialog
//
/////////////////////////////////////////////////////////////////////////////
void CMemFillPage::OnFillCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}

/////////////////////////////////////////////////////////////////////////////
// OnFillHelp
//
//    Do the memory fill help
//
/////////////////////////////////////////////////////////////////////////////
void CMemFillPage::OnFillHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   OnCommandHelp(0, 0);
}  

BOOL  CMemFillPage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_FILL;

   return CPropertyPage::OnSetActive();
}

/////////////////////////////////////////////////////////////////////////////
// OnInirDialog
//
//    Initilaize the dialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMemFillPage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_FILL_SPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_FILL_SPACE_DATA);
      ctrl->EnableWindow(FALSE);
   }
   if (dwiMin == dwiMax) {        // no on_chip area   
      ctrl = GetDlgItem(IDC_FILL_SPACE_CHIP);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}  //End of fill page dialog


/**-----------------------------------------------------------------------**
 **
 **  CmemTestPage dialog
 **   
 **   The memory fill page dialog   
 **
 **-----------------------------------------------------------------------**/

/////////////////////////////////////////////////////////////////////////////
// CmemTestPage dialog

CmemTestPage::CmemTestPage()
   : CPropertyPage(CmemTestPage::IDD)
{
   //{{AFX_DATA_INIT(CmemTestPage)
   m_strTestEndAddr = "";
   m_strTestEndSelect = "EndAddress";
   m_strTestStartAddr = "";
   m_nTestSpace = 0;
   //}}AFX_DATA_INIT
}

void CmemTestPage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CmemTestPage)
   DDX_Control(pDX, IDC_TEST_STARTADDR, m_ctrlTestStartAddr);
   DDX_Control(pDX, IDC_TEST_ENDADDR, m_ctrlTestEndAddr);
   DDX_Text(pDX, IDC_TEST_ENDADDR, m_strTestEndAddr);
   DDV_MaxChars(pDX, m_strTestEndAddr, 50);
   DDX_CBString(pDX, IDC_TEST_ENDSELECT, m_strTestEndSelect);
   DDV_MaxChars(pDX, m_strTestEndSelect, 15);
   DDX_Text(pDX, IDC_TEST_STARTADDR, m_strTestStartAddr);
   DDV_MaxChars(pDX, m_strTestStartAddr, 50);
   DDX_Radio(pDX, IDC_TEST_SPACE, m_nTestSpace);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CmemTestPage, CPropertyPage)
   //{{AFX_MSG_MAP(CmemTestPage)
   ON_BN_CLICKED(IDB_TEST_TEST, OnTestTest)
   ON_BN_CLICKED(IDB_TEST_CANCEL, OnTestCancel)
   ON_BN_CLICKED(IDB_TEST_HELP, OnTestHelp)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//
// CmemTestPage message handlers
//
/////////////////////////////////////////////////////////////////////////////
// DoTest
//
//    Do the memory test
//
/////////////////////////////////////////////////////////////////////////////
void CmemTestPage::DoTest()
{
   // TODO: Add your control notification handler code here
   BOOL          bIsOk = TRUE;
   unsigned char uchMemSpace = 0;
   unsigned short retAddress = 0;   
   
   CString       text;
   ADDRESS       startAddress, endAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   
   //
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchMemSpace = (unsigned char)(m_nTestSpace+1);
   ::DetectSpace(uchMemSpace);
   
   // Convert the start address
   //      
   retCode = ::AdrTextToAddr(m_strTestStartAddr, startAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlTestStartAddr.SetFocus();
      m_ctrlTestStartAddr.SetSel(0, -1);            
      
      return;
   }

   // Get the end select(End address or length)   
   int nSelect = ((CComboBox *)GetDlgItem(IDC_TEST_ENDSELECT))->GetCurSel();

   if ( 0 == nSelect ) {   
      // Convert the end address
      //
      retCode = ::AdrTextToAddr(m_strTestEndAddr, endAddress);
   }
   else {
      // Convert the length
      //
      retCode = ::AdrTextToAddr(m_strTestEndAddr, endAddress, 0);
   }
            
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlTestEndAddr.SetFocus();
      m_ctrlTestEndAddr.SetSel(0, -1);            
      
      return;
   }      

   if (0 == nSelect) {          // End address select
      //
      // If the start address's space is different to end address's space
      // It's error!!!
      //
      if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         if (endAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
            MessageBeep(-1);
            AfxMessageBox("Space define error.");
            m_ctrlTestEndAddr.SetFocus();
            m_ctrlTestEndAddr.SetSel(0, -1);            
         
            return;
         }
      }
   }    
   else {                  // Length select
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);
         ::DisplayError(ER_MEMDLG_LENGTH);
         m_ctrlTestEndAddr.SetFocus();
         m_ctrlTestEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
         // Call error handling
         MessageBeep(-1);
         AfxMessageBox("Space define error.");   
         m_ctrlTestStartAddr.SetFocus();
         m_ctrlTestStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchMemSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchMemSpace;                  
   }
   
   // Check the two addrss
   //                 
   retCode = ::AdrCheck2Addr(startAddress, endAddress);
   if (ADR_OK != retCode) {
       // Call error handling
       //
       DisplayAddrError(retCode);
       m_ctrlTestEndAddr.SetFocus();
       m_ctrlTestEndAddr.SetSel(0, -1);            
       
       return;
   }
   
   // Call memory server
   //
   unsigned short errAddress;
   
   BeginWaitCursor();
#ifndef _NOABI
   // Has ABI
   bIsOk = MemServerTest((unsigned short)startAddress.adrAddress,
                         (unsigned short)endAddress.adrAddress,
                         uchMemSpace,
                         errAddress);
#endif   // _NOABI
    
   // Output result
   //
   char*  result;    
   result = new char[50];    
   ASSERT(NULL != result);
    
   if (bIsOk) {
      switch (uchMemSpace) {
        case   1:
               strcpy(result, "PROGRAM ");
               strcat(result, "Test OK!");
               SetDlgItemText(IDC_TEST_LIST, result);
               break;
               
        case   2:               
               strcpy(result, "DATA ");
               strcat(result, "Test OK!");
               SetDlgItemText(IDC_TEST_LIST, result);
               break;
         
        case   3:
               strcpy(result, "On_Chip DATA ");
               strcat(result, "Test OK!");
               SetDlgItemText(IDC_TEST_LIST, result);
               break;
      }               
   }      
   else {
      sprintf(result, "Failure at 0x%x", errAddress);
      SetDlgItemText(IDC_TEST_LIST, result);
   }
    
   for (int no = 0; no < 3; no ++ ){
     if (isMemOn[no])
        pMemWnd[no] -> InvalidateRect(NULL,FALSE);
   } 
   ::RepaintStack();
   ::RepaintVariable();

   EndWaitCursor();
   if (NULL != result) delete []result;   
    
   return;
}

/////////////////////////////////////////////////////////////////////////////
// OnOK
//
//    Do the memory test
//
/////////////////////////////////////////////////////////////////////////////
void CmemTestPage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoTest();
   ((CMemDlg*)GetParent())->SetModal(TRUE);      
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CmemTestPage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}


/////////////////////////////////////////////////////////////////////////////
// OnTestTest
//
//    Do the memory test
//
/////////////////////////////////////////////////////////////////////////////
void CmemTestPage::OnTestTest()
{
   // TODO: Add your control notification handler code here
   DoTest();
}

/////////////////////////////////////////////////////////////////////////////
// OnTestCancel
//
//    Quit the memory dialog
//
/////////////////////////////////////////////////////////////////////////////
void CmemTestPage::OnTestCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}
                          
/////////////////////////////////////////////////////////////////////////////
// OnTestHelp
//
//    Do the test hep
//
/////////////////////////////////////////////////////////////////////////////
void CmemTestPage::OnTestHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   OnCommandHelp(0, 0);
}  

BOOL  CmemTestPage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_TEST;

   return CPropertyPage::OnSetActive();
}


/////////////////////////////////////////////////////////////////////////////
// OnInitDialog
//
//    Initialize the dialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL CmemTestPage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_TEST_SPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_TEST_SPACE_DATA);
      ctrl->EnableWindow(FALSE);
   }
   if (dwiMin == dwiMax) {        // no on_chip area   
      ctrl = GetDlgItem(IDC_TEST_SPACE_CHIP);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}  // End of Test page dialog

/**-----------------------------------------------------------------------**
 **
 **  CMemChecksumPage dialog
 **   
 **   The memory checksum page dialog   
 **
 **-----------------------------------------------------------------------**/

CMemChecksumPage::CMemChecksumPage()
   : CPropertyPage(CMemChecksumPage::IDD)
{
   //{{AFX_DATA_INIT(CMemChecksumPage)
   m_strChecksumEndAddr = "";
   m_strChecksumEndSelect = "EndAddress";
   m_strChecksumStartAddr = "";
   m_nChecksumSpace = 0;
   m_strChecksumMemsize = "Byte";
   //}}AFX_DATA_INIT
}

void CMemChecksumPage::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMemChecksumPage)
   DDX_Control(pDX, IDC_CHECKSUM_STARTADDR, m_ctrlChecksumStartAddr);
   DDX_Control(pDX, IDC_CHECKSUM_ENDADDR, m_ctrlChecksumEndAddr);
   DDX_Text(pDX, IDC_CHECKSUM_ENDADDR, m_strChecksumEndAddr);
   DDV_MaxChars(pDX, m_strChecksumEndAddr, 50);
   DDX_CBString(pDX, IDC_CHECKSUM_ENDSELECT, m_strChecksumEndSelect);
   DDV_MaxChars(pDX, m_strChecksumEndSelect, 15);
   DDX_Text(pDX, IDC_CHECKSUM_STARTADDR, m_strChecksumStartAddr);
   DDV_MaxChars(pDX, m_strChecksumStartAddr, 50);
   DDX_Radio(pDX, IDC_CHECKSUM_SPACE, m_nChecksumSpace);
   DDX_CBString(pDX, IDC_CHECKSUM_MEMSIZE, m_strChecksumMemsize);
   DDV_MaxChars(pDX, m_strChecksumMemsize, 10);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMemChecksumPage, CPropertyPage)
   //{{AFX_MSG_MAP(CMemChecksumPage)
   ON_BN_CLICKED(IDB_CHECKSUM_CANCEL, OnChecksumCancel)
   ON_BN_CLICKED(IDB_CHECKSUM_CHECKSUM, OnChecksumChecksum)
   ON_BN_CLICKED(IDB_CHECKSUM_HELP, OnChecksumHelp)
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// DoChecksum
//
//    Do the memory checksum
//
/////////////////////////////////////////////////////////////////////////////
void CMemChecksumPage::DoChecksum()
{
   // TODO: Add your control notification handler code here
   unsigned char uchMemSpace = 0;
   unsigned short retAddress = 0;   
   
   CString       text;
   ADDRESS       startAddress, endAddress;
   ADDR_RETCODE  retCode;
   CString       error;
   DWORD         dwLength;   // Idicate to the select is Length. Not the 
                             // end address

   if ( !UpdateData(TRUE) ) return;         // Get data from the dialog
   
   //
   // Get the memory space from the radio button 
   // Radio button is 0 base. Memory space define is 1 base(0 is Undefine)
   // Radio button   Code, Data, Internal(0, 1, 2)
   // Memory space is (1-Code, 2-Data, 3-Internal)
   //
   uchMemSpace = (unsigned char)(m_nChecksumSpace+1);
   ::DetectSpace(uchMemSpace);
      
   // Convert the start address
   //      
   retCode = ::AdrTextToAddr(m_strChecksumStartAddr, startAddress);
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlChecksumStartAddr.SetFocus();
      m_ctrlChecksumStartAddr.SetSel(0, -1);            
      
      return;
   }

   // Get the end select(End address or length)   
   int nSelect = ((CComboBox *)GetDlgItem(IDC_CHECKSUM_ENDSELECT))->GetCurSel();
                              
   if ( 0 == nSelect ) {   
      // Convert the end address
      //
      retCode = ::AdrTextToAddr(m_strChecksumEndAddr, endAddress);
   }
   else {
      // Convert the length
      //
      retCode = ::AdrTextToAddr(m_strChecksumEndAddr, endAddress, 0);
   }
            
   if (ADR_OK != retCode) {
      // Call Error handling
      //
      ::DisplayAddrError(retCode);
      m_ctrlChecksumEndAddr.SetFocus();
      m_ctrlChecksumEndAddr.SetSel(0, -1);            
      
      return;
   }      

   if (0 == nSelect) {          // End address select
       //
       // If the start address's space is different to end address's space
       // It's error!!!
       //
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         if (endAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
            MessageBeep(-1);
            AfxMessageBox("Space define error.");
            m_ctrlChecksumEndAddr.SetFocus();
            m_ctrlChecksumEndAddr.SetSel(0, -1);            
         
            return;
         }
     }         
       
   }    
   else {                  // Length select
     if (SPACE_UNDEFINE != endAddress.adrSpace) {
         // Call Error handling
         //
         MessageBeep(-1);
         //MessageBox("Length may not include area define", 
         //           "Input Error", 
         //           MB_OK|MB_ICONEXCLAMATION);
         ::DisplayError(ER_MEMDLG_LENGTH);
         m_ctrlChecksumEndAddr.SetFocus();
         m_ctrlChecksumEndAddr.SetSel(0, -1);            
         
         return;
     }
     else {
         // Set to length
         dwLength = (DWORD)endAddress.adrAddress;
         // Set to end addresss
         endAddress.adrAddress = startAddress.adrAddress+dwLength-1;
         endAddress.adrSpace = startAddress.adrSpace;
     }
   }
   
   if (SPACE_UNDEFINE != startAddress.adrSpace) {
      // The input address include space define.
      // Check the input space and the space radio button define.
      // If there has different, it is error.
      // 
      if (startAddress.adrSpace != (ADDR_SPACE)uchMemSpace) {
         // Call error handling
         //               
         //::DisplayError(ER_MEMDLG_INPUT);
         MessageBeep(-1);
         AfxMessageBox("Space define error.");
         m_ctrlChecksumStartAddr.SetFocus();
         m_ctrlChecksumStartAddr.SetSel(0, -1);            
         
         return;
      }
   }
   else {
      // The input address does not include space
      // use the space radio button define
      //
      startAddress.adrSpace = (ADDR_SPACE)uchMemSpace;
      endAddress.adrSpace = (ADDR_SPACE)uchMemSpace;                  
   }
   
   // Check the two addrss
   //                 
   retCode = AdrCheck2Addr(startAddress, endAddress);
   if (ADR_OK != retCode) {
       // Call error handling
       //
       ::DisplayAddrError(retCode);
       m_ctrlChecksumEndAddr.SetFocus();
       m_ctrlChecksumEndAddr.SetSel(0, -1);            
       
       return;
   }
   
   long lChecksum = 0;   

   BeginWaitCursor();   
#ifndef _NOABI
   lChecksum = MemServerChecksum((unsigned short)startAddress.adrAddress,
                                 (unsigned short)endAddress.adrAddress,
                                 uchMemSpace);
#endif   // _NOABI
   EndWaitCursor();   
   
   char* result;
   result = new char[50];
   ASSERT (NULL != result);
   
   sprintf(result, "0x%lX", lChecksum);
   SetDlgItemText(IDC_CHECKSUM_LIST, result);
   if (NULL != result)  delete []result;
   
   return;
}

/////////////////////////////////////////////////////////////////////////////
// OnOK
//
//    Do the memory checksum
//
/////////////////////////////////////////////////////////////////////////////
void CMemChecksumPage::OnOK()
{
   // TODO: Add your control notification handler code here
   DoChecksum();
   ((CMemDlg*)GetParent())->SetModal(TRUE);      
}

/////////////////////////////////////////////////////////////////////
// OnCancel
//
//    Reset the m_bModeless
////////////////////////////////////////////////////////////////////
void CMemChecksumPage::OnCancel()
{
   // TODO: Add your control notification handler code here
   ((CMemDlg*)GetParent())->SetModal(FALSE);   
}

/////////////////////////////////////////////////////////////////////////////
// OnChecksumChecksum
//
//    Do the memory checksum
//
/////////////////////////////////////////////////////////////////////////////
void CMemChecksumPage::OnChecksumChecksum()
{
   // TODO: Add your control notification handler code here
   DoChecksum();
}

/////////////////////////////////////////////////////////////////////////////
// OnChecksumCancel
//
//    Quit the memory dialog
//
/////////////////////////////////////////////////////////////////////////////
void CMemChecksumPage::OnChecksumCancel()
{
   // TODO: Add your control notification handler code here
   CWnd *wndParent = NULL;
   wndParent = GetParent();
   // Quit the parent window(memory sheet)
   ((CPropertySheet *)wndParent)->EndDialog(0);
}

////////////////////////////////////////////////////////////////////////////
// OnChecksumHelp
//
// On help (may add)                                                       
//
////////////////////////////////////////////////////////////////////////////
void CMemChecksumPage::OnChecksumHelp()
{
   // TODO: Add your control notification handler code here
   // Active Windows Help system
   OnCommandHelp(0, 0);
}  

BOOL  CMemChecksumPage::OnSetActive()
{
   m_nIDHelp = IDD_MEMGRP_CHECKSUM;

   return CPropertyPage::OnSetActive();
}

////////////////////////////////////////////////////////////////////////////
// OnInitDialog
//
//    Initialize the dialog
//
////////////////////////////////////////////////////////////////////////////
BOOL CMemChecksumPage::OnInitDialog()
{
   CPropertyPage::OnInitDialog();
   
   // TODO: Add extra initialization here
   
   CWnd* ctrl;
      
   if (dwpMin == dwpMax) {        // no code area   
      ctrl = GetDlgItem(IDC_CHECKSUM_SPACE);
      ctrl->EnableWindow(FALSE);
   }
   if (dwxMin == dwxMax) {        // no data area   
      ctrl = GetDlgItem(IDC_CHECKSUM_SPACE_DATA);
      ctrl->EnableWindow(FALSE);
   }
   if (dwiMin == dwiMax) {        // no on_chip area   
      ctrl = GetDlgItem(IDC_CHECKSUM_SPACE_CHIP);
      ctrl->EnableWindow(FALSE);
   }
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}  // End of CMemComparePage


/////////////////////////(EOF of MEMOPAGE.CPP)////////////////////////////////


