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

/////////////////////////////////////////////////////////////////////////////
//
//  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 "address.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 "flttool.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;    
extern BOOL bFile;
/////////////////////////////////////////////////////////////////////////////

#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);
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//  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;         
    
} 

/////////////////////////////////////////////////////////////////////////////
//  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


/////////////////////////////////////////////////////////////////////////////
// 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(ANSI_FIXED_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;          
}

/////////////////////////////////////////////////////////////////////////////
// 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;
*/                          
	//for shell syntax color
    if(m_isAsm) return;
	
	if ( !bFile ) return;
	int nArgc = 0;
	SynColor syncolor[100];                      
		
	m_SEdit.GetHints(nArgc, syncolor);
	m_MsgBar.ShowText(nArgc, syncolor);
    	                                 
    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);
	//for shell syntax color
	str.MakeLower();	                  
	if (m_SEdit.m_nPos == m_SEdit.m_nLength ) {
    	nPos = m_SEdit.m_nPos-1;
	}	       
	else {
		nPos = m_SEdit.m_nPos;
	}                          	

	if (str.Find(';') == -1) {
		if ( !str.IsEmpty() && 
			str.Find("alias") != 0 && (str[nPos] == ' ' || 
			m_SEdit.m_nPos == m_SEdit.m_nLength)) {
			if ( m_SEdit.m_nLength != 255) {
				char ch = ' ';
				m_SEdit.InsChar(ch);
				ShowHints();
				m_SEdit.m_nPos--;
				m_SEdit.DelChar();		
				INPUTLEN = EDITLEN + PROMPTLEN;
				HorzAjust();
			}	
		}
	}	                

    // Get the editor buffer contents and its number.
    char pchBuf[257];
    for ( int i = 0; i <= 255; i++ ) {
        pchBuf[i] = m_SEdit.m_pchText[i-PROMPTLEN];
    }                       
    pchBuf[i] = '\0';
    int nLen;
    if (m_SEdit.m_nLength >= 254)
    	nLen = 255;
    else 
		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);                 
                
    CommandProcess(pchBuf, nLen);
        
    if(nAsmFlag) {
        nShellPrompt = PMT_RND;
        PROMPTLEN = 10;
        m_isAsm = TRUE;  
    }    
	else if ( isDefineMacro ) {
    	nShellPrompt = PMT_MACRO;
    	PROMPTLEN = 6;        
    } 
    else {
        m_isAsm = FALSE;
        nShellPrompt = PMT_NORMAL;
    } 
    
    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;
}                                                            

/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CShellWindow, CMDIChildWnd)

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_SYSKEYDOWN()
    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

    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
    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
    CreateSolidCaret(2, FONTY);
    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();
            	ShowHints();
            }	
            else    MessageBeep(-1);
            break;              
            
        case VK_RIGHT:
            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;   
    }
    
    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);
        TstOpenLog(dlgLog.GetPathName());
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileLoggingoff()
{
    // TODO: Add your command handler code here
    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(TstGetLogOn() && TstGetLogOpened());
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileLoggingon()
{
    // TODO: Add your command handler code here
    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(!TstGetLogOn() && TstGetLogOpened());
}

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

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnFileCloselogfile()
{
    // TODO: Add your command handler code here
    TstCloseLog();
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void CShellWindow::OnUpdateFileCloselogfile(CCmdUI* pCmdUI)
{
    // TODO: Add your command update UI handler code here
    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)///////////////////////////////////////
