// MorseCodeView.cpp : implementation of the CMorseCodeView class
//

#include "stdafx.h"
#include "MorseCode.h"

#include "MorseCodeDoc.h"
#include "MorseCodeView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView

IMPLEMENT_DYNCREATE(CMorseCodeView, CEditView)

BEGIN_MESSAGE_MAP(CMorseCodeView, CEditView)
    //{{AFX_MSG_MAP(CMorseCodeView)
    ON_COMMAND(ID_AM_HIGH, OnAmHigh)
    ON_UPDATE_COMMAND_UI(ID_AM_HIGH, OnUpdateAmHigh)
    ON_COMMAND(ID_AM_LOW, OnAmLow)
    ON_UPDATE_COMMAND_UI(ID_AM_LOW, OnUpdateAmLow)
    ON_COMMAND(ID_COM1, OnCom1)
    ON_UPDATE_COMMAND_UI(ID_COM1, OnUpdateCom1)
    ON_COMMAND(ID_COM2, OnCom2)
    ON_UPDATE_COMMAND_UI(ID_COM2, OnUpdateCom2)
    ON_COMMAND(ID_COM3, OnCom3)
    ON_UPDATE_COMMAND_UI(ID_COM3, OnUpdateCom3)
    ON_COMMAND(ID_COM4, OnCom4)
    ON_UPDATE_COMMAND_UI(ID_COM4, OnUpdateCom4)
    ON_COMMAND(ID_COM5, OnCom5)
    ON_UPDATE_COMMAND_UI(ID_COM5, OnUpdateCom5)
    ON_COMMAND(ID_COM6, OnCom6)
    ON_UPDATE_COMMAND_UI(ID_COM6, OnUpdateCom6)
    ON_COMMAND(ID_COM7, OnCom7)
    ON_UPDATE_COMMAND_UI(ID_COM7, OnUpdateCom7)
    ON_COMMAND(ID_COM8, OnCom8)
    ON_UPDATE_COMMAND_UI(ID_COM8, OnUpdateCom8)
    ON_COMMAND(ID_CW, OnCw)
    ON_UPDATE_COMMAND_UI(ID_CW, OnUpdateCw)
    ON_COMMAND(ID_REPEAT, OnRepeat)
    ON_UPDATE_COMMAND_UI(ID_REPEAT, OnUpdateRepeat)
    ON_COMMAND(ID_SPEED_10, OnSpeed10)
    ON_UPDATE_COMMAND_UI(ID_SPEED_10, OnUpdateSpeed10)
    ON_COMMAND(ID_SPEED_100, OnSpeed100)
    ON_UPDATE_COMMAND_UI(ID_SPEED_100, OnUpdateSpeed100)
    ON_COMMAND(ID_SPEED_2, OnSpeed2)
    ON_UPDATE_COMMAND_UI(ID_SPEED_2, OnUpdateSpeed2)
    ON_COMMAND(ID_SPEED_20, OnSpeed20)
    ON_UPDATE_COMMAND_UI(ID_SPEED_20, OnUpdateSpeed20)
    ON_COMMAND(ID_SPEED_25, OnSpeed25)
    ON_UPDATE_COMMAND_UI(ID_SPEED_25, OnUpdateSpeed25)
    ON_COMMAND(ID_SPEED_3, OnSpeed3)
    ON_UPDATE_COMMAND_UI(ID_SPEED_3, OnUpdateSpeed3)
    ON_COMMAND(ID_SPEED_40, OnSpeed40)
    ON_UPDATE_COMMAND_UI(ID_SPEED_40, OnUpdateSpeed40)
    ON_COMMAND(ID_SPEED_5, OnSpeed5)
    ON_UPDATE_COMMAND_UI(ID_SPEED_5, OnUpdateSpeed5)
    ON_COMMAND(ID_SPEED_50, OnSpeed50)
    ON_UPDATE_COMMAND_UI(ID_SPEED_50, OnUpdateSpeed50)
    ON_COMMAND(ID_SPEED_80, OnSpeed80)
    ON_UPDATE_COMMAND_UI(ID_SPEED_80, OnUpdateSpeed80)
    ON_COMMAND(ID_SPEED_30, OnSpeed30)
    ON_UPDATE_COMMAND_UI(ID_SPEED_30, OnUpdateSpeed30)
    ON_COMMAND(ID_SPEED_1, OnSpeed1)
    ON_UPDATE_COMMAND_UI(ID_SPEED_1, OnUpdateSpeed1)
    ON_WM_SHOWWINDOW()
    ON_COMMAND(ID_TRANSMITTER, OnTransmitter)
    ON_UPDATE_COMMAND_UI(ID_TRANSMITTER, OnUpdateTransmitter)
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CEditView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CEditView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CEditView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView construction/destruction

