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

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  SHLWIN.CPP
//
//  Description:The implement file for the class: CShellWindow
//
//  Author:     Roger Zhang
//
//  Date:       03/10/95
//
//  Modification:
//
//      1. 03/10/95, Initial version 
//
//      2. 09/08/95  0.1a
//
//         2.1 Fixed bug No.41 
//              Modify function: OnReturn
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

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

#include "uicom.h"   
#include "shlcom.h"
#include "shlbuf.h"
#include "shledit.h"
#include "shledit1.h"
#include "spin.h"
#include "shlmsgbr.h"
#include "shlhist.h"
#include "shllogdi.h"
#include "paredit.h"
#include "shlhstdi.h"
#include "shlwin.h"
#include "direct.h"

#include "aliaspub.h"

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

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

extern char szAppPath[_MAX_PATH+1];
//extern int nMaxCmdNo;
extern BOOL isToupper;
extern BOOL isStr;
extern BOOL isDefineMacro;
extern BOOL isRunMacro;
/////////////////////////////////////////////////////////////////////////////

#define PROMPTLEN   PromptLen[nShellPrompt]
#define PROMPTSTR   PromptStr[nShellPrompt]
#define BUFLINES    (m_Buf.m_nLines)
#define POSX        (m_SEdit.m_nPos + PROMPTLEN) 
#define POSY        (m_Buf.m_nLines - 1)
#define EDITLEN     (m_SEdit.m_nLength)
#define LINELEN(i)  (m_Buf.m_LinePtr[i]->m_nLength)
#define LINEPTR(i)  (m_Buf.m_LinePtr[i]->m_pchLine)
#define INPUTLEN    LINELEN(m_Buf.m_nLines - 1)
#define INPUTPTR    LINEPTR(m_Buf.m_nLines - 1)
#define CLIENTX     (m_szClient.cx) 
#define CLIENTY     (m_szClient.cy) 
#define FONTX       (m_szFont.cx)
#define FONTY       (m_szFont.cy)
#define SCRLEFT     (m_rectScroll.left)
#define SCRRIGHT    (m_rectScroll.right)
#define SCRTOP      (m_rectScroll.top)
#define SCRBOTTOM   (m_rectScroll.bottom)
#define BUFX        (m_ptBuf.x)
#define BUFY        (m_ptBuf.y)

/////////////////////////////////////////////////////////////////////////////
int nAsmFlag = 0;    
BOOL isFirstToken = FALSE;

void CommandProcess(char* pchBuf, int nLen);
void ShlReshowLine(char * pch, int nLen);
/////////////////////////////////////////////////////////////////////////////
/*
tagCmdTable* CommandRecord; 

void SplitCommand(CString& strLine,CString& strCommand, CString& strMinKeyword, CString& strHints )
{
	// Get Command token.        
	enum { delimiter = ';', space = ' ' };
	CString strTemp(strLine);
	int nFind = strLine.Find(delimiter);
	if ( -1 == nFind ) {
		return;
	}
	strCommand = strLine.Left(nFind);
	strTemp = strLine.Right(strLine.GetLength()-nFind-1);
	nFind = strTemp.Find(delimiter);
	if ( -1 == nFind ) {
		return;
	}
	strMinKeyword = strTemp.Left(nFind);
	strHints = strTemp.Right(strTemp.GetLength()-nFind-1);
	strHints = strHints.Left(strHints.GetLength()-2);			     
}
*/

/////////////////////////////////////////////////////////////////////////////
//  Name:           ShlOpenWindow 
//  Description:    Open shell window
//  Parameter:      
//      pParent(in):    The owner window of the shell window
/////////////////////////////////////////////////////////////////////////////
void ShlOpenWindow(CMDIFrameWnd * pParent, BOOL isHide)
{
    if(isShellOn)    return;
    pShellWnd = new CShellWindow;                     
    DWORD dwFlag = isHide ? 0 : WS_VISIBLE;
    if(!((CShellWindow *)pShellWnd)->Create("Shell", WS_CHILD
        |WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL|WS_CLIPCHILDREN|dwFlag,
        CFrameWnd::rectDefault, pParent))
        ASSERT(0);
    isShellOn = TRUE;         
    
// Add by Annie, 3/27/96                                
/*
	CommandRecord = new tagCmdTable[nMaxCmdNo];    
	if (!CommandRecord)
		AfxMessageBox("Insufficient Memory !");
	ASSERT(CommandRecord);	
	CString strPath, strFile;
	
	strPath = ::szAppPath;
	mkdir(strPath);                 
	#ifdef _GATES        
	strFile = strPath + "gates.txt";	
	#else
	strFile = strPath + "expand.txt";
	#endif	
	// Assign the open flag.
    CFileStatus status;
	if ( !CFile::GetStatus(strFile, status) ) {
		AfxMessageBox("Cannot find the file:expand.txt");
		nMaxCmdNo = 0;		
		return;
	}

	// Open the record file.
	UINT nOpenFlag = CFile::modeRead | CFile::typeText;
	CStdioFile* fp = new CStdioFile(strFile, nOpenFlag);
	
	// Read from the record file.
	int nMax = 256;
	char* pszLine = new char[nMax];
	//tagCmdTable* CommandRecord = new tagCmdTable[nMaxCmdNo];
	CString strCommand, strMinKeyword, strHints;
	
	int i=0;
	while ( fp->ReadString(pszLine, nMax) ) {
		// Split string.
		SplitCommand(CString(pszLine), strCommand, strMinKeyword, strHints);
		CommandRecord[i].pszCommandName = new char[50];
		ASSERT(CommandRecord[i].pszCommandName);
		CommandRecord[i].pszHints = new char[200];
		ASSERT(CommandRecord[i].pszHints);
		strcpy(CommandRecord[i].pszCommandName, strCommand);
		CommandRecord[i].nMinKeyword = int(atoi(strMinKeyword));
		strcpy(CommandRecord[i].pszHints, strHints);
		i++;
		if (i > nMaxCmdNo) break;;		
	}               
	while (i<nMaxCmdNo) {
	    CommandRecord[i].pszCommandName = new char[10];
		CommandRecord[i].pszHints = new char[10];
		strcpy(CommandRecord[i].pszCommandName, " ");
	    strcpy(CommandRecord[i].pszHints, " "); 
		CommandRecord[i].nMinKeyword = 0;	    
	    i++;
	}
	delete []pszLine;
	
	// Close the record file.
	fp->Close();
	delete fp;	
*/
	//Only for test
	//MakeTable();	
} 

