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