/*
**	ASCIITransfer.c
**
**	ASCII file transfer routines
**
**	Copyright © 1990-1996 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

	/* Local variables. */

STATIC UBYTE	ASCIISendPrompt[256];
STATIC LONG	ASCIISendPromptLen;
STATIC BOOL	(* ASCIISendLine)(register STRPTR,register LONG);

STATIC LONG
MangleASCIIBuffer(BYTE TranslateCR,BYTE TranslateLF,STRPTR Source,LONG SourceLen,STRPTR Destination)
{
	LONG	CR_Len,
		LF_Len;
	STRPTR	CR_String,
		LF_String;
	LONG	Mask;
	LONG	Len = 0;

	switch(TranslateCR)
	{
		case EOL_IGNORE:

			CR_Len = 0;
			break;

		case EOL_CR:

			CR_Len		= 1;
			CR_String	= "\r";
			break;

		case EOL_LF:

			CR_Len		= 1;
			CR_String	= "\n";
			break;

		case EOL_CRLF:

			CR_Len		= 2;
			CR_String	= "\r\n";
			break;

		case EOL_LFCR:

			CR_Len		= 2;
			CR_String	= "\n\r";
			break;
	}

	switch(TranslateLF)
	{
		case EOL_IGNORE:

			LF_Len = 0;
			break;

		case EOL_LF:

			LF_Len		= 1;
			LF_String	= "\n";
			break;

		case EOL_CR:

			LF_Len		= 1;
			LF_String	= "\r";
			break;

		case EOL_LFCR:

			LF_Len		= 2;
			LF_String	= "\n\r";
			break;

		case EOL_CRLF:

			LF_Len		= 2;
			LF_String	= "\r\n";
			break;
	}

	if(Config -> TransferConfig -> StripBit8)
		Mask = 0x7F;
	else
		Mask = 0xFF;

	do
	{
		switch(*Source)
		{
			case '\r':

				if(CR_Len)
				{
					CopyMem(CR_String,Destination,CR_Len);

					Destination	+= CR_Len;
					Len		+= CR_Len;
				}

				break;

			case '\n':

				if(LF_Len)
				{
					CopyMem(LF_String,Destination,LF_Len);

					Destination	+= LF_Len;
					Len		+= LF_Len;
				}

				break;

			default:

				*Destination++ = (*Source) & Mask;

				Len++;

				break;
		}

		Source++;
	}
	while(--SourceLen);

	return(Len);
}

	/* WaitForPrompt(STRPTR Prompt,LONG PromptLen):
	 *
	 *	Scan the incoming data flow for a certain string.
	 */

STATIC BOOL
WaitForPrompt(STRPTR Prompt,LONG PromptLen)
{
	ULONG Signals;

	MatchPrompt(NULL,0,NULL,0);

	if(DataHold)
	{
		DataHold = NULL;

		RestartSerial();
	}

	if(CheckSerialRead())
		Signals = SIG_SERIAL;
	else
		Signals = NULL;

	StartTime(Config -> TransferConfig -> SendTimeout / 100,(Config -> TransferConfig -> SendTimeout % 100) * 10000);

	for(;;)
	{
		if(Signals & SIG_SERIAL)
		{
			if(!WaitSerialRead())
			{
				LONG Length;

				BytesIn++;

				ConProcess(ReadBuffer,1);

				Status = STATUS_READY;

				if(MatchPrompt(ReadBuffer,1,Prompt,PromptLen))
				{
					StopTime();

					RestartSerial();

					return(TRUE);
				}

				do
				{
						/* Check how many bytes are still in
						 * the serial buffer.
						 */

					if(Length = GetSerialWaiting())
					{
						if(Length > SerialBufferSize)
							Length = SerialBufferSize;

						if(!DoSerialRead(ReadBuffer,Length))
						{
							BytesIn += Length;

							ConProcess(ReadBuffer,Length);

							Status = STATUS_READY;

							if(MatchPrompt(ReadBuffer,Length,Prompt,PromptLen))
							{
								StopTime();

								RestartSerial();

								return(TRUE);
							}
						}
					}
				}
				while(Length);
			}

			RestartSerial();
		}

		if(Signals & SIG_TIMER)
		{
			WaitTime();

			return(FALSE);
		}

		Signals = Wait(SIG_SERIAL | SIG_TIMER);
	}
}

	/* ASCIISendLinePrompt(STRPTR Line,LONG Len):
	 *
	 *	Send text line, wait for prompt.
	 */