CMorseCodeView::CMorseCodeView()
{
    // TODO: add construction code here

}

CMorseCodeView::~CMorseCodeView()
{
}

BOOL CMorseCodeView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs

    BOOL bPreCreated = CEditView::PreCreateWindow(cs);
    cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL);         // Enable word-wrapping

    return bPreCreated;
}

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView drawing

void CMorseCodeView::OnDraw(CDC* pDC)
{
    CMorseCodeDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
}

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView printing

BOOL CMorseCodeView::OnPreparePrinting(CPrintInfo* pInfo)
{
    // default CEditView preparation
    return CEditView::OnPreparePrinting(pInfo);
}

void CMorseCodeView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
    // Default CEditView begin printing.
    CEditView::OnBeginPrinting(pDC, pInfo);
}

void CMorseCodeView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
    // Default CEditView end printing
    CEditView::OnEndPrinting(pDC, pInfo);
}

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView diagnostics

#ifdef _DEBUG
void CMorseCodeView::AssertValid() const
{
    CEditView::AssertValid();
}

void CMorseCodeView::Dump(CDumpContext& dc) const
{
    CEditView::Dump(dc);
}

CMorseCodeDoc* CMorseCodeView::GetDocument() // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMorseCodeDoc)));
    return (CMorseCodeDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMorseCodeView message handlers

void CMorseCodeView::OnAmHigh() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_AM_LOW, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_AM_HIGH, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_CW, MF_UNCHECKED | MF_BYCOMMAND);

    modulation( AM_HI );
}

void CMorseCodeView::OnUpdateAmHigh(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnAmLow() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_AM_LOW, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_AM_HIGH, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_CW, MF_UNCHECKED | MF_BYCOMMAND);

    modulation( AM_LO );
}

void CMorseCodeView::OnUpdateAmLow(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
}

void CMorseCodeView::OnCom1() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com1:" );
}

void CMorseCodeView::OnUpdateCom1(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
}

void CMorseCodeView::OnCom2() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com2:" );
}

void CMorseCodeView::OnUpdateCom2(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
}

void CMorseCodeView::OnCom3() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com3:" );
}

void CMorseCodeView::OnUpdateCom3(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
}

void CMorseCodeView::OnCom4() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com4:" );
}

void CMorseCodeView::OnUpdateCom4(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnCom5() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com5:" );
}

void CMorseCodeView::OnUpdateCom5(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnCom6() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com6:" );
}

void CMorseCodeView::OnUpdateCom6(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnCom7() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_UNCHECKED | MF_BYCOMMAND);

    com_port( "com7:" );
}

void CMorseCodeView::OnUpdateCom7(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnCom8() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(5);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_COM1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM4, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM6, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM7, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_COM8, MF_CHECKED | MF_BYCOMMAND);

    com_port( "com8:" );
}

void CMorseCodeView::OnUpdateCom8(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnCw() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_AM_LOW, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_AM_HIGH, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_CW, MF_CHECKED | MF_BYCOMMAND);

    modulation( CW );
}

void CMorseCodeView::OnUpdateCw(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnRepeat() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    UINT state = submenu->GetMenuState( ID_REPEAT, MF_BYCOMMAND );

    if( state & MF_CHECKED )
    {
        repeat( false );
        submenu->CheckMenuItem(ID_REPEAT, MF_UNCHECKED | MF_BYCOMMAND);
    }
    else
    {
        repeat( true );
        submenu->CheckMenuItem(ID_REPEAT, MF_CHECKED | MF_BYCOMMAND);
    }
}

void CMorseCodeView::OnUpdateRepeat(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed10() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 10 );
}

void CMorseCodeView::OnUpdateSpeed10(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed100() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_CHECKED | MF_BYCOMMAND);

    speed( 100);
}

void CMorseCodeView::OnUpdateSpeed100(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed2() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 2 );
}

void CMorseCodeView::OnUpdateSpeed2(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed20() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 20 );
}

void CMorseCodeView::OnUpdateSpeed20(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed25() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 25 );
}

void CMorseCodeView::OnUpdateSpeed25(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed3() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 3 );
}

