/***************************************************************************
**
**    $Header$
**
**    $Log$
** 
****************************************************************************/

/***************************************************************************
**
** File name :  MEMWIN.CPP
** Author:      Chris Fang
** Description: implement file of memory window
**
** coding from: Apr 21, 1997
** Finished date:
**
**
**    Copyright (C) 1997 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"
#include "resource.h"

#include <ctype.h>
#include <errno.h>

#include "memwin.h"
#include "memsvr.h"
#include "ep196.h"
#include "uicom2.h"
//#include "uicom1.h"
#include "mainfrm.h"
#include "memgtdlg.h"
#include "memdlg.h"
#include "colors.h"
#include "dadextfn.h"
#include "dsmedit1.h"
#include "dsmedit2.h"
#include "memschdg.h"
#include "mapbtn.h"
#include "mapdlg.h"
#include "hosterrs.h"
#include "uicom2.h"
//#include "zqueue.h"
//#include "srccom.h"
//#include "xview.h"
//#include "ctype.h"
//#include "errno.h"
//#include "myedit2.h"
//#include "spin.h"
//#include "tabdll11.h"
//#include "tabvbmfc.h"
//#include "mempage.h"          // Add by Daniel
//#include "dad.h"
//#include "cpucom.h"
//#include "abibase.h"
#include "cpusvr.h"

//#include "address.h"
//#include "addrapi.h"
//#include "btnbar.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *    EXTERNAL FUNCTION     *
                        *                          *
                        ****************************/
//extern void GetMemoryRange(CPUMEMORYRANGE& stRange);

/*
    Output : uchStatus = the current cpu status
             STATUS_HALT  == 0
             STATUS_GO    == 1
             STATUS_GORUN == 2
    returN : TRUE ==> GET OK
             FALSE ==> GET FAIL
*/
extern BOOL MyMemServerSearch(ADDRESS Start, ADDRESS End, char* pszPattern, 
					int nInsensitive, ADDRESS& RetAddr, BOOL& bFind);

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

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

                       /****************************
                        *                          *
                        *       GLOBAL VARS        *
                        *                          *
                        ****************************/
//!!! All these static variable should be initialized in ReadMemWndIni(), and
//this routine should be called when init.
//record start address and space of memory window, next time memory
//window opened from this addr.
static ADDR	sadr_LastMemAddr[MAX_MEM_WND];

//record view in byte(1), word(2) or dword(3) in memory window.
static BYTE sb_MemViewMode1[MAX_MEM_WND];

//record view in hex(1), unsigned decimal(2), signed decimal(3) or
//instruction(4) in memory window.
static BYTE sb_MemViewMode2[MAX_MEM_WND];

static BOOL sb_MemShowAscii[MAX_MEM_WND];

//1: normal; 2: short line
static int  sn_MemLineGroup[MAX_MEM_WND];

//record user input address in goto dialog.
static ADDR	sadr_GotoAddr;

                       /****************************
                        *                          *
                        *   CLASS STATIC VARIBLE   *
                        *                          *
                        ****************************/
CMenu NEAR CMemoryWindow::m_menu;

char CMemoryWindow::m_searchStr[200] = "";
char CMemoryWindow::m_szPattern[33] = "";

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
                        
////////////////////////////////////////////////////////////////////////
// Minimize all memory window include the three memory window and the 
//  bit memory window
//       Only for when the CPU at GO status, the memory window can not
//       do anything
//                        
void MinAllMemWnd(void)
{   
/*
    if(gb_isMemOn[0]) gp_MemWnd[0]->ShowWindow(SW_SHOWMINIMIZED);
    if(gb_isMemOn[1]) gp_MemWnd[1]->ShowWindow(SW_SHOWMINIMIZED);
    if(gb_isMemOn[2]) gp_MemWnd[2]->ShowWindow(SW_SHOWMINIMIZED);
    if(isBMemOn) pBMemWnd->ShowWindow(SW_SHOWMINIMIZED);
*/    
}

//////////////////////////////////////////////////////////////////////////
// Open the memory window
//    Called by Mainframe
//                        
void NewMemoryOpenWindow(CMDIFrameWnd *pParent,int no)
{
	ASSERT(no<MAX_MEM_WND);
	if (gb_isMemOn[no])
		return;

	gp_MemWnd[no] = new CMemoryWindow(BYTE(no));
	if(!((CMemoryWindow *)gp_MemWnd[no])->Create("Memory",
			WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
			CFrameWnd::rectDefault, pParent))
		ASSERT(0);
	else
		gb_isMemOn[no]=TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMemoryWindow
//
//
IMPLEMENT_DYNCREATE(CMemoryWindow, CMDIChildWnd)

CMemoryWindow::CMemoryWindow(BYTE no)
{
CPUMEMORYRANGE stRange;

	ASSERT(no>=0&&no<MAX_MEM_WND);
	m_bWndNo=no;

	m_dwStartAddress = sadr_LastMemAddr[no].addr;
	m_wSpaceType = sadr_LastMemAddr[no].addrType;
	m_bViewMode1 = sb_MemViewMode1[no];
	m_bViewMode2 = sb_MemViewMode2[no];
	m_bShowAscii = sb_MemShowAscii[no];
	m_nLineGroup = sn_MemLineGroup[no];

	GetMemoryRange( stRange );         // Get the current cpu memory
	pMin = stRange.pMin;
	pMax = stRange.pMax;
	xMin = stRange.xMin;
	xMax = stRange.xMax;
	iMin = stRange.iMin;
	iMax = stRange.iMax;
	xMin=pMin=0;
//	xMin=iMin=pMin=0;
	xMax=pMax=0xffff;
	//iMax=0xff;
	SetRegionEnd();
	if (m_dwStartAddress < m_dwMemRegionStart)
		m_dwStartAddress = m_dwMemRegionStart & ((DWORD)-16/m_nLineGroup);

	m_nIDHelp = IDR_MEMORY;

	m_nLines = 15;             // modify by Daniel Lin on 1996.7.3

	m_wMemBufferLen=1024;
	m_pMemBuffer = new BYTE[m_wMemBufferLen];
	m_dwBufStartAddr=0xffff;
	m_dwBufEndAddr=0;

	m_wDSMBufferLen=128;
	m_dsm= new struct dsm[m_wDSMBufferLen];

	m_bHScrollOn=TRUE;
	m_nPosX = 0;

	m_wCaretPosX1 = 0;
	m_wCaretPosX2 = 0;
	m_lCaretPosY = 0;
	m_nCaretArea = 1;

	m_nCursor = 0;

	m_lpszValue = new char[20];
	ASSERT(m_lpszValue!=NULL);
}

CMemoryWindow::~CMemoryWindow()
{
	gb_isMemOn[m_bWndNo] = FALSE;
	gp_MemWnd[m_bWndNo] = NULL;

	if (m_pMemBuffer!=NULL)
		delete []m_pMemBuffer;
	if(m_dsm)
		delete []m_dsm;
	if(m_lpszValue)
		delete []m_lpszValue;

	sadr_LastMemAddr[m_bWndNo].addr = m_dwStartAddress;
	sadr_LastMemAddr[m_bWndNo].addrType = m_wSpaceType;
	sb_MemViewMode1[m_bWndNo]=m_bViewMode1;
	sb_MemViewMode2[m_bWndNo]=m_bViewMode2;
	sb_MemShowAscii[m_bWndNo]=m_bShowAscii;
	sn_MemLineGroup[m_bWndNo]=m_nLineGroup;
}

BOOL CMemoryWindow::Create(LPCSTR szTitle, LONG style,
                        const RECT& rect, CMDIFrameWnd * pParent)
{
HBRUSH	hBackGround;

	hBackGround=CreateSolidBrush(PALETTEINDEX(COLOR_WHITE));

	// Setup the shared m_menu
	if(m_menu.m_hMenu == NULL)  m_menu.LoadMenu(IDR_MEMORY);
	m_hMenuShared = m_menu.m_hMenu;
    
	const char * pszMemoryClass =
		AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,NULL,
							hBackGround,	//System will delete this brush when class is freed.
							AfxGetApp()->LoadIcon(IDR_MEMORY));
	if (!(CMDIChildWnd::Create(pszMemoryClass, szTitle,
							style, rect, pParent)))
		return FALSE;                         
	else
		return TRUE;      
}                         

void CMemoryWindow::ShowStatusGo(void)
{
	CString str = "Running. Halt CPU first.";
	((CMainFrame*)((CEp196App *)AfxGetApp()->m_pMainWnd))
		->m_wndStatusBar.UpdateStatusBar(0, str);
}

void CMemoryWindow::SetWindowTitle(long addr)
{
char title[40];

	switch (m_wSpaceType)
	{
		case MEM_P0:
			wsprintf(title, "%d:Program Bank0", m_bWndNo+1);
			break;
		case MEM_P1:
			wsprintf(title, "%d:Program Bank1", m_bWndNo+1);
			break;
		case MEM_P2:
			wsprintf(title, "%d:Program Bank2", m_bWndNo+1);
			break;
		case MEM_P3:
			wsprintf(title, "%d:Program Bank3", m_bWndNo+1);
			break;
		case MEM_X0:
			wsprintf(title, "%d:Data Bank0", m_bWndNo+1);
			break;
		case MEM_X1:
			wsprintf(title, "%d:Data Bank1", m_bWndNo+1);
			break;
		case MEM_I:
			wsprintf(title, "%d:On_Chip Data Memory", m_bWndNo+1);
			break;
		default:
			wsprintf(title, "%d:Memory", m_bWndNo+1);
			ASSERT(0);
			break;
	}
	if(addr!=-1)
		wsprintf(&title[strlen(title)], " : %04X", addr);
	SetWindowText(title);
}

void CMemoryWindow::FillText(LPCSTR lpszText,UINT nCount,
							 RECT rect,CDC* dc, BOOL isGrey)
{
SIZE size;
COLORREF oldColor;
CBrush greyBrush(PALETTEINDEX(7));
CPen whitePen;
CPen blackPen;
CPen *oldPen;

	whitePen.CreatePen(PS_SOLID,1, PALETTEINDEX(19));
	blackPen.CreatePen(PS_SOLID,1,PALETTEINDEX(0));

	size = dc->GetOutputTextExtent(lpszText, nCount);
	int addx = (rect.right - rect.left - size.cx) / 2;
	int addy = (rect.bottom - rect.top - size.cy) / 2 + 1;
	
	if(isGrey)
	{
		oldColor = dc->SetBkColor(PALETTEINDEX(7));
		dc->FillRect(&rect, &greyBrush);
	}
	dc->ExtTextOut(rect.left+addx, rect.top+addy,
					ETO_CLIPPED,
					&rect,
					lpszText,
					nCount,
					NULL);
	if(isGrey)
	{
		oldPen = dc->SelectObject(&blackPen);
	    dc->MoveTo(rect.right,rect.bottom);
	    dc->LineTo(rect.right,rect.top);
	    dc->LineTo(rect.left,rect.top);
	    dc->LineTo(rect.left,rect.bottom);
	    dc->SelectObject(&whitePen);
	    dc->MoveTo(rect.right-1,rect.top+1);
		dc->LineTo(rect.left+1,rect.top+1);
		dc->LineTo(rect.left+1,rect.bottom);

		dc->SetBkColor(oldColor);
		dc->SelectObject(oldPen);
	}
}

void CMemoryWindow::FillText2(LPCSTR lpszText,UINT nCount,RECT rect,CDC* dc)
{
SIZE size;
char text[256];

	nCount=min(nCount, 255);
	memcpy(text, lpszText, nCount);
	memset(&text[nCount],' ',255-nCount);
	text[255]=NULL;
	size = dc->GetOutputTextExtent(lpszText, nCount);
	int addx = m_nCharWidth/2;
	int addy = (rect.bottom - rect.top - size.cy) / 2 + 1;
	dc->ExtTextOut(rect.left+addx, rect.top+addy,
	               ETO_CLIPPED,
	               &rect,
	               text,
	               255,
	               NULL);
}

void CMemoryWindow::SetScrollBar()
{
RECT rect1,rect2;

	GetClientRect(&rect2);
    
	if (m_bViewMode2 != SM_CODE)
	{
		if (m_bShowAscii)
		{
			rect1 = m_gridAscii.GetGridRect(0,0);
			if (rect1.right >= rect2.right)
				m_bHScrollOn = TRUE;
			else
			    m_bHScrollOn = FALSE;
		}
		else
		{
			rect1 = m_gridMem.GetGridRect(m_gridMem.m_nRows-1,0);
			if (rect1.right >= rect2.right)
				m_bHScrollOn = TRUE;
			else
				m_bHScrollOn = FALSE;
		}
	}
	else
	{
		rect1 = m_gridInstruction.GetGridRect(0,0);
		if (rect1.right >= rect2.right)
			m_bHScrollOn = TRUE;
		else
			m_bHScrollOn = FALSE;
	}
	if (m_nPosX<0)
	{
		if (rect2.right>rect1.right)
		{
			m_nPosX = m_nPosX + (rect2.right-rect1.right);
			if (m_nPosX>0)
				m_nPosX = 0;
		}
	}
	else 
		m_nPosX = 0;
	if (m_nPosX<0) 
		m_bHScrollOn = TRUE;
	ShowScrollBar(SB_HORZ, m_bHScrollOn);
	if (m_bHScrollOn)
	{
		SetScrollRange(SB_HORZ, 0, 
					(rect1.right-rect2.right-m_nPosX+3),FALSE);
		SetScrollPos(SB_HORZ, -m_nPosX, TRUE);
	}
}

void CMemoryWindow::SetAddress()
{
	m_gridAddr.SetPos(0,0,0);
	m_gridAddr.SetLines(m_nLines);
	m_gridAddr.SetRows(1);
	m_gridAddr.SetGridWidth(m_nCharWidth*5);
	m_gridAddr.SetGridHeight(m_nLineHeight);
	memcpy(m_gridAddr.m_lpszTitle,"Addr\0",8);
	m_gridAddr.DoRect();
}

void CMemoryWindow::SetAscii()
{
	m_gridAscii.SetPos(m_gridMem.m_rectPos.right,0, m_gridAddr.m_nGridWidth);
	m_gridAscii.SetLines(m_nLines);
	m_gridAscii.SetRows(1);
	m_gridAscii.SetGridWidth(m_nCharWidth*(16/m_nLineGroup+1));
	m_gridAscii.SetGridHeight(m_nLineHeight);
	memcpy(m_gridAscii.m_lpszTitle,"ASCII\0",6);
	m_gridAscii.DoRect();
}

void CMemoryWindow::SetInstruction()
{
	m_gridInstruction.SetPos(m_gridMem.m_rectPos.right,0,
				m_gridAddr.m_nGridWidth);
	m_gridInstruction.SetLines(m_nLines);
	m_gridInstruction.SetRows(1);
	m_gridInstruction.SetGridWidth(m_nCharWidth*256);
	m_gridInstruction.SetGridHeight(m_nLineHeight);
	memcpy(m_gridInstruction.m_lpszTitle,"Instruction\0",12);
	m_gridInstruction.DoRect();
}