STATIC BOOL
ASCIISendLinePrompt(STRPTR Line,LONG Len)
{
	LONG i;

	if(Len == -1)
		Len = strlen(Line);

	while(Len)
	{
		i = 0;

		while(i < Len && Line[i] != '\r')
			i++;


		if(Line[i] == '\r')
		{
			i++;

			SerWrite(Line,i);

			if(!WaitForPrompt(ASCIISendPrompt,ASCIISendPromptLen))
				return(FALSE);
		}
		else
		{
			if(i)
				SerWrite(Line,i);
		}

		Len	-= i;
		Line	+= i;
	}

	return(TRUE);
}

	/* ASCIISendLineDelay(STRPTR Line,LONG Len):
	 *
	 *	Send a text line, include a delay where necessary.
	 */

STATIC BOOL
ASCIISendLineDelay(STRPTR Line,LONG Len)
{
	if(Len == -1)
		Len = strlen(Line);

	while(Len--)
	{
		SerWrite(Line,1);

		if(*Line == '\r')
			DelayTime(Config -> TransferConfig -> LineDelay / 100,(Config -> TransferConfig -> LineDelay % 100) * 10000);
		else
			DelayTime(Config -> TransferConfig -> CharDelay / 100,(Config -> TransferConfig -> CharDelay % 100) * 10000);

		Line++;
	}

	return(TRUE);
}

	/* ASCIISendLineEcho(STRPTR Line,LONG Len):
	 *
	 *	Send a text line, wait for single characters to be echoed.
	 */

STATIC BOOL
ASCIISendLineEcho(STRPTR Line,LONG Len)
{
	ULONG Signals;

	if(DataHold)
	{
		DataHold = NULL;

		RestartSerial();
	}

	if(Len == -1)
		Len = strlen(Line);

	while(Len--)
	{
		SerWrite(Line,1);

		StartTime(Config -> TransferConfig -> SendTimeout / 100,(Config -> TransferConfig -> SendTimeout % 100) * 10000);

		FOREVER
		{
			Signals = Wait(SIG_TIMER | SIG_SERIAL);

			if(Signals & SIG_SERIAL)
			{
				if(!WaitSerialRead())
				{
					if(*(UBYTE *)ReadBuffer == *Line)
					{
						StopTime();

						RestartSerial();

						break;
					}

					RestartSerial();
				}
				else
				{
					StopTime();

					RestartSerial();

					return(FALSE);
				}
			}

			if(Signals & SIG_TIMER)
			{
				WaitTime();

				return(FALSE);
			}
		}

		Line++;
	}

	return(TRUE);
}

	/* ASCIISendLineAnyEcho(STRPTR Line,LONG Len):
	 *
	 *	Send a text line, wait for characters to be echoed.
	 */

STATIC BOOL
ASCIISendLineAnyEcho(STRPTR Line,LONG Len)
{
	ULONG Signals;

	if(DataHold)
	{
		DataHold = NULL;

		RestartSerial();
	}

	if(Len == -1)
		Len = strlen(Line);

	while(Len--)
	{
		SerWrite(Line,1);

		StartTime(Config -> TransferConfig -> SendTimeout / 100,(Config -> TransferConfig -> SendTimeout % 100) * 10000);

		FOREVER
		{
			Signals = Wait(SIG_TIMER | SIG_SERIAL);

			if(Signals & SIG_SERIAL)
			{
				if(!WaitSerialRead())
				{
					StopTime();

					RestartSerial();

					break;
				}
				else
				{
					StopTime();

					RestartSerial();

					return(FALSE);
				}
			}

			if(Signals & SIG_TIMER)
			{
				WaitTime();

				return(FALSE);
			}
		}

		Line++;
	}

	return(TRUE);
}

	/* ASCIISendSetup():
	 *
	 *	Choose the right routine for the text line output job.
	 */