void CMorseCodeView::OnUpdateSpeed3(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed40() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 40 );
}

void CMorseCodeView::OnUpdateSpeed40(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed5() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 5 );
}

void CMorseCodeView::OnUpdateSpeed5(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed50() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 50 );
}

void CMorseCodeView::OnUpdateSpeed50(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed80() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 80 );
}

void CMorseCodeView::OnUpdateSpeed80(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed30() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 30 );
}

void CMorseCodeView::OnUpdateSpeed30(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnSpeed1() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(4);
    if( ! submenu )
        return;

    submenu->CheckMenuItem(ID_SPEED_1, MF_CHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_2, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_3, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_5, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_10, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_20, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_25, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_30, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_40, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_50, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_80, MF_UNCHECKED | MF_BYCOMMAND);
    submenu->CheckMenuItem(ID_SPEED_100, MF_UNCHECKED | MF_BYCOMMAND);

    speed( 1 );
}

void CMorseCodeView::OnUpdateSpeed1(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here

}

void CMorseCodeView::OnShowWindow(BOOL bShow, UINT nStatus) 
{
    CEditView::OnShowWindow(bShow, nStatus);

    transmitting( false );

    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( mmenu )
    {
        CMenu* submenu = mmenu->GetSubMenu(3);
        if( submenu )
        {
            submenu->CheckMenuItem(ID_AM_HIGH, MF_CHECKED | MF_BYCOMMAND);
            submenu->CheckMenuItem(ID_AM_LOW, MF_UNCHECKED | MF_BYCOMMAND);
            modulation( AM_HI );

            submenu->CheckMenuItem(ID_REPEAT, MF_UNCHECKED | MF_BYCOMMAND);
            repeat( false );
        }

        submenu = mmenu->GetSubMenu(4);
        if( submenu )
        {
            submenu->CheckMenuItem(ID_SPEED_5, MF_CHECKED | MF_BYCOMMAND);
            speed( 5 );
        }

        submenu = mmenu->GetSubMenu(5);
        if( submenu )
        {
            submenu->CheckMenuItem(ID_COM1, MF_CHECKED | MF_BYCOMMAND);
            com_port( "com1:" );
        }
    }
}


# include <time.h>

struct
{
    char l;
    char *c;
}
code[] =
{
    'A', ".-",
    'B', "-...",
    'C', "-.-.",
    'D', "-..",
    'E', ".",
    'F', "..-.",
    'G', "--.",
    'H', "....",
    'I', "..",
    'J', ".---",
    'K', "-.-",
    'L', ".-..",
    'M', "--",
    'N', "-.",
    'O', "---",
    'P', ".--.",
    'Q', "--.-",
    'R', ".-.",
    'S', "...",
    'T', "-",
    'U', "..-",
    'V', "...-",
    'W', ".--",
    'X', "-..-",
    'Y', "-.--",
    'Z', "--..",
    '0', "-----",
    '1', ".----",
    '2', "..---",
    '3', "...--",
    '4', "....-",
    '5', ".....",
    '6', "-....",
    '7', "--...",
    '8', "---..",
    '9', "----.",
    '/', "-..-.",
    '+', ".-.-.",
    '=', "-...-",
    '.', ".-.-.-",
    ',', "--..--",
    '?', "..--..",
    '(', "-.--.",
    ')', "-.--.-",
    '-', "-....-",
    '"', ".-..-.",
    '_', "..--.-",
    '\'', ".----.",
    ':', "---...",
    ';', "-.-.-.",
    '$', "...-..-",
    '\1', "=",
    0, 0,
};


HANDLE hFile = INVALID_HANDLE_VALUE;

bool
CMorseCodeView::opencomm( char *which )
{
    if( hFile != INVALID_HANDLE_VALUE )
        CloseHandle( hFile );

    int da = GENERIC_READ | GENERIC_WRITE;
    int sm = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
    int cd = OPEN_EXISTING;
    int flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING;

    hFile = CreateFile( which, da, sm, 0, cd, flags, 0 );

    if( hFile == INVALID_HANDLE_VALUE )
    {
        printf( "Can't open '%s'\n", which );
        return false;
    }

    DCB dcb;

    if( ! GetCommState( hFile, &dcb ) )
    {
        printf( "Can't get comm state for '%s'\n", which );
        return false;
    }

    dcb.fOutxCtsFlow = FALSE;
    dcb.fOutxDsrFlow = FALSE;
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    dcb.fDsrSensitivity = FALSE;
    dcb.fRtsControl = RTS_CONTROL_DISABLE;

    if( ! SetCommState( hFile, &dcb ) )
    {
        printf( "Can't set comm state for '%s'\n", which );
        return false;
    }

    return true;
}

