
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/SRCWIN.CPP   1.7   11 Jun 1996 10:23:18   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/SRCWIN.CPP  $
** 
**    Rev 1.7   11 Jun 1996 10:23:18   ZJRD
** EasyPack/SLD Version 1.97
** 
**    Rev 1.5   05 Jun 1996 14:51:00   ZJRD
** EasyPack/SLD Version 1.96
** 
**    Rev 1.4   29 May 1996 09:27:38   ZJRD
** EasyPack/SLD Version 1.95
** 
**    Rev 1.3   16 May 1996 08:59:18   ZJRD
** EasyPack/SLD Version 1.94
** 
**    Rev 1.1   02 May 1996 10:22:20   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 12:52:44   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:33:34   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:46:32   Shirley
** EasyPack/SLD Version 1.01
** 
**    Rev 1.27   12 Feb 1996 14:01:48   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:27:02   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:42:40   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:11:18   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:11:50   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:12:10   Shirley
** EasyPack/SLD Version 0.35
** 
**    Rev 1.21   24 Jan 1996 10:32:00   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:21:54   Shirley
** EasypPack/SLD Version 0.34c
** 
**    Rev 1.19   18 Jan 1996 10:07:18   Shirley
** EasyPack/SLD Version 0.34b
** 
**    Rev 1.18   15 Jan 1996 16:10:02   Shirley
** EasyPack/SLD Version 0.34a
** 
**    Rev 1.17   04 Jan 1996 11:07:32   Shirley
** EasyPack/SLD Version 0.34
** 
**    Rev 1.16   30 Nov 1995 09:08:02   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:28:56   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:17:50   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:21:38   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:28:02   Shirley
** EasyPack/SLD Version 0.24
** 
**    Rev 1.11   08 Nov 1995 16:27:34   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:39:30   Shirley
** EasyPack/SLD Version 0.22
** 
**    Rev 1.9   02 Nov 1995 10:02:14   Shirley
** EasyPack/SLD Version 0.21
** 
**    Rev 1.8   27 Oct 1995 16:44:52   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:43:10   Shirley
** EasyPack/SLD Version 0.1g
** 
**    Rev 1.6   25 Oct 1995 14:25:40   Shirley
** EasyPack/SLD Version 0.1f
** 
**    Rev 1.5   18 Oct 1995 14:46:44   Shirley
** EasyPack/SLD Version 0.1e
** 
**    Rev 1.4   13 Oct 1995 13:18:36   Shirley
** EasyPack/SLD Version 0.1d
** 
**    Rev 1.3   29 Sep 1995 09:48:00   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:55:20   Shirley
** EasyPack/SLD Version 0.1b
** 
**    Rev 1.1   15 Sep 1995 09:47:42   Shirley
** EasyPack/SLDV0.1a 
** 
**    Rev 1.0   07 Sep 1995 09:55:04   Shirley
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  SRCWIN.CPP
//
//  Description:The implement file for the class: CSourceWindow
//
//  Author:     Roger Zhang
//
//  Date:       05/10/95
//
//  Modification:
//
//      1. 05/10/95, Initial version 
//
//      2. 09/08/95  0.1a
//
//         2.1 Fixed bug No.18 
//              Modify function: OnRunJump
//
//         2.2 Fixed bug No.16,17
//              Modify function: OnViewSourceonly
//
//      3. 09/20/95  0.1b
//
//         3.1 Fixed bug No.75 
//              Modify function: ShowSourceLine
//
//         3.2 Fixed bug No.76 
//              Add function: OnShiftreturn
//
//
//      4. 10/10/95  0.1d
//
//         4.1 Delete Step Option Selection 
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
                                     
#include "colors.h"                                     
#include "zqueue.h"
#include "uicom.h"
#include "srccom.h"
#include "btnbar.h"
#include "zlist.h"
#include "srclist.h"
#include "srcmdl.h"
#include "srcfile.h"
#include "meter.h"
#include "srcdlg1.h"
#include "srcgrp.h"
#include "mainfrm.h"
#include "srcwin.h"
#include "bwswin.h"

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

/////////////////////////////////////////////////////////////////////////////

extern void DoBrowseModule(CSrcGrpDlg &dlg);

extern int SrcGetFuncRange(const char *command, unsigned short& uStart, 
        unsigned short& uEnd);
extern int SrcIsFunction(const char *command);
extern int SrcIsVariable(const char* str,int nLineNo);
extern void VarAddVariable(const CString strToken);
     
    

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
/*BOOL GetLineRange(unsigned short & uStart, unsigned short & uEnd)
{
    unsigned long dwModule;
    unsigned short uLine;    
    unsigned long dwStartAddr, dwEndAddr;
    
    dwStartAddr = SrcGetPC();
    if(SrcAddr2Linenum(dwStartAddr, uLine, dwModule) == -1) 
        return FALSE;
    if(SrcLinenum2Range(dwModule, uLine, dwStartAddr, dwEndAddr) == -1)
        return FALSE;

    uStart = (unsigned short)dwStartAddr;
    uEnd = (unsigned short)dwEndAddr;          
    if(!isSourceOn) return TRUE;
    else if(((CSourceWindow *)pSourceWnd)->m_nDispMode == MODE_SOURCE)  
        return TRUE;
    else return FALSE;        
}*/

void SrcSetText()
{
   if(isSourceOn&&pSourceWnd)
     ((CSourceWindow *)pSourceWnd)->SelectText(FALSE);
}       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsAddr2Line(unsigned short uAddr)
{
    unsigned short uLine;
    unsigned long  dwModule;    
    return BOOL(SrcAddr2Linenum(uAddr, uLine, dwModule) == 0);
}