VOID
ASCIISendSetup()
{
		/* Pick the line send routine. */

	switch(Config -> TransferConfig -> PacingMode)
	{
		case PACE_DIRECT:

			ASCIISendLine = SendLineSimple;
			break;

		case PACE_ECHO:

			if(Config -> TransferConfig -> SendTimeout)
				ASCIISendLine = ASCIISendLineEcho;
			else
				ASCIISendLine = SendLineSimple;

			break;

		case PACE_ANYECHO:

			if(Config -> TransferConfig -> SendTimeout)
				ASCIISendLine = ASCIISendLineAnyEcho;
			else
				ASCIISendLine = SendLineSimple;

			break;

		case PACE_PROMPT:

			if(Config -> TransferConfig -> SendTimeout)
			{
					/* Prepare the prompt string. */

				if(Config -> TransferConfig -> LinePrompt[0])
					ASCIISendPromptLen = TranslateString(Config -> TransferConfig -> LinePrompt,ASCIISendPrompt);
				else
				{
					ASCIISendPrompt[0] = 0;
					ASCIISendPromptLen = 0;
				}

				ASCIISendLine = ASCIISendLinePrompt;
			}
			else
				ASCIISendLine = SendLineSimple;

			break;

		case PACE_DELAY:

			if(Config -> TransferConfig -> LineDelay || Config -> TransferConfig -> CharDelay)
				ASCIISendLine = ASCIISendLineDelay;
			else
				ASCIISendLine = SendLineSimple;

			break;

		case PACE_KEYBOARD:

			ASCIISendLine = SendLineKeyDelay;
			break;
	}
}