void
CMorseCodeView::on( void )
{
    EscapeCommFunction( hFile, SETDTR );
    EscapeCommFunction( hFile, SETRTS );
}

void
CMorseCodeView::off( void )
{
    EscapeCommFunction( hFile, CLRDTR );
    EscapeCommFunction( hFile, CLRRTS );
}

void
CMorseCodeView::dot( void )
{
    if( modulation() == CW )
    {
        on();
        Sleep( dot_length );
        off();
    }
    else if( modulation() == AM_HI )
    {
        for( int i = 0; i < dot_length / 2; i++ )
        {
            on();
            Sleep( 1 );
            off();
            Sleep( 1 );
        }
    }
    else if( modulation() == AM_LO )
    {
        for( int i = 0; i < dot_length / 4; i++ )
        {
            on();
            Sleep( 2 );
            off();
            Sleep( 2 );
        }
    }

    Sleep( token_sep );
}

void
CMorseCodeView::dash( void )
{
    if( modulation() == CW )
    {
        on();
        Sleep( dash_length );
        off();
    }
    else if( modulation() == AM_HI )
    {
        for( int i = 0; i < dash_length / 2; i++ )
        {
            on();
            Sleep( 1 );
            off();
            Sleep( 1 );
        }
    }
    else if( modulation() == AM_LO )
    {
        for( int i = 0; i < dash_length / 4; i++ )
        {
            on();
            Sleep( 2 );
            off();
            Sleep( 2 );
        }
    }

    Sleep( token_sep );
}

void
CMorseCodeView::long_tone( void )
{
    printf( "5 second tone\n" );

    on();
    Sleep( 5000 );
    off();
}

char *
CMorseCodeView::lookup( char c )
{
    for( int i = 0; code[i].c; i++ )
        if( code[i].l == c )
            return code[i].c;

    return "";
}

void
CMorseCodeView::send_char( char c )
{
    if( c == ' ' )
    {
        Sleep( space_length );
        return;
    }

    c = toupper( c );

    char *str = lookup( c );

    while( *str )
    {
        if( *str == '.' )
            dot();
        else if( *str == '-' )
            dash();
        else if( *str == '=' )
            long_tone();
        str++;
    }

    Sleep( char_sep );
    off();
}

void
CMorseCodeView::send( char *str )
{
    do
    {
        while( *str && transmitting() )
            send_char( *str++ );
    } while( repeat() && transmitting() );

    transmitting( false );
}

void
CMorseCodeView::send_lines( void )
{
    do
    {
        CEdit & edit = GetEditCtrl();

        int lines = edit.GetLineCount();

        int start_char = 0;

        for( int i = 0; i < lines; i++ )
        {
            char buf[1024*16];

            int num = edit.GetLine( i, buf, sizeof buf - 1 );
            buf[num] = 0;
            char *str = buf;

            while( *str && transmitting() )
            {
                edit.SetSel( start_char, start_char+1 );
                start_char++;
                send_char( *str++ );
            }
            start_char++;       // \r
            start_char++;       // \n
        }
    } while( repeat() && transmitting() );

    transmitting( false );
}

void
CMorseCodeView::set_speed( int the_speed )
{
    dot_length = 100;
    dash_length = 300;
    token_sep = 100;
    char_sep = 300;
    space_length = 700;

    int character_speed = 15;

    //
    // Using + to mean the transmitter is on for one unit,
    // and - to mean it is off for one unit, the word 'PARIS ' looks like
    //
    // P +- +++- +++- +- --             14 units
    // A +- +++- --                      8 units
    // R +- +++- +- --                  10 units
    // I +- +- --                        6 units
    // S +- +- +- --                     8 units
    //   -- --                           4 units
    //                                  ==============
    //                                  50 units total
    //
    // After each dot or dash, we wait one unit.
    // After each letter, we wait three units (i.e. two additional units).
    // After each word, we wait seven units (i.e. four additional units).
    //
    // We want to send the letters at a speed of at least 15 words per
    // minute, so they can be recognized by their sound.  But we want
    // to only send N words per minute.  So, if N is less than 15, we
    // must add extra time to the space between the letters and the
    // words.  After each letter there are 2 units of silence that
    // have to be stretched.  After each word there are 4 units that
    // have to be stretched.  That makes 14 units that have to be stretched.
    // There are 50 units in all, so there are 50 - 14 = 36 units that are
    // not stretched.  The 14 units come in pairs, so we divide by 7 to
    // get the length of each silence.
    //

    if( character_speed < the_speed )   // farnsworth
        character_speed = the_speed;    // all letters sent at 15 wpm minimum

    dot_length = 60 * 1000 / character_speed / 50;     // 60 seconds, 50 units

    dash_length = 3 * dot_length;
    token_sep = dot_length;

    int milliseconds_per_word = 60 * 1000 / the_speed;
    int milliseconds_in_36_units = 36 * 60 * 1000 / character_speed / 50; 

    char_sep = (milliseconds_per_word - milliseconds_in_36_units) / 7;
    space_length = int((milliseconds_per_word - milliseconds_in_36_units) / 3.5);

    if( modulation() == AM_LO )
    {
        dot_length /= 2;
        dash_length /= 2;
    }
}

