// --------------------------------------------------------------------------
// Citadel: ScrFunc.CPP
//
// General-purpose Script Functions

#include "ctdl.h"
#pragma hdrstop

#include "scrfunc.h"
#include "aplic.h"
#include "events.h"
#include "net.h"
#include "blurbs.h"
#include "tallybuf.h"
#include "miscovl.h"


// --------------------------------------------------------------------------
// Contents
//
// sfPrintm()			prints to modem/console
// sfPrintc()			prints to console

extern ConsoleLockC ConsoleLock;

void sfPrintm(strList *params)
	{
	for (; params; params = (strList *) getNextLL(params))
		{
		mPrintf(pcts, evaluateString(params->string));
		}
	}

void sfOutstrpaced(strList *params)
	{
	if (params)
		{
		if (params->next)
			{
			OutStringWithPacing(evaluateString(params->string),
				evaluateInt(params->next->string));
			}
		else	//duh
			{
			outstring(evaluateString(params->string));
			}
		}
	}

void sfPrintc(strList *params)
	{
	for (; params; params = (strList *) getNextLL(params))
		{
		cPrintf(pcts, evaluateString(params->string));
		}
	}

void sfGetstr(strList *params)
	{
	const char *prompt;

	if (params)
		{
		prompt = evaluateString(params->string);
		params = (strList *) getNextLL(params);

		if (params)
			{
			char dfault[256];

			strcpy(dfault, evaluateString(params->string));
			params = (strList *) getNextLL(params);

			if (params)
				{
				const int i = min(evaluateInt(params->string), 255);

				getString(prompt, CurScript->wowza, i, FALSE, ECHO, dfault);
				CurScript->lastResult.type = TYPE_STRING_MAX;
				CurScript->lastResult.v.string = CurScript->wowza;
				}
			}
		}
	}

void sfWaitfor(strList *params)
	{
	if (params && params->next)
		{
		SETBOOL(wait_for(evaluateString(params->string),
				evaluateInt(params->next->string)));
		}
	else
		{
		SETBOOL(FALSE);
		}
	}

void sfRandom(strList *params)
	{
	if (params)
		{
		SETINT(random(evaluateInt(params->string)));
		}
	}

void sfSetRandom(strList *)
	{
	randomize();
	}

void sfDoCR(strList *)
	{
	doCR();
	}

void sfDoccr(strList *)
	{
	doccr();
	}

void sfDiskfree(strList *params)
	{
	union REGS REG;

	REG.h.ah = 0x36;
	REG.h.dl = toupper(evaluateString(params->string)[0]) - '@';
	intdos(&REG, &REG);

	SETLONG((long) REG.x.cx * (long) REG.x.ax * (long) REG.x.bx);
	}

void sfThisroom(strList *)
	{
	SETINT(TI()thisRoom);
	}

void sfAdduser(strList *params)
	{
	if (params && params->next)
		{
		groupfunc(evaluateString(params->next->string),
				evaluateString(params->string), TRUE);
		}
	}

void sfRemoveuser(strList *params)
	{
	if (params && params->next)
		{
		groupfunc(evaluateString(params->next->string),
				evaluateString(params->string), FALSE);
		}
	}

void sfAskyn(strList *params)
	{
	if (params && params->next)
		{
		SETINT(getYesNo(evaluateString(params->string),
				evaluateInt(params->next->string)));
		}
	}