/////////////////////////////////////////////////////////////////////////////
//  Name:           ShlShowLine
//  Description:    Show text line in the shell window, auto 
//                  execute line feed
//  Parameter:      
//      pch(in):        text to show
//      nLen(in):       text length
/////////////////////////////////////////////////////////////////////////////
void ShlShowLine(char * pch, int nLen)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->AddDispLine(pch, nLen, TRUE);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void ShlStopAsm(void)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->StopAsm();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void ShlRunInclude(const char * pszFileName)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->RunInclude(pszFileName);
}
      
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void ShlRunMacro(char * pszCommand, int nLen)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->RunMacro(pszCommand, nLen);

}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void ShlShowLineNoWS(char * pch, int nLen)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->AddDispLine(pch, nLen, FALSE);
}

/////////////////////////////////////////////////////////////////////////////
//  Name:           ShlReshowLine
//  Description:    Show text line in the last line of the shell 
//                  window, auto execute line feed
//  Parameter:      
//      pch(in):        text to show
//      nLen(in):       text length
/////////////////////////////////////////////////////////////////////////////
void ShlReshowLine(char * pch, int nLen)
{
    if(!isShellOn)  return;
    ((CShellWindow *)pShellWnd)->OvrDispLine(pch, nLen);
}

/////////////////////////////////////////////////////////////////////////////
CMenu NEAR CShellWindow::m_menu;                              

/////////////////////////////////////////////////////////////////////////////
// CShellWindow

IMPLEMENT_DYNCREATE(CShellWindow, CMDIChildWnd)

