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