void CMemoryWindow::SetByteSignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(16/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*5);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='1';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='2';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='3';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='4';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='5';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='6';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='7';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.m_lpszTitle[16]='8';
	m_gridMem.m_lpszTitle[17]='\0';
	m_gridMem.m_lpszTitle[18]='9';
	m_gridMem.m_lpszTitle[19]='\0';
	m_gridMem.m_lpszTitle[20]='A';
	m_gridMem.m_lpszTitle[21]='\0';
	m_gridMem.m_lpszTitle[22]='B';
	m_gridMem.m_lpszTitle[23]='\0';
	m_gridMem.m_lpszTitle[24]='C';
	m_gridMem.m_lpszTitle[25]='\0';
	m_gridMem.m_lpszTitle[26]='D';
	m_gridMem.m_lpszTitle[27]='\0';
	m_gridMem.m_lpszTitle[28]='E';
	m_gridMem.m_lpszTitle[29]='\0';
	m_gridMem.m_lpszTitle[30]='F';
	m_gridMem.m_lpszTitle[31]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetWordSignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(8/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*7);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='2';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='4';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='6';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='8';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='A';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='C';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='E';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetLongSignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(4/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*12);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='4';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='8';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='C';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetByteUnsignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(16/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*4);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='1';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='2';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='3';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='4';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='5';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='6';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='7';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.m_lpszTitle[16]='8';
	m_gridMem.m_lpszTitle[17]='\0';
	m_gridMem.m_lpszTitle[18]='9';
	m_gridMem.m_lpszTitle[19]='\0';
	m_gridMem.m_lpszTitle[20]='A';
	m_gridMem.m_lpszTitle[21]='\0';
	m_gridMem.m_lpszTitle[22]='B';
	m_gridMem.m_lpszTitle[23]='\0';
	m_gridMem.m_lpszTitle[24]='C';
	m_gridMem.m_lpszTitle[25]='\0';
	m_gridMem.m_lpszTitle[26]='D';
	m_gridMem.m_lpszTitle[27]='\0';
	m_gridMem.m_lpszTitle[28]='E';
	m_gridMem.m_lpszTitle[29]='\0';
	m_gridMem.m_lpszTitle[30]='F';
	m_gridMem.m_lpszTitle[31]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetWordUnsignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(8/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*6);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='2';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='4';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='6';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='8';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='A';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='C';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='E';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetLongUnsignedDecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(4/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*11);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='4';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='8';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='C';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetByteHexadecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(16/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*3);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='1';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='2';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='3';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='4';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='5';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='6';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='7';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.m_lpszTitle[16]='8';
	m_gridMem.m_lpszTitle[17]='\0';
	m_gridMem.m_lpszTitle[18]='9';
	m_gridMem.m_lpszTitle[19]='\0';
	m_gridMem.m_lpszTitle[20]='A';
	m_gridMem.m_lpszTitle[21]='\0';
	m_gridMem.m_lpszTitle[22]='B';
	m_gridMem.m_lpszTitle[23]='\0';
	m_gridMem.m_lpszTitle[24]='C';
	m_gridMem.m_lpszTitle[25]='\0';
	m_gridMem.m_lpszTitle[26]='D';
	m_gridMem.m_lpszTitle[27]='\0';
	m_gridMem.m_lpszTitle[28]='E';
	m_gridMem.m_lpszTitle[29]='\0';
	m_gridMem.m_lpszTitle[30]='F';
	m_gridMem.m_lpszTitle[31]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetWordHexadecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(8/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*5);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='2';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='4';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='6';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.m_lpszTitle[8]='8';
	m_gridMem.m_lpszTitle[9]='\0';
	m_gridMem.m_lpszTitle[10]='A';
	m_gridMem.m_lpszTitle[11]='\0';
	m_gridMem.m_lpszTitle[12]='C';
	m_gridMem.m_lpszTitle[13]='\0';
	m_gridMem.m_lpszTitle[14]='E';
	m_gridMem.m_lpszTitle[15]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetLongHexadecimal()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(4/m_nLineGroup);
	m_gridMem.SetGridWidth(m_nCharWidth*9);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='0';
	m_gridMem.m_lpszTitle[1]='\0';
	m_gridMem.m_lpszTitle[2]='4';
	m_gridMem.m_lpszTitle[3]='\0';
	m_gridMem.m_lpszTitle[4]='8';
	m_gridMem.m_lpszTitle[5]='\0';
	m_gridMem.m_lpszTitle[6]='C';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetDisassemble()
{
	m_gridMem.SetPos(m_nPosX,0, m_gridAddr.m_nGridWidth);
	m_gridMem.SetLines(m_nLines);
	m_gridMem.SetRows(1);
	m_gridMem.SetGridWidth(m_nCharWidth*11);
	m_gridMem.SetGridHeight(m_nLineHeight);
	m_gridMem.m_lpszTitle[0]='O';
	m_gridMem.m_lpszTitle[1]='P';
	m_gridMem.m_lpszTitle[2]=' ';
	m_gridMem.m_lpszTitle[3]='c';
	m_gridMem.m_lpszTitle[4]='o';
	m_gridMem.m_lpszTitle[5]='d';
	m_gridMem.m_lpszTitle[6]='e';
	m_gridMem.m_lpszTitle[7]='\0';
	m_gridMem.DoRect();
}

void CMemoryWindow::SetMemoryWindow()
{
	SetAddress();

	switch (m_bViewMode2)
	{
		case SM_CODE:
			SetDisassemble();
			break;
		case SM_HEX:
			switch (m_bViewMode1)
			{
				case SM_BYTE:
					SetByteHexadecimal();
					break;
				case SM_WORD:
					SetWordHexadecimal();
					break;
				case SM_DWORD:
					SetLongHexadecimal();
					break;
				default:
					break;
			}
			break;
		case SM_UDEC:
			switch (m_bViewMode1)
			{
				case SM_BYTE:
					SetByteUnsignedDecimal();
					break;
				case SM_WORD:
					SetWordUnsignedDecimal();
					break;
				case SM_DWORD:
					SetLongUnsignedDecimal();
					break;
				default:
					break;
			}
			break;
		case SM_DEC:
			switch (m_bViewMode1)
			{
				case SM_BYTE:
					SetByteSignedDecimal();
					break;
				case SM_WORD:
					SetWordSignedDecimal();
					break;
				case SM_DWORD:
					SetLongSignedDecimal();
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
	if (m_bViewMode2!=SM_CODE)
	{
		if (m_bShowAscii)
			SetAscii();
	}
	else
		SetInstruction();
}

void CMemoryWindow::ShowAddress(CDC *dc)
{
RECT rect;
int i;
char buf[20];
long addr;

	if(m_bViewMode2!=SM_CODE)
	{
		ASSERT(m_dwStartAddress%(0x10/m_nLineGroup)==0);
		addr = m_dwStartAddress;
		for( i = 1; i < m_nLines; i++ )
		{
			rect = m_gridAddr.GetGridRect(0,i);
			sprintf(buf,"%04X",addr);       // modified by Daniel
			FillText(buf,4,rect,dc, TRUE);        // modified by Daniel
			addr+=(0x10/m_nLineGroup);
		}
	}
	else		//Dissemble
	{
		for(i=1;i<=m_nDSMNum;i++)
		{
			rect = m_gridAddr.GetGridRect(0,i);
			sprintf(buf, "%04X", m_dsm[i-1].address);
			FillText(buf,4,rect,dc, TRUE);
		}
	}
}

void CMemoryWindow::ShowAscii(CDC *dc)
{
RECT rect;
int i,j,pos;
BYTE value;
BYTE *p;
char buf[20];

	p = (BYTE *)m_byMem;
	for ( i = 1; i < m_nLines; i++ )
	{
		rect = m_gridAscii.GetGridRect(0, i);
		for (j = 0; j < 16/m_nLineGroup; j++ )
		{
			pos = (i-1) * (16/m_nLineGroup) + j;
			value = p[pos];
			if (pos+m_dwStartAddress >= m_dwMemRegionStart) {
				if ((0x20 < value) && (value <= 0x7e))
					buf[j]=value;
				else
					buf[j]='.';
			}
			else buf[j] = ' ';
		}
		FillText(buf,16/m_nLineGroup,rect,dc);
	}
}

void CMemoryWindow::ShowInstruction(CDC *dc)
{
RECT rect;
int i;
int j;

	for(i=1;i<=m_nDSMNum;i++)
	{
		rect = m_gridInstruction.GetGridRect(0,i);
		j = strlen(m_dsm[i-1].instruction);
		FillText2((const char*)m_dsm[i-1].instruction,j,rect,dc);
	}
}

void CMemoryWindow::ShowByteSignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
BYTE value;
int	nvalue;
BYTE *p;
char buf[20];

	p = (BYTE *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(16/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(16/m_nLineGroup) + j;
			if (pos+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				nvalue=(char)value;
				sprintf(buf,"%+04d", nvalue);
			}
			else {
				lstrcpy(buf,"    ");
			}
			FillText(buf,4,rect,dc);
		}
	}
}

void CMemoryWindow::ShowWordSignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
WORD value;
WORD *p;
char buf[20];

	p = (WORD *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(8/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(8/m_nLineGroup) + j;
			if (pos*2+1+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%+06d",value);
			}
			else {
				lstrcpy(buf,"      ");
			}
			FillText(buf,6,rect,dc);
		}
	}
}

void CMemoryWindow::ShowLongSignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
long value;
long *p;
char buf[20];

	p = (long *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(4/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(4/m_nLineGroup) + j;
			if (pos*4+3+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%+011ld",value);
			}
			else {
				lstrcpy(buf,"           ");
			}
			FillText(buf,11,rect,dc);
		}
	}
}

void CMemoryWindow::ShowByteUnsignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
BYTE value;
BYTE *p;
char buf[20];

	p = (BYTE *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(16/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(16/m_nLineGroup) + j;
			if (pos+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%03u",value);
			}
			else {
				lstrcpy(buf,"   ");
			}
			FillText(buf,3,rect,dc);
		}
	}
}

void CMemoryWindow::ShowWordUnsignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
WORD value;
WORD *p;
char buf[20];

	p = (WORD *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(8/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(8/m_nLineGroup) + j;
			if (pos*2+1+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%05u",value);
			}
			else {
				lstrcpy(buf,"     ");
			}
			FillText(buf,5,rect,dc);
		}
	}
}

void CMemoryWindow::ShowLongUnsignedDecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
long value;
long *p;
char buf[20];

	p = (long *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(4/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(4/m_nLineGroup) + j;
			if (pos*4+3+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%010lu",value);
			}
			else {
				lstrcpy(buf,"          ");
			}
			FillText(buf,10,rect,dc);
		}
	}
}

void CMemoryWindow::ShowByteHexadecimal(CDC *dc)
{
RECT rect;
int i,j;
BYTE value;
int pos;
char buf[20];

	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(16/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(16/m_nLineGroup) + j;
			if (pos+m_dwStartAddress >= m_dwMemRegionStart) {
				value = m_byMem[pos];
				sprintf(buf,"%02X",value);
			}
			else {
				lstrcpy(buf,"  ");
			}
			FillText(buf,2,rect,dc);
		}
	}
}

void CMemoryWindow::ShowWordHexadecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
WORD value;
WORD *p;
char buf[20];

	p = (WORD *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(8/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(8/m_nLineGroup) + j;
			if (pos*2+1+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%04X",value);
			}
			else {
				lstrcpy(buf,"    ");
			}
			FillText(buf,4,rect,dc);
		}
	}
}

void CMemoryWindow::ShowLongHexadecimal(CDC *dc)
{
RECT rect;
int i,j,pos;
long value;
long *p;
char buf[20];

	p = (long *)m_byMem;
	for(i=1;i<m_nLines;i++)
	{
		for(j=0;j<(4/m_nLineGroup);j++)
		{
			rect = m_gridMem.GetGridRect(j,i);
			pos = (i-1)*(4/m_nLineGroup) + j;
			if (pos*4+3+m_dwStartAddress >= m_dwMemRegionStart) {
				value = p[pos];
				sprintf(buf,"%08lX",value);
			}
			else {
				lstrcpy(buf,"        ");
			}
			FillText(buf,8,rect,dc);
		}
	}
}

void CMemoryWindow::ShowDisassemble(CDC *dc)
{
RECT rect;
int i;
int j;

	for(i=1;i<=m_nDSMNum;i++)
	{
		rect = m_gridMem.GetGridRect(0,i);
		j = strlen(m_dsm[i-1].code);
		FillText2(m_dsm[i-1].code,j,rect,dc);
	}
}