/////////////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::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_SHELL);
    m_hMenuShared = m_menu.m_hMenu;

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

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CShellWindow::CShellWindow()
: m_nFont(STANDARD_FONT), m_ptBuf(0,0), m_isCaretOn(FALSE),
  m_isScrolling(FALSE), m_isEdting(FALSE), m_isCaretVisible(FALSE),
  m_isAsm(FALSE)
{                
    m_nIDHelp = IDR_SHELL;

    nAsmFlag = 0;
    nShellPrompt = PMT_NORMAL;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CShellWindow::~CShellWindow()
{     
    isShellOn = FALSE;          
    //Add by Annie, 3/27/96
    /*
    if (CommandRecord) {
    	for (int i=0 ; i<nMaxCmdNo; i++) {
    		delete []CommandRecord[i].pszCommandName;
    		delete []CommandRecord[i].pszHints;
    	}                              
    	delete []CommandRecord;    	
    }
    */
    //Only for test
    //FreeTable();
}

/////////////////////////////////////////////////////////////////////////////
// Caret Handler
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::StopAsm(void)
{
    RestoreInput();
    if(m_isAsm) {
        nAsmFlag = 0;
        m_isAsm = FALSE;
        nShellPrompt = PMT_NORMAL;
        AddInputLine();
        SwitchCaret();
    }
} 

void CShellWindow::ShowHints(void)
{   	
	if(m_isAsm)	return;
	CString str = m_SEdit.GetHints();
    m_MsgBar.ShowText(str.GetBuffer(str.GetLength()));
    return;
}

void CShellWindow::AddCommand(char * pch, int nLen)
{
    m_SEdit.Clear();
    m_SEdit.InsString(pch, nLen);    
    INPUTLEN = EDITLEN + PROMPTLEN;
}                                

void CShellWindow::RunInclude(const char * pszFileName)
{
    ASSERT(pszFileName);
    
    char pch[256];
    
    strcpy(pch, "Include ");
    strcat(pch, pszFileName);
    int nLen = strlen(pch);
    
    StopAsm();
    AddCommand(pch, nLen);
    int i = (BUFLINES - BUFY - 1) * FONTY + SCRTOP;
    CRect   rect(SCRLEFT, i, SCRRIGHT, i + FONTY); 
    InvalidateRect(&rect);
    UpdateWindow();
    OnReturn();
}

void CShellWindow::RunMacro(const char * pszCommand, int nLen)
{
    ASSERT(pszCommand);
                             
	if (nLen > 251)  nLen = 251;
		                             
    char pch[256];
    memset(pch, 0, 256);
    strncpy(pch, pszCommand, nLen);
    
    StopAsm();
    AddCommand(pch, nLen);
    
    int i = (BUFLINES - BUFY - 1) * FONTY + SCRTOP;
    CRect   rect(SCRLEFT, i, SCRRIGHT, i + FONTY); 
    InvalidateRect(&rect);
    UpdateWindow();
    OnReturn();
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::SetCaret(void)
{                           
    if(!m_isCaretOn)  return;
    int i = POSX - BUFX;
    int j = POSY - BUFY;
    if(i < 0 || i > CLIENTX - 1 || j < 0 || j > CLIENTY - 1) {
        i = -10;    j = -10;   // Hide Caret 
    }
    CPoint pt(i * FONTX + SHLHZEDGE, j * FONTY + SHLVTEDGE);
    SetCaretPos(pt);
}                            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::SwitchCaret(void)
{
    SetCaret();
    if(!m_isCaretOn)  return;
    if(!m_isCaretVisible && m_isEdting) { 
        ShowCaret();
        m_isCaretVisible = TRUE;
        SetCaret();
    }
    else if(m_isCaretVisible && !m_isEdting) {
        HideCaret();
        m_isCaretVisible = FALSE;
    }
}
                                                       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnMoveCaret(void)
{
    int i;
    if(!IsHorzIn()) {
        if(POSX < CLIENTX)    i = 0;
        else i = POSX + 1 - CLIENTX;
        ScrollHorz(i);
    } else SetCaret();
}

/////////////////////////////////////////////////////////////////////////////
// Scroll Window
/////////////////////////////////////////////////////////////////////////////                                                       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::ScrollHorz(int nIdx)
{
    if(nIdx == BUFX) return;
    ScrollWindow(FONTX * (BUFX - nIdx), 0, &m_rectScroll, &m_rectScroll);
    BUFX = nIdx;
    SetScrollPos(SB_HORZ, BUFX);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::ScrollVert(int nIdx)
{
    if(nIdx == BUFY) return;
    ScrollWindow(0, FONTY * (BUFY - nIdx), &m_rectScroll, &m_rectScroll);
    BUFY = nIdx;
    SetScrollPos(SB_VERT, BUFY);
}

/////////////////////////////////////////////////////////////////////////////
// Check if caret in view
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::IsHorzIn(void)
{                                  
    int i = POSX - BUFX;
    return  i >= 0 && i < CLIENTX;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::IsVertIn(void)
{                                  
    int i = POSY - BUFY;
    return  i >= 0 && i < CLIENTY;
}
 
/////////////////////////////////////////////////////////////////////////////
// Set caret in view
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::RestoreInput(void)
{                                    
    BOOL isRedraw = FALSE;
    if(!IsHorzIn()) {
        if(POSX + m_nRsv < CLIENTX)    BUFX = 0;
        else BUFX = POSX + 1 - CLIENTX + m_nRsv;
        SetScrollPos(SB_HORZ, BUFX);
        isRedraw = TRUE;
    }
    if(!IsVertIn()) {
        if(POSY < CLIENTY)    BUFY = 0;
        else BUFY = BUFLINES - CLIENTY;
        SetScrollPos(SB_VERT, BUFY);
        isRedraw = TRUE;
    }
    if(isRedraw)    Invalidate();    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::HorzAjust(void)
{       
    int i;
    RedrawEdit();    
    if(!IsHorzIn()) {
        if(POSX + m_nRsv < CLIENTX)    i = 0;
        else i = POSX + 1 - CLIENTX + m_nRsv;
        ScrollHorz(i);
        UpdateWindow();
    };
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::VertAjust(void)
{       
    ScrollWindow(0, -FONTY, &m_rectScroll, &m_rectScroll);
    UpdateWindow();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::RedrawEdit(void)
{                            
    int i = (POSY - BUFY) * FONTY + SCRTOP;
    CRect   rect(SCRLEFT, i, SCRRIGHT, i + FONTY); 
    InvalidateRect(&rect);
    UpdateWindow();
}                 
                      
/////////////////////////////////////////////////////////////////////////////
// Called when press CR key
/////////////////////////////////////////////////////////////////////////////                      
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnReturn(void)
{                          
    //Add by Annie, 3/29/96 
    //for Auto-Expansion, 
    //case: 1.Fill 0 0xff "dd # dd"
	isStr = FALSE;
	isToupper = TRUE;      
	
	//case: 2.R+Enter  
	CString str(m_SEdit.m_pchText);   
	int nPos = 0;
	str = str.Left(m_SEdit.m_nLength);
	str.TrimLeft();
	str.MakeLower();	                  
	if (m_SEdit.m_nPos == m_SEdit.m_nLength ) {
    	nPos = m_SEdit.m_nPos-1;
	}	       
	else {
		nPos = m_SEdit.m_nPos;
	}
	
//	if (m_SEdit.m_nPos >= m_SEdit.m_nLength) {
	if (str.Find(';') == -1) {
		if ( !str.IsEmpty() && //str[str.GetLength()-1] != ' ' && 
			str.Find("alias") != 0 && (str[nPos] == ' ' || 
			m_SEdit.m_nPos == m_SEdit.m_nLength)) {
			char ch = ' ';
			m_SEdit.InsChar(ch);
			//HorzAjust();
			ShowHints();
			m_SEdit.m_nPos--;
			m_SEdit.DelChar();		
			INPUTLEN = EDITLEN + PROMPTLEN;
			HorzAjust();
		}
	}	                

    // Get the editor buffer contents and its number.
    // Added by Chen, 04/04/95
    char pchBuf[257];
    for ( int i = 0; i <= 255; i++ ) {
// 	for (int i=PROMPTLEN; i< 255; i++) { 
        pchBuf[i] = m_SEdit.m_pchText[i-PROMPTLEN];
    }                       
    pchBuf[i] = '\0';
    int nLen;
    if (m_SEdit.m_nLength > 255)
    	nLen = 255;
    else 
		nLen = m_SEdit.m_nLength;    		
	
    //int nLen = m_SEdit.m_nLength;

    ////////////////////////////////////////////////
    m_Buf.Shrink();
    if(!m_isAsm && INPUTLEN > PROMPTLEN) {
        if(m_Hist.m_nMaxSize > 0) { 
            m_Hist.AddTail(INPUTPTR + PROMPTLEN,               
                INPUTLEN - PROMPTLEN);
        }
    }            
    m_isEdting = FALSE;
    SwitchCaret();    
    ScrollHorz(0);                 
                
    /*if(m_isAsm) {
       DadAssemble(pchBuf);
    } else { */              
//////////////////////////////////////////////////////////////////////
// Added by Chen, 04/04/95
//          
	        
	
        //extern void CommandProcess(char* pchBuf, int nLen);
	        
        CommandProcess(pchBuf, nLen);
        
        if(nAsmFlag) {
            nShellPrompt = PMT_RND;
            PROMPTLEN = 7;
            m_isAsm = TRUE;  
        }    
		//Add by Annie, 4/2/96 
		else if( isDefineMacro ) {
        	nShellPrompt = PMT_MACRO;
        	PROMPTLEN = 6;        
        } else {
            m_isAsm = FALSE;
            nShellPrompt = PMT_NORMAL;
        } 
   // }
    
///////////////////////////////////////////////////////////////
/*
    for(int i = 0; i < 2; i ++) {       
       // if(TestKey(VK_ESCAPE)) break;
        AddDispLine(pszText[i], strlen(pszText[i]));
    }                                        
    for(;;) {
        if(TestKey(VK_ESCAPE)) break;
    }
    OvrDispLine("hhhh", 4);
    for(;;) {
        if(TestKey(VK_ESCAPE)) break;
    }*/
    AddInputLine();
    m_isEdting = TRUE;
    SwitchCaret();    
}                          

/////////////////////////////////////////////////////////////////////////////
// Show Line in window
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::AddInputLine(void)
{
    BOOL is = FALSE;
    if(BUFLINES == MAX_SHELL_LINES) is = TRUE;
    else if(POSY >= BUFY + CLIENTY - 1) {
        is = TRUE;  ++ BUFY;
    }
    m_Buf.AddInputLine();                    
    m_SEdit.SetNew(INPUTPTR + PROMPTLEN, MAX_SHELL_LEN - PROMPTLEN);
    if(CLIENTY >= BUFLINES) {
        SetScrollRange(SB_VERT, 0, 0);
    } else {
        SetScrollRange(SB_VERT, 0, BUFLINES - CLIENTY);
    }
    SetScrollPos(SB_VERT, BUFY);
    if(is)  VertAjust();
    HorzAjust();          
    ShowHints();
    //Annie, 4/19/96 
    isFirstToken = TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::AddDispLine(char * pch, int nLen, BOOL isWS)
{
    BOOL is = FALSE;
    if(BUFLINES == MAX_SHELL_LINES) is = TRUE;
    else if(POSY >= BUFY + CLIENTY - 1) {
        is = TRUE;  ++ BUFY;
    }
    m_Buf.AddDispLine(pch, nLen, isWS);                    
    if(CLIENTY >= BUFLINES) {
        SetScrollRange(SB_VERT, 0, 0);
    } else {
        SetScrollRange(SB_VERT, 0, BUFLINES - CLIENTY);
    }
    SetScrollPos(SB_VERT, BUFY);
    if(is)  VertAjust();
    else {
        int i = (BUFLINES - 1) * FONTY + SCRTOP;
        CRect   rect(SCRLEFT, i, SCRRIGHT, i + FONTY); 
        InvalidateRect(&rect);
        UpdateWindow();
    }
}                                         

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OvrDispLine(char * pch, int nLen)
{
    if(!m_Buf.OvrDispLine(pch, nLen)) return;
    int i = (BUFLINES - BUFY - 1) * FONTY + SCRTOP;
    CRect   rect(SCRLEFT, i, SCRRIGHT, i + FONTY); 
    InvalidateRect(&rect);
    UpdateWindow();
} 

/////////////////////////////////////////////////////////////////////////////
// Recall history
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::RecallPrev(void)
{                  
	if(m_isAsm)	return TRUE;
	
    if(m_Hist.IsEmpty() || m_Hist.m_nMaxSize <= 0) { 
        MessageBeep(-1);
        return FALSE;
    }
    HistoryElement * p = m_Hist.GetPrev();
    m_SEdit.Clear();
    if(p)   m_SEdit.InsString(p->m_pchElem, p->m_nLength);
    INPUTLEN = EDITLEN + PROMPTLEN;
    HorzAjust();                             
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::RecallNext(void)
{
	if(m_isAsm)	return TRUE;
	
    if(m_Hist.IsEmpty() || m_Hist.m_nMaxSize <= 0) { 
        MessageBeep(-1);
        return FALSE;
    }
    HistoryElement * p = m_Hist.GetNext();
    m_SEdit.Clear();
    if(p)   m_SEdit.InsString(p->m_pchElem, p->m_nLength);
    INPUTLEN = EDITLEN + PROMPTLEN;
    HorzAjust();                             
    return TRUE;
}                                                            

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

BEGIN_MESSAGE_MAP(CShellWindow, CMDIChildWnd)
    //{{AFX_MSG_MAP(CShellWindow)
    ON_WM_CHILDACTIVATE()
    ON_WM_CREATE()
    ON_WM_PAINT()
    ON_WM_SIZE()
    ON_WM_KILLFOCUS()
    ON_WM_SETFOCUS()
    ON_WM_SETCURSOR()
    ON_WM_RBUTTONDOWN()
    ON_WM_HSCROLL()
    ON_WM_VSCROLL()
    ON_WM_GETMINMAXINFO()
    ON_WM_CHAR()
    ON_WM_KEYDOWN()
    ON_WM_LBUTTONDOWN()
    ON_WM_MDIACTIVATE()
    ON_COMMAND(ID_FILE_OPENLOGFILE, OnFileOpenlogfile)
    ON_COMMAND(ID_FILE_LOGGINGOFF, OnFileLoggingoff)
    ON_UPDATE_COMMAND_UI(ID_FILE_LOGGINGOFF, OnUpdateFileLoggingoff)
    ON_COMMAND(ID_FILE_LOGGINGON, OnFileLoggingon)
    ON_UPDATE_COMMAND_UI(ID_FILE_LOGGINGON, OnUpdateFileLoggingon)
    ON_UPDATE_COMMAND_UI(ID_FILE_OPENLOGFILE, OnUpdateFileOpenlogfile)
    ON_COMMAND(ID_FILE_CLOSELOGFILE, OnFileCloselogfile)
    ON_UPDATE_COMMAND_UI(ID_FILE_CLOSELOGFILE, OnUpdateFileCloselogfile)
    ON_COMMAND(ID_OPTIONS_SETHISTORYSIZE, OnOptionsSethistorysize)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CShellWindow message handlers

/////////////////////////////////////////////////////////////////////////////
// Windows standard message handler
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int CShellWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: Add your specialized creation code here
    // Create Message Bar
    //SetMainMenuCheck(m_menu);

    m_MsgBar.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|WS_CLIPCHILDREN, 
        CRect(0,0,1,1),this);
                         
    // Get Font Size                         
    TEXTMETRIC tm;
    CDC * pDC = GetDC();
    pDC->SelectStockObject(m_nFont);
    pDC->GetTextMetrics(&tm);
    FONTY = tm.tmHeight + tm.tmExternalLeading;
    FONTX = tm.tmAveCharWidth;
    ReleaseDC(pDC); 
    
    ////////////////////////
    AddInputLine();                    
    m_isEdting = TRUE;
    SwitchCaret();    

    //m_SEdit.SetNew(INPUTPTR + 1);

    return 0;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    
    // TODO: Add your message handler code here
    dc.SelectStockObject(m_nFont);
    dc.IntersectClipRect(m_rectScroll);
    for(int i = 0; i < CLIENTY; i ++) {
        if(i+BUFY >= BUFLINES) break;
        if(LINELEN(i+BUFY) <= BUFX)   continue;
        dc.TextOut(SHLHZEDGE, i * FONTY + SHLVTEDGE, 
            LINEPTR(i+BUFY) + BUFX, LINELEN(i+BUFY) - BUFX);
    }   
    SwitchCaret();
     // Do not call CMDIChildWnd::OnPaint() for painting messages
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnSize(UINT nType, int cx, int cy)
{
    CMDIChildWnd::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
    m_MsgBar.MoveWindow(-1,cy - MSGBARHT + 1, cx + 2, MSGBARHT,TRUE);
    
    CLIENTX = (cx - SHLHZEDGE*2) / FONTX;
    CLIENTY = (cy - MSGBARHT + 1 - SHLVTEDGE*2) / FONTY;
    m_nRsv = CLIENTX / 4;
    if(m_nRsv == 0)   m_nRsv = 1;

    m_rectScroll.SetRect(SHLHZEDGE, SHLVTEDGE, 
        SHLHZEDGE + CLIENTX*FONTX, SHLVTEDGE + CLIENTY*FONTY);

    if(CLIENTX >= MAX_SHELL_LEN) {
        SetScrollRange(SB_HORZ, 0, 0);
    } else {
        SetScrollRange(SB_HORZ, 0, MAX_SHELL_LEN - CLIENTX);
    }
    BUFX = 0;
    SetScrollPos(SB_HORZ,BUFX);

    if(CLIENTY >= BUFLINES) {
        SetScrollRange(SB_VERT, 0, 0);
    } else {
        SetScrollRange(SB_VERT, 0, BUFLINES - CLIENTY);
    }
    BUFY = 0;
    SetScrollPos(SB_VERT,BUFY);
    
    RestoreInput();
    SetCaret();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
    // TODO: Add your message handler code here and/or call default
    CMDIChildWnd::OnGetMinMaxInfo(lpMMI);
    lpMMI->ptMinTrackSize.y = MSGBARHT + 70;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    switch(nSBCode) {
        case SB_LINELEFT:
            if(BUFX) {
                -- BUFX;
                ScrollWindow(FONTX, 0, &m_rectScroll, &m_rectScroll);
                SetScrollPos(SB_HORZ, BUFX);
                m_isScrolling = TRUE;
            }
            break;
        case SB_LINERIGHT:
            if(BUFX < MAX_SHELL_LEN - CLIENTX) {
                ++BUFX;
                ScrollWindow(-FONTX, 0, &m_rectScroll, &m_rectScroll);
                SetScrollPos(SB_HORZ, BUFX);
                m_isScrolling = TRUE;
            }
            break;     
        case SB_PAGELEFT: 
            if(BUFX == 0)    break;
            if(BUFX > CLIENTX) {
                ScrollWindow(FONTX * CLIENTX, 0, 
                    &m_rectScroll, &m_rectScroll);
                BUFX -= CLIENTX;
                m_isScrolling = TRUE;
            }
            else {
                ScrollWindow(FONTX * BUFX, 0, &m_rectScroll, &m_rectScroll);
                BUFX = 0;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_HORZ, BUFX);
            break;
        case SB_PAGERIGHT:
            if(BUFX >= MAX_SHELL_LEN - CLIENTX)    break;
            if(BUFX + 2 * CLIENTX <= MAX_SHELL_LEN) {
                ScrollWindow(-FONTX * CLIENTX, 0, 
                    &m_rectScroll, &m_rectScroll);
                BUFX += CLIENTX;
                m_isScrolling = TRUE;
            } else {
                ScrollWindow(
                    -FONTX * (MAX_SHELL_LEN - CLIENTX - BUFX), 0, 
                    &m_rectScroll, &m_rectScroll);
                BUFX = MAX_SHELL_LEN - CLIENTX;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_HORZ, BUFX);
            break;
        case SB_THUMBPOSITION:           
        case SB_THUMBTRACK:
            if(int(nPos) == BUFX) break;
            ScrollWindow(FONTX * (BUFX - nPos), 0, 
                &m_rectScroll, &m_rectScroll);
            BUFX = nPos;
            SetScrollPos(SB_HORZ, BUFX);
            m_isScrolling = TRUE;
            break;
    }          
    SetCaret();

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

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    switch(nSBCode) {
        case SB_LINEUP:
            if(BUFY) {
                -- BUFY;
                ScrollWindow(0, FONTY, &m_rectScroll, &m_rectScroll);
                SetScrollPos(SB_VERT, BUFY);
                m_isScrolling = TRUE;
            }
            break;
        case SB_LINEDOWN:
            if(BUFY < BUFLINES - CLIENTY) {
                ++BUFY;
                ScrollWindow(0,-FONTY, &m_rectScroll, &m_rectScroll);
                SetScrollPos(SB_VERT, BUFY);
                m_isScrolling = TRUE;
            }
            break;
        case SB_PAGEUP: 
            if(BUFY == 0)    break;
            if(BUFY > CLIENTY) {
                ScrollWindow(0, FONTY * CLIENTY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY -= CLIENTY;
                m_isScrolling = TRUE;
            } else {
                ScrollWindow(0, FONTY * BUFY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY = 0;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_VERT, BUFY);
            break;
        case SB_PAGEDOWN:
            if(BUFY >= BUFLINES - CLIENTY)    break;
            if(BUFY + 2 * CLIENTY <= BUFLINES) {
                ScrollWindow(0, -FONTY * CLIENTY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY += CLIENTY;
                m_isScrolling = TRUE;
            } else {
                ScrollWindow(0,
                    -FONTY * (BUFLINES - CLIENTY - BUFY), 
                    &m_rectScroll, &m_rectScroll);
                BUFY = BUFLINES - CLIENTY;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_VERT, BUFY);
            break;
        case SB_THUMBPOSITION:           
        case SB_THUMBTRACK:
            if(int(nPos) == BUFY) break;
            ScrollWindow(0, FONTY * (BUFY - nPos), 
                &m_rectScroll, &m_rectScroll);
            BUFY = nPos;
            SetScrollPos(SB_VERT, BUFY);
            m_isScrolling = TRUE;
            break;
    }          
    SetCaret();
    
    CMDIChildWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnRButtonDown(UINT /*nFlags*/, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    
    CMenu * pLocalMenu = new CMenu;
    ASSERT( NULL != pLocalMenu );

    pLocalMenu->CreatePopupMenu();
    pLocalMenu->AppendMenu(MF_STRING, ID_FILE_OPENLOGFILE,
                            "Open Lo&g File...");
    pLocalMenu->AppendMenu(MF_STRING, ID_FILE_CLOSELOGFILE,
                            "&Close Log File");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
    pLocalMenu->AppendMenu(MF_STRING, ID_FILE_LOGGINGON,
                            "Logging o&n");
    pLocalMenu->AppendMenu(MF_STRING, ID_FILE_LOGGINGOFF,
                            "Logging o&ff");
    pLocalMenu->AppendMenu(MF_SEPARATOR);
    pLocalMenu->AppendMenu(MF_STRING, ID_OPTIONS_SETHISTORYSIZE,
                            "Set &History Size...");

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

//    CMDIChildWnd::OnRButtonDown(nFlags, point);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Disable parent window from pre-handling the WM_RBUTTONDOWN 
//                  message
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL CShellWindow::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: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnKillFocus(CWnd* pNewWnd)
{
    CMDIChildWnd::OnKillFocus(pNewWnd);
    HideCaret();
    // TODO: Add your message handler code here
//    if(m_isCaretOn)   {
	    
	    DestroyCaret();
//    }
    m_isCaretOn = FALSE;
    m_isCaretVisible = FALSE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnSetFocus(CWnd* pOldWnd)
{
    CMDIChildWnd::OnSetFocus(pOldWnd);
    
    // TODO: Add your message handler code here
//    if(m_isCaretOn)   return;
    //Add by Annie, 4/11/96
    /*
    if (isInsertOn) 
		CreateSolidCaret(2, FONTY);
	else
		CreateSolidCaret(FONTX, FONTY/2);				    
	*/	
    CreateSolidCaret(2, FONTY);
    //ShowCaret();
    m_isCaretOn = TRUE;
    SwitchCaret();    
    Invalidate();
    UpdateWindow();
}

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

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


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: Add your message handler code here and/or call default
    switch(nChar)
    {
        case VK_BACK:
            if(m_SEdit.BackChar()) {
                INPUTLEN = EDITLEN + PROMPTLEN;
                HorzAjust();                 
				ShowHints();
            } else    MessageBeep(-1);
            break;       
            
        case VK_RETURN:
            OnReturn();
            break;           
            
        case VK_ESCAPE:
            if(m_isAsm) {
                nAsmFlag = 0;
                m_isAsm = FALSE;
                nShellPrompt = PMT_NORMAL;
                AddInputLine();
                SwitchCaret();
            } else if(m_SEdit.Clear()) {
                INPUTLEN = EDITLEN + PROMPTLEN;
                HorzAjust();
				ShowHints();
            } else  MessageBeep(-1);    
            isFirstToken = FALSE;
            isToupper = TRUE;
            break;
            
        default:
            if(BYTE(nChar) < 0x20 || BYTE(nChar) > 0x7F) MessageBeep(-1);
            else if(isInsertOn) {
                if(m_SEdit.InsChar(char(nChar))) {
                    INPUTLEN = EDITLEN + PROMPTLEN;
                    HorzAjust();
                } else    MessageBeep(-1);
            } else {
                if(m_SEdit.OvrChar(char(nChar))) {
                    INPUTLEN = EDITLEN + PROMPTLEN;
                    HorzAjust();                 
                } else    MessageBeep(-1);
            }               
			ShowHints(); 
			if (nChar == ' ') {
				if (isFirstToken)
					isFirstToken = FALSE;			
			}
            break;
    }   
    
    CMDIChildWnd::OnChar(nChar, nRepCnt, nFlags);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: Add your message handler code here and/or call default
    if(m_isScrolling && nChar != VK_PRIOR && nChar != VK_NEXT) {
        m_isScrolling = FALSE;
        RestoreInput();
    }

    switch(nChar) 
    {
        case VK_HOME:
            if(m_SEdit.GotoHome()) {
            	OnMoveCaret();
            	ShowHints();
            }	
            else    MessageBeep(-1);
            break;
    
        case VK_END:
            if(m_SEdit.GotoEnd()) {
            	OnMoveCaret();
            	ShowHints();
            }	
            else    MessageBeep(-1);
            break;              
            
        case VK_LEFT:
            //if(m_SEdit.GotoPrev()) OnMoveCaret(); 
            if(m_SEdit.GotoPrev()) {
            	OnMoveCaret();
            	ShowHints();
            }	
            else    MessageBeep(-1);
            break;              
            
        case VK_RIGHT:
            //if(m_SEdit.GotoNext()) OnMoveCaret();
            if(m_SEdit.GotoNext()) {
            	OnMoveCaret();
            	ShowHints();
            }	
            else    MessageBeep(-1);
            break;              
            
        case VK_UP:
            if(!RecallPrev())   MessageBeep(-1);       
			ShowHints();
			isFirstToken = FALSE;
            break;

        case VK_DOWN:
            if(!RecallNext())   MessageBeep(-1);
			ShowHints();         
			isFirstToken = FALSE;
            break;

        case VK_PRIOR:
            if(BUFY == 0)    break;
            if(BUFY > CLIENTY) {
                ScrollWindow(0, FONTY * CLIENTY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY -= CLIENTY;
                m_isScrolling = TRUE;
            } else {
                ScrollWindow(0, FONTY * BUFY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY = 0;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_VERT, BUFY);
            break;
        
        case VK_NEXT:
            if(BUFY >= BUFLINES - CLIENTY)    break;
            if(BUFY + 2 * CLIENTY <= BUFLINES) {
                ScrollWindow(0, -FONTY * CLIENTY, 
                    &m_rectScroll, &m_rectScroll);
                BUFY += CLIENTY;
                m_isScrolling = TRUE;
            } else {
                ScrollWindow(0,
                    -FONTY * (BUFLINES - CLIENTY - BUFY), 
                    &m_rectScroll, &m_rectScroll);
                BUFY = BUFLINES - CLIENTY;
                m_isScrolling = TRUE;
            }
            SetScrollPos(SB_VERT, BUFY);
            break;
                        
        case VK_DELETE:
            if(m_SEdit.DelChar()) { 
                INPUTLEN = EDITLEN + PROMPTLEN;
                HorzAjust();
      			ShowHints();
            } else    MessageBeep(-1);
            break;   
            //Add by Annie, 4/11/96            
		/*
		case VK_INSERT:            
			if (isInsertOn) {
				CreateSolidCaret(2, FONTY);				
			}
			else {
				CreateSolidCaret(FONTX, FONTY);
			}
		    SwitchCaret();
		    break;
		*/    
    }
    
    CMDIChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    point.x = (point.x - SHLHZEDGE) / FONTX;
    point.y = (point.y - SHLVTEDGE) / FONTY;
    if(m_isEdting) {
        if(point.y + BUFY == BUFLINES - 1) {
            m_SEdit.SetPos(point.x + BUFX - 1);
            SetCaret();                              
        }
    }                             
                             
    CMDIChildWnd::OnLButtonDown(nFlags, point);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, 
    CWnd* pDeactivateWnd)
{
    CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
    
    // TODO: Add your message handler code here
    if(bActivate && pActivateWnd == this)
        GetMDIFrame()->SendMessage(XM_MDIACTIVE, WORD(bActivate), 
            LONG(WID_SHELL));
    else if(!bActivate && !pActivateWnd)
        GetMDIFrame()->SendMessage(XM_MDIACTIVE, WORD(bActivate)); 
}                                                              

/////////////////////////////////////////////////////////////////////////////
// Menu command handler -- File Submenu
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileOpenlogfile()
{
    // TODO: Add your command handler code here
    CLogDialog  dlgLog;
    if(dlgLog.DoModal()==IDOK) {      
        TstSetLogAppend(dlgLog.m_nAppend);
        TstSetLogCommand(dlgLog.m_nCommand);
        //TstSetLogOn(1);
        //TstSetLogOpened(1);
        
        TstOpenLog(dlgLog.GetPathName());

        /*nLogAppend  = dlgLog.m_nAppend;
        nLogCommand = dlgLog.m_nCommand;
        strLogFile = dlgLog.GetPathName();
        AfxMessageBox(strLogFile);
        nLogOpened = 1;
        nLogOn = 1;*/
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileLoggingoff()
{
    // TODO: Add your command handler code here
    //nLogOn = 0;    
    if(TstGetLogOpened())    TstSetLogOn(0);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnUpdateFileLoggingoff(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    //pCmdUI->Enable(nLogOn && nLogOpened);
    pCmdUI->Enable(TstGetLogOn() && TstGetLogOpened());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileLoggingon()
{
    // TODO: Add your command handler code here
    //if(nLogOpened)  nLogOn = 1;    
    if(TstGetLogOpened())  TstSetLogOn(1);    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnUpdateFileLoggingon(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    //pCmdUI->Enable(!nLogOn && nLogOpened);
    pCmdUI->Enable(!TstGetLogOn() && TstGetLogOpened());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnUpdateFileOpenlogfile(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    //pCmdUI->Enable(!nLogOpened);
    pCmdUI->Enable(!TstGetLogOpened());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileCloselogfile()
{
    // TODO: Add your command handler code here
    //nLogOpened = 0; 
    //nLogOn = 0;                   
    TstCloseLog();
    //TstSetLogOn(0);
    //TstSetLogOpened(0);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnUpdateFileCloselogfile(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    //pCmdUI->Enable(nLogOpened);
    pCmdUI->Enable(TstGetLogOpened());
}

/////////////////////////////////////////////////////////////////////////////
// Menu command handler -- Options Submenu
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnOptionsSethistorysize()
{
    // TODO: Add your command handler code here
    
    // Load MUSCROLL.DLL
    HINSTANCE hLib;                                            
    
    if ((hLib = ::LoadLibrary("MUSCROLL.DLL")) < HINSTANCE_ERROR) 
        AfxMessageBox("Can't find MUSCROLL.DLL");
    
    // Run dialog
    CHistoryDialog dlgHist;
    if(dlgHist.DoModal() == IDOK) {
        m_Hist.SetMaxSize(dlgHist.m_nVal);
        nShellHistSize = dlgHist.m_nVal;                    
    }                             
    
    // Free MUSCROLL.DLL
    if(hLib > HINSTANCE_ERROR)   ::FreeLibrary(hLib);
}

void ShellShowTop(void)
{
    if(!isShellOn) {   //  source window hasn't been opened
        ShlOpenWindow((CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
        pShellWnd->BringWindowToTop();
        pShellWnd->ShowWindow(SW_SHOW);
    } else if(pShellWnd->IsIconic()) { // source window is minimized
        pShellWnd->ShowWindow(SW_RESTORE);
    } else {    // source window may be not on top
        pShellWnd->BringWindowToTop();
    }        
}
/////////////////////////////////(EOF)///////////////////////////////////////