/////////////////////////////////////////////////////////////////////////////
SyntaxColor SrcColor;

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcOpenWindow(BOOL isPCOn, CMDIFrameWnd * pParent, BOOL isHide)
{
    if(isSourceOn)    return;
    pSourceWnd = new CSourceWindow(isPCOn);                        
    DWORD dwFlag = isHide ? 0 : WS_VISIBLE;
    if(!((CSourceWindow *)pSourceWnd)->Create("SOURCE", WS_CHILD
        |WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL|dwFlag,
        CFrameWnd::rectDefault, pParent)) {
        ASSERT(0);                         
        if(LoadOpt.m_isWarnings)
            AfxMessageBox(IDS_ERR_OPENSRC);
    }
    isSourceOn = TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcResetView(void)
{
    if(isSourceOn && pSourceWnd!=NULL) 
      ((CSourceWindow *)pSourceWnd)->NewSource();
       
    if(isBrowseOn && pBrowseWnd!=NULL) 
      ((CBrowseWindow *)pBrowseWnd)->NewSource();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Update display of source window by re-disassemble
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcUpdate()
{
    if(!isSourceOn) return;
    ((CSourceWindow *)pSourceWnd)->UpdateDisp();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   SrcDispMode()
//
//  Description: Get display mode of the source window
//
//  Input:  NULL
//
//  Output: NULL
//
//  Return: -1  -- source window is not opened
//          0   -- Source Mode
//          1   -- Mixed Mode
//          2   -- Asm Mode    
//
/////////////////////////////////////////////////////////////////////////////
int SrcDispMode(void)
{
    if(!isSourceOn) return -1;
    else return ((CSourceWindow *)pSourceWnd)->m_nDispMode;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Show C source code at the specified address
//
//  Input:  
//      uAddr   --  the address
//
//  Output: NULL
//
//  Return: NULL
//
/////////////////////////////////////////////////////////////////////////////
void SrcShowSource(unsigned short uAddr)
{       
    unsigned short uLine;
    unsigned long dwModule;
    char ach[40];                 
                                              
    if(SrcIsLoaded() == -1) {   // no symbol information
        if(LoadOpt.m_isWarnings)
            AfxMessageBox(IDS_PRM_NOSYMINFO);
        return;
    }
                                                        
    if(SrcAddr2Linenum(uAddr, uLine, dwModule) != 0) {  // invalid address
        wsprintf(ach, "No source code at address: %Xh!", uAddr);        
        if(LoadOpt.m_isWarnings)
            AfxMessageBox(ach);
        return;
    }
    
    if(SrcLoadModule(dwModule, TRUE) == SRC_LOAD_ERROR) {   // load error
        return;
    }             
    
    ((CSourceWindow *)pSourceWnd)->SelectText(FALSE);
    
    if(!isSourceOn) {   //  source window hasn't been opened
        SrcOpenWindow(FALSE, 
            (CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd), TRUE);
        pSourceWnd->BringWindowToTop();
        ((CSourceWindow *)pSourceWnd)->UpdateSource(uLine - 1);
        pSourceWnd->ShowWindow(SW_SHOW);
    } else if(pSourceWnd->IsIconic()) { // source window is minimized
        ((CSourceWindow *)pSourceWnd)->UpdateSource(uLine - 1);
        pSourceWnd->ShowWindow(SW_RESTORE);
    } else {    // source window may be not on top
        ((CSourceWindow *)pSourceWnd)->UpdateSource(uLine - 1);
        pSourceWnd->BringWindowToTop();
    }        
}

/////////////////////////////////////////////////////////////////////////////
CMenu NEAR CSourceWindow::m_menu;                                            

/////////////////////////////////////////////////////////////////////////////
// CSourceWindow                                                             
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CSourceWindow, CMDIChildWnd)

/////////////////////////////////////////////////////////////////////////////         
// Constructor/Destructor
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::Create(LPCSTR szTitle, LONG style,
    const RECT& rect, CMDIFrameWnd * pParent)
{
    // Setup the shared m_menu
    if(m_menu.m_hMenu == NULL)
        m_menu.LoadMenu(IDR_SOURCE);
    m_hMenuShared = m_menu.m_hMenu;

    const char * pszSourceClass =
        AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, NULL,
            (HBRUSH)(COLOR_WINDOW+1),
            AfxGetApp()->LoadIcon(IDR_SOURCE));
    return CMDIChildWnd::Create(pszSourceClass, szTitle,
        style, rect, pParent);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CSourceWindow::CSourceWindow(BOOL isPCOn)
 : m_nFont(STANDARD_FONT), m_ptOffset(0, 0), m_rectClip(5, 5, 10, 10),
   m_isSel(FALSE/*TRUE*/)
{              
    // Set Help ID
    m_nIDHelp = IDR_SOURCE;
//    m_bOldPC=0;
    m_rectOldPC=CRect(0,0,0,0);
    // Load BP Markers
    if(m_bmpBP.LoadBitmap(IDB_BP)==FALSE)
        TRACE("Error Loading Bitmap : bp.bmp\n");
    if(m_bmpPCHandle.LoadBitmap(IDB_PC)==FALSE)
        TRACE("Error Loading Bitmap : pc.bmp\n");
    if(m_bmpBPPC.LoadBitmap(IDB_BPPC)==FALSE)
        TRACE("Error Loading Bitmap : bp.bmp\n");
        
    if(SrcEmu.GetPC())  SrcEmu.GetModule();    
                                        
    if(MdlInfo.m_uModules != 0 && MdlInfo.IsModuleOn()) {             
    // File has been downloaded, and at least one source module
    // has been loaded
        if(!isPCOn || SrcEmu.IsPCModule(MdlInfo.CurModule())) {
        // We need not mark PC or the current module is PC module,
        // then we can display on source mode
            m_nDispMode = MODE_SOURCE;
            SetStepOpt();
            //SrcEmu.m_nStepOpt = STEP_LINE;
            //m_nLeft = ::isLineNo ? 8 : 2;
            CalcLeftEdge();
            m_ptOffset.x = 0;
            m_ptIndex.x = 0;
            if(SrcEmu.IsPCModule(MdlInfo.CurModule())) {
            // The current module is PC module, we display from PC line
                m_ptIndex.y = SrcEmu.m_nPCLine;
                m_ptOffset.y = SrcEmu.m_nPCLine;            
            } else {
            // The current module is not PC module, display from first line
                m_ptIndex.y = 0;
                m_ptOffset.y = 0;            
            }
            Index2Caret();
            return;    
        }
    }                  
             
    // No file been downloaded, or no source module been loaded,             
    // then dispalay on asm mode
    long    lAddr;
    m_nDispMode = MODE_ASM;
    SetStepOpt();
    //SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    
    if(SrcEmu.m_lPCAddr < 0x10000L) lAddr = SrcEmu.m_lPCAddr;
    else    lAddr = 0;    
    if(!SrcAsm.Dsm((unsigned short)lAddr)) {
        AfxMessageBox(IDS_ERR_MEM);
    }        
    //m_nLeft = 7;           
    CalcLeftEdge();
    SrcAsm.m_nOffset = 0;
    SrcAsm.m_nIndex = 0;
    m_ptOffset.y = int(SrcEmu.m_lPCAddr) / 4;
    m_ptOffset.x = 0;
    m_ptIndex.x = 0;
    Index2Caret();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CSourceWindow::~CSourceWindow()
{
    isSourceOn = FALSE;
    
    SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
                   
    // Free BP Markers                   
    m_bmpBP.DeleteObject();
    m_bmpBPPC.DeleteObject();
}                                                           

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Update display of source window by re-disassemble
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::UpdateDisp(void)
{
    if(m_nDispMode == MODE_SOURCE)  return;
    else if(m_nDispMode == MODE_MIXED) {
        UpdateMixed(m_ptOffset.y);
    } else {
        UpdateAsm(long(m_ptOffset.y)*4);    
    }
}

/////////////////////////////////////////////////////////////////////////////
// Set window status
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ActivateFrame(int nCmdShow)
{
    CMDIChildWnd::ActivateFrame(nCmdShow);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Set Step Option
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SetStepOpt(void)
{
    if(m_nDispMode == MODE_SOURCE) {
        if(SrcEmu.m_isStatement) {
            SrcEmu.m_nStepOpt = STEP_STATEMENT;            
        } else {
            SrcEmu.m_nStepOpt = STEP_LINE;            
        }
    } else {
        SrcEmu.m_nStepOpt = STEP_INSTRUCTION;            
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Set the title of the source window
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SetTitle(void)
{
    CString   str;
    const int nLimited=30;
    
    if(m_nDispMode != MODE_ASM) {
        str = "Source: ";
        if(SRCMDL.m_strFileName.GetLength()>nLimited)
        {
          CString s=SRCMDL.m_strFileName;
          str +="...";
          while(s.GetLength()>nLimited)
          { 
            int nIdx=s.Find('\\');
            if(nIdx<0) break;
            s=s.Mid(nIdx+1);
          }
          if(s[0]!='\\')
            str+="\\";
          str+=s;  
        }
        else   
           str += SRCMDL.m_strFileName;
           
    } else {
        str = "Source: [Disassembly]";
    }                                 
    
    SetWindowText(str);
}
                                          
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Set caret position
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SetCaret(void)
{                       
    if(GetFocus() == this) {
        SetCaretPos(CPoint(Col2X(m_ptCaret.x), Row2Y(m_ptCaret.y)));
    }    
}                      

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: calculate font size
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::CalcFontSize(void)
{
    TEXTMETRIC tm;
    CDC * pDC = GetDC();
    CFont * font = (CFont *)(pDC->SelectStockObject(m_nFont));
    pDC->GetTextMetrics(&tm);
    m_szFont.cy = tm.tmHeight + tm.tmExternalLeading;
    m_szFont.cx = tm.tmAveCharWidth;
    pDC->SelectObject(font);
    ReleaseDC(pDC); 
} 

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Calculate left space left for various display mode
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::CalcLeftEdge(void)
{
    if(m_nDispMode == MODE_ASM) m_nLeft = 3+5;    // 2+4+1
    else if(::isLineNo)         m_nLeft = 3+6;    // 2+5+1
    else                        m_nLeft = 3;    // 2
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: calculate view size
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::CalcViewSize(int cx, int cy)
{                               
    // Calculate left space left for various display mode
    /*if(m_nDispMode == MODE_ASM) m_nLeft = 7;    // 2+4+1
    else if(::isLineNo)           m_nLeft = 8;    // 2+5+1
    else                        m_nLeft = 2;    // 2
    */
    CalcLeftEdge();

    m_szView.cx = (cx - m_rectClip.left) / m_szFont.cx;
    m_szView.cy = (cy - m_rectClip.top) / m_szFont.cy;

    m_rectClip.right = m_rectClip.left + m_szView.cx * m_szFont.cx;
    m_rectClip.bottom = m_rectClip.top + m_szView.cy * m_szFont.cy;

    m_rectScroll = m_rectClip;
    m_rectScroll.left += m_nLeft * m_szFont.cx;
}                                 
                      
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: calculate scroll szie                      
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::CalcScrollSize(void)
{
    SetScrollRange(SB_HORZ, 0, SourceList::MAX_LINELEN);
                                               
    if(m_nDispMode == MODE_ASM) 
        SetScrollRange(SB_VERT, 0, MAX_ASM_RANGE);
    else                                               
        SetScrollRange(SB_VERT, 0, SRCLINES);

    SetScrollPos(SB_HORZ, m_ptOffset.x);
    SetScrollPos(SB_VERT, m_ptOffset.y);
}                                                   
                                                 
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: return the start address of the line with caret on it  
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
long CSourceWindow::GetCaretAddr(void)
{    
    unsigned long dwAddr;
    AsmLine * pAsm;
    int nLine, nAsm;  
    
    if(m_nDispMode == MODE_SOURCE) {
        if(m_ptIndex.y >= SRCLINES) return 0x10000L;
        if(SrcLinenum2Addr(MdlInfo.CurModule(), 
            (unsigned short)(m_ptIndex.y + 1), dwAddr) == -1) 
            return 0x10000L;    
    } else if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nIndex >= ASMLINES) return 0x10000L;
        pAsm = (AsmLine *)(SrcAsm.GetLine(SrcAsm.m_nIndex));
        if(pAsm->m_chLabel) return 0x10000L;
        else dwAddr = pAsm->m_uAddr;    
    } else {
        if(SrcMix.m_nIndex >= MIXLINES) return 0x10000L;
        nLine = SrcMix.Ofs2Line(SrcMix.m_nIndex, nAsm); 
        if(nAsm == -1)  return 0x10000L;
        pAsm = (AsmLine *)(SrcMix.GetLine(nLine, nAsm));           
        if(pAsm->m_chLabel) return 0x10000L;
        else dwAddr = pAsm->m_uAddr;    
    }
    
    return dwAddr;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Must have been get PC & get PC module                  
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::LoadModule(unsigned long dwModule, BOOL isHist)
{   
    if(SrcLoadModule(dwModule, isHist) == SRC_LOAD_ERROR) {
        return FALSE;
    }                       
    
    SelectText(FALSE);

    if(SrcEmu.IsPCModule(MdlInfo.CurModule()))
        return UpdateSource(SrcEmu.m_nPCLine);
    else    return UpdateSource(0);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: called when download a new source                 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::NewSource(void)
{                                                  
    SelectText(FALSE);
    if(MdlInfo.IsModuleOn()) {
        if(SrcEmu.IsPCModule(MdlInfo.CurModule())) 
            UpdateSource(SrcEmu.m_nPCLine);
        else UpdateSource(0);
    } else if(SrcEmu.GetPC()) UpdateAsm(SrcEmu.m_lPCAddr);
    else UpdateAsm(0);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Update Source Window
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::UpdateSource(int nLine)
{
    ASSERT(MdlInfo.IsModuleOn());
    ASSERT(nLine >= 0 && nLine <= SRCLINES);
    
/*    if(m_nDispMode != MODE_SOURCE)
        SrcEmu.m_nStepOpt = STEP_LINE;*/
    m_nDispMode = MODE_SOURCE;
    SetStepOpt();                

    //m_nLeft = ::isLineNo ? 8 : 2;
    CalcLeftEdge();
    m_ptOffset.x = 0;
    m_ptIndex.x = 0;
    m_ptIndex.y = nLine;
    m_ptOffset.y = nLine;

    Index2Caret();

    CRect rect;
    GetClientRect(rect);
    CalcViewSize(rect.Width(), rect.Height());
    CalcScrollSize();
    InvalidateRect(NULL);          

    SetTitle();

    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::UpdateAsm(long lAddr)
{
    SelectText(FALSE);

    long lAddr1;
    
    if(lAddr > 0xFFFFL) lAddr1 = 0xFFF0;
    else lAddr1 = lAddr;
    
    if(!SrcAsm.Dsm((unsigned short)lAddr1)) {
        AfxMessageBox(IDS_ERR_MEM);
        return FALSE;
    }          

    m_nDispMode = MODE_ASM;
    //SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    SetStepOpt();
    
    //m_nLeft = 7;           
    CalcLeftEdge();
    m_ptOffset.x = 0;        
    m_ptIndex.x = 0;
    
    if(lAddr < 0x10000L) {
        SrcAsm.m_nOffset = 0;
        SrcAsm.m_nIndex = 0;  
    } else {
        SrcAsm.m_nOffset = ASMLINES;
        SrcAsm.m_nIndex = ASMLINES;  
    }
    m_ptOffset.y = int(lAddr) / 4;
    
    Index2Caret();

    CRect rect;
    GetClientRect(rect);
    CalcViewSize(rect.Width(), rect.Height());
    CalcScrollSize();
    InvalidateRect(NULL);          

    SetTitle();
    
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::UpdateMixed(int nLine)
{
    ASSERT(MdlInfo.IsModuleOn());
    ASSERT(nLine >= 0 && nLine <= SRCLINES);
    
    SelectText(FALSE);

    int nLine1;
    if(nLine < SRCLINES)    nLine1 = nLine;
    else    nLine1 = SRCLINES - 1;

    if(!SrcMix.Dsm(nLine1)) {
        AfxMessageBox(IDS_ERR_MEM);
        return FALSE;
    }
                                             
    int nOfs = nLine < SRCLINES ? 0 : MIXLINES;
                                                 
    UpdateMixedMode(nOfs);
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::UpdateMixed(long lAddr)
{
    ASSERT(lAddr >= 0 && lAddr < 0x10000L);
    
    unsigned short uLine;
    unsigned long dwModule;
    if(SrcAddr2Linenum(lAddr, uLine, dwModule) != 0)    
        return FALSE;

    if(!MdlInfo.IsModuleOn() || dwModule != MdlInfo.CurModule()) {
        if(SrcLoadModule(dwModule) == SRC_LOAD_ERROR) 
            return FALSE;
    }

    if(!SrcMix.Dsm(uLine - 1)) {
        AfxMessageBox(IDS_ERR_MEM);
        return FALSE;
    }                  
    
    int nOfs = SrcMix.Addr2Ofs((unsigned short)lAddr);
            
    UpdateMixedMode(nOfs);
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::UpdateMixedMode(int nOfs)
{
    m_nDispMode = MODE_MIXED;
    //SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    SetStepOpt();

    CRect rect;          
    GetClientRect(rect);
    CalcViewSize(rect.Width(), rect.Height());            
    CalcScrollSize();
               
    int nLine, nAsm;
    nLine = SrcMix.Ofs2Line(nOfs, nAsm);
                   
    m_ptOffset.x = 0;
    m_ptOffset.y = nLine;
    m_ptIndex.x = 0;
    SrcMix.m_nOffset = nOfs;
    SrcMix.m_nIndex = nOfs;                
    
    Index2Caret();
    InvalidateRect(NULL);
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    SetScrollPos(SB_VERT, m_ptOffset.y);
    
    SetTitle();
}

/////////////////////////////////////////////////////////////////////////////
// Char position <-> Point position                        
/////////////////////////////////////////////////////////////////////////////             
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::Row2Y(int nRow) const
{
    return  nRow * m_szFont.cy + m_rectClip.top;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::Col2X(int nCol) const
{
    return  nCol * m_szFont.cx + m_rectClip.left;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::Y2Row(int ny) const
{
    return  (ny - m_rectClip.top) / m_szFont.cy;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::X2Col(int nx) const
{
    return  (nx - m_rectClip.left) / m_szFont.cx;
}                   

/////////////////////////////////////////////////////////////////////////////
// Caret position <-> Buffer position                       
/////////////////////////////////////////////////////////////////////////////            
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::Caret2Index(void)
{                              
    m_ptIndex.x = m_ptCaret.x - m_nLeft + m_ptOffset.x;
    
    if(m_nDispMode == MODE_SOURCE)
        m_ptIndex.y = Row2Line(m_ptCaret.y); 
    else if(m_nDispMode == MODE_ASM) 
        SrcAsm.m_nIndex = Row2Line(m_ptCaret.y);
    else 
        SrcMix.m_nIndex = Row2Line(m_ptCaret.y);  
}                                           

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::Index2Caret(void)
{
    m_ptCaret.x = m_ptIndex.x + m_nLeft - m_ptOffset.x;
    
    if(m_nDispMode == MODE_SOURCE) 
        m_ptCaret.y = Line2Row(m_ptIndex.y);
    else if(m_nDispMode == MODE_ASM) 
        m_ptCaret.y = Line2Row(SrcAsm.m_nIndex);        
    else 
        m_ptCaret.y = Line2Row(SrcMix.m_nIndex);
}

/////////////////////////////////////////////////////////////////////////////         
// Line number <-> Row Number                          
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::Line2Row(int nLine) const
{                                           
    if(m_nDispMode == MODE_SOURCE)  // nLine is offset to source lines 
        return  nLine - m_ptOffset.y;
    else if(m_nDispMode == MODE_ASM)    // nLine is offset to asm lines in buffer     
        return  nLine - SrcAsm.m_nOffset;
    else    // nLine is offset to current mixed lines in buffer
        return  nLine - SrcMix.m_nOffset;
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::Row2Line(int nRow) const
{
    if(m_nDispMode == MODE_SOURCE) 
        return  nRow + m_ptOffset.y;
    else if(m_nDispMode == MODE_ASM) 
        return  nRow + SrcAsm.m_nOffset;
    else    // return offset to mixed lines
        return  nRow + SrcMix.m_nOffset;
}
                                                       
/////////////////////////////////////////////////////////////////////////////                                                       
// Hit Test
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Test if Line in view                                  
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::IsYIn(int ny) const
{                                         
    int nRow = Line2Row(ny);
    return nRow >= 0 && nRow < m_szView.cy;
}                                    
                       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: test if Col in view                                    
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::IsXIn(int nx) const
{
    return nx >= m_ptOffset.x && nx < m_ptOffset.x + m_szView.cx - m_nLeft;
}                                    
  


/////////////////////////////////////////////////////////////////////////////                                                         
// Show PC Marker
/////////////////////////////////////////////////////////////////////////////                                                         
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowPCMarker(void)
{           
    if(m_nDispMode == MODE_SOURCE) {
        ShowPCLineMarker();
    } else if(m_nDispMode == MODE_ASM) {
        ShowPCAsmMarker();
    } else {
        ShowPCMixMarker();
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowPCAsmMarker(void)
{
    ASSERT(m_nDispMode == MODE_ASM);
    //ASSERT(SrcEmu.m_nStepOpt == STEP_INSTRUCTION);
        
    int nRow, nLine;   
    
    // Clear old PC Marker                     
    if(SrcEmu.m_lPCAddr < 0x10000L) {
        nLine = SrcAsm.Addr2Line(SrcEmu.m_lPCAddr);
        if(nLine < ASMLINES) {
            nRow = Line2Row(nLine);        
            if(nRow >= 0 && nRow < m_szView.cy) {
                SrcEmu.m_lPCAddr = 0x10000L;
                UpdateRow(nRow);
            }
        }
    }
                
    // Get new PC Addr            
    if(!SrcEmu.GetPC()) return;
    
    if(SrcEmu.GetModule()) {
        if(LoadModule(SrcEmu.m_dwPCModule)) {
            //if(SrcEmu.m_nStepOpt == STEP_INSTRUCTION)
              //  SrcEmu.m_nStepOpt = STEP_LINE;
            SetStepOpt();  
            return;
        }
    }

    // PC Line is in view
    nLine = SrcAsm.Addr2Line(SrcEmu.m_lPCAddr);
    if(nLine < ASMLINES) {
        nRow = Line2Row(nLine);        
        if(nRow >= 0 && nRow < m_szView.cy) {
            SrcAsm.m_nIndex = nLine;
            Index2Caret();
            SetCaret();
            UpdateRow(nRow);  
            return;
        }
    }
                    
    // PC Line is not in view                    
    UpdateAsm(SrcEmu.m_lPCAddr);
}                            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowPCLineMarker(void)
{
    ASSERT(m_nDispMode == MODE_SOURCE);
    ASSERT(MdlInfo.IsModuleOn());
//    ASSERT(SrcEmu.m_nStepOpt == STEP_LINE);

    int nRow;                   

    // Clear old PC Marker                 
    if(SrcEmu.IsPCModule(MdlInfo.CurModule()) && 
        SrcEmu.m_nPCLine >= 0 && SrcEmu.m_nPCLine < SRCLINES) {
        nRow = Line2Row(SrcEmu.m_nPCLine);    
        if(nRow >= 0 && nRow < m_szView.cy) {
            SrcEmu.m_lPCAddr = 0x10000L;
            UpdateRow(nRow);
        }
    }    
         
    // Get new PC Addr     
    if(!SrcEmu.GetPC()) return;
    SrcEmu.GetModule();
    
    if(SrcEmu.m_nPCLine >= 0 && SrcEmu.m_dwPCModule == MdlInfo.CurModule()) {
        nRow = Line2Row(SrcEmu.m_nPCLine);
        if(nRow >= 0 && nRow < m_szView.cy) {
            m_ptIndex.y = SrcEmu.m_nPCLine;
            Index2Caret();
            SetCaret();
            UpdateRow(nRow);  
        } else UpdateSource(SrcEmu.m_nPCLine);
    } else if(SrcEmu.m_nPCLine >= 0 && 
        SrcLoadModule(SrcEmu.m_dwPCModule) != SRC_LOAD_ERROR) {
        SelectText(FALSE);
        UpdateSource(SrcEmu.m_nPCLine);                        
    } else UpdateAsm(SrcEmu.m_lPCAddr);
}   

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowPCMixMarker(void)
{
    ASSERT(m_nDispMode == MODE_MIXED);
    //ASSERT(SrcEmu.m_nStepOpt == STEP_INSTRUCTION);

    int nRow;   
    int nOfs;
    
    // Clear old PC Marker                     
    if(SrcEmu.IsPCModule(MdlInfo.CurModule()) && 
        SrcEmu.m_nPCLine >= 0 && SrcEmu.m_nPCLine < SRCLINES) {
        nOfs = SrcMix.Addr2Ofs((unsigned short)(SrcEmu.m_lPCAddr));
        if(nOfs < MIXLINES) {
            nRow = Line2Row(nOfs);        
            if(nRow >= 0 && nRow < m_szView.cy) {
                SrcEmu.m_lPCAddr = 0x10000L;
                UpdateRow(nRow);
            }
        }
    }
                
    // Get new PC Addr            
    if(!SrcEmu.GetPC()) return;
    SrcEmu.GetModule();
            
    if(SrcEmu.m_nPCLine >= 0 && SrcEmu.m_dwPCModule == MdlInfo.CurModule()) {
        nOfs = SrcMix.Addr2Ofs((unsigned short)(SrcEmu.m_lPCAddr));
        if(nOfs < MIXLINES) {
            nRow = Line2Row(nOfs);        
            if(nRow >= 0 && nRow < m_szView.cy) {
                SrcMix.m_nIndex = nOfs;
                Index2Caret();
                SetCaret();
                UpdateRow(nRow);
                return;
            }
        } 
        UpdateMixed(SrcEmu.m_lPCAddr);
    } else if(SrcEmu.m_nPCLine >= 0 && SrcLoadModule(SrcEmu.m_dwPCModule) 
        != SRC_LOAD_ERROR)
        UpdateMixed(SrcEmu.m_lPCAddr);
    else UpdateAsm(SrcEmu.m_lPCAddr);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::UpdateRow(int nRow)
{             
    ASSERT(nRow >= 0 && nRow < m_szView.cy);

    CRect   rect(CPoint(m_rectClip.left, Row2Y(nRow)),
                CSize(m_rectClip.Width(), m_szFont.cy)); 
    InvalidateRect(&rect);
}  
                        
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ClearMarker(CDC * pDC, int nRow)
{                                                 
    ASSERT(pDC);

    if(nRow < 0 || nRow >= m_szView.cy) return;

    CRect   rect(CPoint(Col2X(0), Row2Y(nRow)),
                CSize(2 * m_szFont.cx, m_szFont.cy));
    CBrush br(PALETTEINDEX(SrcColor.m_nBackground));
    pDC->FillRect(rect, &br);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SetMarker(CDC * pDC, int nRow, int nType)
{                 
    ASSERT(pDC);                               
    
    if(nRow < 0 || nRow >= m_szView.cy) return;

    CRect   rect(CPoint(Col2X(0), Row2Y(nRow)),
                CSize(3 * m_szFont.cx, m_szFont.cy));
    if(nType == MARKER_PC) {
        if(m_bmpPC.m_hObject != NULL) 
            DrawBitmap(&m_bmpPC, rect, pDC);
            
    } else if(nType == MARKER_BP) {
        if(m_bmpBP.m_hObject != NULL) 
            DrawBitmap(&m_bmpBP, rect, pDC);
        if(m_rectOldPC==rect) 
           m_bOldPC=0;

    } else if(nType == MARKER_BPPC){
        if(m_bmpBPPC.m_hObject != NULL) 
            DrawBitmap(&m_bmpBPPC, rect, pDC);
            
    } else if(nType == MARKER_PCHANDLE) {
        if(m_bOldPC)
        {
	        CBrush brush(GetSysColor(COLOR_WINDOW));
	        pDC->FillRect(&m_rectOldPC,&brush);
            m_bOldPC=0;
	    }    
        if(m_bmpPCHandle.m_hObject != NULL) 
        {                            
	        m_rectOldPC=rect;
            DrawBitmap(&m_bmpPCHandle, 
                        rect,//CRect(rect.left,rect.top,-rect.right,rect.bottom), 
                        pDC);      
        }    
   }  
 }

/////////////////////////////////////////////////////////////////////////////
// Show Line
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowSourceLine(CDC * pDC, int nRow, int nLine)
{       
    ASSERT(m_nDispMode != MODE_ASM);
    ASSERT(pDC);
    ASSERT(nRow >= 0 && nRow < m_szView.cy);
    
    if(nLine < 0 || nLine >= SRCLINES)  return;

    int ny = Row2Y(nRow);
    int nx;
    int nNext;
    BOOL bPC=0;
             
    nNext = 3;
    nx = Col2X(nNext);

    // Show Line Number    
    if(::isLineNo) {  
        char szLineNo[7];
        wsprintf(szLineNo, "%5d ", nLine + 1);
        pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nCodeLine));
        pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackground));
        pDC->TextOut(nx, ny, szLineNo);    
        nNext += 6;
        nx = Col2X(nNext);
    }
                   
    // Show Source Line                   
    int nFirst = m_ptOffset.x;
    SourceElement * p1 = SRCMDL.GetLine(nLine);
    if(!p1) return;

    // Show PC Marker                   
    if(m_nDispMode == MODE_SOURCE &&
        MdlInfo.CurModule() == SrcEmu.m_dwPCModule &&
        nLine == SrcEmu.m_nPCLine && SrcEmu.m_nStepOpt != STEP_STATEMENT) {           
        CRect rect(CPoint(m_rectScroll.left, Row2Y(nRow)),
                CSize(m_rectScroll.Width(), m_szFont.cy)); 
        CBrush br(PALETTEINDEX(SrcColor.m_nBackPCLine));        
        pDC->FillRect(rect, &br);        
        pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nForePCLine));
        pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackPCLine));
        if(p1->m_nLength > m_ptOffset.x)
            pDC->TextOut(Col2X(m_nLeft), ny, p1->m_szLine + m_ptOffset.x);
        SetMarker(pDC, nRow, MARKER_PCHANDLE);  
        m_bOldPC=1;
        bPC=1;
    } else { 
        if(p1->m_nLength == 0 || nFirst > p1->m_nLength - 1)   goto SRC_BP1;
        SyntaxColorElement * p2 = 
            (SyntaxColorElement *)(p1->m_Color.GetFirst());
        while(p2) {
            if(nFirst >= p2->m_nFirstCol && nFirst <= p2->m_nLastCol) {
                if(p2->m_nSyntaxType == CSYN_CODE || 
                    p2->m_nSyntaxType == CSYN_STRING) {
                    if(m_nDispMode == MODE_SOURCE)
                        pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nSource));
                    else
                        pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nSrcKey));
                    pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackground));
                } else if(p2->m_nSyntaxType == CSYN_KEYWORD) {
                    pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nKeyword));
                    pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackground));
                } else if(p2->m_nSyntaxType == CSYN_COMMENT) {
                    pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nComment));
                    pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackground));
                }
                pDC->TextOut(nx, ny, p1->m_szLine + nFirst, 
                    p2->m_nLastCol - nFirst + 1);
                nNext += p2->m_nLastCol - nFirst + 1;
                nFirst = p2->m_nLastCol + 1;
                nx = Col2X(nNext);
            }   
            p2 = (SyntaxColorElement *)(p1->m_Color.GetNext());
        }                 
    }                   

    // Show statement marker
    if(m_nDispMode == MODE_SOURCE &&
        MdlInfo.CurModule() == SrcEmu.m_dwPCModule &&
        nLine == SrcEmu.m_nPCLine && SrcEmu.m_nStepOpt == STEP_STATEMENT) {           
        pDC->SetTextColor(PALETTEINDEX(SrcColor.m_nForePCLine));
        pDC->SetBkColor(PALETTEINDEX(SrcColor.m_nBackPCLine));
        int nFirst, nLast;  
        if(SrcEmu.m_nPCFirst == 32767)  nFirst = p1->m_nLength - 1;
        else nFirst = /*p1->ExpandTab(*/SrcEmu.m_nPCFirst/*)*/;
        if(SrcEmu.m_nPCLast == 32767)  nLast = p1->m_nLength - 1;
        else nLast = /*p1->ExpandTab(*/SrcEmu.m_nPCLast/*)*/;          
        if(nLast >= p1->m_nLength)  nLast = p1->m_nLength - 1;
        while(nFirst < p1->m_nLength) {
            if(p1->m_szLine[nFirst] == ' ')  ++ nFirst;
            else break;
        }                                           
        while(nLast >= nFirst) {
            if(p1->m_szLine[nLast] == ' ')  -- nLast;
            else break;
        }
        if(nFirst < p1->m_nLength) {
            if(nLast < m_ptOffset.x) goto SRC_BP1 ;
            else if(nFirst >= m_ptOffset.x)
                pDC->TextOut(Col2X(nFirst - m_ptOffset.x + m_nLeft),
                    ny, p1->m_szLine + nFirst, nLast - nFirst + 1);
            else
                pDC->TextOut(Col2X(m_nLeft), ny, p1->m_szLine + m_ptOffset.x,
                    nLast - m_ptOffset.x + 1);
        }        
        SetMarker(pDC, nRow, MARKER_PCHANDLE);  
        m_bOldPC=1;
        bPC=1;
    }
    
    // Show Selected text
    if(m_isSel && m_nDispMode == MODE_SOURCE && 
        nLine == m_nSelLine) {
        pDC->SetTextColor(PALETTEINDEX(COLOR_WHITE));
        pDC->SetBkColor(PALETTEINDEX(COLOR_BLACK));
        if(m_nSelCol + m_strSel.GetLength() <= m_ptOffset.x)   goto SRC_BP1;
        else if(m_nSelCol >= m_ptOffset.x)
            pDC->TextOut(Col2X(m_nSelCol - m_ptOffset.x + m_nLeft), 
                ny, p1->m_szLine + m_nSelCol, m_strSel.GetLength());
        else
            pDC->TextOut(Col2X(m_nLeft), ny, p1->m_szLine + m_ptOffset.x, 
                m_nSelCol + m_strSel.GetLength() - m_ptOffset.x);
    } 
      