void CMemoryWindow::ShowMemoryWindow(CDC *dc)
{
	switch (m_bViewMode2)
	{
		case SM_CODE:
			ShowDisassemble(dc);
			break;
		case SM_HEX:
			switch (m_bViewMode1)
			{
				case SM_BYTE:
					ShowByteHexadecimal(dc);
					break;
				case SM_WORD:
					ShowWordHexadecimal(dc);
					break;
				case SM_DWORD:
					ShowLongHexadecimal(dc);
					break;
				default:
					break;
			}
			break;
		case SM_UDEC:
			switch (m_bViewMode1)
			{
				case SM_BYTE:
					ShowByteUnsignedDecimal(dc);
					break;
				case SM_WORD:
					ShowWordUnsignedDecimal(dc);
					break;
				case SM_DWORD:
					ShowLongUnsignedDecimal(dc);
					break;
				default:
					break;
			}
			break;
		case SM_DEC:
			switch (m_bViewMode1)        
			{
				case SM_BYTE:
					ShowByteSignedDecimal(dc);
					break;
				case SM_WORD:
					ShowWordSignedDecimal(dc);
					break;
				case SM_DWORD:
					ShowLongSignedDecimal(dc);
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}

	if (m_bViewMode2!=SM_CODE)
	{
		if (m_bShowAscii)
			ShowAscii(dc);
	}
	else 
		ShowInstruction(dc);
	ShowAddress(dc);
}

void CMemoryWindow::SetMyCaretPos()
{
WORD wValue;
int i;
RECT rect;
POINT pos;

	if (!m_bFocus) return;

	if (m_bViewMode2==SM_CODE)	//no caret in this mode
	{
		pos.x = -30;
		pos.y = -30;
		SetCaretPos(pos);
	}
	else
	{
		switch (m_nCaretArea)
		{
		case 2:		//in ascii area
            wValue = WORD(m_dwStartAddress/(16/m_nLineGroup));
			if ((m_lCaretPosY>=long(wValue))&&(m_lCaretPosY<long(wValue+m_nLines)))
			{
				i = int(m_lCaretPosY - wValue);
				rect = m_gridAscii.GetGridRect(0,i+1);
				pos.x = rect.left+m_wCaretPosX2*m_nCharWidth+m_nCharWidth/2-1;
				pos.y = rect.top + 2;
				SetCaretPos(pos);
				ShowCaret();
			}
			else
			{
				pos.x = -30;
				pos.y = -30;
				SetCaretPos(pos);
			}
			break;

		default:		//not in Ascii
			ASSERT(m_dwStartAddress<0x100000);
			wValue = WORD(m_dwStartAddress/(16/m_nLineGroup));
			if ((m_lCaretPosY>=long(wValue))&&(m_lCaretPosY<long(wValue+m_nLines)))
			{
				i = int(m_lCaretPosY - wValue);
				rect = m_gridMem.GetGridRect(m_wCaretPosX1,i+1);
				pos.x = rect.left+m_wCaretPosX2*m_nCharWidth+m_nCharWidth/2-1;
				if(pos.x<m_gridAddr.m_nGridWidth)
					pos.x=-30;
				pos.y = rect.top + 2;
				SetCaretPos(pos);
				ShowCaret();
			}
			else
			{
				pos.x = -30;
				pos.y = -30;
				SetCaretPos(pos);
			}
			break;
		}
	}
}

void CMemoryWindow::GotoCursor()
{
	OnVScroll(SB_THUMBPOSITION, (WORD)m_lCaretPosY, NULL);
}

void CMemoryWindow::xGotoCursor(void)
{
int virtualx;
RECT rect;
	
	if(m_bViewMode2==SM_CODE)
		return;
	if(m_nCaretArea==2)			//in Ascii
		virtualx=m_gridAscii.GetLeftPos()+
				 m_nCharWidth*m_wCaretPosX2+m_nCharWidth/2;
	else
	{
		rect=m_gridMem.GetGridRect(m_wCaretPosX1,0);
		virtualx=rect.left+m_wCaretPosX2*m_nCharWidth;
	}
	GetClientRect(&rect);
	if(virtualx+m_nCharWidth>=rect.right||virtualx<m_gridAddr.m_nGridWidth)
	{
		if(virtualx+m_nCharWidth>=rect.right)
		{
			virtualx+=m_nCharWidth*2;
			OnHScroll(SB_THUMBTRACK, virtualx-rect.right-m_nPosX, NULL);
		}
		else
		{
			virtualx-=m_nCharWidth;
			OnHScroll(SB_THUMBTRACK, max(0, virtualx-m_nPosX-
						m_gridAddr.m_nGridWidth), NULL);
		}
	}
}

BOOL CMemoryWindow::InWnd()
{
WORD i;

	i = (WORD)(m_dwStartAddress/(16/m_nLineGroup));
	if((m_lCaretPosY>=long(i))&&(m_lCaretPosY<long(i+m_nLines-2)))
		return TRUE;
	else
		return FALSE;
}

void CMemoryWindow::PaintLine(WORD line)
{
	ASSERT(line>=0&&line<WORD(m_nLines));
	
RECT rect, rectwnd;
	
	rect=m_gridAddr.GetGridRect(0, line+1);
	GetClientRect(&rectwnd);
	rectwnd.top=rect.top;
	rectwnd.bottom=rect.bottom;
	InvalidateRect(&rectwnd);
}

void CMemoryWindow::Right()
{
	if (m_nCaretArea == 2)
	{
		if (m_wCaretPosX2==WORD(16/m_nLineGroup-1))
		{
			if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
			{
				MessageBeep(-1);
				return;
			}
			m_wCaretPosX2=0;
			Down();
			return;
		}
		else
			m_wCaretPosX2++;
	}
	else
		switch(m_bViewMode2)
		{
		case SM_CODE:            // Disassembly
			break;

		case SM_HEX:            // Hexdecimal
			switch(m_bViewMode1)
			{
				case SM_BYTE:             // Byte
					if ((m_wCaretPosX1==WORD(16/m_nLineGroup-1))&&(m_wCaretPosX2==1))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==1)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
			    case SM_WORD:             // Word
					if ((m_wCaretPosX1==WORD(8/m_nLineGroup-1))&&(m_wCaretPosX2==3))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==3)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
			    case SM_DWORD:             // Long
					if ((m_wCaretPosX1==WORD(4/m_nLineGroup-1))&&(m_wCaretPosX2==7))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==7)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				default:
					break;
			}
			break;

		case SM_UDEC:            // Unsigned Decimal
			switch(m_bViewMode1)
			{
				case SM_BYTE:          // Byte
					if ((m_wCaretPosX1==WORD(16/m_nLineGroup-1))&&(m_wCaretPosX2==2))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
					    return;
					}
					if (m_wCaretPosX2==2)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;        
				case SM_WORD:           // Word
					if ((m_wCaretPosX1==WORD(8/m_nLineGroup-1))&&(m_wCaretPosX2==4))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==4)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				case SM_DWORD:          // Long
					if ((m_wCaretPosX1==WORD(4/m_nLineGroup-1))&&(m_wCaretPosX2==9))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==9)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				default:
					break;
			}
			break;

		case SM_DEC:         // Signed Decimal
			switch(m_bViewMode1)
			{
				case SM_BYTE:          // Byte
					if ((m_wCaretPosX1==WORD(16/m_nLineGroup-1))&&(m_wCaretPosX2==3))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==3)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				case SM_WORD:       // Word
					if ((m_wCaretPosX1==WORD(8/m_nLineGroup-1))&&(m_wCaretPosX2==5))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
							MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==5)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				case SM_DWORD:       // Long
					if ((m_wCaretPosX1==WORD(4/m_nLineGroup-1))&&(m_wCaretPosX2==10))
					{
						if(m_lCaretPosY==long(m_dwMemRegionEnd/(16/m_nLineGroup)))
						{
						MessageBeep(-1);
							return;
						}
						m_wCaretPosX1 = 0;
						m_wCaretPosX2 = 0;
						Down();
						return;
					}
					if (m_wCaretPosX2==10)
					{
						m_wCaretPosX1++;
						m_wCaretPosX2=0;
					}
					else
						m_wCaretPosX2++;
					break;
				default:
					break;
			}
			break;  

		default:
		    break;
		}
}

void CMemoryWindow::Left()
{
	DWORD dwCurAddr = GetCaretAddr();
	if (m_nCaretArea == 2)	//in ascii
	{
		if (dwCurAddr <= m_dwMemRegionStart) {
			MessageBeep(-1);
			return;
		}
		if (m_wCaretPosX2==0)
		{
			if(m_lCaretPosY==0)
			{
				MessageBeep(-1);
				return;
			}
			m_wCaretPosX2=WORD(16/m_nLineGroup-1);
			Up();
			return;
		}
		else
			m_wCaretPosX2--;
	}
	else
		switch(m_bViewMode2)
		{
			case SM_CODE:            // Disassembly
				break;                       
			case SM_HEX:            // Hexdecimal
				switch(m_bViewMode1)
				{
					case SM_BYTE:             // Byte
						if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
						{
							if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(16/m_nLineGroup-1);
							m_wCaretPosX2 = 1;
							Up();
							return;
						}
						if (m_wCaretPosX2==0)
						{
						    m_wCaretPosX1--;
						    m_wCaretPosX2=1;
						}
						else
							m_wCaretPosX2--;
						break;
				    case SM_WORD:             // Word
				        if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
				        {
				        	if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(8/m_nLineGroup-1);
				        	m_wCaretPosX2 = 3;
				        	Up();
				        	return;
				        }
				        if (m_wCaretPosX2==0)
				        {
				            m_wCaretPosX1--;
				            m_wCaretPosX2=3;
				        }
				        else
				        	m_wCaretPosX2--;
				        break;
				    case SM_DWORD:             // Long
				        if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
				        {
				            if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(4/m_nLineGroup-1);
				            m_wCaretPosX2 = 7;
				            Up();
				            return;
				        }
				        if (m_wCaretPosX2==0)
				        {
				            m_wCaretPosX1--;
				            m_wCaretPosX2=7;
				        }
				        else
				            m_wCaretPosX2--;
				        break;
				    default:
				        break;
				}
				break;
				
			case SM_UDEC:         // Unsigned decimal
			    switch(m_bViewMode1)
			    {
			        case SM_BYTE:       // Byte
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(16/m_nLineGroup-1);
			                m_wCaretPosX2 = 2;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=2;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        case SM_WORD:       // Word
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(8/m_nLineGroup-1);
			                m_wCaretPosX2 = 4;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=4;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        case SM_DWORD:       // Long
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(4/m_nLineGroup-1);
			                m_wCaretPosX2 = 9;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=9;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        default:
			            break;
			    }
			    break;

			case SM_DEC:            // Decimal
			    switch(m_bViewMode1)
			    {
			        case SM_BYTE:       // Byte
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(16/m_nLineGroup-1);
			                m_wCaretPosX2 = 3;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=3;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        case SM_WORD:       // Word
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(8/m_nLineGroup-1);
			                m_wCaretPosX2 = 5;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=5;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        case SM_DWORD:       // Long
			            if ((m_wCaretPosX1==0)&&(m_wCaretPosX2==0))
			            {
			                if(m_lCaretPosY==m_dwMemRegionStart/(16/m_nLineGroup))
							{
								MessageBeep(-1);
								return;
							}
							m_wCaretPosX1 = WORD(4/m_nLineGroup-1);
			                m_wCaretPosX2 = 10;
			                Up();
			                return;
			            }
			            if (m_wCaretPosX2==0)
			            {
			                m_wCaretPosX1--;
			                m_wCaretPosX2=10;
			            }
			            else
			                m_wCaretPosX2--;
			            break;
			        default:
			            break;
			    }
			    break;

			default:
			    break;
		}
}

void CMemoryWindow::Up()
{
	long lMinY = (long)(m_dwMemRegionStart/(0x10/m_nLineGroup));
	if(lMinY==m_lCaretPosY)
	{
		MessageBeep(-1);
		return;
	}
	m_lCaretPosY--;
}

void CMemoryWindow::Down()
{
	if(m_lCaretPosY>=long(m_dwMemRegionEnd/(16/m_nLineGroup)))
	{
		MessageBeep(-1);
		return;
	}
	m_lCaretPosY++;
	if(m_lCaretPosY==long((m_dwStartAddress/(16/m_nLineGroup)+m_nLines-2)))
		OnVScroll(SB_LINEDOWN, 0, NULL);
}

void CMemoryWindow::Home()
{
	if(m_wCaretPosX1==0&&m_wCaretPosX2==0&&m_nCaretArea==1)
	{
		OnHScroll(SB_THUMBTRACK, 0, NULL);
		return;
	}
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;
}

void CMemoryWindow::End()
{
	if (m_nCaretArea == 2)
		m_wCaretPosX2=WORD(16/m_nLineGroup-1);
	else
		switch(m_bViewMode2)
		{
			case SM_CODE:         // Disassembly
				return;
			case SM_HEX:         // Hexdeciaml
				switch(m_bViewMode1)
				{
					case SM_BYTE:          // Byte
						m_wCaretPosX1=WORD(16/m_nLineGroup-1);
						m_wCaretPosX2=1;
						break;
					case SM_WORD:          // Word
						m_wCaretPosX1=WORD(8/m_nLineGroup-1);
						m_wCaretPosX2=3;
						break;
					case SM_DWORD:          // Long
						m_wCaretPosX1=WORD(4/m_nLineGroup-1);
						m_wCaretPosX2=7;
						break;
					default:         
						break;
				}
				break;

			case SM_UDEC:         // Unsigned decimal
				switch(m_bViewMode1)
				{
					case SM_BYTE:          // Byte
						m_wCaretPosX1=WORD(16/m_nLineGroup-1);
						m_wCaretPosX2=2;
						break;
					case SM_WORD:          // Word
						m_wCaretPosX1=WORD(8/m_nLineGroup-1);
						m_wCaretPosX2=4;
						break;
					case SM_DWORD:          // Long
						m_wCaretPosX1=WORD(4/m_nLineGroup-1);
						m_wCaretPosX2=9;
						break;
					default:
						break;
				}
				break;

			case SM_DEC:         // Signed decimal   
				switch(m_bViewMode1) 
				{
					case SM_BYTE:       // Byte
						m_wCaretPosX1=WORD(16/m_nLineGroup-1);
						m_wCaretPosX2=3;
						break;
					case SM_WORD:       // Word
						m_wCaretPosX1=WORD(8/m_nLineGroup-1);
						m_wCaretPosX2=5;
						break;
					case SM_DWORD:       // Long
						m_wCaretPosX1=WORD(4/m_nLineGroup-1);
						m_wCaretPosX2=10;
						break;
					default:
						break;
				}
				break;

			default:
				break;
		}
}

void CMemoryWindow::Tab()
{
	if (m_nCaretArea==2)
	{
		if(m_bViewMode1==SM_BYTE)
			m_wCaretPosX1=m_wCaretPosX2;
		else if(m_bViewMode1==SM_WORD)
			m_wCaretPosX1=m_wCaretPosX2/2;
		else
			m_wCaretPosX1=m_wCaretPosX2/4;
		m_wCaretPosX2=0;
		m_nCaretArea=1;
	}
	else
	{
		if(m_bViewMode1==SM_BYTE)
			m_wCaretPosX2=m_wCaretPosX1;
		else if(m_bViewMode1==SM_WORD)
			m_wCaretPosX2=m_wCaretPosX1*2;
		else
			m_wCaretPosX2=m_wCaretPosX1*4;
		m_nCaretArea=2;
	}
}

void CMemoryWindow::OnModeChange(void)
{
LPARAM	lParam;
WPARAM	type;            
RECT	rect;
	
	m_nPosX=0;
	GetClientRect(&rect);
	if (IsZoomed())
		type=SIZE_MAXIMIZED;
	else
		type=SIZE_RESTORED;
	if(IsIconic())
		type=SIZE_MINIMIZED;
	lParam = rect.bottom;
	lParam <<=16;
	lParam += rect.right;
	SendMessage(WM_SIZE,type,lParam);
	Invalidate();
}

void CMemoryWindow::GetDsm(int space, DWORD startAddress, int line)
{
int nResult, i;
const char*	cpstr;
ADDR	addrStart;
CDADExtFnBase* pClass;
POSITION pos;
CString str;

	addrStart.addrType=(BYTE)space;
	addrStart.addr=startAddress;
	pClass=new CDADExtFnCom(addrStart,WORD(line));
	ASSERT(pClass);
	nResult=pClass->GetResult();
	if(nResult!=CDADExtFnBase::DAD_OK)
	{
	//Err handler:
		delete pClass;
		ErrDisplayError(ER_DAD_ERROR);
		return;
	}
	CStringList& slCode=pClass->GetCodeList();
	CStringList& slInst=pClass->GetInstrList();
	CStringList& slAddr=pClass->GetAddrList();
	for(i=0, pos=slCode.GetHeadPosition();pos!=NULL&&i<line; i++)
	{
		str=slCode.GetNext(pos);
		strcpy(m_dsm[i].code, (const char*)str);
	}
	for(i=0, pos=slInst.GetHeadPosition();pos!=NULL&&i<line; i++)
	{
		str=slInst.GetNext(pos);
		strcpy(m_dsm[i].instruction, (const char*)str);
	}
	for(i=0, pos=slAddr.GetHeadPosition();pos!=NULL&&i<line; i++)
	{
		str=slAddr.GetNext(pos);
		cpstr=(const char*)str;
		ASSERT(cpstr);
		while(*cpstr!=':')
			cpstr++;
		m_dsm[i].address= (DWORD)strtol(cpstr+1, NULL, 16);
	}
	delete pClass;
}

