
/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/SRCFILE.CPP   1.2.1.4   17 Apr 1997 16:00:32   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/SRCFILE.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 16:00:32   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:33:32   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:42:58   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:21:40   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:25:50   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:35:46   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:50:12   ZJRD
** Initial revision.
** 
**    Rev 1.7.1.0.1.2   09 Dec 1996 10:16:48   ZJRD
** EasyPack/SLD Version 2.0P
** 
**    Rev 1.7.1.0.1.0   11 Nov 1996 13:00:02   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.7.1.4   09 Sep 1996 13:19:58   ZJRD
** No change.
** 
**    Rev 1.7.1.3   05 Sep 1996 11:31:28   ZJRD
** No change.
** 
**    Rev 1.7.1.2   02 Sep 1996 09:58:34   ZJRD
** No change.
** 
**    Rev 1.7.1.1   28 Aug 1996 15:50:48   ZJRD
** EasyPack/SLD Version 1.9b
** 
**    Rev 1.6   10 Jun 1996 10:23:14   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:34:26   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 08:59:52   ZJRD
** EasyPack/SLD Version 1.94
** 
**    Rev 1.1   02 May 1996 10:30:42   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 12:55:50   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:34:50   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:49:16   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:04:44   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:31:20   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:46:10   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:19:42   Shirley
** EasyPack/SLD Version 0.35b
** 
**    Rev 1.23   26 Jan 1996 09:16:34   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:16:28   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:34:24   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:28:52   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:13:44   Shirley
** No change.
** 
**    Rev 1.18   15 Jan 1996 16:10:34   Shirley
** No change.
** 
**    Rev 1.17   04 Jan 1996 11:09:52   Shirley
** No change.
** 
**    Rev 1.16   30 Nov 1995 09:13:14   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:35:34   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:23:38   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:26:00   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:29:40   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:31:30   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:43:04   Shirley
** EasyPack/SLD Version 0.22
** 
**    Rev 1.9   02 Nov 1995 10:03:54   Shirley
** EasyPack/SLD Version 0.21
** 
**    Rev 1.8   27 Oct 1995 16:50:32   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:46:56   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:29:54   Shirley
** No change.
** 
**    Rev 1.5   18 Oct 1995 14:48:24   Shirley
** No change.
** 
**    Rev 1.4   13 Oct 1995 13:20:28   Shirley
** No change.
** 
**    Rev 1.3   29 Sep 1995 09:48:36   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:53:20   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:48:02   Shirley
** No change.
** 
**    Rev 1.0   07 Sep 1995 09:54:26   Shirley
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  SRCFILE.CPP
//
//  Description:The implement file for the class: 
//                  SourceAssemble
//                  SourceMixed
//
//  Author:     Roger Zhang
//
//  Date:       06/20/95
//
//  Modification:
//
//      1. 06/20/95, Initial version 
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"

#include "zqueue.h"
#include "uicom.h"
#include "srccom.h"                  
#include "zlist.h"
#include "srclist.h"
#include "srcmdl.h" 
#include "bwsmdl.h" 
#include "srcfile.h"
#include "cfmtadr.h"

/////////////////////////////////////////////////////////////////////////////
extern ADDR_SIZE  dwpMax;        // program  max address
extern int SRCDisAsm(int spacebank, unsigned DAsmStartAddr, unsigned DAsmInCodeBlkLen,
                    unsigned *DAsmInstrNum, unsigned *DAsmBytesNum,
                    char     **InstrArray, unsigned *AddrLenArray,
                    char     **LabelArray);