SRC_BP1:    
    // Show breakpoint 
    
    if(m_nDispMode == MODE_SOURCE) {
        unsigned long dwAddr;    
        BYTE eFlag;
        if(SrcLinenum2Addr(MdlInfo.CurModule(), (unsigned short)(nLine + 1), 
            dwAddr)==0) {                 
            if(BptSearchBpt((unsigned short)dwAddr, eFlag)) 
                if(eFlag)
                {
                   
                   if(bPC==1)
                   {  
                      SetMarker(pDC, nRow, MARKER_BPPC);
                   }
                   else
                      SetMarker(pDC, nRow, MARKER_BP);  
                }   
        }                               
    }
}                                  

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowDsmLine(CDC * pDC, int nRow, int nLine)
{
    ASSERT(m_nDispMode == MODE_ASM);
    ASSERT(pDC);
    ASSERT(nRow >= 0 && nRow < m_szView.cy);

    int ny = Row2Y(nRow);
    BOOL  bPC=0;
    
    AsmLine * pAsm = SrcAsm.GetLine(nLine);
    if(!pAsm)   return;

    if(long(pAsm->m_uAddr) == SrcEmu.m_lPCAddr && !(pAsm->m_chLabel)) {
        CRect rect(CPoint(m_rectScroll.left, Row2Y(nRow)),
                CSize(m_rectScroll.Width(), m_szFont.cy)); 
        CBrush br(PALETTEINDEX(COLOR_BLACK));        
        pDC->FillRect(rect, &br);        
        pDC->SetTextColor(PALETTEINDEX(COLOR_WHITE));
        pDC->SetBkColor(PALETTEINDEX(COLOR_BLACK));
        SetMarker(pDC, nRow, MARKER_PCHANDLE);  
        m_bOldPC=bPC=1;

    } else {
        pDC->SetTextColor(PALETTEINDEX(COLOR_BLACK));
        pDC->SetBkColor(PALETTEINDEX(COLOR_WHITE));
    }
    
    // Show Address    
    if(pAsm->m_chLabel == 0) {
        char szAddr[6];
        wsprintf(szAddr, "%04X ", pAsm->m_uAddr);
        pDC->TextOut(Col2X(3), ny, szAddr );    
    }
    
    // Show Source Line                         
    if(m_ptOffset.x < pAsm->m_strText.GetLength())
        pDC->TextOut(Col2X(m_nLeft), ny, 
            (const char *)(pAsm->m_strText) + m_ptOffset.x);
                                         
    BYTE eFlag;                                         
    if(!(pAsm->m_chLabel) && BptSearchBpt(pAsm->m_uAddr, eFlag)) 
        if(eFlag){
           SetMarker(pDC, nRow, MARKER_BP);                                             
           if(bPC==1)
           {
              SetMarker(pDC, nRow, MARKER_BPPC);
           }
           else
              SetMarker(pDC, nRow, MARKER_BP);
        }   
}       

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ShowMixedLine(CDC * pDC, int nRow, int nSrc, int nAsm)
{   
    ASSERT(m_nDispMode == MODE_MIXED);
    ASSERT(pDC);
    ASSERT(nRow >= 0 && nRow < m_szView.cy);
    BOOL bPC=0;
    if(nSrc < 0 || nSrc >= SRCLINES)    return;
    if(nAsm < 0)    return;

    int ny = Row2Y(nRow);
    AsmLine * pAsm = SrcMix.GetLine(nSrc, nAsm);
    if(!pAsm)   return;
                                                      
    char szAddr[6];
    if(pAsm->m_chLabel == 0) {
        wsprintf(szAddr, "%04X ", pAsm->m_uAddr);
    } else {
        strcpy(szAddr, "     ");
    }
    CString str(szAddr);
    str += pAsm->m_strText;
                                  
    if(long(pAsm->m_uAddr) == SrcEmu.m_lPCAddr && !(pAsm->m_chLabel)) {
        CRect rect(CPoint(m_rectScroll.left, Row2Y(nRow)),
                CSize(m_rectScroll.Width(), m_szFont.cy)); 
        CBrush br(PALETTEINDEX(COLOR_BLACK));        
        pDC->FillRect(rect, &br);        
        pDC->SetTextColor(PALETTEINDEX(COLOR_WHITE));
        pDC->SetBkColor(PALETTEINDEX(COLOR_BLACK));
        SetMarker(pDC, nRow, MARKER_PCHANDLE);
        m_bOldPC=bPC=1;
        
    } else {
        pDC->SetTextColor(PALETTEINDEX(COLOR_BLACK));
        pDC->SetBkColor(PALETTEINDEX(COLOR_WHITE));
    }

    if(m_ptOffset.x < pAsm->m_strText.GetLength() + 5)
        pDC->TextOut(Col2X(m_nLeft), ny, (const char *)str + m_ptOffset.x);
                                           
    BYTE eFlag;                                           
    if(!(pAsm->m_chLabel) && BptSearchBpt(pAsm->m_uAddr, eFlag)) 
        if(eFlag){                        
           if(bPC==1)
           {        
              SetMarker(pDC, nRow, MARKER_BPPC);
              m_bOldPC=0;
           }
           else                                 
           {                                    
              SetMarker(pDC, nRow, MARKER_BP);
           }   
        }   
}                           