//caller condition:
// 1. scroll vertically.
// 2. change memory region
// 3. window size change
// 4. refresh hard.
// 5. window create
void CMemoryWindow::PrepareData()
{
DWORD head, movelen;
DWORD end;
DWORD begAddr;

//	ASSERT((m_dwStartAddress+(m_nLines-2)*(0x10/m_nLineGroup)-1)<0x10000);
	ASSERT(m_dwStartAddress<0x10000);
	end=min(m_dwStartAddress+(m_nLines-2)*0x10-1, 0x10000-1);

	end=min(end, m_dwMemRegionEnd);
	if(m_dwStartAddress>=m_dwBufStartAddr&&end<=m_dwBufEndAddr)
		m_byMem=&m_pMemBuffer[m_dwStartAddress-m_dwBufStartAddr];
	else if(m_dwStartAddress<m_dwBufStartAddr&&end>=m_dwBufStartAddr&&
			end<=m_dwBufEndAddr)
	{
		//will use head part data in buffer.
		head=min(m_wMemBufferLen/3, m_dwStartAddress);
		movelen=head+m_dwBufStartAddr-m_dwStartAddress;
		if(m_wMemBufferLen-(m_dwBufEndAddr-m_dwBufStartAddr+1)>movelen)
		{
			ASSERT(m_dwBufEndAddr-m_dwBufStartAddr+1<0x8000);
			memmove(&m_pMemBuffer[movelen], m_pMemBuffer, 
					int(m_dwBufEndAddr-m_dwBufStartAddr+1));
		}
		else    //lost useful data in tail:
		{
			ASSERT(m_wMemBufferLen-movelen<0x8000);
			memmove(&m_pMemBuffer[movelen], m_pMemBuffer,
					int(m_wMemBufferLen-movelen));
			m_dwBufEndAddr=min(m_dwBufEndAddr,
					m_dwBufStartAddr+(m_wMemBufferLen-movelen)-1);
		}
		ASSERT(m_dwBufEndAddr>=end);
		begAddr=m_dwBufStartAddr-movelen;
		MemServerDump(m_pMemBuffer, begAddr, WORD(movelen), m_wSpaceType);
		m_dwBufStartAddr-=movelen;
		m_byMem=&m_pMemBuffer[head];
	}
	else if(m_dwStartAddress>=m_dwBufStartAddr&&m_dwStartAddress<=m_dwBufEndAddr
			&&end>m_dwBufEndAddr)
	{
		//will use tail part data in buffer.
		if(end<m_dwBufStartAddr+m_wMemBufferLen-1)	//not need move buffer
		{
			movelen=min(m_wMemBufferLen-m_dwBufEndAddr+
						m_dwBufStartAddr-1, m_dwMemRegionEnd-m_dwBufEndAddr);
			begAddr=m_dwBufEndAddr+1;
			MemServerDump(&m_pMemBuffer[m_dwBufEndAddr-m_dwBufStartAddr+1], 
					begAddr, WORD(movelen), m_wSpaceType);
			m_dwBufEndAddr+=movelen;
			m_byMem=&m_pMemBuffer[m_dwStartAddress-m_dwBufStartAddr];
		}
		else
		{
			ASSERT(m_dwStartAddress-m_dwBufStartAddr>m_wMemBufferLen/3);
			head=m_dwStartAddress-m_dwBufStartAddr-m_wMemBufferLen/3;
			ASSERT(m_dwBufEndAddr-m_dwBufStartAddr+1-head<0X8000);
			memmove(m_pMemBuffer, &m_pMemBuffer[head],
					int(m_dwBufEndAddr-m_dwBufStartAddr+1-head));
			m_dwBufStartAddr+=head;
			movelen=min(m_wMemBufferLen-(m_dwBufEndAddr-m_dwBufStartAddr+1),
						m_dwMemRegionEnd-m_dwBufEndAddr);
			begAddr=m_dwBufEndAddr+1;
			MemServerDump(&m_pMemBuffer[m_dwBufEndAddr-m_dwBufStartAddr+1], 
						begAddr, WORD(movelen), m_wSpaceType);
			m_dwBufEndAddr+=movelen;
			m_byMem=&m_pMemBuffer[m_dwStartAddress-m_dwBufStartAddr];
		}
	}
	else
	{
		m_dwBufStartAddr=m_dwStartAddress>m_wMemBufferLen/3?
					m_dwStartAddress-m_wMemBufferLen/3:0;
		movelen=m_dwBufStartAddr+m_wMemBufferLen-1>m_dwMemRegionEnd?
				m_dwMemRegionEnd-m_dwBufStartAddr+1:m_wMemBufferLen;
		begAddr=m_dwBufStartAddr;
		ASSERT(movelen<0x10000);
		MemServerDump(m_pMemBuffer, begAddr, (WORD)movelen, m_wSpaceType);
		m_dwBufEndAddr=m_dwBufStartAddr+movelen-1;
		m_byMem=&m_pMemBuffer[m_dwStartAddress-m_dwBufStartAddr];
	}
	if(m_bViewMode2==SM_CODE)
	{
		m_nDSMNum=m_nLines-2;
		ASSERT(m_nDSMNum>=0&&m_wDSMBufferLen>=(WORD)m_nDSMNum);
		GetDsm(m_wSpaceType, m_dwStartAddress, m_nDSMNum);
		m_dwBottomlineAddr=m_dsm[m_nDSMNum-1].address;
	}
	if(m_dwBufEndAddr-m_dwBufStartAddr+1>m_wMemBufferLen)
		ASSERT(0);
	return;
}

BOOL CMemoryWindow::InputCheck(WORD nChar)
{
BOOL bOk;

	bOk = FALSE;

	if(m_nCaretArea==2)
	{
		if(isprint(nChar))
			bOk=TRUE;
		if(bOk)
			GetValue();
	}
	else
	{
		switch(m_bViewMode2) 
		{
			case SM_CODE:
				break;
			case SM_HEX:
				if (('0'<=nChar)&&(nChar<='9'))
					bOk=TRUE;
				if (('a'<=nChar)&&(nChar<='f'))
					bOk=TRUE;
				if (('A'<=nChar)&&(nChar<='F'))
					bOk=TRUE;
				if (bOk)
				{
					GetValue();
					ValueToStr();
					m_lpszValue[m_wCaretPosX2]=(char)nChar;
					bOk = StrToValue();
				}
				break;
			case SM_UDEC:
				if (('0'<=nChar)&&(nChar<='9'))
					bOk=TRUE;
				if (bOk) 
				{
					GetValue();
					ValueToStr();
					m_lpszValue[m_wCaretPosX2]=(char)nChar;
					bOk = StrToValue();
				}
				break;
			case SM_DEC:
				if (m_wCaretPosX2==0)
				{
					if (('+'==nChar)||((nChar=='-')&&(m_bViewMode1!=SM_BYTE)))
						bOk=TRUE;
				}
				else if (('0'<=nChar)&&(nChar<='9')) bOk=TRUE;
				if (bOk)
				{
					GetValue();
					ValueToStr();
					m_lpszValue[m_wCaretPosX2]=(char)nChar;
					bOk = StrToValue();
				}
				break;
			default:
				break;
		}
	}
	if(m_wSpaceType==MEM_I)
	{
		DWORD addr = GetCaretAddr();
/*		int	  i;
		if(m_nCaretArea==2)
			addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX2;
		else
		{
			if(m_bViewMode1==SM_DWORD)
				i=4;
			else if(m_bViewMode1==SM_WORD)
				i=2;
			else
				i=1;
			addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX1*i;
		}
*/		
		if (m_bViewMode2 != SM_HEX) {
			int i = 1;
			if(m_bViewMode1==SM_DWORD)
				i=4;
			else if(m_bViewMode1==SM_WORD)
				i=2;
			addr = addr / i * i;
		}
		if(addr<m_dwMemRegionStart)
			bOk=FALSE;
	}
	if (!bOk) 
		MessageBeep(-1);
	return bOk;
}

void CMemoryWindow::WriteMemory(WORD nChar)
{
long* l;
WORD* w;
BYTE* b;
BYTE value;
WORD i;
DWORD addr;
BYTE* f;
DWORD begAddr;

	b = (BYTE *)m_byMem;
	w = (WORD *)m_byMem;
	l = (long *)m_byMem;
	i = WORD(m_lCaretPosY - (m_dwStartAddress/(16/m_nLineGroup)));

	if (m_nCaretArea==2)
	{
		b = b + i*(16/m_nLineGroup) + m_wCaretPosX2;

		addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX2;
		value = (BYTE)nChar;
		begAddr=addr;
		MemServerFill(begAddr, value, m_wSpaceType);
		MemServerDump(&value, begAddr, 1, m_wSpaceType);
		*b = value;
	}
	else
	{
		switch(m_bViewMode1)
		{
		case SM_DWORD:
			l = l + i*(4/m_nLineGroup) + m_wCaretPosX1;
			f = (BYTE *)(&m_lValue);
			addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX1*4;
            begAddr=addr;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			f++;
			addr++;
			begAddr++;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			f++;
			addr++;
			begAddr++;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			f++;
			addr++;
			begAddr++;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			*l = m_lValue;
			break;

		case SM_WORD:
			w = w + i*(8/m_nLineGroup) + m_wCaretPosX1;
			f = (BYTE *)(&m_wValue);
			addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX1*2;
            begAddr=addr;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			f++;
			addr++;
			begAddr++;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			*w = m_wValue;
			break;

		case SM_BYTE:
			b = b + i*(16/m_nLineGroup) + m_wCaretPosX1;

			f = &m_byValue;
			addr = m_lCaretPosY*(16/m_nLineGroup) + m_wCaretPosX1;
            begAddr=addr;
			MemServerFill(begAddr,*f, m_wSpaceType);
			MemServerDump(&value,begAddr,1, m_wSpaceType);
			*f = value;

			*b = m_byValue;
			break;

		default:
			break;
		}
	}
}

void CMemoryWindow::GetValue()
{
long* l;
WORD* w;
BYTE* b;
int j,pos;
BYTE value;
WORD i;

    b = (BYTE *)m_byMem;
    w = (WORD *)m_byMem;
    l = (long *)m_byMem;
    
    i = WORD(m_lCaretPosY - (m_dwStartAddress/(16/m_nLineGroup)));

    if (m_nCaretArea==2) {
        b = b + i*(16/m_nLineGroup);
        for(j=0;j<(16/m_nLineGroup);j++) {
            pos = j;
            value = b[pos];
            if ((0x20<value)&&(value<=0x7e)) m_lpszValue[j]=value;
            else m_lpszValue[j]='.';
        }
        m_lpszValue[j]='\0';
    }
    else {
        switch(m_bViewMode1) {
            case SM_DWORD:
                l = l + i*(4/m_nLineGroup) + m_wCaretPosX1;
                m_lValue = *l;
                break;
            case SM_WORD:
                w = w + i*(8/m_nLineGroup) + m_wCaretPosX1;
                m_wValue = *w;
                break;
            case SM_BYTE:
                b = b + i*(16/m_nLineGroup) + m_wCaretPosX1;
                m_byValue = *b;
                break;
            default:
                break;
        }
    }
}

void CMemoryWindow::ValueToStr()
{
    switch (m_bViewMode2) {
        case SM_HEX:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    sprintf(m_lpszValue,"%08lX",m_lValue);
                    break;
                case SM_WORD:
                    sprintf(m_lpszValue,"%04X",m_wValue);
                    break;
                case SM_BYTE:
                    sprintf(m_lpszValue,"%02X",m_byValue);
                    break;
                default:
                    break;
            }
            break;
        case SM_UDEC:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    sprintf(m_lpszValue,"%010lu",m_lValue);
                    break;
                case SM_WORD:
                    sprintf(m_lpszValue,"%05u",m_wValue);
                    break;
                case SM_BYTE:
                    sprintf(m_lpszValue,"%03u",m_byValue);
                    break;
                default:
                    break;
            }
            break;
        case SM_DEC:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    sprintf(m_lpszValue,"%+011ld",m_lValue);
                    break;
                case SM_WORD:
                    sprintf(m_lpszValue,"%+06d",m_wValue);
                    break;
                case SM_BYTE:
                    sprintf(m_lpszValue,"%+04d",m_byValue);
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
}

BOOL CMemoryWindow::StrToValue()
{
long value;
BOOL bOk;

    bOk=TRUE;
    switch (m_bViewMode2) {
        case SM_HEX:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    value=strtoul(m_lpszValue,NULL,16);
                    m_lValue = value;
                    break;
                case SM_WORD:
                    value=strtol(m_lpszValue,NULL,16);
                    m_wValue = (WORD)value;
                    break;
                case SM_BYTE:
                    value=strtol(m_lpszValue,NULL,16);
                    m_byValue = (BYTE)value;
                    break;
                default:
                    break;
            }
            break;
        case SM_UDEC:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    value=strtoul(m_lpszValue,NULL,10);
                    if (errno==ERANGE) bOk = FALSE;
                    else bOk=TRUE;
                    errno=0;
                    m_lValue = value;
                    break;
                case SM_WORD:
                    value=strtol(m_lpszValue,NULL,10);
                    if ((value>=0)&&(value<=0xffff)) bOk = TRUE;
                    else bOk=FALSE;
                    m_wValue = (WORD)value;
                    break;
                case SM_BYTE:
                    value=strtol(m_lpszValue,NULL,10);
                    if ((value>=0)&&(value<=0xff)) bOk = TRUE;
                    else bOk=FALSE;
                    m_byValue = (BYTE)value;
                    break;
                default:
                    break;
            }
            break;
            
        case SM_DEC:
            switch(m_bViewMode1) {
                case SM_DWORD:
                    value=strtol(m_lpszValue,NULL,10);
                    if (errno==ERANGE) bOk = FALSE;
                    else bOk=TRUE;
                    errno=0;
                    m_lValue = value;
                    break;
                case SM_WORD:
                    value=strtol(m_lpszValue,NULL,10);
                    if ((value>=(long)(-32768))&&(value<=0x7fff)) bOk = TRUE;
                    else bOk=FALSE;
                    m_wValue = (WORD)value;
                    break;
                case SM_BYTE:
                    value=strtol(m_lpszValue,NULL,10);
                    if ((value>=0)&&(value<=0xff)) bOk = TRUE;
                    else bOk=FALSE;
                    m_byValue = (BYTE)value;
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
    
    return bOk;
}

void CMemoryWindow::SetRegionEnd(void)
{
	switch(m_wSpaceType)
	{
		case MEM_P0:
		case MEM_P1:
		case MEM_P2:
		case MEM_P3:
			m_dwMemRegionEnd=pMax;
			m_dwMemRegionStart = pMin;
			break;
		case MEM_X0:
		case MEM_X1:
			m_dwMemRegionEnd=xMax;
			m_dwMemRegionStart = xMin;
			break;
		case MEM_I:
			m_dwMemRegionEnd=iMax;
			m_dwMemRegionStart = iMin;
			break;
		default:
			ASSERT(0);
			break;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CMemoryWindow message handlers
//

int CMemoryWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

TEXTMETRIC tm;
CDC* pdc=GetDC();

	pdc->SelectStockObject(ANSI_FIXED_FONT);
	pdc->GetTextMetrics(&tm);
	m_nCharWidth=tm.tmAveCharWidth;
	m_nLineHeight=tm.tmHeight+tm.tmExternalLeading+2;
	ReleaseDC(pdc);

	PrepareData();
	SetWindowTitle();
	m_gridAddr.SetGridHeight(m_nLineHeight);
	SetFocus();      // Add on 1996.4.12
	return 0;
}

void CMemoryWindow::OnPaint()
{
static int dbCount=0;
	CPaintDC dc(this); // device context for painting

//	TRACE("call OnPaint %d time, m_dwStartAddress is %04x.\n", dbCount++,
//		m_dwStartAddress);
	// TODO: Add your message handler code here
	m_gridMem.Show(&dc,TRUE);
	if (m_bViewMode2!=SM_CODE)
	{
		if (m_bShowAscii)
			m_gridAscii.Show(&dc,TRUE);
	}
	else
		m_gridInstruction.Show(&dc, 2);
	m_gridAddr.Show(&dc,TRUE);
	
	dc.SelectStockObject(ANSI_FIXED_FONT);
	ShowMemoryWindow(&dc);
	SetMyCaretPos();
//	SetScrollPos(SB_VERT, (WORD)(m_dwStartAddress/0x10), TRUE);

	// Do not call CMDIChildWnd::OnPaint() for painting messages
}

void CMemoryWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    CMenu * pLocalMenu = new CMenu;

    ASSERT(pLocalMenu!=NULL);
    pLocalMenu->CreatePopupMenu();
    
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_REFRESH, "&Refresh");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
   
    pLocalMenu->AppendMenu(MF_STRING, ID_GROUP_MEMORY, "&Memory...");
    pLocalMenu->AppendMenu(MF_STRING, ID_OPTIONS_MAP, "Ma&p...");
    pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_GOTO, "&Goto...");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
   
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SHORTLINE, "Sh&ort line mode");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_ASCII, "Show &ASCII");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
   
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_HEXADECIMAL, "&Hexadecimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SIGNEDDECIMAL, "&Signed Decimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_UNSIGNEDDECIMAL, "&Unsigned Decimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_DISASSEMBLE, "&Disassemble");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
   
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_BYTE, "&Byte");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_WORD, "&Word");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_LONG, "&Long");
       
    ClientToScreen(&point);
    pLocalMenu->TrackPopupMenu(TPM_CENTERALIGN, point.x, point.y, this);
    
    delete pLocalMenu;

    CMDIChildWnd::OnRButtonDown(nFlags, point);
}