/////////////////////////////////////////////////////////////////////////////
// Disassemble mode class : SourceAssemble
/////////////////////////////////////////////////////////////////////////////
SourceAssemble SrcAsm;
SourceAssemble BwsAsm;
            
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
SourceAssemble::~SourceAssemble()
{
    DeleteList();
}                         

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SourceAssemble::DeleteList(void)
{
AsmLine* pData;
    
    POSITION pos = m_AsmList.GetHeadPosition();
    while(pos) {
        pData=(AsmLine*)m_AsmList.GetNext(pos);
        pData->m_strText.Empty();
        delete pData;
    }                                 
    m_AsmList.RemoveAll();
}                

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::Dsm(int nBank, unsigned short uAddr, unsigned short uRange)
{                                 
    int spacebank=nBank;
    unsigned * pAddr = new unsigned [MAX_RANGE * 2];
    if(!pAddr)  return  FALSE;
    char ** pText1, ** pText2;         
    typedef char * PCHAR;
    if((pText1 = new PCHAR[MAX_RANGE * 2])==0) return  FALSE;
    if((pText2 = new PCHAR[MAX_RANGE * 2])==0) return  FALSE;
    for(int i = 0; i < MAX_RANGE * 2; i ++) {
        if((pText1[i] = new char [255])==0) return FALSE;
        if((pText2[i] = new char [255])==0) return FALSE;
    }
                                 
    unsigned uBytes;
    unsigned uLines;
    SRCDisAsm(spacebank, uAddr, uRange, &uLines, &uBytes, pText1, pAddr, pText2);
    
    m_lStartAddr = long(uAddr);
    m_lRange = long(uBytes);

    AsmLine * pAsm;             
    
    for(i = 0; i < int(uLines); i ++) {
        if(pText2[i] && strlen(pText2[i]) > 0) {
            if((pAsm = new AsmLine) == 0)   return FALSE;
            pAsm->m_uAddr   = uAddr;
            pAsm->m_nBank=nBank;
            pAsm->m_strText = CString("       ") + pText2[i];
            pAsm->m_chLabel = 1;
            m_AsmList.AddTail(pAsm);            
        }
        if((pAsm = new AsmLine) == 0)   return FALSE;
        pAsm->m_uAddr   = uAddr;
        pAsm->m_nBank=nBank;
        pAsm->m_strText = pText1[i];
        pAsm->m_chLabel = 0;
        uAddr += (unsigned short)(pAddr[i]);
        m_AsmList.AddTail(pAsm);            
    }

    for(i = 0; i < MAX_RANGE * 2; i ++) {
        delete [] pText1[i];
        delete [] pText2[i];
    }
    delete [] pText1;
    delete [] pText2;
    delete [] pAddr;              
              
    return  TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::Dsm(int nBank, unsigned short uAddr)
{                                      
    unsigned short uRange = MAX_RANGE;
    //modify by chris:
    if(dwpMax+1 - long(uAddr) < MAX_RANGE)  
        //uRange = (unsigned short)(0x10000L - long(uAddr) + 1);
        uRange = (unsigned short)(dwpMax+1 - long(uAddr));
    
    DeleteList();                    

    if(Dsm(nBank, uAddr, uRange) == FALSE) return  FALSE;

    return  TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::CheckAddr(int nBank, unsigned short uAddr) const
{
    POSITION pos = m_AsmList.GetHeadPosition();
    AsmLine  * pAsm;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(pAsm->m_uAddr == uAddr&&pAsm->m_nBank==nBank) return TRUE;
    }                                               
    return FALSE;
}                

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::DsmAddr(int nBank, unsigned short uStart, unsigned short uChk)
{                     
    ASSERT(uChk >= uStart);
    
    for(int i = 0; i < MAX_CHECK; i ++) {
        if(!Dsm(nBank, uStart))   return  FALSE;   // out of memory
        if(CheckAddr(nBank, uChk)) return  TRUE;   // Ok!
        if(uStart < dwpMax)    ++ uStart;
        else return TRUE;                   // Not Match 
    }                                               
    return  TRUE;                           // Not Match
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
AsmLine * SourceAssemble::GetLine(int nLine) const
{
    AsmLine * p;      
    POSITION pos = m_AsmList.GetHeadPosition();
    int i = 0;
    while(pos) {
        p = (AsmLine *)m_AsmList.GetNext(pos);
        if(i++ == nLine)    return p;        
    }
    return  0;
}                          

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::IsHome(void) const
{
    ASSERT(!m_AsmList.IsEmpty());
    
    /*AsmLine * p = (AsmLine *)m_AsmList.GetHead();
    if(!p)  return  FALSE;
    
    return p->m_uAddr < (unsigned short)MAX_CHECK;*/
    return BOOL(m_lStartAddr == 0);
}                            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::IsEnd(void) const
{                        
    ASSERT(!m_AsmList.IsEmpty());
    
    /*AsmLine * p = (AsmLine *)m_AsmList.GetTail();
    if(!p)  return  FALSE;
    
    return 0x10000L - long(p->m_uAddr) <= long(MAX_CHECK);*/
    return BOOL(m_lStartAddr + m_lRange >= dwpMax+1);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::DsmPrev(void)
{
    ASSERT(!IsHome());
    ASSERT(!m_AsmList.IsEmpty());
    
    AsmLine * p = (AsmLine *)m_AsmList.GetHead();
    if(!p)  return  FALSE;
    
    unsigned short uNew = (p->m_uAddr >= (unsigned short)MAX_PAGE) ? 
        p->m_uAddr - MAX_PAGE : 0;
    return DsmAddr(p->m_nBank, uNew, p->m_uAddr);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::DsmNext(void)
{
    ASSERT(!IsEnd());
    ASSERT(!m_AsmList.IsEmpty());
    
    AsmLine * p1 = (AsmLine *)m_AsmList.GetHead();
    if(!p1)  return  FALSE;
    AsmLine * p2 = (AsmLine *)m_AsmList.GetTail();
    if(!p2)  return  FALSE;
    
    long lNew = long(p1->m_uAddr) + long(MAX_PAGE);
    if(lNew > dwpMax)   lNew = long(p1->m_uAddr);
    return DsmAddr(p1->m_nBank, (unsigned short)lNew, p2->m_uAddr);
}                                          

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceAssemble::Addr2Line(int nBank, long lAddr) const
{                                 
    if(lAddr > dwpMax)  return m_AsmList.GetCount();
    
    POSITION pos = m_AsmList.GetHeadPosition();
    int i = 0;
    AsmLine * pAsm;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(pAsm->m_uAddr == (unsigned short)lAddr && !(pAsm->m_chLabel)&&
        	pAsm->m_nBank==nBank) 
            return  i;        
        else    ++ i;
    }                
    return  i;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceAssemble::MatchAddr2LineL(int nBank, long lAddr) const
{
    if(lAddr > dwpMax) return m_AsmList.GetCount();
    
    POSITION pos = m_AsmList.GetHeadPosition();
    AsmLine * pAsm;             
    int i = 0;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(pAsm->m_uAddr >= (unsigned short)lAddr&&nBank==pAsm->m_nBank) 
            return  i;
        else ++ i;
    }                
    return  i;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SourceAssemble::Line2AddrL(int nLine, int& nBank, long& lAddr)
{                      
    ASSERT(nLine >= 0);
    
    if(nLine >= m_AsmList.GetCount())
    {
       lAddr=dwpMax+1;
       return;
    }
    POSITION pos = m_AsmList.GetHeadPosition();
    int i = 0;
    AsmLine * pAsm;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(i == nLine)
        {
        	nBank=pAsm->m_nBank;
        	lAddr=pAsm->m_uAddr;
        	return;
        }
        else    ++ i;
    }                
    lAddr=dwpMax+1;
    return;
}            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceAssemble::IsLabelLine(int nLine)
{
    ASSERT(nLine >= 0);
    
    if(nLine >= m_AsmList.GetCount())   return TRUE;

    POSITION pos = m_AsmList.GetHeadPosition();
    int i = 0;
    AsmLine * pAsm;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(i == nLine) {
            if(pAsm->m_chLabel) return TRUE;
            else return  FALSE;        
        } else    ++ i;
    }                
    return  FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// Mixed Mode Class : SourceMixed
/////////////////////////////////////////////////////////////////////////////
SourceMixed SrcMix(0);                
SourceMixed BwsMix(1);


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
SourceMixed::~SourceMixed()
{
    DeleteList();
}

#ifdef _DEBUG
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SourceMixed::DumpFile(const char * pszFileName) const
{
    FILE * fp = fopen(pszFileName, "wt");
    if(fp == NULL)  return;
    
    fprintf(fp, "m_nSrcStart = %d\n", m_nSrcStart);
    fprintf(fp, "m_nSrcLines = %d\n", m_nSrcLines);
        
    fprintf(fp, "m_nAsmPos:\n");        
    for(int i = 0; i < m_nSrcLines; i ++)
        fprintf(fp, "%d --> %d\n", i, m_nAsmPos[i]);
        
    fprintf(fp, "m_AsmList:\n");        

    POSITION pos = m_AsmList.GetHeadPosition();
    AsmLine * pAsm;
    i = 0;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);            
        fprintf(fp, "%d -->", i++);
        fprintf(fp, "%s\n", (const char *)(pAsm->m_strText));
    }                                 

    fclose(fp);
} 

#endif            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SourceMixed::DeleteList(void)
{
AsmLine* pData;
    
    POSITION pos = m_AsmList.GetHeadPosition();
    while(pos) {
        pData=(AsmLine*)m_AsmList.GetNext(pos);
        pData->m_strText.Empty();
        delete pData;
    }                                 
    m_AsmList.RemoveAll();
}                

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::GetLineAddr(int nLine, int& nBank, unsigned short &uAddr, 
    unsigned short &uRange)
{                                 
    int nSrcLines=(m_bBrowse?BWSSRCLINES:SRCLINES);
    
    ASSERT(nLine >= 0 && nLine <= nSrcLines);
    
    if(nLine == nSrcLines)   return FALSE;
    
    unsigned long dwStart, dwEnd;
    unsigned long dwModule=(m_bBrowse?bwsMdlInfo.CurModule():MdlInfo.CurModule());
    
    if(SrcLinenum2Range(dwModule, (unsigned short)(nLine + 1), dwStart, dwEnd, nBank) == -1)
        return FALSE;
        
    uAddr = (unsigned short)dwStart;
    uRange = (unsigned short)(dwEnd - dwStart + 1);               

    return  TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Disassemble address range
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::Dsm(int nBank, unsigned short uAddr, unsigned short uRange)
{                                 
    int spacebank=nBank;
    unsigned * pAddr = new unsigned [MAX_RANGE * 2];
    if(!pAddr)  return  FALSE;
    char ** pText1, ** pText2;         
    typedef char * PCHAR;
    if((pText1 = new PCHAR[MAX_RANGE * 2])==0) return  FALSE;
    if((pText2 = new PCHAR[MAX_RANGE * 2])==0) return  FALSE;
    for(int i = 0; i < MAX_RANGE * 2; i ++) {
        if((pText1[i] = new char [255])==0) return FALSE;
        if((pText2[i] = new char [255])==0) return FALSE;
    }
                                 
    unsigned uBytes;
    unsigned uLines;
    SRCDisAsm(spacebank, uAddr, uRange, &uLines, &uBytes, pText1, pAddr, pText2);

    AsmLine * pAsm;             
    
    for(i = 0; i < int(uLines); i ++) {
        if(pText2[i] && strlen(pText2[i]) > 0) {
            if((pAsm = new AsmLine) == 0)   return FALSE;
            pAsm->m_uAddr   = uAddr;
            pAsm->m_nBank=nBank;
            pAsm->m_strText = CString("       ") + pText2[i];
            pAsm->m_chLabel = 1;
            m_AsmList.AddTail(pAsm);            
        }
        if((pAsm = new AsmLine) == 0)   return FALSE;
        pAsm->m_uAddr   = uAddr;
        pAsm->m_nBank=nBank;
        pAsm->m_strText = pText1[i];
        pAsm->m_chLabel = 0;
        uAddr += (unsigned short)(pAddr[i]);
        m_AsmList.AddTail(pAsm);            
    }

    for(i = 0; i < MAX_RANGE * 2; i ++) {
        delete [] pText1[i];
        delete [] pText2[i];
    }
    delete [] pText1;
    delete [] pText2;
    delete [] pAddr;              
              
    return  TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::DsmLine(int nLine)
{                        
    unsigned short uAddr, uRange;
    int nBank;
    if(!GetLineAddr(nLine, nBank, uAddr, uRange))  // no code
        m_nAsmPos[nLine - m_nSrcStart] = -1;
    else {
        m_nAsmPos[nLine - m_nSrcStart] = m_AsmList.GetCount();
        while(uRange > MAX_RANGE) {
            if(!Dsm(nBank, uAddr, MAX_RANGE))  return FALSE;
            else {
                uAddr += MAX_RANGE;
                uRange -= MAX_RANGE;
            }            
        }
        if(uRange > 0) {
            if(!Dsm(nBank, uAddr, uRange))  return FALSE;
        } 
    }    
    return TRUE;
}               

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::Dsm(int nLine)
{                                         
    int nSrcLines=(m_bBrowse?BWSSRCLINES:SRCLINES);

    ASSERT(nLine >= 0 && nLine <= nSrcLines);
    
    if(nLine == nSrcLines)  return  FALSE;          
    
    DeleteList();
    m_nSrcStart = nLine;
    m_nSrcLines = 0;
        
	int n;        
    if(!DsmLine(nLine)) return FALSE;       
    else {
        ++ m_nSrcLines; ++ nLine;
    	n = m_AsmList.GetCount() + m_nSrcLines;
        if(nLine == nSrcLines)    return TRUE;
    }
    while(m_AsmList.GetCount() + m_nSrcLines - n < MIN_LINES) {
        if(!DsmLine(nLine)) return FALSE;
        else {
            ++ m_nSrcLines; ++ nLine;
            if(nLine == nSrcLines)    break;
        }
    }                                        
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
AsmLine * SourceMixed::GetLine(int nSrcLine, int nAsmLine) const
{                                               
    int nSrcLines=(m_bBrowse?BWSSRCLINES:SRCLINES);
    ASSERT(nSrcLine >= 0 && nSrcLine <= nSrcLines);
    ASSERT(nAsmLine >= -1);

    if(nSrcLine == nSrcLines || nAsmLine == -1)    return  0;
    if(nSrcLine < m_nSrcStart || nSrcLine >= m_nSrcStart + m_nSrcLines)
        return  0;
    
    int nPos = m_nAsmPos[nSrcLine - m_nSrcStart];
    if(nPos == -1)  return  0;
    
    POSITION pos = m_AsmList.GetHeadPosition();
    int i = 0;
    int j = 0;
    AsmLine * pAsm;
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);       
        if(i == nPos) {
            if(j == nAsmLine)   return  pAsm;
            else    ++ j;
        } else  ++ i;
    }                
    return  0;
}   

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::IsHome(void) const
{
    return  m_nSrcStart == 0;
}                          

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::IsEnd(void) const
{
    return  m_nSrcStart + m_nSrcLines >= (m_bBrowse?BWSSRCLINES:SRCLINES);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::DsmPrev(void)
{
    ASSERT(!IsHome());
     
    unsigned short uAddr, uRange;
	int nBank;     
    for(int i = 0, nLine = m_nSrcStart - 1; i < MAX_PAGELINE; ++ i, -- nLine) {
        if(GetLineAddr(nLine, nBank, uAddr, uRange))   break;
        else if(nLine == 0) break;            
    }
    
    return  Dsm(nLine);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceMixed::DsmNext(void)
{                   
    ASSERT(!IsEnd());

    int nLine = m_nSrcStart + m_nSrcLines - 1;
    return  Dsm(nLine);    
}                                
                                     
// nLine is the offset to m_nSrcStart, also return offset                                     
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceMixed::GetNextAsmLine(int nLine) const
{
    ASSERT(nLine >= 0 && nLine < m_nSrcLines);
    
    while(++nLine < m_nSrcLines) {                  
        if(m_nAsmPos[nLine] != -1)  return nLine;
    }
    return  -1;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceMixed::GetAsmLines(int nLine) const
{                                          
    int nSrcLines=m_bBrowse?BWSSRCLINES:SRCLINES;
    //ASSERT(nLine >= 0 && nLine <= nSrcLines);
    
    if(nLine == nSrcLines)  return  0;
    if(nLine < m_nSrcStart || nLine >= m_nSrcStart + m_nSrcLines)
        return  0;
        
    int nOfs = nLine - m_nSrcStart;
    if(m_nAsmPos[nOfs] == -1)   // no asm line
        return  0;
    else {                                             
        int i = GetNextAsmLine(nOfs);
        if(i == -1)
            return  m_AsmList.GetCount() - m_nAsmPos[nOfs];
        else
            return  m_nAsmPos[i] - m_nAsmPos[nOfs];
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceMixed::Line2Ofs(int nSrc, int nAsm) const
{                                       
    int nSrcLines=m_bBrowse?BWSSRCLINES:SRCLINES;
    ASSERT(nAsm >= -1); 
    ASSERT(nSrc >= 0 && nSrc <= nSrcLines);
    
    if(nSrc == nSrcLines)    
        return  m_nSrcLines + m_AsmList.GetCount() + nAsm + 1;
                         
    int k = 0;
    for(int i = 0; i < nSrc - m_nSrcStart; i ++) 
        k += GetAsmLines(i + m_nSrcStart) + 1;
    return k + nAsm + 1;
}                           
                              
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceMixed::Ofs2Line(int nOfs, int &nAsm) const
{
    ASSERT(nOfs >= 0);
    int nSrcLines=(m_bBrowse?BWSSRCLINES:SRCLINES);
    
    nAsm = nOfs;
    int n = m_nSrcStart;
    int k = (m_bBrowse?(BwsMix.GetAsmLines(n)+1):(SrcMix.GetAsmLines(n) + 1));
    while(nAsm >= k) {
        nAsm -= k;        
        ++ n;
        if(n < nSrcLines) k = (m_bBrowse?(BwsMix.GetAsmLines(n)+1):(SrcMix.GetAsmLines(n)+ 1));
    }                                          
    -- nAsm;                      
    return  n;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceMixed::Addr2Ofs(int nBank, unsigned short uAddr) const
{
    POSITION pos = m_AsmList.GetHeadPosition();
    AsmLine * pAsm;
    int i = 0, j = -1, k;                                            
    while(pos) {
        pAsm = (AsmLine *)m_AsmList.GetNext(pos);
        if(uAddr == pAsm->m_uAddr && pAsm->m_chLabel == 0&&
        	nBank==pAsm->m_nBank) {
            j = i;  break;
        } else ++ i;
    }               
    
    if(j == -1) return m_bBrowse?BWSMIXLINES:MIXLINES;
    
    for(i = 0, k = -1; i < m_nSrcLines && m_nAsmPos[i] <= j; i ++) {
        if(m_nAsmPos[i] == -1)  continue;
        else    k = i;            
    }           
    if(k == -1) return m_bBrowse?BWSMIXLINES:MIXLINES;
    else return  j + k + 1;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcCleanAsm(void)
{
    SrcAsm.DeleteList();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcCleanMix(void)
{
    SrcMix.DeleteList();
}


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