#help_index "InFile;Help System/Training"
#help_file "::/Doc/InFile"

public U0 InGetStr(U8 *st)
{//Wait for user to type certain str.
    I64 ch, sc;
    U8  buf[256], *st2;

    while (*st)
    {
        ch=KeyGet(&sc,FALSE);
        if (sc.u8[0] != SC_SHIFT &&
                    sc.u8[0] != SC_ALT &&
                    sc.u8[0] != SC_CTRL)
        {
            if (ch == *st)
            {
                '' ch;
                st++;
            }
            else
            {
                st2 = Char2KeyName(*st);
                StrPrint(buf, "Press the $GREEN$<%s>$FG$ key.", st2);
                Free(st2);
                PopUpOk(buf);
            }
        }
    }
}

public U0 InPrint(I64 mS=100, U8 *format,...)
{//Print message with delay after each char.
    U8 *buf = StrPrintJoin(NULL, format, argc, argv), *st=buf;
    I64 ch;

    while (ch = *st++)
    {
        '' ch;
        Sleep(mS);
    }
    Free(buf);
}

public U0 InKeyGet(I64 scan_code, I64 sc_mask = 0xFF | SCF_SHIFT | SCF_CTRL | SCF_ALT)
{//Wait for user to press certain key.
    I64 sc, ch;
    U8  buf[STR_LEN], *st;

    do
    {
        ch = KeyGet(&sc);
        if (sc.u8[0] != SC_PRINTSCREEN1 &&
                    !(sc.u8[0] == SC_SHIFT && scan_code & SCF_SHIFT) &&
                    !(sc.u8[0] == SC_CTRL && scan_code & SCF_CTRL) &&
                    !(sc.u8[0] == SC_ALT && scan_code & SCF_ALT) )
        {
            if (sc & sc_mask != scan_code & sc_mask)
            {
                st = ScanCode2KeyName(scan_code);
                StrPrint(buf, "Press the $GREEN$<%s>$FG$ key", st);
                Free(st);
                PopUpOk(buf);
            }
        }
    }
    while (sc & sc_mask != scan_code & sc_mask);

    Message(MESSAGE_KEY_DOWN, ch, sc);
}

public I64 InCharGet(...)
{//Wait for user to press one of set of chars.
    I64 i, sc, ch;
    U8  buf[512], *st;

    while (TRUE)
    {
        ch = KeyGet(&sc);
        if (sc.u8[0] != SC_SHIFT && sc.u8[0] != SC_ALT && sc.u8[0] != SC_CTRL)
        {
            for (i = 0; i < argc; i++)
                if (ch == argv[i])
                {
                    Message(MESSAGE_KEY_DOWN, ch, sc);
                    return ch;
                }
            StrPrint(buf, "Press ");
            for (i = 0; i < argc; i++)
            {
                st = Char2KeyName(argv[i]);
                CatPrint(buf, "$GREEN$<%s>$FG$", st);
                Free(st);
                if (argc == i+1)
                    CatPrint(buf, ".");
                else if (argc == i + 2)
                    CatPrint(buf, " or ");
                else
                    CatPrint(buf, ", ");
            }
            PopUpOk(buf);
        }
    }
}

public U0 InUntilKey(I64 scan_code, I64 sc_mask = 0xFF | SCF_SHIFT | SCF_CTRL | SCF_ALT)
{//Let user type until he presses certain key.
    I64 sc, ch;

    do
    {
        ch = KeyGet(&sc);
        Message(MESSAGE_KEY_DOWN, ch, sc);
    }
    while (sc & sc_mask != scan_code & sc_mask);
}

public I64 InUntilChar(...)
{//Let user type until he presses one of set of chars.
    I64 i, sc, ch;

    while (TRUE)
    {
        ch = KeyGet(&sc);
        Message(MESSAGE_KEY_DOWN, ch, sc);
        for (i = 0 ;i < argc; i++)
            if (ch == argv[i])
                return ch;
    }
}

public Bool InView()
{//Let user type until <ESC> or <SHIFT-ESC>.
    Bool res = View;

    DocBottom;

    return res;
}

#help_index "InFile;Help System/Training;Mouse"
I64 in_plot_l, in_plot_r;

Bool InSetMousePlot(I64 mS, I64 x, I64 y, I64 z)
{
    MouseSet(x, y, z, in_plot_l, in_plot_r);
    Sleep(mS);

    return TRUE;
}

public U0 InSetMouse(I64 mS=7, I64 x = I64_MAX, I64 y = I64_MAX, I64 z = I64_MAX, I64 l = I64_MAX, I64 r = I64_MAX)
{//Move mouse to spot at certain speed.
    if (!(0 <= x < GR_WIDTH))
        x = mouse.pos.x;
    if (!(0 <= y < GR_HEIGHT))
        y = mouse.pos.y;
    if (z == I64_MAX)
        z = mouse.pos.z;
    if (!(FALSE <= l <= TRUE))
        l = mouse.lb;
    if (!(FALSE <= r <= TRUE))
        r = mouse.rb;
    in_plot_l = l; in_plot_r = r;
    Line(mS, mouse.pos.x, mouse.pos.y, mouse.pos.z, x, y, z, &InSetMousePlot);
}