// prompt, keys, dflt, ...
void sfGetOneKey(strList *params)
	{
	char Prompt[256];
	char Keys[37];
	char dfault;
	label RepList[36];

	CopyStringToBuffer(Prompt, evaluateString(params->string), sizeof(Prompt) - 1);
	CopyStringToBuffer(Keys, evaluateString(params->next->string), sizeof(Keys) - 1);
	dfault = evaluateString(params->next->next->string)[0];

	strList *wow = params->next->next->next;

	for (int rlC = 0; rlC < 36; rlC++)
		{
		if (wow)
			{
			CopyStringToBuffer(RepList[rlC], evaluateString(wow->string), LABELSIZE);
			wow = (strList *) getNextLL(wow);
			}
		else
			{
			*RepList[rlC] = 0;
			}
		}

	int Result = GetOneKey(Prompt, Keys, dfault, MAXBLBS, RepList[0], RepList[1],
			RepList[2], RepList[3], RepList[4], RepList[5], RepList[6],
			RepList[7], RepList[8], RepList[9], RepList[10], RepList[11],
			RepList[12], RepList[13], RepList[14], RepList[15], RepList[16],
			RepList[17], RepList[18], RepList[19], RepList[20], RepList[21],
			RepList[22], RepList[23], RepList[24], RepList[25], RepList[26],
			RepList[27], RepList[28], RepList[29], RepList[30], RepList[31],
			RepList[32], RepList[33], RepList[34], RepList[35]);

	SETINT(Result);
	}

void sfRunapplic(strList *params)
	{
	const Bool ChDir = params->next ? evaluateBool(params->next->string) : TRUE;
	SETINT(RunApplication(evaluateString(params->string), NULL, TRUE, ChDir));
	}

void sfChatreq(strList *params)
	{
	SETBOOL(ringSysop(evaluateBool(params->string), evaluateBool(params->next->string)));
	}

void sfPlaysound(strList *params)
	{
#ifndef WINCIT
	(*start_snd_src)(evaluateInt(params->string), evaluateString(params->next->string));
	SETINT((*play_sound)(evaluateInt(params->string)));
#endif
	}

void sfSayascii(strList *params)
	{
#ifndef WINCIT
	SETINT((*say_ascii)(evaluateString(params->string), strlen(evaluateString(params->string))));
#endif
	}

void sfGetconnectrate(strList *)
	{
	SETLONG(connectbauds[TI()ModemSpeed]);
	}

void sfGetportrate(strList *)
	{
	SETLONG(bauds[TI()SerialPort.GetSpeed()]);
	}


void sfSetportrate(strList *params)
	{
	Bool Ret;

	if (params)
		{
		PortSpeedE PS = digitbaud(evaluateLong(params->string));

		if (PS != PS_ERROR)
			{
			TI()SerialPort.SetSpeed(PS);
			Ret = TRUE;
			}
		else
			{
			Ret = FALSE;
			}
		}
	else
		{
		TI()SerialPort.SetSpeed(cfg.initbaud);
		Ret = TRUE;
		}

	SETBOOL(Ret);
	}

void sfChat(strList *)
	{
	chat();
	}

void sfDochat(strList *params)
	{
	SETBOOL(doChat(evaluateBool(params->string), evaluateBool(params->next->string)));
	}

void sfGetparam(strList *params)
	{
	char line[256];
	char *words[256];
	int count, i = evaluateInt(params->next->string) - 1;

	strcpy(line, evaluateString(params->string));
	count = parse_it(words, line);

	if (i < count)
		{
		SETSTR(words[i]);
		}
	else
		{
		SETSTR(ns);
		}
	}

void sfGetparamcount(strList *params)
	{
	char line[256];
	char *words[256];

	strcpy(line, evaluateString(params->string));
	SETINT(parse_it(words, line));
	}

void sfIchar(strList *)
	{
	char wow[2];
	wow[1] = 0;

	wow[0] = iChar();

	SETSTR(wow);
	}

void sfIcharne(strList *)
	{
	char wow[2];
	wow[1] = 0;

	wow[0] = iCharNE();

	SETSTR(wow);
	}

void sfGetModemStr(strList *params)
	{
	char wow[256];

	uint len = (params)
			? evaluateUint(params->string)
			: sizeof(wow) - 1;

	if (len > sizeof(wow) - 1)
		{
		len = sizeof(wow) - 1;
		}

	getModStr(wow, len);

	SETSTR(wow);
	}

void sfDumpf(strList *params)
	{
	dumpf(evaluateString(params->string),
			evaluateBool(params->next->string), FALSE);
	}

