/*
**	termRemember.c
**
**	Login learn routines
**
**	Copyright © 1990-1994 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

	/* How many characters to remember. */

#define REMEMBER_OUT	40
#define REMEMBER_IN	256

	/* Yet another node variant. */

struct RecordNode
{
	struct Node	Node;
	struct timeval	Time;
};

	/* What type of text was recorded. */

enum	{	RECORD_OUTPUT,RECORD_INPUT };

	/* The last ten bytes received. */

STATIC UBYTE		 RememberOutputData[2 * REMEMBER_OUT + 10];
STATIC WORD		 RememberOutputSize;

	/* The last 256 bytes sent. */

STATIC UBYTE		 RememberInputData[2 * REMEMBER_IN + 10];
STATIC WORD		 RememberInputSize;

	/* The name of the BBS we are currently recording for. */

STATIC UBYTE		 RecordName[50];

	/* Recorded lines. */

STATIC struct List	*RecordList;
STATIC LONG		 RecordCount;

	/* Auxilary data. */

STATIC STRPTR		 RecordAuxBuffer;

	/* Start of recording. */

STATIC struct timeval	 RecordTime;

	/* FinishRecord():
	 *
	 *	Finish the recording process, store the
	 *	recorded data in a file.
	 */

VOID
FinishRecord()
{
	if(RecordCount)
	{
		UBYTE			 DummyBuffer[MAX_FILENAME_LENGTH];
		struct FileRequester	*FileRequest;

		BlockWindows();

		Recording = RecordingLine = FALSE;

		Status = STATUS_READY;

		if(RecordName[0])
			strcpy(DummyBuffer,RecordName);
		else
		{
			strcpy(DummyBuffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));

			strcpy(RecordName,DummyBuffer);
		}

		FixName(DummyBuffer);

		DummyBuffer[27] = 0;

		strcat(DummyBuffer,".term");

		if(FileRequest = GetFile(Window,LocaleString(MSG_SAVE_RECORDED_FILE_TXT),"",DummyBuffer,DummyBuffer,"#?.(term|rexx)",TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_GAD),TRUE))
		{
			BPTR		FileHandle;
			LONG		Error = 0;
			struct timeval	Delta = { 0,0 };

			if(FileHandle = Open(DummyBuffer,MODE_NEWFILE))
			{
				SetIoErr(0);

				if(FPrintf(FileHandle,LocaleString(MSG_RECORDFILE_HEADER_TXT),RecordName) < 1)
					Error = IoErr();

				if(!Error)
				{
					struct RecordNode *Node = (struct RecordNode *)RecordList -> lh_Head;

					while(Node -> Node . ln_Succ && !Error)
					{
						if(Delta . tv_secs != Node -> Time . tv_secs)
						{
							LONG Secs;

							Secs = (3 * Node -> Time . tv_secs) / 2 + (3 * Node -> Time . tv_micro) / 2000000;

							SetIoErr(0);

							if(FPrintf(FileHandle,"TIMEOUT %ld\n",Secs) < 1)
							{
								Error = IoErr();

								break;
							}
							else
								Delta = Node -> Time;
						}

						SetIoErr(0);

						if(Node -> Node . ln_Type == RECORD_OUTPUT)
						{
							if(FPrintf(FileHandle,"WAIT TEXT \"%s\"\n",Node -> Node . ln_Name) < 1)
								Error = IoErr();
						}
						else
						{
							if(FPrintf(FileHandle,"SEND TEXT \"%s\"\n\n",Node -> Node . ln_Name) < 1)
								Error = IoErr();
						}

						Node = (struct RecordNode *)Node -> Node. ln_Succ;
					}
				}

				Close(FileHandle);

				if(ChosenEntry)
				{
					if(MyEasyRequest(Window,LocaleString(MSG_USE_AS_LOGIN_SCRIPT_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),ChosenEntry -> Header -> Name))
					{
						if(!ChosenEntry -> Config -> CommandConfig)
						{
							if(!CreateConfigEntry(ChosenEntry -> Config,PREF_COMMAND))
								ShowError(Window,ERR_NO_MEM,NULL,NULL);
						}

						if(ChosenEntry -> Config -> CommandConfig)
						{
							PhonebookChanged = TRUE;

							SPrintf(ChosenEntry -> Config -> CommandConfig -> LoginMacro,"\\a %s",DummyBuffer);
						}
					}
				}
			}
			else
				Error = IoErr();

			if(!Error && Config -> MiscConfig -> CreateIcons && IconBase)
			{
				struct DiskObject *Icon;

				if(!(Icon = GetDiskObject("ENV:def_term")))
				{
					if(!(Icon = GetDiskObject("ENV:def_rexx")))
					{
						if(Icon = GetDefDiskObject(WBPROJECT))
							Icon -> do_DefaultTool = "RX";
					}
				}

				if(Icon)
				{
					Icon -> do_CurrentX = Icon -> do_CurrentY = NO_ICON_POSITION;

					PutDiskObject(DummyBuffer,Icon);

					FreeDiskObject(Icon);
				}
			}

			if(Error)
				ShowError(Window,ERR_SAVE_ERROR,Error,DummyBuffer);

			FreeAslRequest(FileRequest);
		}

		DeleteRecord();

		ReleaseWindows();
	}
}

	/* CreateRecord(STRPTR BBSName):
	 *
	 *	Start recording incoming and outgoing text.
	 */