BOOL CMemoryWindow::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    // TODO: Add your message handler code here and/or call default
    if (message==WM_RBUTTONDOWN)
        return FALSE;

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

void CMemoryWindow::OnViewByte()
{
	// TODO: Add your command handler code here
	if (m_bViewMode1==SM_BYTE)
		return;
	m_bViewMode1 = SM_BYTE;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;
	OnModeChange();
}

void CMemoryWindow::OnUpdateViewByte(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if(GetCpuStatus(uchCpuStatus))
	{
		if(1==uchCpuStatus)			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else
			pCmdUI->Enable(TRUE);
	}
	if (m_bViewMode2 == SM_CODE)
		pCmdUI->Enable(FALSE);
	if (m_bViewMode1==SM_BYTE)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewWord()
{
    // TODO: Add your command handler code here
	if (m_bViewMode1==SM_WORD)
		return;
	m_bViewMode1=SM_WORD;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;

	OnModeChange();
}

void CMemoryWindow::OnUpdateViewWord(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else          
			pCmdUI->Enable(TRUE);
	}
	if (m_bViewMode2 == SM_CODE)
		pCmdUI->Enable(FALSE);
	if (m_bViewMode1==SM_WORD)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewLong()
{
    // TODO: Add your command handler code here
	if (m_bViewMode1==SM_DWORD)
		return;
	m_bViewMode1=SM_DWORD;
    m_wCaretPosX1=0;
    m_wCaretPosX2=0;

	OnModeChange();
}

void CMemoryWindow::OnUpdateViewLong(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else          
			pCmdUI->Enable(TRUE);
	}
	if (m_bViewMode2 == SM_CODE)
		pCmdUI->Enable(FALSE);
	if (m_bViewMode1==SM_DWORD)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewSigneddecimal()
{
	// TODO: Add your command handler code here
	if (m_bViewMode2==SM_DEC)
		return;
	m_dwStartAddress &=(long)0xFFF0+(m_nLineGroup==2?8:0);
	m_bViewMode2=SM_DEC;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;
	OnModeChange();
}

void CMemoryWindow::OnUpdateViewSigneddecimal(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else
			pCmdUI->Enable(TRUE);
	}
	if (m_bViewMode2==SM_DEC)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewUnsigneddecimal()
{
	// TODO: Add your command handler code here
	if (m_bViewMode2==SM_UDEC)
		return;
	m_dwStartAddress &=(long)0xFFF0+(m_nLineGroup==2?8:0);
	m_bViewMode2=SM_UDEC;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;
	OnModeChange();
}

void CMemoryWindow::OnUpdateViewUnsigneddecimal(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else          
			pCmdUI->Enable(TRUE);
	}
	if (m_bViewMode2==SM_UDEC)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewHexadecimal()
{
    // TODO: Add your command handler code here
	if (m_bViewMode2==SM_HEX)
		return;
	m_dwStartAddress &=0xFFF0+(m_nLineGroup==2?8:0);
	m_bViewMode2=SM_HEX;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;

	OnModeChange();
}

void CMemoryWindow::OnUpdateViewHexadecimal(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else          
			pCmdUI->Enable(TRUE);
	}

	if (m_bViewMode2==SM_HEX)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewDisassemble()
{
	// TODO: Add your command handler code here
	if (m_bViewMode2==SM_CODE)
		return;
	m_bViewMode2=SM_CODE;
	OnModeChange();
}

void CMemoryWindow::OnUpdateViewDisassemble(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else
			pCmdUI->Enable(TRUE);
	}
	if (m_wSpaceType == MEM_I) pCmdUI->Enable(FALSE);
	if (m_bViewMode2 == SM_CODE)
		pCmdUI->SetRadio(TRUE);
	else
		pCmdUI->SetRadio(FALSE);
}

void CMemoryWindow::OnViewShortline()
{
	// TODO: Add your command handler code here
	if (m_bViewMode2 == SM_CODE)
		return;
	m_nLineGroup=3-m_nLineGroup;
	if (m_dwStartAddress < m_dwMemRegionStart) 
		m_dwStartAddress = m_dwMemRegionStart;
	m_dwStartAddress &=(long)0xFFF0+(m_nLineGroup==2?8:0);
	if(m_nLineGroup==1)			//from short line mode to normal mode
	{
		if(m_lCaretPosY%2)
		{
			if(m_nCaretArea==1)
				m_wCaretPosX1+=WORD(m_bViewMode1==SM_BYTE?8:m_bViewMode1==SM_WORD?4:2);
			else
				m_wCaretPosX2+=8;
		}
		m_lCaretPosY/=2;
	}
	else
	{
		m_lCaretPosY*=2;
		if(m_nCaretArea==2?m_wCaretPosX2>7:(m_bViewMode1==SM_BYTE?
			(m_wCaretPosX1>7):(m_bViewMode1==SM_WORD?(m_wCaretPosX1>3):
			(m_wCaretPosX1>1))))
		{
			m_lCaretPosY+=1;
			if(m_nCaretArea==1)
				m_wCaretPosX1-=WORD(m_bViewMode1==SM_BYTE?8:m_bViewMode1==SM_WORD?4:2);
			else
				m_wCaretPosX2-=8;
		}
	}
	OnModeChange();
}

void CMemoryWindow::OnUpdateViewShortline(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else
			pCmdUI->Enable(TRUE);
	}
    if (m_bViewMode2 == SM_CODE)
    	pCmdUI->Enable(FALSE);
	if (m_nLineGroup==2)
		pCmdUI->SetCheck(TRUE);
	else
		pCmdUI->SetCheck(FALSE);
	
}

void CMemoryWindow::OnViewAscii()    
{
	// TODO: Add your command handler code here
	if (m_bViewMode2 == SM_CODE)
		return;
	m_bShowAscii = !m_bShowAscii;
	m_wCaretPosX1=0;
	m_wCaretPosX2=0;
	if (!m_bShowAscii)
		m_nCaretArea = 1;

	OnModeChange();
}

void CMemoryWindow::OnUpdateViewAscii(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
	//pCmdUI->Enable(TRUE);
unsigned char uchCpuStatus;

	if (GetCpuStatus(uchCpuStatus))
	{
		if ( 1 == uchCpuStatus )			// Is on GO status (STATUS_GO)
			pCmdUI->Enable(FALSE);
		else
			pCmdUI->Enable(TRUE);
	}
    if (m_bViewMode2 == SM_CODE)
    	pCmdUI->Enable(FALSE);
	if (m_bShowAscii)
		pCmdUI->SetCheck(TRUE);
	else
		pCmdUI->SetCheck(FALSE);
}

void CMemoryWindow::OnSize(UINT nType, int cx, int cy)
{
static int dbcount=0;

int		lines = 0;
RECT	rect;
DWORD	wAddr = 0;

//	TRACE("OnSize called %d, cx: %d, cy: %d\n", 
//			dbcount++, cx, cy);
	CMDIChildWnd::OnSize(nType, cx, cy);
	m_bIconic=(nType==SIZE_MINIMIZED);
	if(m_bIconic)
		return;

	//set m_nLines
	int nLineBytes = 0x10/m_nLineGroup;
	lines=cy/m_gridAddr.m_nGridHeight+1;
	wAddr = m_dwStartAddress+(lines-2)*nLineBytes;
	// Adjust the lines in views
	if(wAddr>m_dwMemRegionEnd+1)
	{
		if(m_dwMemRegionEnd-m_dwMemRegionStart+1<(lines-2)*nLineBytes)
		{
			m_dwStartAddress=m_dwMemRegionStart;//0;
			m_dwStartAddress &= ((DWORD)-nLineBytes);
			GetWindowRect(&rect);
//			rect.bottom-=((lines-2-(m_dwMemRegionEnd+1)/
			rect.bottom-=((lines-2-(m_dwMemRegionEnd-m_dwStartAddress+1)/
							nLineBytes)*m_nLineHeight
							+cy%m_gridAddr.m_nGridHeight);
			SetWindowPos(NULL, rect.left,
						rect.top, 
						rect.right-rect.left,
						rect.bottom-rect.top,
						SWP_NOMOVE);
			return;
		}
		else
			m_dwStartAddress=m_dwMemRegionEnd+1-(lines-2)*nLineBytes;
	}
	m_nLines = lines;
	SetMemoryWindow();		//depend on m_nLines and m_nPosX

	//set HScrollBar
	SetScrollBar();				//note: maybe cause WM_SIZE message.
	
	//set window height
	//int ret=(cy-2)%m_gridAddr.m_nGridHeight;	//mark by chris
	int ret=cy%m_gridAddr.m_nGridHeight;
	if(ret)
	{
		GetWindowRect(&rect);
		SetWindowPos(NULL,
					rect.left, rect.top,
					rect.right-rect.left,
					rect.bottom-rect.top-ret,
					SWP_NOMOVE);
		return;
	}

	//set VScrollBar
	ASSERT((m_dwMemRegionEnd+1)/nLineBytes-(m_nLines-2)+1<0x8000);
	int nScrollRange=int((m_dwMemRegionEnd+1)/nLineBytes-(m_nLines-2));
	int nMinPos = (m_dwMemRegionStart/nLineBytes);
	SetScrollRange(SB_VERT, nMinPos, nScrollRange, FALSE);	
	ASSERT(m_dwStartAddress/nLineBytes<0x8000);
	SetScrollPos(SB_VERT, int(m_dwStartAddress/nLineBytes), TRUE);
	PrepareData();
}

void CMemoryWindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* /*pScrollBar*/)
{
     // TODO: Add your message handler code here and/or call default
long dwTempAddress = 0, dwTempAddress2 = 0;
unsigned char uchCpuStatus;
WORD oldv, line;
RECT rect;

	ASSERT(m_dwStartAddress<0x10000);
	oldv=WORD(m_dwStartAddress);
	if(!GetCpuStatus(uchCpuStatus))
	{
		return;
	}
	if (1==uchCpuStatus)		// CPU not at GO
	{
		ShowStatusGo();
		return;
	}
	switch (nSBCode)
	{
		case SB_LINEUP:
			if (m_dwStartAddress<=m_dwMemRegionStart)
				return;
			if(m_bViewMode2 != SM_CODE)
				m_dwStartAddress-=(0x10/m_nLineGroup);
			else
				m_dwStartAddress--;
			break;
		case SB_LINEDOWN:
			if (m_bViewMode2 != SM_CODE)
			{
				if(m_dwStartAddress+(m_nLines-2)*(0x10/m_nLineGroup)>m_dwMemRegionEnd)
					return;
				m_dwStartAddress += (0x10/m_nLineGroup);
			}
			else		//disassemble
			{
				if(m_dwBottomlineAddr>=m_dwMemRegionEnd)
					return;
				m_dwStartAddress++;
			}
			break;
		case SB_PAGEUP:
			if (m_bViewMode2!=SM_CODE)
			{
				ASSERT(m_nLines>=0);
				line=WORD(m_nLines>3?m_nLines-3:m_nLines);
				m_dwStartAddress=m_dwStartAddress>line*(0x10/m_nLineGroup)?
								 m_dwStartAddress-line*(0x10/m_nLineGroup):0;
			}
			else
				m_dwStartAddress=m_dwStartAddress>0x10?
								 m_dwStartAddress-0x10:0;
			break;
		case SB_PAGEDOWN:
			if (m_bViewMode2 != SM_CODE)
			{
				m_dwStartAddress=m_dwStartAddress+(m_nLines-3)*(0x10/m_nLineGroup);
				if(m_dwStartAddress+(m_nLines-2)*(0x10/m_nLineGroup)>m_dwMemRegionEnd)
					m_dwStartAddress=m_dwMemRegionEnd+1-(m_nLines-2)*(0x10/m_nLineGroup);
			}
			else
			{
				m_dwStartAddress = m_dwBottomlineAddr;
				if(m_dwStartAddress+m_nLines-2>m_dwMemRegionEnd)
					m_dwStartAddress=m_dwMemRegionEnd+1-(m_nLines-2);
			}   
			break;
		case SB_THUMBTRACK:
			SetWindowTitle(nPos*(0x10/m_nLineGroup));
			break;
		case SB_THUMBPOSITION:
			SetWindowTitle();
			m_dwStartAddress=(unsigned short)nPos*(0x10/m_nLineGroup);
			if (m_bViewMode2 != SM_CODE)
			{
				if(m_dwStartAddress+(m_nLines-2)*(0x10/m_nLineGroup)>m_dwMemRegionEnd)
					m_dwStartAddress=m_dwMemRegionEnd+1-(m_nLines-2)*(0x10/m_nLineGroup);
			}
			else
			{
				if((m_dwStartAddress+(m_nLines-2)*0x3-1)>m_dwMemRegionEnd)
					m_dwStartAddress=m_dwMemRegionEnd+1-(m_nLines-2)*3;
			}
//			EnableScrollBar( SB_VERT, ESB_DISABLE_BOTH );
//			EnableScrollBar( SB_VERT, ESB_ENABLE_BOTH );
			break;
		default:
			return;
	}
	if (m_dwStartAddress<=m_dwMemRegionStart) {
		m_dwStartAddress=m_dwMemRegionStart&((DWORD)-0x10/m_nLineGroup);
	}
	if(oldv==m_dwStartAddress)
		return;
	PrepareData();
	ASSERT(m_dwStartAddress/(0x10/m_nLineGroup)<0x8000);
	SetScrollPos(SB_VERT, int(m_dwStartAddress/(0x10/m_nLineGroup)), TRUE);
	if(labs(oldv/(0x10/m_nLineGroup)-m_dwStartAddress/(0x10/m_nLineGroup))<m_nLines-2
		&&m_bViewMode2!=SM_CODE)
	{
		GetClientRect(&rect);
		rect.top = m_gridAddr.m_nGridHeight+1;
		ScrollWindow(0,	int(long(oldv/(0x10/m_nLineGroup))-long(m_dwStartAddress/(0x10/m_nLineGroup)))*
					 m_gridAddr.m_nGridHeight, &rect, &rect);
		UpdateWindow();
	}
	else 
		Invalidate();
//	SetMyCaretPos();
}