void sfDumpfc(strList *params)
	{
	dumpfc(evaluateString(params->string),
			evaluateBool(params->next->string));
	}

void sfPause(strList *params)
	{
	pause(evaluateInt(params->string));
	}

void sfGetFormattedString(strList *params)
	{
	char Prompt[256];
	char Result[256];

	strcpy(Prompt, evaluateString(params->string));

	getFmtString(Prompt, Result, evaluateBool(params->next->string),
			evaluateBool(params->next->next->string));

	SETSTR(Result);
	}

void sfAsciitochar(strList *params)
	{
	char wow[2];
	wow[1] = 0;

	wow[0] = evaluateInt(params->string);

	SETSTR(wow);
	}

void sfChartoascii(strList *params)
	{
	SETINT(evaluateString(params->string)[0]);
	}

void sfSformat(strList *params)
	{
	char RepList[10][255];

	strList *wow = params->next->next;

	for (int rlC = 0; rlC < 10; rlC++)
		{
		if (wow)
			{
			strcpy(RepList[rlC], evaluateString(wow->string));
			wow = (strList *) getNextLL(wow);
			}
		else
			{
			*RepList[rlC] = 0;
			}
		}

	char Result[256];
	sformat(Result, evaluateString(params->string),
			evaluateString(params->next->string), RepList[0], RepList[1],
			RepList[2], RepList[3], RepList[4], RepList[5], RepList[6],
			RepList[7], RepList[8], RepList[9]);

	SETSTR(Result);
	}

void sfStrftime(strList *params)
	{
	char Result[256];

	strftime(Result, evaluateInt(params->next->next->string),
			evaluateString(params->string),
			evaluateLong(params->next->string));

	SETSTR(Result);
	}

void sfGetcurrenttime(strList *)
	{
	SETLONG(time(NULL));
	}

void sfHangup(strList *)
	{
	Hangup();
	}

void sfModemflush(strList *)
	{
	TI()SerialPort.Flush();
	}

void sfModeminitport(strList *)
	{
	Initport();
	}

void sfGetContextSensitiveText(strList *)
	{
	SETSTR(TI()ContextSensitiveScriptText);
	}

void sfMemoryFree(strList *)
	{
	SETLONG(farcoreleft());
	}

void sfStartDupCheck(strList *)
	{
	disposeLL((void **) &CurScript->dupCheck);
	}

void sfAddDupCheck(strList *params)
	{
	strList *cur = (strList *) addLL((void **) &CurScript->dupCheck,
			sizeof(strList) + strlen(evaluateString(params->string)));

	if (cur)
		{
		strcpy(cur->string, evaluateString(params->string));
		}

	SETBOOL(cur != NULL);
	}

void sfCheckForDup(strList *params)
	{
	for (strList *cur = CurScript->dupCheck; cur; cur = (strList *) getNextLL(cur))
		{
		if (SameString(cur->string, evaluateString(params->string)))
			{
			break;
			}
		}

	SETBOOL(cur != NULL);
	}

void sfSetOutImpervious(strList *)
	{
	TI()UserControl.SetOutFlag(IMPERVIOUS);
	}

void sfSetOutNormal(strList *)
	{
	TI()UserControl.SetOutFlag(OUTOK);
	}

void sfSetOutNostop(strList *)
	{
	TI()UserControl.SetOutFlag(NOSTOP);
	}

void sfIsCanOutput(strList *)
	{
	SETBOOL(TI()UserControl.CanOutput());
	}

void sfCheckUserOutControl(strList *params)
	{
	SETBOOL(TI()UserControl.CheckInput(evaluateBool(params->string)));
	}

void sfIsOutputStop(strList *)
	{
	SETBOOL(TI()UserControl.GetOutFlag() == OUTSKIP);
	}

void sfIsOutputNext(strList *)
	{
	SETBOOL(TI()UserControl.GetOutFlag() == OUTNEXT);
	}

void sfIsOutputJump(strList *)
	{
	SETBOOL(TI()UserControl.GetOutFlag() == OUTPARAGRAPH);
	}