BOOLEAN __regargs
CreateRecord(STRPTR BBSName)
{
	DeleteRecord();

	if(RecordList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
	{
		if(RecordAuxBuffer = (STRPTR)AllocVecPooled(1024,MEMF_ANY))
		{
			strcpy(RecordName,BBSName);

			NewList(RecordList);

			TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;

			DoIO(TimeRequest);

			RecordTime = TimeRequest -> tr_time;

			return(TRUE);
		}

		FreeVecPooled(RecordList);

		RecordList = NULL;
	}

	return(FALSE);
}

	/* DeleteRecord():
	 *
	 *	Stop recording, free auxilary buffers.
	 */

VOID
DeleteRecord()
{
	if(RecordAuxBuffer)
	{
		FreeVecPooled(RecordAuxBuffer);

		RecordAuxBuffer = NULL;
	}

	if(RecordList)
	{
		DeleteList(RecordList);

		RecordList = NULL;
	}

	RecordCount = 0;
}

	/* RememberResetOutput():
	 *
	 *	Reset output monitoring.
	 */

VOID
RememberResetOutput()
{
	RememberOutputSize = 0;
}

	/* RememberOutputText(register STRPTR String,register LONG Size):
	 *
	 *	Remember the last ten characters received.
	 */

VOID __regargs
RememberOutputText(register STRPTR String,register LONG Size)
{
	if(Size >= REMEMBER_OUT)
	{
		CopyMem(String + Size - REMEMBER_OUT,RememberOutputData,REMEMBER_OUT);

		RememberOutputSize = REMEMBER_OUT;
	}
	else
	{
		if(RememberOutputSize + Size > REMEMBER_OUT)
		{
			LONG Delta = RememberOutputSize + Size - REMEMBER_OUT,i;

			for(i = 0 ; i < RememberOutputSize - Delta ; i++)
				RememberOutputData[i] = RememberOutputData[Delta + i];

			while(i < REMEMBER_OUT)
				RememberOutputData[i++] = *String++;

			RememberOutputSize = REMEMBER_OUT;
		}
		else
		{
			CopyMem(String,&RememberOutputData[RememberOutputSize],Size);

			RememberOutputSize += Size;
		}
	}
}

	/* RememberResetInput():
	 *
	 *	Reset input monitoring.
	 */

VOID
RememberResetInput()
{
	RememberInputSize = 0;
}

	/* RememberInputText(register STRPTR String,register LONG Size):
	 *
	 *	Remember the last 256 characters sent.
	 */

VOID __regargs
RememberInputText(register STRPTR String,register LONG Size)
{
	if(Size >= REMEMBER_IN)
	{
		CopyMem(String + Size - REMEMBER_IN,RememberInputData,REMEMBER_IN);

		RememberInputSize = REMEMBER_IN;
	}
	else
	{
		if(RememberInputSize + Size > REMEMBER_IN)
		{
			LONG Delta = RememberInputSize + Size - REMEMBER_IN,i;

			for(i = 0 ; i < RememberInputSize - Delta ; i++)
				RememberInputData[i] = RememberInputData[Delta + i];

			while(i < REMEMBER_IN)
				RememberInputData[i++] = *String++;

			RememberInputSize = REMEMBER_IN;
		}
		else
		{
			CopyMem(String,&RememberInputData[RememberInputSize],Size);

			RememberInputSize += Size;
		}
	}
}

	/* DoubleQuotes(STRPTR Source,LONG Len):
	 *
	 *	Double all double-quotes in the input string
	 *	in order to avoid trouble with the ARexx
	 *	parser.
	 */

STATIC VOID __regargs
DoubleQuotes(STRPTR Source,LONG Len)
{
	STRPTR	Dest = RecordAuxBuffer;
	LONG	i,Count = 0;

	for(i = 0 ; i < Len ; i++)
	{
		if(Source[i] == '\"')
		{
			*Dest++ = '\"';

			Count++;
		}

		*Dest++ = Source[i];
	}

	if(Count)
	{
		*Dest = 0;

		strcpy(Source,RecordAuxBuffer);
	}
}

	/* RememberSpill():
	 *
	 *	`Spill' the collected text, put it into the list.
	 */

VOID
RememberSpill()
{
	if(RecordList)
	{
		struct RecordNode	*Node;
		struct timeval		 Delta;

			/* Calculate the difference in time
			 * between the last line stored and this
			 * line getting stored.
			 */

		TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;

		DoIO(TimeRequest);

		Delta = TimeRequest -> tr_time;

		SubTime(&Delta,&RecordTime);

		RecordTime = TimeRequest -> tr_time;

		if(!Delta . tv_secs)
			Delta . tv_secs = 1;

		Delta . tv_micro = 0;

		if(RememberOutputSize)
		{
			DoubleQuotes(RememberOutputData,RememberOutputSize);

			TranslateBack(RememberOutputData,RememberOutputSize,RecordAuxBuffer);

			if(Node = (struct RecordNode *)AllocVecPooled(sizeof(struct RecordNode) + strlen(RecordAuxBuffer) + 1,MEMF_ANY))
			{
				Node -> Node . ln_Name = (STRPTR)(Node + 1);
				Node -> Node . ln_Type = RECORD_OUTPUT;

				strcpy(Node -> Node . ln_Name,RecordAuxBuffer);

				Node -> Time = Delta;

				AddTail(RecordList,(struct Node *)Node);

				RecordCount++;
			}
		}

		if(RememberInputSize)
		{
			DoubleQuotes(RememberInputData,RememberInputSize);

			TranslateBack(RememberInputData,RememberInputSize,RecordAuxBuffer);

			if(Node = (struct RecordNode *)AllocVecPooled(sizeof(struct RecordNode) + strlen(RecordAuxBuffer) + 1,MEMF_ANY))
			{
				Node -> Node . ln_Name = (STRPTR)(Node + 1);
				Node -> Node . ln_Type = RECORD_INPUT;

				strcpy(Node -> Node . ln_Name,RecordAuxBuffer);

				Node -> Time = Delta;

				AddTail(RecordList,(struct Node *)Node);

				RecordCount++;
			}
		}
	}

	RememberOutputSize = RememberInputSize = 0;
}