void CMemoryWindow::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* /*pScrollBar*/)
{
    // TODO: Add your message handler code here and/or call default
int nInt1,nInt2;
unsigned char uchCpuStatus;
int oldh=m_nPosX;
RECT	rect;

	if(!m_bHScrollOn)
		return;
	if(!GetCpuStatus(uchCpuStatus))
	{
		return;
	}
	if (1==uchCpuStatus)		// CPU not at GO
	{
		ShowStatusGo();
		return;
	}
	GetScrollRange(SB_HORZ,&nInt1,&nInt2);
	GetClientRect(&rect);
	
	switch (nSBCode)
	{
		case SB_LINEUP:
			if(m_nPosX>=0)
				return;
			if ((m_nPosX+m_gridMem.m_nGridWidth) > 0)
				m_nPosX = 0;
			else
			  m_nPosX += m_gridMem.m_nGridWidth;
			break;
		case SB_LINEDOWN:
			if((m_nPosX+nInt2)<=0)
				return;
			if ((m_nPosX+nInt2) < m_gridMem.m_nGridWidth)
			  m_nPosX = -nInt2;
			else
			  m_nPosX -= m_gridMem.m_nGridWidth;
			break;
		case SB_PAGEUP:
			if (m_nPosX >=0)
				return;
			if((m_nPosX+rect.right)>0)
				m_nPosX = 0;
			else
				m_nPosX += rect.right;
			break;
			                  
		case SB_PAGEDOWN:
			if((m_nPosX+nInt2)<=0)
				return;
			if((m_nPosX+nInt2)<rect.right)
				m_nPosX = -nInt2;
			else
				m_nPosX -= rect.right;
			break;
		case SB_THUMBTRACK:
			m_nPosX=-int(nPos);
			break;
		default:
			break;
	}
	if(oldh!=m_nPosX)
	{
		SetMemoryWindow();		//depend on m_nLines and m_nPosX
		GetClientRect(&rect);
		rect.left = m_gridAddr.m_nGridWidth+1;
		SetScrollPos(SB_HORZ, -m_nPosX, TRUE);
		ScrollWindow(m_nPosX-oldh, 0, &rect, &rect);
		UpdateWindow();
	}
}

void CMemoryWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    BOOL bOk;
    CRect rect;
    RECT rect2;
    int i,j;

    bOk = FALSE;

    if (m_bViewMode2!=SM_CODE) {
        if (m_bShowAscii) {
            rect.left = m_gridAscii.GetLeftPos();
            rect.right = m_gridAscii.GetRightPos();
            rect.top = m_gridAscii.m_rectPos.top+m_gridAscii.m_nGridHeight;
            rect.bottom = m_gridAscii.m_rectPos.bottom;
            bOk = rect.PtInRect(point);
            if (bOk) m_nCaretArea = 2;
            if (bOk) {
                i = point.x - m_gridAscii.GetLeftPos();
                if (i>1) i--;
                m_wCaretPosX1 = 0;
                m_wCaretPosX2 = WORD((i+m_nCharWidth/2-1) / m_nCharWidth);
                if (m_wCaretPosX2>WORD(16/m_nLineGroup-1))
                	m_wCaretPosX2 = WORD(16/m_nLineGroup-1);
                i = point.y - rect.top;
                m_lCaretPosY =long(i / m_gridAscii.m_nGridHeight + 
                	(WORD)(m_dwStartAddress/(16/m_nLineGroup)));
            }
        }
        if (!bOk) {
            rect.left = m_gridAddr.m_nGridWidth;
            rect.right = m_gridMem.GetRightPos();
            rect.top = m_gridMem.m_rectPos.top+m_gridMem.m_nGridHeight;
            rect.bottom = m_gridMem.m_rectPos.bottom;
            bOk = rect.PtInRect(point);
            if (bOk) m_nCaretArea = 1;
            if (bOk) {
                i = point.y - rect.top;
                m_lCaretPosY =long(i / m_gridMem.m_nGridHeight +
                	(WORD)(m_dwStartAddress/(16/m_nLineGroup)));
                for(j=0;j<m_gridMem.m_nRows;j++) {
                    rect2 = m_gridMem.GetGridRect(j,(i/m_gridMem.m_nGridHeight+1));
                    rect.CopyRect(&rect2);
                    bOk = rect.PtInRect(point);
                    if (bOk) break;
                }

                i = point.x - rect.left;
                m_wCaretPosX1 = WORD(j);
                if (i>1) i--;
                m_wCaretPosX2 =WORD((i+m_nCharWidth/2-1) / m_nCharWidth);
                switch (m_bViewMode2) {
                    case SM_DEC:
                        switch (m_bViewMode1) {
                            case SM_BYTE:
                                if (m_wCaretPosX2>3) m_wCaretPosX2 = 3;
                                break;
                            case SM_WORD:
                                if (m_wCaretPosX2>5) m_wCaretPosX2 = 5;
                                break;
                            case SM_DWORD:
                                if (m_wCaretPosX2>10) m_wCaretPosX2 = 10;
                                break;
                            default:
                                break;
                        }
                        break;
                    case SM_UDEC:
                        switch (m_bViewMode1) {
                            case SM_BYTE:
                                if (m_wCaretPosX2>2) m_wCaretPosX2 = 2;
                                break;
                            case SM_WORD:
                                if (m_wCaretPosX2>4) m_wCaretPosX2 = 4;
                                break;
                            case SM_DWORD:
                                if (m_wCaretPosX2>9) m_wCaretPosX2 = 9;
                                break;
                            default:
                                break;
                        }
                        break;
                    case SM_HEX:
                        switch (m_bViewMode1) {
                            case SM_BYTE:
                                if (m_wCaretPosX2>1) m_wCaretPosX2 = 1;
                                break;
                            case SM_WORD:
                                if (m_wCaretPosX2>3) m_wCaretPosX2 = 3;
                                break;
                            case SM_DWORD:
                                if (m_wCaretPosX2>7) m_wCaretPosX2 = 7;
                                break;
                            default:
                                break;
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }
    if (bOk) {
        SetMyCaretPos();
    }

    CMDIChildWnd::OnLButtonDown(nFlags, point);
}

void CMemoryWindow::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    CRect rect1;
    BOOL bOk;

    bOk = FALSE;
    if (m_bViewMode2!=SM_CODE) {
        rect1.left = m_gridAddr.m_nGridWidth;
        rect1.right = m_gridMem.GetRightPos();
        rect1.top = m_gridMem.m_rectPos.top+m_gridMem.m_nGridHeight;
        rect1.bottom = m_gridMem.m_rectPos.bottom;
        if (m_bShowAscii) {
            rect1.right = m_gridAscii.GetRightPos();
            rect1.bottom = m_gridAscii.m_rectPos.bottom;
        }
        bOk = rect1.PtInRect(point);
    }
    if (bOk)
       SetCursor(::LoadCursor(NULL,IDC_IBEAM));
    else
       SetCursor(::LoadCursor(NULL,IDC_ARROW));

    CMDIChildWnd::OnMouseMove(nFlags, point);
}

void CMemoryWindow::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
    // TODO: Add your message handler code here and/or call default
DWORD dwTemp;
BOOL Up_Flag = 1;
BOOL Down_Flag = 1;
long dwTempAddress2 = 0;
unsigned char uchCpuStatus;
int	minpos, maxpos;
int bCtrl = GetKeyState(VK_CONTROL)&0x8000;
//int bShift= GetKeyState(VK_SHIFT) & 0x8000;

	if(m_bIconic)
		return;
	if(!GetCpuStatus(uchCpuStatus))
	{
		return;
	}
	if ( 1 == uchCpuStatus )			// CPU not at GO
	{
		ShowStatusGo();
		return;
	}
	if(m_bViewMode2 ==SM_CODE)
	{
		switch(nChar)
		{
			case VK_RIGHT:
				OnHScroll(SB_LINERIGHT, 0, NULL);
				break;
			case VK_LEFT:
				OnHScroll(SB_LINELEFT, 0, NULL);
				break;
			case VK_UP:
				OnVScroll(SB_LINEUP, 0, NULL);
				break;
			case VK_DOWN:
				OnVScroll(SB_LINEDOWN, 0, NULL);
				break;
			case VK_PRIOR:
				if(bCtrl)
					OnHScroll(SB_PAGEUP, 0, NULL);
				else
					OnVScroll(SB_PAGEUP, 0, NULL);
				break;
			case VK_NEXT:
				if(bCtrl)
					OnHScroll(SB_PAGEDOWN, 0, NULL);
				else
					OnVScroll(SB_PAGEDOWN, 0, NULL);
				break;
			case VK_HOME:
				if(bCtrl)
					OnVScroll(SB_THUMBPOSITION, 0, NULL);
				OnHScroll(SB_THUMBTRACK, 0, NULL);
				break;
			case VK_END:
				GetScrollRange(SB_HORZ, &minpos, &maxpos);
				if(bCtrl)
				{
					GetScrollRange(SB_VERT, &minpos, &maxpos);
					OnVScroll(SB_THUMBPOSITION, maxpos, NULL);
					break;
				}
				if(maxpos)
					OnHScroll(SB_THUMBTRACK, maxpos, NULL);
				break;
			default:
				break;
		}
		return;
	}
	switch (nChar) 
	{
		case VK_RIGHT:
			Right();
			break;
		case VK_LEFT:
			Left();
			break;
		case VK_UP:
			Up();
			break;
		case VK_DOWN:
			Down();
			break;
		case VK_PRIOR:
			dwTemp = m_dwStartAddress;
			if(InWnd())
			{	
				OnVScroll(SB_PAGEUP, 0, NULL);
				ASSERT((dwTemp-m_dwStartAddress)/(16/m_nLineGroup)<0X10000);
				m_lCaretPosY-=long((dwTemp-m_dwStartAddress)/(16/m_nLineGroup));
			}
			else
				m_lCaretPosY-=long(m_nLines>3?m_nLines-3:m_nLines);
			if(m_lCaretPosY<0)
				m_lCaretPosY=0;
			break;         
		case VK_NEXT:
			dwTemp = m_dwStartAddress;
			if(InWnd())
			{	
				OnVScroll(SB_PAGEDOWN, 0, NULL);
				ASSERT((m_dwStartAddress-dwTemp)/(16/m_nLineGroup)<0X10000);
				m_lCaretPosY+=long((m_dwStartAddress-dwTemp)/(16/m_nLineGroup));
			}
			else
			{
				m_lCaretPosY+=long(m_nLines>3?m_nLines-3:m_nLines);
				if(m_lCaretPosY+m_nLines-2>m_dwMemRegionEnd/(16/m_nLineGroup))
				{
					ASSERT(m_dwMemRegionEnd/(16/m_nLineGroup)-m_nLines+2<0x10000);
					m_lCaretPosY=long(m_dwMemRegionEnd/(16/m_nLineGroup)-m_nLines+2);
				}
			}
			ASSERT(m_lCaretPosY<=long(m_dwMemRegionEnd/(16/m_nLineGroup)));
			break;         
		case VK_HOME:
			Home();
			break;
		case VK_END:
			End();
			break;
		case VK_TAB:
			Tab();
			break;
		default:
			break;
	}
	if (!InWnd())
		GotoCursor();
	xGotoCursor();
	SetMyCaretPos();
}

void CMemoryWindow::OnStkTab()
{
	// TODO: Add your command handler code here
///	OnKeyDown(VK_TAB, 1, 0);
}

void CMemoryWindow::OnChar(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
    // TODO: Add your message handler code here and/or call default
unsigned char uchCpuStatus;
    
	if(m_bIconic)
		return;
	if(!GetCpuStatus(uchCpuStatus))
	{
		return;
	}
	if(1==uchCpuStatus)			// CPU not at GO
	{
		ShowStatusGo();
		return;
	}
	if (m_bViewMode2==SM_CODE)
	{
		return;
	}
	if (nChar!=VK_TAB)
	{
		if (InputCheck((WORD)nChar)) 
		{
			WriteMemory((WORD)nChar);
			PaintLine(WORD(m_lCaretPosY-m_dwStartAddress/(0x10/m_nLineGroup)));
			Right();   
			if (gb_isMemOn[0]&&(m_bWndNo!=0))
			{
				((CMemoryWindow*)gp_MemWnd[0])->RefreshMemWin(TRUE);
			}
			if (gb_isMemOn[1]&&(m_bWndNo!=1))
			{
				((CMemoryWindow*)gp_MemWnd[1])->RefreshMemWin(TRUE);
			}
			if (gb_isMemOn[2]&&(m_bWndNo!=2))
			{
				((CMemoryWindow*)gp_MemWnd[2])->RefreshMemWin(TRUE);
			}
			///::RepaintStack();
			///::RepaintVariable();
			// Added by Chen only for the stack window
			SetFocus();
		}
	}   
}

void CMemoryWindow::OnGroupMemory()
{
	// TODO: Add your command handler code here
	BOOL focus;

	focus = m_bFocus;
	m_bFocus = FALSE;
	CMemDlg dlg(NULL);
	dlg.DoModal();
	if (focus) m_bFocus = TRUE;
	RefreshMemWin(TRUE);
}

void CMemoryWindow::OnUpdateGroupMemory(CCmdUI* pCmdUI)
{
   // TODO: Add your command update UI handler code here
   unsigned char uchCpuStatus;
    
   if (GetCpuStatus(uchCpuStatus)) {
     if ( 1 == uchCpuStatus ) {       // Is on GO status (STATUS_GO)
        pCmdUI->Enable(FALSE);
     }
     else {
      pCmdUI->Enable(TRUE);
     }      
   }
}

void CMemoryWindow::OnOptionsMap()
{
    // TODO: Add your command handler code here
    // Open Map dialog.
    HINSTANCE hLib;
    if ( (hLib = LoadLibrary("MUSCROLL.DLL")) < HINSTANCE_ERROR ) {
        AfxMessageBox("MUSCROLL.DLL loading error.");
        // ::ErrGetErrorText(....);
        return;
    }
    
    CMapDlg dlg;
    dlg.DoModal();
    
    if ( hLib >= HINSTANCE_ERROR ) FreeLibrary(hLib);
}

void CMemoryWindow::OnUpdateMap(CCmdUI* pCmdUI)
{
   // TODO: Add your command update UI handler code here
   unsigned char uchCpuStatus;
    
   if (GetCpuStatus2() != STATUS_HALT) {
        pCmdUI->Enable(FALSE);
   } else {
      pCmdUI->Enable(TRUE);
   }
}

long CMemoryWindow::OnXMRepaint(UINT /*wParam*/,LONG /*lParam*/)
{
	RefreshMemWin(TRUE);
	return 0;
}

void CMemoryWindow::OnSetFocus(CWnd* pOldWnd)
{
	CMDIChildWnd::OnSetFocus(pOldWnd);

	// TODO: Add your message handler code here
	m_bFocus = TRUE;
	CreateSolidCaret(2, m_nLineHeight-2);
//	if (!InWnd())
//		GotoCursor();
	SetMyCaretPos();
}

void CMemoryWindow::OnKillFocus(CWnd* pNewWnd)
{
	CMDIChildWnd::OnKillFocus(pNewWnd);

	// TODO: Add your message handler code here
	m_bFocus = FALSE;
	DestroyCaret();
}

void CMemoryWindow::OnEditGoto()
{
    // TODO: Add your command handler code here
CMemGtDlg* pMemGtDlg;
BOOL	bSizeMsg=FALSE;

	if (IsIconic())
		ShowWindow( SW_RESTORE );

	pMemGtDlg=new CMemGtDlg(this, m_bViewMode2==SM_CODE);
	pMemGtDlg->m_wSpace=sadr_GotoAddr.addrType;
	pMemGtDlg->m_dwAddress=sadr_GotoAddr.addr;
	if(IDOK==pMemGtDlg->DoModal())
	{
		sadr_GotoAddr.addrType=pMemGtDlg->m_wSpace;
		sadr_GotoAddr.addr=pMemGtDlg->m_dwAddress;
		if(m_wSpaceType!=sadr_GotoAddr.addrType)
		{
			if(m_wSpaceType==MEM_I&&IsZoomed())			//onchip data
				bSizeMsg=TRUE;
			m_wSpaceType=sadr_GotoAddr.addrType;
			SetRegionEnd();
			//reset buffer content:
			m_dwBufStartAddr=0xffff;
			m_dwBufEndAddr=0;
			SetWindowTitle();
		}
		m_dwStartAddress=sadr_GotoAddr.addr;
		if(m_bViewMode2!=SM_CODE)
			m_dwStartAddress&=0xfff0+(m_nLineGroup==2?8:0);
		else
		{
			if(m_dwStartAddress+(m_nLines-2)*0x3-1>m_dwMemRegionEnd)
				m_dwStartAddress=m_dwMemRegionEnd+1-(m_nLines-2)*0x3;
		}
		ASSERT(m_dwStartAddress/(0x10/m_nLineGroup)<0x10000);
		m_lCaretPosY=long(m_dwStartAddress/(0x10/m_nLineGroup));
		m_nCaretArea==1;
		switch(m_bViewMode1)
		{
			case SM_BYTE:
				m_wCaretPosX1=WORD(sadr_GotoAddr.addr&0xf);
				m_wCaretPosX2=0;
				break;
			case SM_WORD:
				m_wCaretPosX1=WORD((sadr_GotoAddr.addr&0xf)/2);
				m_wCaretPosX2=0;
				break;
			case SM_DWORD:
				m_wCaretPosX1=WORD((sadr_GotoAddr.addr&0xf)/4);
				m_wCaretPosX2=0;
				break;
			default:
				break;
		}
		OnModeChange();
		GotoCursor();
		Invalidate();
	}
	delete pMemGtDlg;
	if(bSizeMsg)
	{
		ShowWindow(SW_SHOWMAXIMIZED);
		return;
		LPARAM	lParam;
		RECT	rect;

		(AfxGetApp()->m_pMainWnd)->GetClientRect(&rect);
		lParam = rect.bottom;
		lParam-=(lParam%m_gridAddr.m_nGridHeight);
		lParam <<=16;
		lParam += rect.right;
		PostMessage(WM_SIZE, SIZE_MAXIMIZED, lParam);
	}
}

void CMemoryWindow::OnUpdateEditGoto(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
	//pCmdUI->Enable(TRUE);
	unsigned char uchCpuStatus;
	if (m_bIconic)
	{
		pCmdUI->Enable(FALSE);
		return;
	}

	if (GetCpuStatus2() != STATUS_HALT) {
	    pCmdUI->Enable(FALSE);
	} else {
	    pCmdUI->Enable(TRUE);
	}
}

void CMemoryWindow::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd,
                               CWnd* pDeactivateWnd)
{
    CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);

    // TODO: Add your message handler code here
    if(bActivate && pActivateWnd == this) {
        /*AfxGetApp()->m_pMainWnd*/
        GetMDIFrame()->SendMessage(XM_MDIACTIVE, WORD(bActivate),
            LONG(WID_MEMORY));
        //GotoCursor();
    }
    else if(!bActivate && !pActivateWnd)
        /*AfxGetApp()->m_pMainWnd*/
        GetMDIFrame()->SendMessage(XM_MDIACTIVE, WORD(bActivate));
}

void CMemoryWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
{
        // TODO: Add your message handler code here and/or call default
DWORD address;
DWORD address2;
int i;
CRect rect1;
CRect rect2;

    if (m_bViewMode2==SM_CODE) {
            m_gridMem.DoRect();
            m_gridInstruction.DoRect();

            rect1.left = m_gridMem.m_rectPos.left+m_gridAddr.m_rectPos.right;
            rect1.top = m_gridMem.m_rectPos.top+m_gridMem.m_nGridHeight;
            rect1.right = m_gridMem.m_rectPos.right+m_gridAddr.m_rectPos.right;
            rect1.bottom = m_gridMem.m_rectPos.bottom;

            rect2.left = m_gridInstruction.m_rectPos.left+m_gridAddr.m_rectPos.right;
            rect2.top = m_gridInstruction.m_rectPos.top+m_gridInstruction.m_nGridHeight;
            rect2.right = m_gridInstruction.m_rectPos.right+m_gridAddr.m_rectPos.right;
            rect2.bottom = m_gridInstruction.m_rectPos.bottom;

            if (rect1.PtInRect(point)) {
                    for(i=1;i<m_nLines;i++) {
                            rect1 = m_gridMem.GetGridRect(0,i);
                            if (rect1.PtInRect(point)) {
                                    address =m_dsm[i-1].address;
                                    break;
                            }
                    }
                    CDsmEdit1 dlg(this);
                    dlg.m_dwAddress = address;
                    dlg.m_wSpaceType = m_wSpaceType;
                    address2 = m_dwStartAddress;
                    dlg.DoModal();
                    m_dwStartAddress = address2;
                    InvalidateRect(NULL,FALSE);
                    ::RepaintMemory();
            }
            else if (rect2.PtInRect(point)) {
                    for(i=1;i<m_nLines;i++) {
                            rect1 = m_gridInstruction.GetGridRect(0,i);
                            if (rect1.PtInRect(point)) {
                                    address = m_dsm[i-1].address;
                                    break;
                            }
                    }
                    CDsmEdit2 dlg(this);
                    dlg.m_dwAddress = address;
                    dlg.m_wSpaceType = m_wSpaceType;
                    address2 = m_dwStartAddress;
                    dlg.DoModal();
                    m_dwStartAddress = address2;
                    InvalidateRect(NULL,FALSE);
                    ::RepaintMemory();
            }
    }

    CMDIChildWnd::OnLButtonDblClk(nFlags, point);
}

void CMemoryWindow::RefreshMemWin(BOOL hard)
{              
	if(hard)
	{
		m_dwBufStartAddr=0xffff;
		m_dwBufEndAddr=0;
		PrepareData();
	}
	SetWindowTitle();
	Invalidate();
}

void CMemoryWindow::OnViewRefresh()
{
     // TODO: Add your command handler code here
int bCtrl = GetKeyState(VK_CONTROL)&0x8000;

    RefreshMemWin(1);
}

void CMemoryWindow::OnUpdateViewRefresh(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    unsigned char uchCpuStatus;
    
    if (GetCpuStatus2() != ICE_OK) {
         pCmdUI->Enable(FALSE);
    } else {
       pCmdUI->Enable(TRUE);
    }
}

DWORD CMemoryWindow::GetCaretAddr()
{
	int nLineByte = 16/m_nLineGroup;
	DWORD dwStartAddress = m_lCaretPosY*nLineByte;
//	DWORD dwStartAddress = m_dwStartAddress;
//	dwStartAddress += (m_lCaretPosY-m_dwStartAddress/16)*16;
	if (m_nCaretArea==1)
	{
		switch(m_bViewMode1)
		{
		case SM_BYTE:
			dwStartAddress += (unsigned short)m_wCaretPosX1;
			break;
		case SM_WORD:
			dwStartAddress += (unsigned short)m_wCaretPosX1*2; 
			dwStartAddress += 1-m_wCaretPosX2/2;
			break;
		case SM_DWORD:
			dwStartAddress += (unsigned short)m_wCaretPosX1*4;
			dwStartAddress += 3-m_wCaretPosX2/2;
			break;
		default:
			break;
		}
	}
	if (m_nCaretArea==2)
		dwStartAddress += (unsigned short)m_wCaretPosX2;
	return dwStartAddress;
}

BOOL CMemoryWindow::SearchNext(DWORD dwStartAddr,LPSTR lpszPattern)
{
	DWORD dwMax;
	switch( m_wSpaceType ) {
	case MEM_P0:
	case MEM_P1:
	case MEM_P2:
	case MEM_P3:
		 // Add by Daniel Lin 
		 dwMax = pMax;
		 break;
	case MEM_X0:
	case MEM_X1:
		 // Add by Daniel Lin 
		 dwMax = xMax;
		 break;
	case MEM_I:
		 // Add by Daniel Lin 
		 dwMax = iMax;
		break;
	default:
		ASSERT(0);
	}                          

	ADDRESS begAddr,endAddr,retAddr;
	endAddr.adrSpace = begAddr.adrSpace = m_wSpaceType;
	begAddr.adrAddress = dwStartAddr;
	endAddr.adrAddress = dwMax;
	CString strMsg;
	
	BeginWaitCursor();
	STATUS ret = MemServerSearch(begAddr,endAddr,lpszPattern+1,
				*lpszPattern,0,retAddr,strMsg,1);
    EndWaitCursor();
	if (ret != ICE_OK) {
		AfxMessageBox(strMsg);
		return FALSE;
	}
	else {
		int nLineByte = 16/m_nLineGroup;
		DWORD dwFindAddr = retAddr.adrAddress & 0xffff;
		m_dwStartAddress = (unsigned short)(dwFindAddr&0xFFFFFFF0L);
		DWORD dwTempAddress = (m_dwStartAddress+(m_nLines-2)*nLineByte);
		if (dwTempAddress > dwMax) {
			m_dwStartAddress = dwMax-(m_nLines-2)*nLineByte+1;
		}
		
		int i = (int)dwFindAddr % nLineByte;
		m_lCaretPosY = dwFindAddr/nLineByte;
		if (m_nCaretArea==1) {
		  	switch(m_bViewMode1) {
				case SM_BYTE:
					m_wCaretPosX1=WORD(i);
					m_wCaretPosX2=0;
					break;
				case SM_WORD:
					m_wCaretPosX1=WORD(i/2);
					m_wCaretPosX2=0;
					break;
				case SM_DWORD:
					m_wCaretPosX1=WORD(i/4);
					m_wCaretPosX2=0;
					break;
				default:
					break;
			}
		}  
		if (m_nCaretArea==2) {
			m_wCaretPosX2 = (WORD)i;
		}
		RefreshMemWin(1);
		SetScrollPos(SB_VERT, (UINT)(m_dwStartAddress/nLineByte), TRUE);
	}
	return TRUE;
}

void CMemoryWindow::OnEditSearch()
{
	// TODO: Add your command handler code here
	CMemSearchDlg dlg(this);
	dlg.m_str = m_searchStr;

	if (dlg.DoModal() == IDOK) {
	    lstrcpy(m_searchStr, dlg.m_str);
//	    lstrcpy(m_szPattern,dlg.m_szPattern); 
	    memcpy(m_szPattern,dlg.m_szPattern,sizeof(m_szPattern)); 
	    SearchNext(GetCaretAddr(),m_szPattern);
	}
/*
	CMemSearchDlg dlg(this);
	int i;

	dlg.m_wSpaceType = m_wSpaceType;
	dlg.m_dwStartAddress = m_dwStartAddress;
	dlg.m_dwStartAddress += (m_lCaretPosY-m_dwStartAddress/16)*16;
	if (m_nCaretArea==1)
	{
		switch(m_bViewMode1)
		{
		case SM_BYTE:
			dlg.m_dwStartAddress += (unsigned short)m_wCaretPosX1;
			break;
		case SM_WORD:
			dlg.m_dwStartAddress += (unsigned short)m_wCaretPosX1*2;
			break;
		case SM_DWORD:
			dlg.m_dwStartAddress += (unsigned short)m_wCaretPosX1*4;
			break;
		default:
			break;
		}
	}
	if (m_nCaretArea==2)
		dlg.m_dwStartAddress += (unsigned short)m_wCaretPosX2;
	strcpy(dlg.m_str, m_searchStr);
	i = dlg.DoModal();
	if (i)
	{
		strcpy(m_searchStr, dlg.m_str);
		if (dlg.m_dwFindAddress == -1)
		{
			MessageBox("Not Found!",NULL, MB_OK);
			return;
		}
		m_dwStartAddress = (dlg.m_dwFindAddress&0xFFFFFFF0);
		DWORD dwTempAddress = 0;
		dwTempAddress = (m_dwStartAddress+(m_nLines-4)*16);
		switch( m_wSpaceType ) {
			case MEM_P0:
			case MEM_P1:
			case MEM_P2:
			case MEM_P3:
				// Add by Daniel Lin 
				if (dwTempAddress >= ((DWORD)pMax&0xFFF0)) {
				  m_dwStartAddress = pMax-(m_nLines-3)*16;
				  m_dwStartAddress &= 0xFFF0;
				}
				break;
			case MEM_X0:
			case MEM_X1:
			  // Add by Daniel Lin 
			  if (dwTempAddress > ((DWORD)xMax&0xFFF0)) {
			      m_dwStartAddress = xMax-(m_nLines-3)*16;
			      m_dwStartAddress &= 0xFFF0;
			  }
			  break;
			case MEM_I:
			  // Add by Daniel Lin 
			  if (dwTempAddress > ((DWORD)iMax&0xFFF0)) {
			      m_dwStartAddress = iMax-(m_nLines-3)*16;
			      m_dwStartAddress &= 0xFFF0;
			  }
			  break;
			default:
				ASSERT(0);
		}
		i = (int)(dlg.m_dwFindAddress&0x0000000F);
		m_lCaretPosY = (long)(dlg.m_dwFindAddress>>4);
		if (m_nCaretArea==1)
		{
			switch(m_bViewMode1)
			{
				case SM_BYTE:
					m_wCaretPosX1=WORD(i);
					m_wCaretPosX2=0;
					break;
				case SM_WORD:
					m_wCaretPosX1=WORD(i/2);
					m_wCaretPosX2=0;
					break;
				case SM_DWORD:
					m_wCaretPosX1=WORD(i/4);
					m_wCaretPosX2=0;
					break;
				default:
					break;
			}
		}
		if (m_nCaretArea==2)
		{
			m_wCaretPosX2 = WORD(i);
		}
		RefreshMemWin(1);
		SetScrollPos(SB_VERT,(WORD)(m_dwStartAddress/0x10),TRUE);
	}
*/
}

void CMemoryWindow::OnUpdateEditSearch(CCmdUI* pCmdUI)
{
	// TODO: Add your command update UI handler code here
	unsigned char uchCpuStatus;		     
	if (m_wSpaceType != SPACE_I && m_bViewMode2!=SM_CODE)  {
		if (GetCpuStatus2() != ICE_OK) {
		    pCmdUI->Enable(FALSE);
		} else {
		  	pCmdUI->Enable(TRUE);
		}
	}     
	else 
		pCmdUI->Enable(FALSE);
}