void sfKeyboardFlush(strList *)
	{
	KeyboardBuffer.Flush();
	}

void sfKeyboardAdd(strList *params)
	{
	Bool Good = TRUE;

	for (; Good && params; params = (strList *) getNextLL(params))
		{
		const char *str = evaluateString(params->string);
		const int slen = strlen(str);

		for (int i = 0; i < slen; i++)
			{
			if (!KeyboardBuffer.Add(str[i] == '\n' ? '\r' : str[i]))
				{
				Good = FALSE;
				break;
				}
			}
		}
	}

void sfExitCitadel(strList *params)
	{
	return_code = evaluateInt(params->string);
	TI()ExitToMsdos = TRUE;
	}

void sfIsConsoleLocked(strList *)
	{
	SETBOOL(ConsoleLock.IsLocked());
	}

void sfSetConsoleLock(strList *params)
	{
	if (evaluateBool(params->string))
		{
		ConsoleLock.Lock();
		}
	else
		{
		ConsoleLock.Unlock();
		}
	}

void sfIsLoggedIn(strList *)
	{
	SETBOOL(TI()loggedIn);
	}

void sfAddCommasToNumber(strList *params)
	{
	SETSTR(ltoac(evaluateLong(params->string)));
	}

void sfStrPos(strList *params)
	{
	char c = *evaluateString(params->string);
	SETINT(strpos(c, evaluateString(params->next->string)));
	}

void sfHexToDec(strList *params)
	{
	SETLONG(strtol(evaluateString(params->string), NULL, 16));
	}

void sfDecToHex(strList *params)
	{
	const int Width = params->next ? evaluateInt(params->next->string) : 0;
	char buf[256];

	sprintf(buf, "%0*lX", Width, evaluateLong(params->string));

	SETSTR(buf);
	}

void sfHowLongAgoWasIt(strList *params)
	{
	SETSTR(diffstamp(evaluateLong(params->string)));
	}

void sfParseDateString(strList *params)
	{
	char DateString[256];

	CopyStringToBuffer(DateString, evaluateString(params->string),
			sizeof(DateString) - 1);

	datestruct FillDate;

	gdate(DateString, &FillDate);

	struct date dt;
	struct time tm;

	tm.ti_min = 0;
	tm.ti_hour = 0;
	tm.ti_sec = 0;

	if (FillDate.Date)
		{
		dt.da_year = FillDate.Year + 1900;	// i hate dostounix
		dt.da_day = FillDate.Date;
		dt.da_mon = FillDate.Month + 1; 	// i hate dostounix
		}
	else
		{
		dt.da_year = 1970;	// i hate dostounix
		dt.da_day = 1;
		dt.da_mon = 1;		// i hate dostounix
		}

	SETLONG(dostounix(&dt, &tm));
	}

void sfParseTimeString(strList *params)
	{
	char TimeString[256];

	CopyStringToBuffer(TimeString, evaluateString(params->string),
			sizeof(TimeString) - 1);

	timestruct FillTime;

	gtime(TimeString, &FillTime);

	if (FillTime.Hour >= 0)
		{
		struct date dt;
		struct time tm;

		tm.ti_min = FillTime.Minute;
		tm.ti_hour = FillTime.Hour;
		tm.ti_sec = FillTime.Second;

		dt.da_year = 1970;	// i hate dostounix
		dt.da_day = 1;
		dt.da_mon = 1;		// i hate dostounix

		SETLONG(dostounix(&dt, &tm));
		}
	else
		{
		SETLONG(0);
		}
	}

void sfIsMatchWildcard(strList *params)
	{
	SETBOOL(u_match(evaluateString(params->string),
			evaluateString(params->next->string)));
	}

void sfSetRoomBypassed(strList *params)
	{
	SetRoomBypass(evaluateInt(params->string),
			evaluateBool(params->next->string));
	}

void sfIsRoomBypassed(strList *params)
	{
	SETBOOL(WasRoomBypassed(evaluateInt(params->string)));
	}