/////////////////////////////////////////////////////////////////////////////
// Scroll viewport                                                 
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUp(void)
{
    if(m_nDispMode == MODE_SOURCE) {
        if(m_ptOffset.y > 0) {
            -- m_ptOffset.y;
            ScrollWindow(0, m_szFont.cy, &m_rectClip, &m_rectClip);
        }
    } else if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nOffset == 0 && SrcAsm.IsHome()) return;
        if(SrcAsm.m_nOffset > 0) {
            -- SrcAsm.m_nOffset;
            ScrollWindow(0, m_szFont.cy, &m_rectClip, &m_rectClip);
        } else {              
            long lAddr = SrcAsm.Line2AddrL(SrcAsm.m_nOffset);
            if(!SrcAsm.DsmPrev()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();
            SrcAsm.m_nOffset = SrcAsm.MatchAddr2LineL(lAddr);
            if(SrcAsm.m_nOffset > 0) {
                -- SrcAsm.m_nOffset;
                ScrollWindow(0, m_szFont.cy, &m_rectClip, &m_rectClip);
            }
        }    
        m_ptOffset.y = int(SrcAsm.Line2AddrL(SrcAsm.m_nOffset) / 4);
    } else {          
        if(SrcMix.m_nOffset == 0 && SrcMix.IsHome()) return;
        int nSrc, nAsm;
        if(SrcMix.m_nOffset > 0) {
            -- SrcMix.m_nOffset;
        } else {
            nSrc = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
            if(!SrcMix.DsmPrev()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();                            
            SrcMix.m_nOffset = SrcMix.Line2Ofs(nSrc, nAsm);            
            -- SrcMix.m_nOffset;
        }   
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        ScrollWindow(0, m_szFont.cy, &m_rectClip, &m_rectClip);
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnDown(void)
{
    if(m_nDispMode == MODE_SOURCE) {
        if(m_ptOffset.y < SRCLINES) {
            ++ m_ptOffset.y;
            ScrollWindow(0, -m_szFont.cy, &m_rectClip, &m_rectClip);
        }
    } else if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nOffset >= ASMLINES && SrcAsm.IsEnd())   
            return;                           
        if(SrcAsm.m_nOffset + m_szView.cy < ASMLINES || 
            SrcAsm.IsEnd()) {   
            if(SrcAsm.m_nOffset < ASMLINES) {
                ++ SrcAsm.m_nOffset;   
                ScrollWindow(0, -m_szFont.cy, &m_rectClip, &m_rectClip);
            }
        } else {
            long lAddr = SrcAsm.Line2AddrL(SrcAsm.m_nOffset);
            if(!SrcAsm.DsmNext()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();
            SrcAsm.m_nOffset = SrcAsm.MatchAddr2LineL(lAddr); 
            if(SrcAsm.m_nOffset < ASMLINES) {
                ++ SrcAsm.m_nOffset;   
                ScrollWindow(0, -m_szFont.cy, &m_rectClip, &m_rectClip);
            }
        }    
        m_ptOffset.y = int(SrcAsm.Line2AddrL(SrcAsm.m_nOffset) / 4);
    } else {                    
        if(SrcMix.m_nOffset >= MIXLINES && SrcMix.IsEnd())  return;
        int nSrc, nAsm;    
        if(SrcMix.m_nOffset + m_szView.cy < MIXLINES || SrcMix.IsEnd()) {
            ++ SrcMix.m_nOffset;
        } else {
            nSrc = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
            if(!SrcMix.DsmNext()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();
            SrcMix.m_nOffset = SrcMix.Line2Ofs(nSrc, nAsm);            
            ++ SrcMix.m_nOffset;
        }
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        ScrollWindow(0, -m_szFont.cy, &m_rectClip, &m_rectClip);
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnLeft(void)
{
    if(m_ptOffset.x > 0) {
        -- m_ptOffset.x;
        ScrollWindow(m_szFont.cx, 0, &m_rectScroll, &m_rectScroll);
    }
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRight(void)
{
    if(m_ptOffset.x < SourceList::MAX_LINELEN) {
        ++ m_ptOffset.x;
        ScrollWindow(-m_szFont.cx, 0, &m_rectScroll, &m_rectScroll);
    }
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnPgUp(void)
{                         
    int nPage = 0;
    
    if(m_nDispMode == MODE_SOURCE) {
        if(m_ptOffset.y >= m_szView.cy) nPage = m_szView.cy;
        else nPage = m_ptOffset.y;
        m_ptOffset.y -= nPage;
        ScrollWindow(0, m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
    } else if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nOffset == 0 && SrcAsm.IsHome()) return;
        if(SrcAsm.m_nOffset > m_szView.cy) {
            SrcAsm.m_nOffset -= m_szView.cy;
            ScrollWindow(0, m_szFont.cy * m_szView.cy, &m_rectClip, &m_rectClip);
        } else if(SrcAsm.IsHome()) { 
            nPage = SrcAsm.m_nOffset;
            SrcAsm.m_nOffset = 0;
            ScrollWindow(0, m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
        } else {              
            long lAddr = SrcAsm.Line2AddrL(SrcAsm.m_nOffset);
            if(!SrcAsm.DsmPrev()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();
            SrcAsm.m_nOffset = SrcAsm.MatchAddr2LineL(lAddr);
            if(SrcAsm.m_nOffset > m_szView.cy) {
                nPage = m_szView.cy;
                SrcAsm.m_nOffset -= m_szView.cy;
            } else {
                nPage = SrcAsm.m_nOffset;
                SrcAsm.m_nOffset = 0;
            }
            ScrollWindow(0, m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
        }    
        m_ptOffset.y = int(SrcAsm.Line2AddrL(SrcAsm.m_nOffset) / 4);
    } else {                               
        int nSrc, nAsm;
        if(SrcMix.m_nOffset == 0 && SrcMix.IsHome())    return;
        else if(SrcMix.m_nOffset < m_szView.cy && !SrcMix.IsHome()) {
            nSrc = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
            if(!SrcMix.DsmPrev()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();        
            SrcMix.m_nOffset = SrcMix.Line2Ofs(nSrc, nAsm);            
        }
        if(SrcMix.m_nOffset >= m_szView.cy) 
            nPage = m_szView.cy;
        else  
            nPage = SrcMix.m_nOffset;
        SrcMix.m_nOffset -= nPage;
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        ScrollWindow(0, m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnPgDn(void)
{
    int nPage = 0;
    
    if(m_nDispMode == MODE_SOURCE) {
        if(m_ptOffset.y <= SRCLINES - m_szView.cy) nPage = m_szView.cy;
        else nPage = SRCLINES - m_ptOffset.y;
        m_ptOffset.y += nPage;
        ScrollWindow(0, -m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
    } else if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nOffset >= ASMLINES && SrcAsm.IsEnd())   
            return;                           
        if(SrcAsm.m_nOffset + m_szView.cy * 2 < ASMLINES || 
            SrcAsm.IsEnd()) {   
            if(SrcAsm.m_nOffset + m_szView.cy < ASMLINES) {
                nPage = m_szView.cy;
                SrcAsm.m_nOffset += m_szView.cy;   
            } else {
                nPage = ASMLINES - SrcAsm.m_nOffset;
                SrcAsm.m_nOffset = ASMLINES;            
            }    
            ScrollWindow(0, -m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
        } else {
            long lAddr = SrcAsm.Line2AddrL(SrcAsm.m_nOffset);
            if(!SrcAsm.DsmNext()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();
            SrcAsm.m_nOffset = SrcAsm.MatchAddr2LineL(lAddr); 
            if(SrcAsm.m_nOffset + m_szView.cy < ASMLINES) {
                nPage = m_szView.cy;
                SrcAsm.m_nOffset += m_szView.cy;   
            } else {
                nPage = ASMLINES - SrcAsm.m_nOffset;
                SrcAsm.m_nOffset = ASMLINES;            
            }    
            ScrollWindow(0, -m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
        }    
        m_ptOffset.y = int(SrcAsm.Line2AddrL(SrcAsm.m_nOffset) / 4);
    } else {                        
        int nSrc, nAsm;
        if(SrcMix.m_nOffset + 2 * m_szView.cy > MIXLINES && !SrcMix.IsEnd()) {
            nSrc = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
            if(!SrcMix.DsmNext()) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();                                             
            SrcMix.m_nOffset = SrcMix.Line2Ofs(nSrc, nAsm);
        }
        if(SrcMix.m_nOffset + m_szView.cy <= MIXLINES) 
            nPage = m_szView.cy;
        else 
            nPage = MIXLINES - SrcMix.m_nOffset;
        SrcMix.m_nOffset += nPage;
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        ScrollWindow(0, -m_szFont.cy * nPage, &m_rectClip, &m_rectClip);
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnPgLeft(void)
{                         
    int nPage = 0;
    if(m_ptOffset.x >= m_szView.cx - m_nLeft) 
        nPage = m_szView.cx - m_nLeft;
    else nPage = m_ptOffset.x;
    m_ptOffset.x -= nPage;
    ScrollWindow(m_szFont.cx * nPage, 0, &m_rectScroll, &m_rectScroll);
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnPgRight(void)
{
    int nPage = 0;
    if(m_ptOffset.x <= SourceList::MAX_LINELEN - m_szView.cx + m_nLeft) 
        nPage = m_szView.cx - m_nLeft;
    else nPage = SourceList::MAX_LINELEN - m_ptOffset.x + m_nLeft;
    m_ptOffset.x += nPage;
    ScrollWindow(-m_szFont.cx * nPage, 0, &m_rectScroll, &m_rectScroll);
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnHome(void)
{
    ScrollWindow(m_szFont.cx * m_ptOffset.x, 0, 
        &m_rectScroll, &m_rectScroll);
    m_ptOffset.x = 0;
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: return right most index,-1 means no text in this line
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::OnEnd(void)
{                                   
    int n1, n2;
    if(m_nDispMode == MODE_SOURCE) {
        SourceElement * p = SRCMDL.GetLine(m_ptIndex.y);
        if(!p)  return -1;
        else n1 = p->m_nLength;
    } else if(m_nDispMode == MODE_ASM) {
        AsmLine * p = SrcAsm.GetLine(SrcAsm.m_nIndex);
        if(!p)  return -1;
        else n1 = p->m_strText.GetLength();
    } else {           
        int nSrc, nAsm;
        nSrc = SrcMix.Ofs2Line(SrcMix.m_nIndex, nAsm);     
        if(nAsm == -1) {
            SourceElement * p = SRCMDL.GetLine(nSrc);
            if(!p)  return -1;
            else n1 = p->m_nLength;
        } else {
            AsmLine * p = SrcMix.GetLine(nSrc, nAsm);
            if(!p)  return -1;
            else n1 = p->m_strText.GetLength() + 5;
        }
    }
        
    if(n1 >= SourceList::MAX_LINELEN)    n1 = SourceList::MAX_LINELEN - 1;
    if(!IsXIn(n1)) {
        n2 = n1 - m_szView.cx + m_nLeft + 1;
        if(n2 < 0)  n2 = 0;
        HorzScroll(n2);
    }     
    
    return  n1;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpMost(void)
{
    if(m_nDispMode == MODE_SOURCE) {
        ScrollWindow(0, m_szFont.cy * m_ptOffset.y, 
            &m_rectClip, &m_rectClip);
        m_ptOffset.y = 0;
    } else if(m_nDispMode == MODE_ASM) {
        return;    
    } else {
        if(!SrcMix.Dsm(0)) {
            AfxMessageBox(IDS_ERR_MEM);
            return;
        } else Invalidate();                            
        SrcMix.m_nOffset = 0;                                
        int nAsm;
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        InvalidateRect(&m_rectClip);    
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnDownMost(void)
{
    if(m_nDispMode == MODE_SOURCE) {
        ScrollWindow(0, -m_szFont.cy * (SRCLINES - m_ptOffset.y), 
            &m_rectClip, &m_rectClip);
        m_ptOffset.y = SRCLINES;
    } else if(m_nDispMode == MODE_ASM) {
        return;    
    } else {
        if(!SrcMix.Dsm(SRCLINES - 1)) {
            AfxMessageBox(IDS_ERR_MEM);
            return;
        } else Invalidate();                           
        SrcMix.m_nOffset = MIXLINES;                          
        int nAsm;
        m_ptOffset.y = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
        InvalidateRect(&m_rectClip);    
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::HorzScroll(int nx)
{
    ScrollWindow(m_szFont.cx * (m_ptOffset.x - nx), 0, 
        &m_rectScroll, &m_rectScroll);
    m_ptOffset.x = nx;
    
    SetScrollPos(SB_HORZ, m_ptOffset.x);
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::VertScroll(int ny)
{
    if(m_nDispMode == MODE_SOURCE) {
        ScrollWindow(0, m_szFont.cy * (m_ptOffset.y - ny), 
            &m_rectClip, &m_rectClip);
        m_ptOffset.y = ny;
    } else if(m_nDispMode == MODE_ASM) {
        unsigned k = (ny == 0x4000) ? 4 * (unsigned(ny) - 16) : 
            4 * unsigned(ny);
        if(!SrcAsm.Dsm((unsigned short)k)) {
            AfxMessageBox(IDS_ERR_MEM);
            return;
        } else Invalidate();                            
        SrcAsm.m_nOffset = SrcAsm.MatchAddr2LineL(long(ny) * 4);
        m_ptOffset.y = ny;
        InvalidateRect(&m_rectClip);
    } else {
        m_ptOffset.y = ny >= SRCLINES ? SRCLINES - 1 : ny;
        if(!SrcMix.Dsm(m_ptOffset.y)) {
            AfxMessageBox(IDS_ERR_MEM);
            return;
        } else Invalidate();                           
        SrcMix.m_nOffset = SrcMix.Line2Ofs(m_ptOffset.y, -1);
        InvalidateRect(&m_rectClip);    
    }
    
    SetScrollPos(SB_VERT, m_ptOffset.y);
    Caret2Index();
} 

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::ScrollTo(int nLine, int nCol, int nLen, BOOL isLeft)
{                              
    ASSERT(m_nDispMode == MODE_SOURCE);
    
    if(!IsYIn(nLine))   VertScroll(nLine);                                     
            
    if(IsXIn(nCol) && IsXIn(nCol + nLen))   return;        

    if(isLeft) {
        if(!IsXIn(nCol))    HorzScroll(nCol);
    } else {
        int n = nCol + nLen - m_szView.cx + m_nLeft + 1;
        if(n < 0)   n = 0;
        HorzScroll(n);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Search Text
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::Search(void)
{                             
    int nLine = m_ptIndex.y, nCol = m_ptIndex.x;
    if(nLine < 0 || nLine >= SRCLINES)
        nLine = 0; 
    
    BOOL isRval;
    if(SrcSrchData.m_nUp == 0) {            // Up
        isRval = SRCMDL.SearchBefore(nLine, nCol, 0);
        if(isRval == FALSE) {
            MessageBeep(-1);
            return  FALSE;
        }
    } else if(SrcSrchData.m_nUp == 1) {     // Down
        isRval = SRCMDL.SearchAfter(nLine, nCol, SRCLINES - 1);
        if(isRval == FALSE) {
            MessageBeep(-1);
            return  FALSE;
        }
    } else {                                // All
        isRval = SRCMDL.SearchAfter(nLine, nCol, SRCLINES - 1);
        if(isRval == FALSE) isRval = SRCMDL.SearchAfter(0, 0, nLine);
        if(isRval == FALSE) {
            MessageBeep(-1);
            return  FALSE;
        } else {
            if(SrcSrchData.m_isFirst == TRUE) {
                SrcSrchData.m_isFirst = FALSE;
                SrcSrchData.m_nInitLine = SrcSrchData.m_nCurLine;
                SrcSrchData.m_nInitCol  = SrcSrchData.m_nCurCol;
            }/*else if(SrcSrchData.m_nCurLine == SrcSrchData.m_nInitLine &&
                SrcSrchData.m_nCurCol == SrcSrchData.m_nInitCol) {                                
                MessageBeep(-1);
                return  FALSE;  
                
            }*/
        } 
    }
    if(SrcSrchData.m_nUp == 0) {    
        ScrollTo(SrcSrchData.m_nCurLine, SrcSrchData.m_nCurCol, 
            SrcSrchData.m_strText.GetLength(), TRUE);
        m_ptIndex.x = SrcSrchData.m_nCurCol+SrcSrchData.m_strText.GetLength();
    } else {
        ScrollTo(SrcSrchData.m_nCurLine, SrcSrchData.m_nCurCol, 
            SrcSrchData.m_strText.GetLength(), FALSE);
        m_ptIndex.x = SrcSrchData.m_nCurCol + 
            SrcSrchData.m_strText.GetLength();
    }       
    m_ptIndex.y = SrcSrchData.m_nCurLine;

    Index2Caret();
    SetCaret();
    return  TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Hilite text found by search command
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SelectText(BOOL isSel)
{                  
    if(m_nDispMode != MODE_SOURCE)  return;

    //int nRow = Line2Row(SrcSrchData.m_nCurLine);
    int nRow = Line2Row(m_nSelLine);
    if(isSel) { 
        if(m_isSel) SelectText(FALSE);
        m_isSel = TRUE;
    } else {
        m_isSel = FALSE;
    }
    if(nRow >= 0 && nRow < m_szView.cy) UpdateRow(nRow);
}                                  
                                                         
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Set Breakpoint
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::SetBreakpoint(int nRow)
{       
    AsmLine * pAsm;
    int nLine = Row2Line(nRow);
    unsigned long dwAddr;  
    BYTE eFlag;
    if(m_nDispMode == MODE_SOURCE) {
        if(nLine >= SRCLINES)   return;
        if(SrcLinenum2Addr(MdlInfo.CurModule(), (unsigned short)(nLine + 1), 
            dwAddr) == 0) {
            if(BptSearchBpt((unsigned short)dwAddr, eFlag)) {
                if(eFlag) BptClrOneBptfromWnd((unsigned short)dwAddr);
                else if(!BptEnableBpt((unsigned short)dwAddr)) return;
            } else if(!BptAddBptfromWnd((unsigned short)dwAddr)) return;
        }
    } else if(m_nDispMode == MODE_ASM) {
        if(nLine >= ASMLINES)   return;
        pAsm = (AsmLine *)SrcAsm.GetLine(nLine);
        if(pAsm->m_chLabel) return;          
        if(BptSearchBpt(pAsm->m_uAddr, eFlag)) {
            if(eFlag)   BptClrOneBptfromWnd(pAsm->m_uAddr);
            else if(!BptEnableBpt(pAsm->m_uAddr)) return;
        } else if(!BptAddBptfromWnd(pAsm->m_uAddr))    return;
    } else {
        if(nLine >= MIXLINES)   return;            
        int nSrc, nAsm;
        nSrc = SrcMix.Ofs2Line(nLine, nAsm);
        if(nAsm == -1)  return;
        pAsm = (AsmLine *)SrcMix.GetLine(nSrc, nAsm);
        if(pAsm->m_chLabel) return;          
        if(BptSearchBpt(pAsm->m_uAddr, eFlag)) {
            if(eFlag)   BptClrOneBptfromWnd(pAsm->m_uAddr);
            else if(!BptEnableBpt(pAsm->m_uAddr)) return;
        } else if(!BptAddBptfromWnd(pAsm->m_uAddr))    return;
    }         
    UpdateRow(nRow);
}                      

BOOL CSourceWindow::PreTranslateMessage(MSG *pMsg)
{                   
  if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)
  {                
	if(GetFocus()!=this)
	   pSourceWnd->PostMessage(WM_COMMAND,ID_EDIT_SEARCHNEXT);
  }
  return CMDIChildWnd::PreTranslateMessage(pMsg);
}
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CSourceWindow, CMDIChildWnd)
    //{{AFX_MSG_MAP(CSourceWindow)
    ON_CBN_KILLFOCUS(IDC_SRCHCOMBO, OnSrchComboKillFocus)
    ON_MESSAGE(XM_SRCSHOWPC, OnXMSrcShowPC)
    ON_MESSAGE(XM_REPAINT, OnXMRepaint)
    ON_WM_CHILDACTIVATE()
    ON_WM_MDIACTIVATE()
    ON_WM_SETCURSOR()
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_VSCROLL()
    ON_WM_HSCROLL()
    ON_WM_KEYDOWN()  
    ON_WM_KEYUP()
    ON_WM_KILLFOCUS()
    ON_WM_LBUTTONDOWN()
    ON_WM_PAINT()
    ON_WM_RBUTTONDOWN()
    ON_WM_SETFOCUS()
    ON_COMMAND(ID_EDIT_BROWSEFROMADDRESS, OnEditBrowsefromaddress)
    ON_COMMAND(ID_EDIT_BROWSEFROMLINE, OnEditBrowsefromline)
    ON_COMMAND(ID_EDIT_BROWSEFROMPC, OnEditBrowsefrompc)
    ON_COMMAND(ID_EDIT_SEARCH, OnEditSearch)
    ON_COMMAND(ID_EDIT_SEARCHNEXT, OnEditSearchnext)
    ON_COMMAND(ID_FILE_LOADINFO, OnFileLoadinfo)
    ON_COMMAND(ID_FILE_PREVMODULE, OnFilePrevmodule)
    ON_COMMAND(ID_FILE_NEXTMODULE, OnFileNextmodule)
    ON_COMMAND(ID_OPTIONS_SOURCEEXTENSIONNAMES, OnOptionsSourceextensionnames)
    ON_COMMAND(ID_OPTIONS_SOURCEOPTIONS, OnOptionsSourceoptions)
    ON_COMMAND(ID_OPTIONS_SOURCEPATH, OnOptionsSourcepath)
    ON_COMMAND(ID_RUN_GOTOCURSOR, OnRunGotocursor)
    ON_COMMAND(ID_RUN_GOFROMCURSOR, OnRunGofromcursor)
    ON_COMMAND(ID_RUN_JUMPTOCURSOR, OnRunJumptocursor)
    ON_COMMAND(ID_VIEW_SOURCEONLY, OnViewSourceonly)
    ON_COMMAND(ID_VIEW_MIXED, OnViewMixed)
    ON_UPDATE_COMMAND_UI(ID_VIEW_MIXED, OnUpdateViewMixed)
    ON_UPDATE_COMMAND_UI(ID_VIEW_SOURCEONLY, OnUpdateViewSourceonly)
    ON_COMMAND(ID_VIEW_SYMBOLICDISASSEMBLY, OnViewSymbolicdisassembly)
    ON_UPDATE_COMMAND_UI(ID_VIEW_SYMBOLICDISASSEMBLY, OnUpdateViewSymbolicdisassembly)
    ON_COMMAND(ID_VIEW_LINENUMBERING, OnViewLinenumbering)
    ON_UPDATE_COMMAND_UI(ID_VIEW_LINENUMBERING, OnUpdateViewLinenumbering)
    ON_COMMAND(ID_VIEW_SYNTAXCOLORING, OnViewSyntaxcoloring)
    ON_UPDATE_COMMAND_UI(ID_VIEW_SYNTAXCOLORING, OnUpdateViewSyntaxcoloring)
    ON_WM_MOUSEMOVE()
    ON_UPDATE_COMMAND_UI(ID_EDIT_SEARCH, OnUpdateEditSearch)
    ON_UPDATE_COMMAND_UI(ID_EDIT_BROWSEFROMLINE, OnUpdateEditBrowsefromline)
    ON_UPDATE_COMMAND_UI(ID_EDIT_SEARCHNEXT, OnUpdateEditSearchnext)
    ON_WM_CLOSE()
    ON_UPDATE_COMMAND_UI(ID_FILE_PREVMODULE, OnUpdateFilePrevmodule)
    ON_UPDATE_COMMAND_UI(ID_FILE_NEXTMODULE, OnUpdateFileNextmodule)
    ON_COMMAND(ID_FILE_BROWSEMODULE, OnFileBrowsemodule)
    ON_UPDATE_COMMAND_UI(ID_FILE_BROWSEMODULE, OnUpdateFileBrowsemodule)
    ON_COMMAND(ID_FILE_LOAD, OnFileLoad)
    ON_COMMAND(ID_RUN_BREAKPOINT, OnRunBreakpoint)
//    ON_COMMAND(ID_RUN_SETBP, OnRunSetBP)
    ON_COMMAND(ID_RUN_JUMP, OnRunJump)
    ON_COMMAND(ID_RUN_RESET, OnRunReset)
    ON_COMMAND(ID_VIEW_SMA, OnViewSma)
    ON_COMMAND(ID_SHIFTRETURN, OnShiftreturn)
    ON_COMMAND(IDM_SETBP_FUNC, OnSetBPFunc)
    ON_COMMAND(IDM_CLRBP_FUNC, OnClrBPFunc)
    ON_COMMAND(IDM_SETBP_VAR, OnSetBPVar)
    ON_COMMAND(IDM_CLRBP_VAR, OnClrBPVar)
    ON_COMMAND(IDM_LOAD_ADDR, OnShowLoadAddr)
    ON_COMMAND(IDM_WATCH_VAR, OnWatchVariable)
    ON_COMMAND(IDM_INSPECT_FUNC, OnInspectFunc)
    ON_WM_LBUTTONDBLCLK()
    ON_UPDATE_COMMAND_UI(IDC_SRCHCOMBO, OnUpdateSearchCombo)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CSourceWindow message handlers
/*
void CSourceWindow::OnRunSetBP()
{                            
    int nRow;    
    if(m_rectClip.PtInRect(m_ptCaret) && !m_rectScroll.PtInRect(m_ptCaret)) {
        nRow = Y2Row(m_ptCaret.y);
        if(nRow >= 0 && nRow < m_szView.cy)
            SetBreakpoint(nRow);            
    }        
} 
*/                           
/////////////////////////////////////////////////////////////////////////////
// Tool Bar Message Handler -- Search ComboBox                            
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnSrchComboKillFocus(void)
{   
    CMainFrame * pMain = (CMainFrame *)AfxGetApp()->m_pMainWnd;
    CString str = pMain->m_wndToolBar.GetSrchEditText();    
    if(str != "") { 
        pMain->m_wndToolBar.AddSrchText(str);
        SrcSrchData.AddNew(str);       
        SrcSrchData.m_strText = str;
    } else {
        SrcSrchData.m_strText = "";
    }
}

/////////////////////////////////////////////////////////////////////////////
// User Defined Message Handler -- Show PC Marker
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
LONG CSourceWindow::OnXMRepaint(UINT /*wParam*/, LONG /*lParam*/)
{
    Invalidate(); 
    return  0;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
LONG CSourceWindow::OnXMSrcShowPC(UINT /*wParam*/, LONG /*lParam*/)
{             
    ShowPCMarker();   
    return  0;
}
                                                 
/////////////////////////////////////////////////////////////////////////////
// Windows Standard Message Handler
/////////////////////////////////////////////////////////////////////////////                                                 
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::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->SendMessage(XM_MDIACTIVE, WORD(bActivate), 
            LONG(WID_SOURCE));
    else if(!bActivate && !pActivateWnd)
        AfxGetApp()->m_pMainWnd->SendMessage(XM_MDIACTIVE, WORD(bActivate)); 
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::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);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CSourceWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: Add your specialized creation code here
    
    CalcFontSize();       

    SetTitle();
    return 0;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnSize(UINT nType, int cx, int cy)
{
    CMDIChildWnd::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
    CalcViewSize(cx, cy);            
    CalcScrollSize();        
    
    if(m_nDispMode == MODE_ASM) {
        if(SrcAsm.m_nOffset + m_szView.cy < ASMLINES) {                  
            AsmLine * pAsm = (AsmLine *)(SrcAsm.GetLine(SrcAsm.m_nOffset));
            unsigned short uAddr = pAsm->m_uAddr;
            char chLabel = pAsm->m_chLabel;
            if(!SrcAsm.Dsm(uAddr)) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();                            
            pAsm = (AsmLine *)(SrcAsm.GetLine(0));
            if(pAsm->m_chLabel == chLabel)  SrcAsm.m_nOffset = 0;
            else SrcAsm.m_nOffset = 1;
            m_ptOffset.y = uAddr / 4;
            InvalidateRect(&m_rectClip);         
            SetScrollPos(SB_VERT, m_ptOffset.y);
        } 
    } else if(m_nDispMode == MODE_MIXED) {
        if(m_ptOffset.y < SRCLINES) {
            int nAsm;
            SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);
            if(!SrcMix.Dsm(m_ptOffset.y)) {
                AfxMessageBox(IDS_ERR_MEM);
                return;
            } else Invalidate();                           
            SrcMix.m_nOffset = SrcMix.Line2Ofs(m_ptOffset.y, nAsm);
            InvalidateRect(&m_rectClip);    
        }
    }
    
    
    m_ptCaret.x = m_nLeft;
    m_ptCaret.y = 0;
    Caret2Index();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    if(m_nDispMode == MODE_SOURCE) {
        if(!MdlInfo.IsModuleOn() || SRCLINES == 0)   return;
    } else if(m_nDispMode == MODE_MIXED) {
        if(!MdlInfo.IsModuleOn() || MIXLINES == 0)   return;
    } else {    
        if(ASMLINES == 0) return;
    }     
    
    switch(nSBCode) {
        case SB_LINEUP:  
            OnUp();
            break;
        case SB_LINEDOWN:
            OnDown();
            break;
        case SB_PAGEUP: 
            OnPgUp();
            break;
        case SB_PAGEDOWN:
            OnPgDn();
            break;
        case SB_THUMBPOSITION:           
            VertScroll(nPos);
            break;
        case SB_THUMBTRACK:
            if(m_nDispMode == MODE_SOURCE) VertScroll(nPos);
            break;
    }          
                  
    CMDIChildWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    if(m_nDispMode == MODE_SOURCE) {
        if(!MdlInfo.IsModuleOn() || SRCLINES == 0)   return;
    } else if(m_nDispMode == MODE_MIXED) {
        if(!MdlInfo.IsModuleOn() || MIXLINES == 0)   return;
    } else {    
        if(ASMLINES == 0) return;
    }     
    
    switch(nSBCode) {
        case SB_LINELEFT:
            OnLeft();
            break;
        case SB_LINERIGHT:
            OnRight();
            break;     
        case SB_PAGELEFT: 
            OnPgLeft();
            break;
        case SB_PAGERIGHT:
            OnPgRight();
            break;
        case SB_THUMBPOSITION:           
            HorzScroll(nPos);
            break;
        case SB_THUMBTRACK:
            HorzScroll(nPos);
            break;
    }          

    CMDIChildWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{                                                 
  m_nbCanDo=0;
  CMDIChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}             

void CSourceWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: Add your message handler code here and/or call default
    if(m_nbCanDo>0)
       return;
    else
       m_nbCanDo=1;
    
    if(m_nDispMode == MODE_SOURCE) {
        if(!MdlInfo.IsModuleOn() || SRCLINES == 0)   return;
    } else if(m_nDispMode == MODE_MIXED) {
        if(!MdlInfo.IsModuleOn() || MIXLINES == 0)   return;
    } else {    
        if(ASMLINES == 0) return;
    }     
    
    SelectText(FALSE);
    
    int nState = GetKeyState(VK_CONTROL) & 0x8000;  
    int nTmp;
        
    switch(nChar)
    {
        case VK_HOME:
            OnHome();
            m_ptIndex.x = 0;
            Index2Caret();
            if(nState && m_nDispMode != MODE_ASM) {    // Ctrl+Home              
                OnUpMost();
                m_ptCaret.y = 0;
                Caret2Index();
            }
            break;
    
        case VK_END:                                              
            if(!nState) {
                nTmp = OnEnd();
                if(nTmp != -1)  m_ptIndex.x = nTmp;
            } else if(m_nDispMode != MODE_ASM) {    // Ctrl+End
                OnHome();
                OnDownMost();
                m_ptIndex.x = 0;  
                if(m_nDispMode == MODE_SOURCE)  
                    m_ptIndex.y = SRCLINES;
                else if(m_nDispMode == MODE_MIXED)   
                    SrcMix.m_nIndex = MIXLINES;
            }       
            break;              
            
        case VK_LEFT:
            if(m_ptCaret.x > m_nLeft) {
                -- m_ptCaret.x;
                Caret2Index();
            } else{
             OnLeft();
             m_nbCanDo=2;
            } 
            break;              
            
        case VK_RIGHT:
            if(m_ptCaret.x < m_szView.cx - 1) {
                ++ m_ptCaret.x;
                Caret2Index();
            } else{
            OnRight();
            m_nbCanDo=2;
            }
            break;              
            
        case VK_UP:
            if(m_ptCaret.y > 0) {
                -- m_ptCaret.y;
                Caret2Index();
            } else{
            OnUp();
            m_nbCanDo=2;
            }
            break;

        case VK_DOWN:
            if(m_ptCaret.y < m_szView.cy - 1) {
                ++ m_ptCaret.y;
                Caret2Index();
            } else{
            OnDown();
            m_nbCanDo=2;
            }
            break;    
            
        case VK_PRIOR:
            if(!nState) {
                OnPgUp();
                Caret2Index();
            }
            break;
        
        case VK_NEXT:
            if(!nState) {
                OnPgDn();
                Caret2Index();
            }
            break;
    }
    
    Index2Caret();
    SetCaret();
    m_nbCanDo--;

    CMDIChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnKillFocus(CWnd* pNewWnd)
{
    CMDIChildWnd::OnKillFocus(pNewWnd);
    
    // TODO: Add your message handler code here
    DestroyCaret();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    SetFocus();
    SelectText(FALSE);
    
    CPoint  pt = point;

    if(point.x < m_rectScroll.left)         pt.x = m_rectScroll.left;
    if(point.x > m_rectScroll.right - 1)    pt.x = m_rectScroll.right - 1;
    if(point.y < m_rectScroll.top)          pt.y = m_rectScroll.top;
    if(point.y > m_rectScroll.bottom - 1)   pt.y = m_rectScroll.bottom - 1;
    
    m_ptCaret.x = X2Col(pt.x);
    m_ptCaret.y = Y2Row(pt.y);

    Caret2Index();
    SetCaret();           
        
    int nRow;    
    if(m_rectClip.PtInRect(point) && !m_rectScroll.PtInRect(point)) {
        nRow = Y2Row(point.y);
        if(nRow >= 0 && nRow < m_szView.cy)
            SetBreakpoint(nRow);            
    }
        
    CMDIChildWnd::OnLButtonDown(nFlags, point);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnPaint()
{                          
    m_nbCanDo=1;
    CPaintDC dc(this); // device context for painting
    
    // TODO: Add your message handler code here
    
    dc.IntersectClipRect(m_rectClip);
    CFont * font = (CFont *)(dc.SelectStockObject(m_nFont));
        
    int i;        
    if(m_nDispMode == MODE_SOURCE) {
        for(i = 0; i < m_szView.cy 
            && i + m_ptOffset.y < SRCLINES; i++) {
            ShowSourceLine(&dc, i, Row2Line(i));    
        }                               
    } else if(m_nDispMode == MODE_ASM) {
        for(i = 0; i < m_szView.cy 
            && i + SrcAsm.m_nOffset < ASMLINES; i++) {
            ShowDsmLine(&dc, i, Row2Line(i));    
        }                               
    } else {
        for(i = 0; i < m_szView.cy; i++) {
            int nSrc, nAsm;
            nSrc = SrcMix.Ofs2Line(Row2Line(i), nAsm);
            if(nAsm == -1)  
                ShowSourceLine(&dc, i, nSrc);
            else
                ShowMixedLine(&dc, i, nSrc, nAsm);    
        }                               
    }       
    
    dc.SelectObject(font);
                               
    SetCaret();
    m_nbCanDo=0;
    
    // Do not call CMDIChildWnd::OnPaint() for painting messages
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSourceWindow::IsFunction()
{
    if(m_nDispMode != MODE_SOURCE)  return  FALSE;
    
    if(!m_isSel)    return FALSE;
    
    CString str("#");
    str += m_strSel;              
    
    return BOOL(SrcIsFunction(str) == 0);
}

BOOL CSourceWindow::IsVariable()
{
    if(m_nDispMode != MODE_SOURCE)  return  FALSE;
    
    if(!m_isSel)    return FALSE;

    unsigned long dwModule = MdlInfo.CurModule();
    
    char tmp[200];
    if(SrcGetModuleName(dwModule, tmp) == -1)   return FALSE;
    
    CString str("#");
    str += tmp;
    str += "#";
    str += m_strSel;
    
    return BOOL(SrcIsVariable(str, m_nSelLine + 1) == 0);
}

void CSourceWindow::OnLocalMenu(CPoint point)
{                                                            
    CString str;
    
    CMenu * pLocalMenu = new CMenu;
    ASSERT( NULL != pLocalMenu );

    pLocalMenu->CreatePopupMenu();
    
    if(IsFunction()) {
        str = "Inspect Source of the Function:";
        str += m_strSel;
        pLocalMenu->AppendMenu(MF_STRING, IDM_INSPECT_FUNC, str);
        pLocalMenu->AppendMenu(MF_STRING, IDM_LOAD_ADDR, "Show Load Address");
        pLocalMenu->AppendMenu(MF_STRING, IDM_SETBP_FUNC, "Set Breakpoint");
        pLocalMenu->AppendMenu(MF_STRING, IDM_CLRBP_FUNC, "Clear Breakpoint");
    } else if(IsVariable()) {
        str = "Watch variable:";
        str += m_strSel;
        pLocalMenu->AppendMenu(MF_STRING, IDM_WATCH_VAR, str);
        pLocalMenu->AppendMenu(MF_STRING, IDM_SETBP_VAR, "Set Breakpoint");
        pLocalMenu->AppendMenu(MF_STRING, IDM_CLRBP_VAR, "Clear Breakpoint");
    } else {
        pLocalMenu->AppendMenu(MF_STRING, ID_FILE_LOAD, "Load...");
        pLocalMenu->AppendMenu(MF_STRING, ID_FILE_BROWSEMODULE,
                                "Browse Module...");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_RUN_JUMPTOCURSOR,
                                "Jump To Cursor");
        pLocalMenu->AppendMenu(MF_STRING, ID_RUN_JUMP,
                                "Jump...");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_RUN_RESET,
                                "Reset");
        pLocalMenu->AppendMenu(MF_STRING, ID_RUN_BREAKPOINT, "Breakpoint...");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_BROWSEFROMLINE,
                                "Browse From Line...");
        pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_BROWSEFROMADDRESS,
                                "Browse From Address...");
        pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_BROWSEFROMPC,
                                "Browse From PC");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_SEARCH,
                                "Search...");
        pLocalMenu->AppendMenu(MF_STRING, ID_EDIT_SEARCHNEXT,
                                "Search Next");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_OPTIONS_SOURCEOPTIONS,
                                "Source Options...");
        pLocalMenu->AppendMenu(MF_SEPARATOR);
        pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_SOURCEONLY,
                                "Source Only");
        pLocalMenu->AppendMenu(MF_STRING, ID_VIEW_MIXED,
                                "Mixed Source And Asm");
        pLocalMenu->SetMenuItemBitmaps(ID_VIEW_SOURCEONLY, MF_BYCOMMAND, 
            &bmpMenuUncheck, &bmpMenuCheck);
        pLocalMenu->SetMenuItemBitmaps(ID_VIEW_MIXED, MF_BYCOMMAND, 
            &bmpMenuUncheck, &bmpMenuCheck);
    
    }

    ClientToScreen(&point);
    pLocalMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
    delete pLocalMenu;
}


void CSourceWindow::OnShiftreturn()
{
    // TODO: Add your command handler code here
    OnLocalMenu(CPoint(20, 20));
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    
    OnLocalMenu(point);
    
    CMDIChildWnd::OnRButtonDown(nFlags, point);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnSetFocus(CWnd* pOldWnd)
{
    CMDIChildWnd::OnSetFocus(pOldWnd);
    
    // TODO: Add your message handler code here
    m_bOldPC=0;
    CreateSolidCaret(2, m_szFont.cy);
    SetCaret();                      
    ShowCaret();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnChildActivate()
{
    CMDIChildWnd::OnChildActivate();

    // TODO: Add your message handler code here
    SetFocus();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
                       
    // Set cursor shape                            
    if(m_rectScroll.left > point.x)
        SetCursor(AfxGetApp()->LoadCursor(IDC_BULLEYE));    
    else 
        SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
    
    CMDIChildWnd::OnMouseMove(nFlags, point);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnClose()
{
    // TODO: Add your message handler code here and/or call default
    if(isSrcSrchDlg)    m_pdlgSrch->DestroyWindow();
    
    CMDIChildWnd::OnClose();
}

/////////////////////////////////////////////////////////////////////////////
// Menu Message Handler -- Edit Submenu
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnEditBrowsefromaddress()
{
    // TODO: Add your command handler code here
    CBrowseAddrDialog dlg(TRUE, this);
    if(dlg.DoModal() != IDOK) return;
    
    UpdateAsm(uBrowseAddr);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnEditBrowsefromline()
{
    // TODO: Add your command handler code here
    CBrowseAddrDialog dlg(FALSE, this);
    if(dlg.DoModal() == IDOK) {
        if(nBrowseLine > SRCLINES)  nBrowseLine = SRCLINES;
        UpdateSource(nBrowseLine - 1);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnEditBrowsefrompc()
{
    // TODO: Add your command handler code here
    if(!SrcEmu.GetPC()) return;
    if(SrcEmu.GetModule()) {
        SrcLoadModule(SrcEmu.m_dwPCModule);    
        SelectText(FALSE);
    }   
    
    if(m_nDispMode == MODE_SOURCE) {
        if(SrcEmu.m_nPCLine >= 0 && SrcEmu.IsPCModule(MdlInfo.CurModule())) 
            UpdateSource(SrcEmu.m_nPCLine);
        else UpdateAsm(SrcEmu.m_lPCAddr);
    } else if(m_nDispMode == MODE_MIXED) {
        if(UpdateMixed(SrcEmu.m_lPCAddr))   return;
        else UpdateAsm(SrcEmu.m_lPCAddr);
    } else UpdateAsm(SrcEmu.m_lPCAddr);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateEditBrowsefromline(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(m_nDispMode != MODE_ASM);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnEditSearch()
{
    // TODO: Add your command handler code here
    m_pdlgSrch = new CSourceSearch(this,FALSE);
    m_pdlgSrch->ShowWindow(SW_SHOW);    
    isSrcSrchDlg = TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateEditSearch(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(!isSrcSrchDlg && m_nDispMode == MODE_SOURCE);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnEditSearchnext()
{
    // TODO: Add your command handler code here
    ActivateFrame(-1);
    SelectText(FALSE);                     
    
    if(SrcSrchData.m_strText == "") return;
    
    BOOL is = Search();
    if(!is) {                              
        CString str("Can't find \"");
        str += SrcSrchData.m_strText;
        str += "\"";
        AfxMessageBox(str);
        if(isSrcSrchDlg)    m_pdlgSrch->DestroyWindow();
    } else {
        m_strSel = SrcSrchData.m_strText;
        m_nSelLine = SrcSrchData.m_nCurLine;
        m_nSelCol = SrcSrchData.m_nCurCol;
        SelectText(TRUE);
    }   
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateEditSearchnext(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(m_nDispMode == MODE_SOURCE);    
}

/////////////////////////////////////////////////////////////////////////////
// Menu Message Handler -- File Submenu
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnFileLoadinfo()
{
    // TODO: Add your command handler code here
    // Get load information
    char szModule[100];       
    int nDummy;
    if(SrcGetLdrStats(szModule, &(LoadInfo.m_lSymbols),
        &((unsigned short &)(LoadInfo.m_lModules)), &(LoadInfo.m_lTypes), 
        &(LoadInfo.m_lFunctions), &(LoadInfo.m_lLines),
        &(LoadInfo.m_lBytes), &nDummy) == -1) {
        if(LoadOpt.m_isWarnings)
            AfxMessageBox(IDS_ERR_LOADINFO);
        return;                          
    }      
              
    // Show load information              
    CLoadInfoDialog dlg(this);
    dlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnFilePrevmodule()
{
    // TODO: Add your command handler code here
    BrsMdl.GotoPrev();   
    //int n = SrcEmu.m_nStepOpt;
    SelectText(FALSE);
    if(LoadModule(BrsMdl.GetElem(), FALSE))
        //SrcEmu.m_nStepOpt = n;    
        SetStepOpt();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnFileNextmodule()
{
    // TODO: Add your command handler code here
    BrsMdl.GotoNext();
    //int n = SrcEmu.m_nStepOpt;
    SelectText(FALSE);
    if(LoadModule(BrsMdl.GetElem(), FALSE))    
        //SrcEmu.m_nStepOpt = n;    
        SetStepOpt();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateFilePrevmodule(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(!BrsMdl.IsEmpty() && !BrsMdl.IsHead());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateFileNextmodule(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(!BrsMdl.IsEmpty() && !BrsMdl.IsTail());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnFileBrowsemodule()
{
    // TODO: Add your command handler code here
    CSrcGrpDlg    dlg(3,this);
    dlg.DoModal();
    
/*
    CSourceGroup    dlg(1,this);
     if(dlg.DoModal() == IDOK) {
        SelectText(FALSE);
        DoBrowseModule(dlg);
    }   
    Invalidate();
*/    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateFileBrowsemodule(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    if(MdlInfo.m_uModules == 0) {
     	pCmdUI->Enable(FALSE);
    } else {
     	for(int i = 0; i < int(MdlInfo.m_uModules); i ++) {
			if(SrcCheckModuleHasLineInfo(MdlInfo.m_pModule[i]) == 0) {
		     	pCmdUI->Enable(TRUE);
		     	return;
			}    		 	
     	}
    }
    pCmdUI->Enable(FALSE);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnFileLoad()
{
    // TODO: Add your command handler code here
    DoFileLoad();    
}

/////////////////////////////////////////////////////////////////////////////
// Menu Message Handler -- Options Submenu
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnOptionsSourceextensionnames()
{
    // TODO: Add your command handler code here

    CSrcGrpDlg dlg(1, this);
    dlg.DoModal();


/*    
    CSourceGroup    dlg(4, this);
    if(dlg.DoModal() == IDOK) {
        DoBrowseModule(dlg);
    }   
    Invalidate();    
*/    
    /*if(SrcOpt.m_isTabChanged) {
        SrcOpt.m_isTabChanged = FALSE;
        MdlInfo.Reload();        
    }*/
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnOptionsSourceoptions()
{
    // TODO: Add your command handler code here
    CSrcGrpDlg    dlg(2, this);
    dlg.DoModal();
/*    
    CSourceGroup    dlg(3, this);
    if(dlg.DoModal() == IDOK) {
        DoBrowseModule(dlg);
    }   
    Invalidate();
*/    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnOptionsSourcepath()
{
    // TODO: Add your command handler code here

    CSrcGrpDlg   dlg(4, this);
    dlg.DoModal();
/*
    CSourceGroup    dlg(2, this);
    if(dlg.DoModal() == IDOK) {
        DoBrowseModule(dlg);
    }   
    Invalidate();
*/    
}

/////////////////////////////////////////////////////////////////////////////
// Menu Message Handler -- Run Submenu
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunGotocursor()
{
    // TODO: Add your command handler code here
    extern void EmuServerGo(int nMode, unsigned short uAddr);
    long lAddr = GetCaretAddr();
    if(lAddr == 0x10000L) {
        MessageBeep(-1);
        return;
    }          

    BeginWaitCursor();
    EmuServerGo(3, (unsigned short)lAddr);
    EndWaitCursor();
    OnEmulation();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunGofromcursor()
{
    // TODO: Add your command handler code here
    extern void EmuServerGo(int nMode, unsigned short uAddr);
    long lAddr = GetCaretAddr();
    if(lAddr == 0x10000L) {
        MessageBeep(-1);
        return;
    }          

    BeginWaitCursor();
    EmuServerGo(2, (unsigned short)lAddr);
    EndWaitCursor();
    OnEmulation();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunJumptocursor()
{
    // TODO: Add your command handler code here
    SelectText(FALSE);

    extern void EmuServerJump(unsigned short uAddr);
    long lAddr = GetCaretAddr();
    if(lAddr == 0x10000L) {
        MessageBeep(-1);
        return;
    }          
    
    BeginWaitCursor();
    EmuServerJump((unsigned short)lAddr);
    EndWaitCursor();
    OnEmulation();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunBreakpoint()
{
    // TODO: Add your command handler code here
    DoBreakPoint(NULL);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunJump()
{
    // TODO: Add your command handler code here
    SelectText(FALSE);

    BeginWaitCursor();
    if(DoJump(this)) {    
        OnEmulation();
    }    
    EndWaitCursor();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnRunReset()
{
    // TODO: Add your command handler code here
    if(AfxMessageBox("Confirm reset operation?", MB_YESNO|MB_ICONQUESTION)
        == IDNO)    
        return;

    SelectText(FALSE);
        
    BeginWaitCursor();
    DoReset();    
    EndWaitCursor();
    OnEmulation();
}

/////////////////////////////////////////////////////////////////////////////
// Menu Message Handler -- View Submenu
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewSourceonly()
{
    // TODO: Add your command handler code here
    if(m_nDispMode == MODE_SOURCE)  return;    
    SelectText(FALSE);
    if(m_nDispMode == MODE_MIXED) {   
        if(SrcEmu.IsPCModule(MdlInfo.CurModule())) 
            UpdateSource(SrcEmu.m_nPCLine);       
        else    UpdateSource(m_ptOffset.y);
        return;
    }
               
    // no source file downloaded               
    if(MdlInfo.m_uModules == 0) {
        //AfxMessageBox(IDS_PRM_NOSYMINFO);
        return;
    }                              
    
    if(SrcEmu.GetPC() && SrcEmu.GetModule()) 
        if(SrcLoadModule(SrcEmu.m_dwPCModule) != SRC_LOAD_ERROR) {                
            UpdateSource(SrcEmu.m_nPCLine);   
            return;
        }
                                              
    if(SrcLoadModule(MdlInfo.m_pModule[0]) == SRC_LOAD_ERROR)                 
        return;
    
    UpdateSource(0);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateViewSourceonly(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->SetRadio(m_nDispMode == MODE_SOURCE);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewMixed()
{
    // TODO: Add your command handler code here
    if(m_nDispMode == MODE_MIXED)   return;    
    SelectText(FALSE);
    if(m_nDispMode == MODE_SOURCE) {
        if(SrcEmu.IsPCModule(MdlInfo.CurModule())) 
            UpdateMixed(SrcEmu.m_lPCAddr);       
        else    UpdateMixed(m_ptOffset.y);
        return;
    }
        
    if(MdlInfo.m_uModules == 0) {
        if(LoadOpt.m_isWarnings)
            AfxMessageBox(IDS_PRM_NOSYMINFO);
        return;
    }
    
    if(SrcEmu.GetPC() && SrcEmu.GetModule()) 
        if(UpdateMixed(SrcEmu.m_lPCAddr))   return;
                                              
    if(SrcLoadModule(MdlInfo.m_pModule[0]) == SRC_LOAD_ERROR)                 
        return;
    
    UpdateMixed(0);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateViewMixed(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->SetRadio(m_nDispMode == MODE_MIXED);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewSymbolicdisassembly()
{
    // TODO: Add your command handler code here
    if(isSymDsm)    isSymDsm = FALSE;
    else    isSymDsm = TRUE;

    AsmLine * pAsm;                
    int nLine, nAsm;
    if(m_nDispMode == MODE_ASM) {
        pAsm = (AsmLine *)SrcAsm.GetLine(SrcAsm.m_nOffset);
        if(!pAsm)   UpdateAsm(0L);
        else    UpdateAsm(pAsm->m_uAddr);
    } else if(m_nDispMode == MODE_MIXED) {
        nLine = SrcMix.Ofs2Line(SrcMix.m_nOffset, nAsm);            
        if(nAsm == -1)  UpdateMixed(nLine);
        else {
            pAsm = (AsmLine *)SrcMix.GetLine(nLine, nAsm);
            if(!pAsm)   UpdateMixed(0L);
            else    UpdateMixed(long(pAsm->m_uAddr));
        }
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateViewSymbolicdisassembly(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->SetCheck(isSymDsm);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewLinenumbering()
{
    // TODO: Add your command handler code here
    ASSERT(m_nDispMode != MODE_ASM);

    ::isLineNo = ::isLineNo ? FALSE : TRUE;    
    //m_nLeft = ::isLineNo ? 8 : 2;
    CalcLeftEdge();

    CRect rect;          
    GetClientRect(rect);
    CalcViewSize(rect.Width(), rect.Height());            
    CalcScrollSize();
    m_ptCaret.x = m_nLeft;
    Caret2Index();
    InvalidateRect(NULL);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateViewLinenumbering(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->SetCheck(::isLineNo);    
    pCmdUI->Enable(m_nDispMode != MODE_ASM);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewSyntaxcoloring()
{
    // TODO: Add your command handler code here
    if(SrcColor.m_isColorOn)    SrcColor.DisableColor();
    else                        SrcColor.EnableColor();
    InvalidateRect(NULL);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnUpdateViewSyntaxcoloring(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    pCmdUI->SetCheck(SrcColor.m_isColorOn);    
    pCmdUI->Enable(m_nDispMode != MODE_ASM);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Switch between Source/Mixed/Asm Mode
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CSourceWindow::OnViewSma()
{
    // TODO: Add your command handler code here
    if(m_nDispMode == MODE_SOURCE) 
        SendMessage(WM_COMMAND, ID_VIEW_MIXED);
    else if(m_nDispMode == MODE_ASM)   
        SendMessage(WM_COMMAND, ID_VIEW_SOURCEONLY);
    else { 
        if(SrcEmu.GetPC())  UpdateAsm(SrcEmu.m_lPCAddr);
        else                UpdateAsm(0);
    }
}   

/*static BOOL IsDelimit(char ch)
{
    return BOOL(strchr("~`!@$%^&*()-+=|\\}]{[\"\':;<,>.?/ \t\n\r", ch) 
                != NULL);
}*/

void CSourceWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    int nLeft, nRight;
    
    SetFocus();
    SelectText(FALSE);
    
    CPoint  pt = point;

    if(point.x < m_rectScroll.left)         pt.x = m_rectScroll.left;
    if(point.x > m_rectScroll.right - 1)    pt.x = m_rectScroll.right - 1;
    if(point.y < m_rectScroll.top)          pt.y = m_rectScroll.top;
    if(point.y > m_rectScroll.bottom - 1)   pt.y = m_rectScroll.bottom - 1;
    
    m_ptCaret.x = X2Col(pt.x);
    m_ptCaret.y = Y2Row(pt.y);

    Caret2Index();
    SetCaret();                   
    
    if(m_nDispMode != MODE_SOURCE)  return;
    
    if(m_ptIndex.y < 0 || m_ptIndex.y >= SRCLINES)  return;
    
    SourceElement * p1 = SRCMDL.GetLine(m_ptIndex.y);
    if(!p1) return;                                
                                   
    if(p1->m_nLength <= m_ptIndex.x)    return;
    
    SyntaxColorElement * p2 = (SyntaxColorElement *)(p1->m_Color.GetFirst());
    while(p2) {
        if(m_ptIndex.x >= p2->m_nFirstCol && m_ptIndex.x <= p2->m_nLastCol) {
            if(p2->m_nSyntaxType == CSYN_CODE)  goto DBC1;
        }    
        p2 = (SyntaxColorElement *)(p1->m_Color.GetNext());
    }           
    
    return;
    
DBC1:      
    nLeft = m_ptIndex.x;          
    if(!::IsDelimit(p1->m_szLine[nLeft])) {
        while(nLeft) {
            if(::IsDelimit(p1->m_szLine[nLeft -1])) break;
            -- nLeft;
        }                 
    }
    
    nRight = m_ptIndex.x;
    while(nRight < p1->m_nLength) {
        if(::IsDelimit(p1->m_szLine[nRight]))   break;
        ++ nRight;
    }             
    
    if(nRight == nLeft) return;     
    
    m_strSel = CString(p1->m_szLine + nLeft, nRight - nLeft);
    m_nSelLine = m_ptIndex.y;
    m_nSelCol = nLeft;
    SelectText(TRUE);
/*  
    unsigned long dwModule = MdlInfo.CurModule();
    
    char tmp[200];
    if(SrcGetModuleName(dwModule, tmp) == -1)   return;
    
    CString str("#");
    str += tmp;
    
    CString str1(p1->m_szLine + nLeft, nRight - nLeft);
    str += "#";
    str += str1;
    
    str += "\n";
    
    wsprintf(tmp, "Line number:%d", m_ptIndex.y + 1);
    str += tmp;
    
    AfxMessageBox(str);
*/      
    CMDIChildWnd::OnLButtonDblClk(nFlags, point);
}

void CSourceWindow::OnSetBPFunc()
{
    CString str("#");
    str += m_strSel;
    
    WORD wStart, wEnd;
    if(SrcGetFuncRange(str, wStart, wEnd) != 0) return;

    BYTE eFlag;
    if(BptSearchBpt(wStart, eFlag)) {
        if(!eFlag) BptEnableBpt(wStart);
    } else BptAddBptfromWnd(wStart);
    Invalidate();
}
 
void CSourceWindow::OnClrBPFunc()
{
    CString str("#");
    str += m_strSel;
    
    WORD wStart, wEnd;
    if(SrcGetFuncRange(str, wStart, wEnd) != 0) return;

    BYTE eFlag;
    if(BptSearchBpt(wStart, eFlag)) 
        BptClrOneBptfromWnd(wStart);
    Invalidate();
}

void CSourceWindow::OnSetBPVar()
{
    unsigned long dwAddr;  
    BYTE eFlag;
    if(SrcLinenum2Addr(MdlInfo.CurModule(), (unsigned short)(m_nSelLine + 1), 
        dwAddr) == 0) {
        if(BptSearchBpt((unsigned short)dwAddr, eFlag)) {
            if(!eFlag) BptEnableBpt((unsigned short)dwAddr);
        } else BptAddBptfromWnd((unsigned short)dwAddr);
        UpdateRow(Line2Row(m_nSelLine));
    }
}
 
void CSourceWindow::OnClrBPVar()
{
    unsigned long dwAddr;  
    BYTE eFlag;
    if(SrcLinenum2Addr(MdlInfo.CurModule(), (unsigned short)(m_nSelLine + 1), 
        dwAddr) == 0) {
        if(BptSearchBpt((unsigned short)dwAddr, eFlag)) {
            BptClrOneBptfromWnd((unsigned short)dwAddr);
            UpdateRow(Line2Row(m_nSelLine));
        }   
    }
}

void CSourceWindow::OnShowLoadAddr()
{
    CString str("#");
    str += m_strSel;
    
    CString str1;              
    
    char szStart[10], szEnd[10];    
        
    WORD wStart, wEnd;
    if(SrcGetFuncRange(str, wStart, wEnd) != 0) {
        if(LoadOpt.m_isWarnings)
            AfxMessageBox("Can't get load address!");
    } else {
        wsprintf(szStart, "%04Xh", wStart);
        wsprintf(szEnd, "%04Xh", wEnd);
        str1 = "The load address of the function: ";
        str1 += m_strSel;
        str1 += "\n";
        str1 += szStart;
        str1 += " -- ";
        str1 += szEnd;
        AfxMessageBox(str1);
    }
}

void CSourceWindow::OnWatchVariable()
{
    unsigned long dwModule = MdlInfo.CurModule();
    
    char tmp[200];
    if(SrcGetModuleName(dwModule, tmp) == -1)   return;
    
    CString str("#");
    str += tmp;
    str += "#";
    str += m_strSel;
    
    VarAddVariable(str);
}

void CSourceWindow::OnInspectFunc()
{
    CString str("#");
    str += m_strSel;

    WORD wStart, wEnd;
    if(SrcGetFuncRange(str, wStart, wEnd) != 0) {
        if(LoadOpt.m_isWarnings)
            AfxMessageBox("Can't get load address!");
    } else {
        SrcShowSource(wStart);
    }
}

void CSourceWindow::OnUpdateSearchCombo(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(m_nDispMode == MODE_SOURCE);
}


/////////////////////////////////(EOF)///////////////////////////////////////
