#define M_DASH_THRESHOLD    0.140
#define M_SPACE_THRESHOLD   0.300

U8 *morse_list =
"A.-\0"
"B-...\0"
"C-.-.\0"
"D-..\0"
"E.\0"
"F..-.\0"
"G--.\0"
"H....\0"
"I..\0"
"J.---\0"
"K-.-\0"
"L.-..\0"
"M--\0"
"N-.\0"
"O---\0"
"P.--.\0"
"Q--.-\0"
"R.-.\0"
"S...\0"
"T-\0"
"U..-\0"
"V...-\0"
"W.--\0"
"X-..-\0"
"Y-.--\0"
"Z--..\0"

"1.----\0"
"2..---\0"
"3...--\0"
"4....-\0"
"5.....\0"
"6-....\0"
"7--...\0"
"8---..\0"
"9----.\0"
"0-----\0"

"/-..-.\0"
"+.-.-.\0"
"..-.-.-\0"
",--..--\0"
"?..--..\0"
"(-.--.\0"
")-.--.-\0"
"--....-\0"
"\".-..-.\0"
"_..--.-\0"
"'.----.\0"
":---...\0"
";-.-.-.\0"
"=-...-\0";

U0 MorseTable()
{
    U8 *st;
    I64 i = 0;

    for (i = 0; i < 13; i++ )
    {
        if (st = ListSub(i ,morse_list))
            "$RED$%C$FG$ %-7s ", *st, st + 1;
        if (st = ListSub(i + 13, morse_list))
            "$RED$%C$FG$ %-7s ", *st, st + 1;
        if (st = ListSub(i + 26, morse_list))
            "$RED$%C$FG$ %-7s ", *st, st + 1;
        if (st = ListSub(i + 39, morse_list))
            "$RED$%C$FG$ %-7s ", *st, st + 1;
        '\n';
    }
    '\n';
}

F64  m_start, m_end, dt_down, dt_up;
Bool space_sent;

U8 *MorseTimes(CDoc *, CDocEntry *, CTask *mem_task)
{
    U8 *st = MAlloc(64, mem_task);

    StrPrint(st, "Down:%10.6f Up:%10.6f", dt_down, dt_up);

    return st;
}

I64 MorseWaitKey()
{
    I64 ch;
    F64 dt;

    while (TRUE)
    {
        if (m_start)
        {
            MessageGet(NULL, NULL, 1 << MESSAGE_KEY_UP);
            m_end = tS;
            Sound;
            dt_down = m_end - m_start;
            m_start = 0;
            space_sent = FALSE;
            if (dt_down < M_DASH_THRESHOLD)
                return '.';
            else
                return '-';
        }
        else
        {
            if (!space_sent)
            {
                while (!MessageScan(&ch, NULL, 1 << MESSAGE_KEY_DOWN))
                {
                    dt = tS - m_end;
                    if (dt >= M_SPACE_THRESHOLD)
                    {
                        space_sent = TRUE;
                        return CH_SPACE;
                    }
                    Yield;
                }
            }
            else
                ch = CharGet(, FALSE);
            m_start = tS;
            Sound(74);
            if (ch == CH_SHIFT_ESC || ch == CH_ESC)
            {
                '\n';
                Sound;
                throw; //exit program
            }
            dt_up = m_start - m_end;
            if (!space_sent && dt_up >= M_SPACE_THRESHOLD)
            {
                space_sent = TRUE;
                return CH_SPACE;
            }
        }
    }
}

U0 Morse()
{
    CDocEntry *doc_e;
    I64 ch;
    U8 buf[8], *dst, *src;

    MorseTable;
    m_start = 0;
    m_end = tS;
    dt_down = 0;
    dt_up = 0;
    space_sent = TRUE;

    "$GREEN$";

    doc_e = DocPrint(DocPut, "$TX+TC,\" \"$");
    doc_e->tag_cb = &MorseTimes;

    "$FG$\n";

    dst = buf;
    while (TRUE)
    {
        ch = MorseWaitKey;
        if (ch == CH_SPACE)
        {
            *dst = 0;
            src = morse_list;
            while (*src) {
                if (!StrCompare(src + 1, buf))
                {
                    "$GREEN$%C$FG$", *src;
                    break;
                }
                else
                    src += StrLen(src) + 1;
            }
            '' CH_SPACE;
            dst = buf;
        }
        else
        {
            if (dst - buf < sizeof(buf) - 1)
            {
                '' ch;
                *dst++ = ch;
            }
        }
    }
    Sound;
}

Morse;