void CMemoryWindow::OnEditSearchnext()
{
        // TODO: Add your command handler code here
	DWORD dwSAddr = GetCaretAddr();
	if (m_nCaretArea==1)
		switch(m_bViewMode1)
		{
			case SM_BYTE:
				dwSAddr += 1;
				break;
			case SM_WORD:
				dwSAddr += 2;
				break;
			case SM_DWORD:
				dwSAddr += 4;
				break;
			default:
				break;
		}
	if (m_nCaretArea==2) dwSAddr += 1;
	SearchNext(dwSAddr,m_szPattern);
/*
int i;
ADDRESS startAddress, endAddress, addr;
long FindAddress;
BOOL bFind;
char *text;

	text = new char [200];
	ASSERT(NULL != text);
	i = strlen(m_searchStr);
	if (i<=0)
		OnEditSearch();
	else
	{
		startAddress.adrAddress = m_dwStartAddress;
		startAddress.adrAddress += (m_lCaretPosY-m_dwStartAddress/16)*16;
		if (m_nCaretArea==1)
			switch(m_bViewMode1)
			{
				case SM_BYTE:
					startAddress.adrAddress += (unsigned short)(m_wCaretPosX1+1);
					break;
				case SM_WORD:
					startAddress.adrAddress += (unsigned short)(m_wCaretPosX1*2+2);
					break;
				case SM_DWORD:
					startAddress.adrAddress += (unsigned short)(m_wCaretPosX1*4+4);
					break;
				default:
					break;
			}
		if (m_nCaretArea==2)
		{
			startAddress.adrAddress += (unsigned short)(m_wCaretPosX2+1);
		}
		strcpy(text, m_searchStr+2);
		startAddress.adrSpace=(::ADDR_SPACE)m_wSpaceType;
		endAddress.adrSpace=(::ADDR_SPACE)m_wSpaceType;
		endAddress.adrAddress=0xffff;
		BeginWaitCursor();
		if(!MyMemServerSearch(startAddress,endAddress,text,0,addr, bFind))
			ASSERT(0);
		EndWaitCursor();
		if (!bFind) {
			MessageBox("Not Found!",NULL, MB_OK);
			return;
		}
		else {
		 FindAddress = addr.adrAddress;
		 m_dwStartAddress = (unsigned short)(FindAddress&(long)0xFFFFFFF0);
		 LONG   dwTempAddress = 0;
		 dwTempAddress = (m_dwStartAddress+(m_nLines-2)*16);
		 switch( m_wSpaceType ) {
			case MEM_P0:
			case MEM_P1:
			case MEM_P2:
			case MEM_P3:
		     // Add by Daniel Lin 
		     if (dwTempAddress >= ((long)pMax&0xFFF0)) {
		         m_dwStartAddress = pMax-(m_nLines-3)*16;
		         m_dwStartAddress &= 0xFFF0;
		     }
		     break;
			case MEM_X0:
			case MEM_X1:
		     // Add by Daniel Lin 
		     if (dwTempAddress > ((long)xMax&0xFFF0)) {
		         m_dwStartAddress = xMax-(m_nLines-3)*16;
		         m_dwStartAddress &= 0xFFF0;
		     }
		     break;
		   	case MEM_I:
		     // Add by Daniel Lin 
		     if (dwTempAddress > ((long)iMax&0xFFF0)) {
		         m_dwStartAddress = iMax-(m_nLines-3)*16;
		         m_dwStartAddress &= 0xFFF0;
		     }
		    break;
		    default:
		    	ASSERT(0);
		 }                          
			             
		 i = (int)(FindAddress&(long)0x0000000F);
		 m_lCaretPosY = (long)(FindAddress>>4);
		 if (m_nCaretArea==1)
		 switch(m_bViewMode1) {
		     case SM_BYTE:
		         m_wCaretPosX1=WORD(i);
		         m_wCaretPosX2=0;
		         break;
			                     
		     case SM_WORD:
		         m_wCaretPosX1=WORD(i/2);
		         m_wCaretPosX2=0;
		         break;
			                     
		     case SM_DWORD:
		         m_wCaretPosX1=WORD(i/4);
		         m_wCaretPosX2=0;
		         break;
			                     
		     default:
		         break;
		 }
		 if (m_nCaretArea==2) {
		         m_wCaretPosX2 = WORD(i);
		 }
		 RefreshMemWin(1);
		 SetScrollPos(SB_VERT, (WORD)(m_dwStartAddress/0x10), TRUE);
		}
	}
	delete []text;
*/	
}

void CMemoryWindow::OnUpdateEditSearchnext(CCmdUI* pCmdUI)
{
  // TODO: Add your command update UI handler code here
  unsigned char uchCpuStatus;

  if (m_wSpaceType != SPACE_I && m_szPattern[0] && m_bViewMode2!=SM_CODE) {
    if (GetCpuStatus(uchCpuStatus)) {
      if ( 1 == uchCpuStatus ) {       // Is on GO status (STATUS_GO)
         pCmdUI->Enable(FALSE);
      }
      else {
       pCmdUI->Enable(TRUE);
      }      
    }
  }  
  else pCmdUI->Enable(FALSE);
}

void CMemoryWindow::OnSysCommand(UINT nID, LPARAM lParam)
{
   // TODO: Add your message handler code here and/or call default
   unsigned char uchCpuStatus;
   
   if (GetCpuStatus(uchCpuStatus)) {
     if ( 1 == uchCpuStatus ) {       // Is on GO status (STATUS_GO)
      if ( SC_ZOOM == nID ) {
         ShowStatusGo();
         return;          // Zoomed
      }         
      if ( SC_MAXIMIZE == nID ) {
         ShowStatusGo();
         return;      // Zoomed
      }         
      if ( SC_RESTORE == nID ) {
         ShowStatusGo();
         return;       // Restore
      }         
      if ( SC_SIZE == nID ) {
         ShowStatusGo();
         return;       // Restore
      }         
      //if ( SC_MOVE == nID ) return;       // Restore      
     }
   }        
      
   CMDIChildWnd::OnSysCommand(nID, lParam);
}

BEGIN_MESSAGE_MAP(CMemoryWindow, CMDIChildWnd)
	//{{AFX_MSG_MAP(CMemoryWindow)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_RBUTTONDOWN()
	ON_WM_SETCURSOR()
	ON_COMMAND(ID_VIEW_BYTE, OnViewByte)
	ON_UPDATE_COMMAND_UI(ID_VIEW_BYTE, OnUpdateViewByte)
	ON_COMMAND(ID_VIEW_WORD, OnViewWord)
	ON_UPDATE_COMMAND_UI(ID_VIEW_WORD, OnUpdateViewWord)
	ON_COMMAND(ID_VIEW_LONG, OnViewLong)
	ON_UPDATE_COMMAND_UI(ID_VIEW_LONG, OnUpdateViewLong)
	ON_COMMAND(ID_VIEW_SIGNEDDECIMAL, OnViewSigneddecimal)
	ON_UPDATE_COMMAND_UI(ID_VIEW_SIGNEDDECIMAL, OnUpdateViewSigneddecimal)
	ON_COMMAND(ID_VIEW_HEXADECIMAL, OnViewHexadecimal)
	ON_UPDATE_COMMAND_UI(ID_VIEW_HEXADECIMAL, OnUpdateViewHexadecimal)
	ON_COMMAND(ID_VIEW_DISASSEMBLE, OnViewDisassemble)
	ON_UPDATE_COMMAND_UI(ID_VIEW_DISASSEMBLE, OnUpdateViewDisassemble)
	ON_COMMAND(ID_VIEW_ASCII, OnViewAscii)
	ON_UPDATE_COMMAND_UI(ID_VIEW_ASCII, OnUpdateViewAscii)
	ON_COMMAND(ID_VIEW_UNSIGNEDDECIMAL, OnViewUnsigneddecimal)
	ON_UPDATE_COMMAND_UI(ID_VIEW_UNSIGNEDDECIMAL, OnUpdateViewUnsigneddecimal)
	ON_WM_SIZE()
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
	ON_WM_SETFOCUS()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_KEYDOWN()
	ON_WM_CHAR()
	ON_MESSAGE(XM_REPAINT,OnXMRepaint)
	ON_WM_KILLFOCUS()
	ON_COMMAND(ID_EDIT_GOTO, OnEditGoto)
	ON_UPDATE_COMMAND_UI(ID_EDIT_GOTO, OnUpdateEditGoto)
	ON_WM_MDIACTIVATE()
	ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh)
	ON_UPDATE_COMMAND_UI(ID_VIEW_REFRESH, OnUpdateViewRefresh)
	ON_COMMAND(ID_EDIT_SEARCH, OnEditSearch)
	ON_UPDATE_COMMAND_UI(ID_EDIT_SEARCH, OnUpdateEditSearch)
	ON_COMMAND(ID_EDIT_SEARCHNEXT, OnEditSearchnext)
	ON_UPDATE_COMMAND_UI(ID_EDIT_SEARCHNEXT, OnUpdateEditSearchnext)
	ON_COMMAND(ID_GROUP_MEMORY, OnGroupMemory)
	ON_UPDATE_COMMAND_UI(ID_OPTIONS_MAP, OnUpdateMap)    
	ON_UPDATE_COMMAND_UI(ID_GROUP_MEMORY, OnUpdateGroupMemory)
	ON_WM_SYSCOMMAND()
	ON_WM_NCHITTEST()
	ON_COMMAND(ID_VIEW_SHORTLINE, OnViewShortline)
	ON_UPDATE_COMMAND_UI(ID_VIEW_SHORTLINE, OnUpdateViewShortline)
	ON_WM_LBUTTONDBLCLK()
	ON_COMMAND(ID_SHIFTF10, OnShiftf10)
	ON_COMMAND(ID_OPTIONS_MAP, OnOptionsMap)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

UINT CMemoryWindow::OnNcHitTest(CPoint point)
{
   // TODO: Add your message handler code here and/or call default
unsigned char uchCpuStatus;
UINT nHitTest = 0;

   nHitTest = CMDIChildWnd::OnNcHitTest(point);          
   
   if (GetCpuStatus(uchCpuStatus)) {
      if ( 1 != uchCpuStatus ) {       // Is not on GO status (STATUS_GO)
         return nHitTest; /*CMDIChildWnd::OnNcHitTest(point);*/
      }
      else {            // On GO
         //if ( SrcEmu.m_isRunAccess ) {       // GO and Run Access
         //   return CMDIChildWnd::OnNcHitTest(point);
         //}
         //else {         // Go and Run access off
         switch ( nHitTest ) {
               /*
            case HTBORDER     :
            case HTBOTTOM       :
            case HTBOTTOMLEFT   : 
            case HTBOTTOMRIGHT  :  
            case HTHSCROLL      :
            case HTLEFT         :
            case HTRIGHT        :
            case HTTOP          :
            case HTTOPLEFT      :
            case HTTOPRIGHT     :
            case HTVSCROLL      :
                ShowStatusGo();
                return HTERROR;
            */                      
            case HTZOOM         :
            case HTSYSMENU      :            
            case HTCAPTION      :
            //case HTCLIENT       :
            case HTMINBUTTON    :            
                return nHitTest;
                
            default:
                ShowStatusGo();
                 return HTERROR;   
                   
         }
         //}   
      }         
   }
   else
      return HTERROR;
}

BOOL
ReadMemWndIni()
{
WORD mem1area=1, mem2area=1, mem3area=1;
DWORD mem1addr=0, mem2addr=0, mem3addr=0;

	CString strBuffer = AfxGetApp()->
			GetProfileString("MemWindow", "StartAddr", "1 0 1 0 1 0");
	           
	sscanf(strBuffer, "%x %lx %x %lx %x %lx", 
			&mem1area, &mem1addr, 
			&mem2area, &mem2addr,
			&mem3area, &mem3addr);
	if(mem1area == 0) mem1area = 0x0a;		
	if(mem2area == 0) mem2area = 0x0a;
	if(mem3area == 0) mem3area = 0x0a;
	sadr_LastMemAddr[0].addr = mem1addr&0xfffffff0;
	sadr_LastMemAddr[1].addr = mem2addr&0xfffffff0;
	sadr_LastMemAddr[2].addr = mem3addr&0xfffffff0;
	sadr_LastMemAddr[0].addrType = mem1area;
	sadr_LastMemAddr[1].addrType = mem2area;
	sadr_LastMemAddr[2].addrType = mem3area;

	strBuffer = AfxGetApp()->
		GetProfileString("MemWindow", "Mode", "1 1 1 1 1 1 1 1 1 1 1 1");
	sscanf(strBuffer, "%x %x %x %x %x %x %x %x %x %x %x %x",
		&sb_MemViewMode1[0], &sb_MemViewMode1[1], &sb_MemViewMode1[2],
		&sb_MemViewMode2[0], &sb_MemViewMode2[1], &sb_MemViewMode2[2],
		&sb_MemShowAscii[0], &sb_MemShowAscii[1], &sb_MemShowAscii[2],
		&sn_MemLineGroup[0], &sn_MemLineGroup[1], &sn_MemLineGroup[2]);

	for(int i=0; i<3; i++)
	{
		if(sb_MemViewMode1[i]<1||sb_MemViewMode1[i]>3)
			sb_MemViewMode1[i]=1;
		if(sb_MemViewMode2[i]<1||sb_MemViewMode2[i]>4)
			sb_MemViewMode2[i]=1;
		if(sb_MemShowAscii[i]!=FALSE)
			sb_MemShowAscii[i]=TRUE;
		if(sn_MemLineGroup[i]<1||sn_MemLineGroup[i]>2)
			sn_MemLineGroup[i]=1;
	}
	strBuffer = AfxGetApp()->
		GetProfileString("MemWindow", "GotoAddr", "1 0");
	sscanf(strBuffer, "%x %lx", &sadr_GotoAddr.addrType, &sadr_GotoAddr.addr);

	return TRUE;
}

BOOL
WriteMemWndIni()
{
char szBuffer[100];
WORD mem1area, mem2area, mem3area;
DWORD mem1addr, mem2addr, mem3addr;
	    
	mem1addr = sadr_LastMemAddr[0].addr;
	mem2addr = sadr_LastMemAddr[1].addr;
	mem3addr = sadr_LastMemAddr[2].addr;
	
	mem1area = sadr_LastMemAddr[0].addrType;
	mem2area = sadr_LastMemAddr[1].addrType;
	mem3area = sadr_LastMemAddr[2].addrType;
	
	sprintf(szBuffer, "%x %lx %x %lx %x %lx", 
	                    mem1area, mem1addr, 
	                    mem2area, mem2addr,
	                    mem3area, mem3addr);
	AfxGetApp()->WriteProfileString("MemWindow", "StartAddr", szBuffer);

	sprintf(szBuffer, "%x %x %x %x %x %x %x %x %x %x %x %x",
		sb_MemViewMode1[0], sb_MemViewMode1[1], sb_MemViewMode1[2],
		sb_MemViewMode2[0], sb_MemViewMode2[1], sb_MemViewMode2[2],
		sb_MemShowAscii[0], sb_MemShowAscii[1], sb_MemShowAscii[2],
		sn_MemLineGroup[0], sn_MemLineGroup[1], sn_MemLineGroup[2]);
	AfxGetApp()->WriteProfileString("MemWindow", "Mode", szBuffer);

	sprintf(szBuffer, "%x %lx",
			sadr_GotoAddr.addrType, sadr_GotoAddr.addr);
	AfxGetApp()->WriteProfileString("MemWindow", "GotoAddr", szBuffer);

	return TRUE;
}

/////////////////////(EOF of NWMEM.CPP)/////////////////////////////

void CMemoryWindow::OnShiftf10()
{
	// TODO: Add your command handler code here
	
    CMenu * pLocalMenu = new CMenu;

    ASSERT(pLocalMenu!=NULL);

    pLocalMenu->CreatePopupMenu();
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_REFRESH, "&Refresh");
    pLocalMenu->AppendMenu(MF_SEPARATOR);

    pLocalMenu->AppendMenu(MF_STRING, ID_GROUP_MEMORY, "&Memory...");
    pLocalMenu->AppendMenu(MF_STRING, ID_OPTIONS_MAP, "Ma&p...");
    pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_GOTO, "&Goto...");
    pLocalMenu->AppendMenu(MF_SEPARATOR);

    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SHORTLINE, "Sh&ort line mode");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_ASCII, "Show &ASCII");
    pLocalMenu->AppendMenu(MF_SEPARATOR);

    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_HEXADECIMAL, "&Hexadecimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SIGNEDDECIMAL, "&Signed Decimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_UNSIGNEDDECIMAL, "&Unsigned Decimal");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_DISASSEMBLE, "&Disassemble");
    pLocalMenu->AppendMenu(MF_SEPARATOR);

    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_BYTE, "&Byte");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_WORD, "&Word");
    pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_LONG, "&Long");
    
    CPoint point(20, 20);
    ClientToScreen(&point);
    pLocalMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
              
    delete pLocalMenu;
}