BOOL
InternalASCIIUpload(STRPTR SingleFile,BOOL WaitForIt)
{
	BYTE	OldStatus = Status;
	BOOL	DidSend = FALSE;
	BPTR	NewDir,OldDir;

		/* We are uploading data. */

	Uploading = TRUE;

	if(NewDir = Lock(Config -> PathConfig -> ASCIIUploadPath,ACCESS_READ))
		OldDir = CurrentDir(NewDir);
	else
		OldDir = NULL;

	BlockWindows();

	if(!FileTransferInfo)
	{
		if(SingleFile)
		{
			ULONG Size;

			if(Size = GetFileSize(SingleFile))
			{
				if(FileTransferInfo = AllocFileTransferInfo())
				{
					if(!AddFileTransferNode(FileTransferInfo,SingleFile,Size))
					{
						FreeFileTransferInfo(FileTransferInfo);

						FileTransferInfo = NULL;
					}
				}
			}
		}
		else
		{
			struct FileRequester	*FileRequest;
			UBYTE			 DummyBuffer[MAX_FILENAME_LENGTH];

			if(FileRequest = GetFile(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + TRANSFER_ASCII),Config -> PathConfig -> ASCIIUploadPath,"",DummyBuffer,"",FALSE,TRUE,FALSE,LocaleString(MSG_TERMTRANSFER_SEND_TXT),TRUE))
			{
				strcpy(Config -> PathConfig -> ASCIIUploadPath,FileRequest -> fr_Drawer);

				ConfigChanged = TRUE;

				FileTransferInfo = BuildFileTransferInfo(FileRequest);

				FreeAslRequest(FileRequest);
			}
		}
	}
	else
	{
		if(SingleFile)
		{
			ULONG Size;

			if(Size = GetFileSize(SingleFile))
			{
				if(!AddFileTransferNode(FileTransferInfo,SingleFile,Size))
				{
					FreeFileTransferInfo(FileTransferInfo);

					FileTransferInfo = NULL;
				}
			}
		}
	}

	TransferAborted = FALSE;

	TransferFailed = TRUE;

	TransferError = FALSE;

	if(FileTransferInfo)
	{
		struct Window *ThisWindow;

		if(ThisWindow = CreateASCIIWindow(TRUE))
		{
			struct Buffer	*File;
			LONG		 Chars = 0,Lines = 0,Len,i;
			BOOL		 Terminated = FALSE;

			FileTransferInfo -> DoneSize	= 0;
			FileTransferInfo -> DoneFiles	= 0;

			FileTransferInfo -> CurrentFile	= (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
			FileTransferInfo -> CurrentSize	= FileTransferInfo -> CurrentFile -> Size;

			Status = STATUS_UPLOAD;

			ASCIISendSetup();

			if(DataHold)
			{
				if(!Config -> TransferConfig -> QuietTransfer)
				{
					ConProcess(DataHold,DataSize);

					Status = STATUS_UPLOAD;
				}

				DataHold = NULL;

				RestartSerial();
			}

			while(!Terminated && FileTransferInfo -> CurrentFile -> Node . mln_Succ)
			{
				if(File = BufferOpen(FileTransferInfo -> CurrentFile -> Name,"r"))
				{
					UBYTE	DummyBuffer[512],
						OtherBuffer[256];
					ULONG	Signals;
					BOOL	LastCR = FALSE,Skipped = FALSE;

					AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_OPENING_FILE_TXT),FileTransferInfo -> CurrentFile -> Name);

					while(!Skipped && !Terminated && (Len = BufferRead(File,OtherBuffer,256)) > 0)
					{
						if(Len = MangleASCIIBuffer(Config -> TransferConfig -> SendCR,Config -> TransferConfig -> SendLF,OtherBuffer,Len,DummyBuffer))
						{
							for(i = 0 ; i < Len ; i++)
							{
								if(DummyBuffer[i] == '\r')
								{
									Lines++;

									LastCR = TRUE;
								}
								else
								{
									if(DummyBuffer[i] == '\n' && !LastCR)
										Lines++;

									LastCR = FALSE;
								}
							}

							Chars += Len;

							DidSend = TRUE;

							TransferFailed = FALSE;

							(*ASCIISendLine)(DummyBuffer,Len);
						}

						Signals = CheckSignal(SIG_BREAK | SIG_SERIAL | PORTMASK(ThisWindow -> UserPort));

						if(Signals & SIG_BREAK)
							Terminated = TransferAborted = TRUE;

						if(Signals & PORTMASK(ThisWindow -> UserPort))
						{
							switch(HandleASCIIWindow())
							{
								case 1:	Terminated = TransferAborted = TRUE;
									break;

								case 2:	Skipped = TRUE;
									break;
							}

							if(Terminated || Skipped)
								break;
						}

						if(Signals & SIG_SERIAL)
						{
							if(!WaitSerialRead())
							{
								LONG Length;

								if(!Config -> TransferConfig -> QuietTransfer)
								{
									BytesIn++;

									ConProcess(ReadBuffer,1);

									Status = STATUS_UPLOAD;
								}

									/* Check how many bytes are still in
									 * the serial buffer.
									 */

								if(Length = GetSerialWaiting())
								{
									if(Length > SerialBufferSize)
										Length = SerialBufferSize;

									if(Length > Config -> SerialConfig -> Quantum)
										Length = Config -> SerialConfig -> Quantum;

									if(!DoSerialRead(ReadBuffer,Length))
									{
										if(!Config -> TransferConfig -> QuietTransfer)
										{
											BytesIn += Length;

												/* Send the data to the console. */

											ConProcess(ReadBuffer,Length);

											Status = STATUS_UPLOAD;
										}
									}
								}
							}

							RestartSerial();
						}

						UpdateASCIIWindow(ThisWindow,Chars,FileTransferInfo -> CurrentFile -> Size,Lines);
					}

					if(Len < 0)
					{
						AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_READING_FILE_TXT),FileTransferInfo -> CurrentFile -> Name);

						TransferFailed = TRUE;

						break;
					}

					BufferClose(File);

					RemoveUploadListItem(FileTransferInfo -> CurrentFile -> Name);
				}
				else
				{
					AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_OPENING_FILE_TXT),FileTransferInfo -> CurrentFile -> Name);

					TransferFailed = TRUE;

					break;
				}

				FileTransferInfo -> DoneSize	+= FileTransferInfo -> CurrentSize;
				FileTransferInfo -> DoneFiles	+= 1;

				FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
				FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
			}

			if(TransferFailed || TransferError)
				WakeUp(ThisWindow,SOUND_BADTRANSFER);
			else
			{
				WakeUp(ThisWindow,SOUND_GOODTRANSFER);

				DelayTime(2,0);
			}

			DeleteASCIIWindow(ThisWindow,TransferFailed && WaitForIt);
		}

		FreeFileTransferInfo(FileTransferInfo);

		FileTransferInfo = NULL;
	}

	if(TransferFailed || TransferAborted)
		Say(LocaleString(MSG_GLOBAL_TRANSFER_FAILED_OR_ABORTED_TXT));
	else
		Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT));

	if(OldDir)
		CurrentDir(OldDir);

	if(NewDir)
		UnLock(NewDir);

	SendAbort = FALSE;

	Status = OldStatus;

	ReleaseWindows();

	DidTransfer = FALSE;

	if(WaitForIt)
	{
		if(Config -> CommandConfig -> DownloadMacro[0])
			SerialCommand(Config -> CommandConfig -> UploadMacro);
	}

	DidTransfer = FALSE;

	return(DidSend);
}