class InThread
{
    HANDLE h;
    static unsigned long __stdcall entry( void *d );

    virtual void work( void ) = 0;

public:

    InThread( void );
  ~ InThread( void );

    void start( void );
};


unsigned long __stdcall
InThread::entry( void *d )
{
    ((InThread *)d)->work();
    return 0;
}

void
InThread::start( void )
{
    const int sa = 0;                // security attributes (0 = no inheritance)
    const int ss = 1024 * 128;       // stack size
    void *pm = (void *) this;        // parameter sent to thread start routine
    const int cf = 0;                // create flags (0 = start immediately)
    unsigned long tid;

    h = CreateThread( 0, ss, entry, pm, cf, &tid );
    SetThreadPriority( h, THREAD_PRIORITY_TIME_CRITICAL );
}

InThread::InThread( void )
{
    h = INVALID_HANDLE_VALUE;
}

InThread::~InThread( void )
{
    if( h != INVALID_HANDLE_VALUE )
        CloseHandle( h );
    h = INVALID_HANDLE_VALUE;
}

struct StartTransmitting : public InThread
{
    CMorseCodeView *view;

    StartTransmitting( CMorseCodeView *p )
    {
        view = p;
    }

    void work( void )
    {
        view->set_speed( view->speed() );

        view->opencomm( view->com_port() );

        view->off();

        view->send_lines();
    }
};

StartTransmitting *s = 0;

void
CMorseCodeView::kill_morse( void )
{
    transmitting( false );
    Sleep( 200 );
    if( s )
        delete s;
    s = 0;
}

void
CMorseCodeView::init_morse( void )
{
    if( s )     // Should not happen
    {
        kill_morse();
    }

    transmitting( true );
    s = new StartTransmitting( this );
    s->start();
}

void CMorseCodeView::OnTransmitter() 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    UINT state = submenu->GetMenuState( ID_TRANSMITTER, MF_BYCOMMAND );

    if( state & MF_CHECKED )
    {
        if( transmitting() )
        {
            transmitting( false );
            Sleep( 200 );
            kill_morse();
            submenu->CheckMenuItem(ID_TRANSMITTER, MF_UNCHECKED | MF_BYCOMMAND);
        }
        else
        {
            submenu->CheckMenuItem(ID_TRANSMITTER, MF_UNCHECKED | MF_BYCOMMAND);
        }
    }
    else
    {
        if( transmitting() )    // Should not happen
        {
            transmitting( false );
            Sleep( 200 );
            kill_morse();
            init_morse();
            submenu->CheckMenuItem(ID_TRANSMITTER, MF_CHECKED | MF_BYCOMMAND);
        }
        else
        {
            init_morse();
            submenu->CheckMenuItem(ID_TRANSMITTER, MF_CHECKED | MF_BYCOMMAND);
        }
    }
}

void CMorseCodeView::OnUpdateTransmitter(CCmdUI* pCmdUI) 
{
    CMenu* mmenu = GetTopLevelParent()->GetMenu();
    if( ! mmenu )
        return;

    CMenu* submenu = mmenu->GetSubMenu(3);
    if( ! submenu )
        return;

    if( transmitting() )
    {
        submenu->CheckMenuItem(ID_TRANSMITTER, MF_CHECKED | MF_BYCOMMAND);
    }
    else
    {
        submenu->CheckMenuItem(ID_TRANSMITTER, MF_UNCHECKED | MF_BYCOMMAND);
    }
}