BOOL
InternalASCIIDownload(STRPTR Name,BOOL WaitForIt)
{
	struct FileRequester	*FileRequest;
	UBYTE			 DummyBuffer[MAX_FILENAME_LENGTH];
	BYTE			 OldStatus = Status;
	BOOL			 DidSend = FALSE;
	BPTR			 NewDir,OldDir;

	ClearGenericList(GenericListTable[GLIST_DOWNLOAD]);

	DownloadPath = Config -> PathConfig -> ASCIIDownloadPath;

	if(DownloadPath[0])
	{
		if(NewDir = Lock(DownloadPath,ACCESS_READ))
			OldDir = CurrentDir(NewDir);
		else
			OldDir = NULL;
	}
	else
		NewDir = OldDir = NULL;

	BlockWindows();

	if(!Name)
	{
		if(FileRequest = GetFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + TRANSFER_ASCII),DownloadPath,"",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),TRUE))
		{
				/* Save the download path. */

			strcpy(DownloadPath,FileRequest -> fr_Drawer);

			ConfigChanged = TRUE;

			FreeAslRequest(FileRequest);

			Name = DummyBuffer;
		}
	}
	else
	{
		STRPTR Index;

		strcpy(DownloadPath,Name);

		ConfigChanged = TRUE;

		Index = PathPart(DownloadPath);

		*Index = 0;
	}

	TransferAborted = FALSE;

	TransferFailed = TRUE;

	TransferError = FALSE;

	if(Name)
	{
		struct Window *ThisWindow;

		if(ThisWindow = CreateASCIIWindow(FALSE))
		{
			struct Buffer *File;

			if(File = BufferOpen(Name,"w"))
			{
				UBYTE	OtherBuffer[512];
				LONG	Chars = 0,Lines = 0,i;
				BOOL	Terminated = FALSE;
				ULONG	Signals;

				AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_OPENING_FILE_TXT),Name);

				TransferFailed = FALSE;

				Status = STATUS_DOWNLOAD;

				if(DataHold)
				{
					LONG Size,Len;

					do
					{
						if(DataSize > 256)
							Size = 256;
						else
							Size = DataSize;

						if(Len = MangleASCIIBuffer(Config -> TransferConfig -> ReceiveCR,Config -> TransferConfig -> ReceiveLF,DataHold,Size,OtherBuffer))
						{
							if(Config -> TransferConfig -> IgnoreDataPastArnold)
							{
								for(i = 0 ; i < Len ; i++)
								{
									if(OtherBuffer[i] == '\r')
										Lines++;

									if(OtherBuffer[i] == Config -> TransferConfig -> TerminatorChar)
									{
										Len = i;

										Terminated = TRUE;

										break;
									}
								}
							}
							else
							{
								for(i = 0 ; i < Len ; i++)
								{
									if(OtherBuffer[i] == '\r')
										Lines++;
								}
							}

							if(Len)
							{
								Chars += Len;

								if(BufferWrite(File,OtherBuffer,Len) != Len)
								{
									TransferFailed = Terminated = TRUE;

									AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_WRITING_FILE_TXT),Name);
								}
							}
						}

						if(!Config -> TransferConfig -> QuietTransfer)
						{
							ConProcess(DataHold,Size);

							Status = STATUS_DOWNLOAD;
						}

						DataSize -= Size;

						if(DataSize > 0)
							DataHold += Size;
						else
							DataHold = NULL;
					}
					while(DataHold && !Terminated);

					RestartSerial();

					UpdateASCIIWindow(ThisWindow,Chars,0,Lines);
				}

				if(!Terminated)
				{
					StartTime(5,0);

					do
					{
						Signals = Wait(SIG_BREAK | SIG_SERIAL | SIG_TIMER | PORTMASK(ThisWindow -> UserPort));

						if(Signals & PORTMASK(ThisWindow -> UserPort))
						{
							if(HandleASCIIWindow())
								break;
						}

						if(Signals & SIG_SERIAL)
						{
							StopTime();

							if(!WaitSerialRead())
							{
								LONG Length;

								BytesIn++;

								if(!Config -> TransferConfig -> QuietTransfer)
								{
									ConProcess(ReadBuffer,1);

									Status = STATUS_DOWNLOAD;
								}

								if(Length = MangleASCIIBuffer(Config -> TransferConfig -> ReceiveCR,Config -> TransferConfig -> ReceiveLF,ReadBuffer,1,OtherBuffer))
								{
									if(Config -> TransferConfig -> IgnoreDataPastArnold)
									{
										for(i = 0 ; i < Length ; i++)
										{
											if(OtherBuffer[i] == Config -> TransferConfig -> TerminatorChar)
											{
												Length = i;

												Terminated = TRUE;

												break;
											}
										}

										if(Terminated)
										{
											RestartSerial();

											break;
										}
									}

									if(Length)
									{
										if(BufferWrite(File,OtherBuffer,Length) != Length)
										{
											TransferFailed = Terminated = TRUE;

											AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_WRITING_FILE_TXT),Name);
										}

										for(i = 0 ; i < Length ; i++)
										{
											if(OtherBuffer[i] == '\r')
												Lines++;
										}

										Chars += Length;
									}
								}

									/* Check how many bytes are still in
									 * the serial buffer.
									 */

								if(Length = GetSerialWaiting())
								{
									if(Length > SerialBufferSize)
										Length = SerialBufferSize;

									if(Length > Config -> SerialConfig -> Quantum)
										Length = Config -> SerialConfig -> Quantum;

									if(Length > 256)
										Length = 256;

									if(!DoSerialRead(ReadBuffer,Length))
									{
										BytesIn += Length;

											/* Send the data to the console. */

										if(!Config -> TransferConfig -> QuietTransfer)
										{
											ConProcess(ReadBuffer,Length);

											Status = STATUS_DOWNLOAD;
										}

										if(Length = MangleASCIIBuffer(Config -> TransferConfig -> ReceiveCR,Config -> TransferConfig -> ReceiveLF,ReadBuffer,Length,OtherBuffer))
										{
											if(Config -> TransferConfig -> IgnoreDataPastArnold)
											{
												for(i = 0 ; i < Length ; i++)
												{
													if(OtherBuffer[i] == '\r')
														Lines++;

													if(OtherBuffer[i] == Config -> TransferConfig -> TerminatorChar)
													{
														Length = i;

														Terminated = TRUE;

														break;
													}
												}
											}
											else
											{
												for(i = 0 ; i < Length ; i++)
												{
													if(OtherBuffer[i] == '\r')
														Lines++;
												}
											}

											if(Length)
											{
												Chars += Length;

												if(BufferWrite(File,OtherBuffer,Length) != Length)
												{
													TransferFailed = Terminated = TRUE;

													AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_WRITING_FILE_TXT),Name);
												}
											}
										}
									}
								}

								UpdateASCIIWindow(ThisWindow,Chars,0,Lines);
							}

							StartTime(5,0);

							Signals &= ~SIG_TIMER;

							RestartSerial();
						}

						if(Signals & SIG_TIMER)
							Terminated = TRUE;

						if(Signals & SIG_BREAK)
							TransferAborted = Terminated = TRUE;
					}
					while(!Terminated);

					StopTime();
				}

				BufferClose(File);
			}
			else
			{
				AddASCIIMessage(ThisWindow,LocaleString(MSG_ASCIIPANEL_ERROR_OPENING_FILE_TXT),Name);

				TransferFailed = TRUE;
			}

			if(TransferFailed || TransferError)
				WakeUp(ThisWindow,SOUND_BADTRANSFER);
			else
			{
				WakeUp(ThisWindow,SOUND_GOODTRANSFER);

				DelayTime(2,0);
			}

			DeleteASCIIWindow(ThisWindow,TransferFailed && WaitForIt);
		}
	}

	if(TransferFailed || TransferAborted)
		Say(LocaleString(MSG_GLOBAL_TRANSFER_FAILED_OR_ABORTED_TXT));
	else
		Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT));

	if(OldDir)
		CurrentDir(OldDir);

	if(NewDir)
		UnLock(NewDir);

	SendAbort = FALSE;

	Status = OldStatus;

	ReleaseWindows();

	DownloadPath = NULL;

	DidTransfer = FALSE;

	if(WaitForIt)
	{
		if(Config -> CommandConfig -> DownloadMacro[0])
			SerialCommand(Config -> CommandConfig -> DownloadMacro);
	}

	DidTransfer = FALSE;

	return(DidSend);
}
