/*
**	Dial.c
**
**	The dialing routine as called by the phonebook
**
**	Copyright © 1990-1996 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

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

	/* Panel gadget IDs. */

enum	{	GAD_CALLING=1,GAD_TIME,GAD_NOTE,
			GAD_SKIP,GAD_REMOVE,GAD_ONLINE,GAD_ABORT
		};

STATIC VOID __stdargs
DialPrintBox(LayoutHandle *Handle,LONG Box,LONG Line,STRPTR String,...)
{
	UBYTE	 LocalBuffer[256];
	va_list	 VarArgs;

	va_start(VarArgs,String);
	VSPrintf(LocalBuffer,String,VarArgs);
	va_end(VarArgs);

	LT_SetAttributes(Handle,Box,
		LABX_Index,	Line,
		LABX_Text,	LocalBuffer,
	TAG_DONE);
}

STATIC BOOL
SendSomeCommand(LayoutHandle *Handle,STRPTR Command,STRPTR Message,STRPTR ErrorMessage)
{
	DialPrintBox(Handle,GAD_NOTE,0,Message);

	FlowInit(TRUE);

	SerialCommand(Command);

	DelayTime(1,0);

	HandleSerial();

	if(FlowInfo . Changed && FlowInfo . Error)
	{
		DialPrintBox(Handle,GAD_NOTE,0,ErrorMessage);

		WakeUp(Handle -> Window,SOUND_ERROR);

		return(TRUE);
	}
	else
		return(FALSE);
}

	/* BuildName(STRPTR Name):
	 *
	 *	Build a file name from a BBS name and the current date.
	 */

STATIC VOID
BuildName(STRPTR Name,STRPTR Date)
{
	if(Date[0])
	{
		LONG	NameLen = strlen(Name),
				DateLen = strlen(Date),
				Delta;

		if((Delta = NameLen + 1 + DateLen - 32) > 0)
			Name[NameLen - Delta] = 0;

		strcat(Name,"_");
		strcat(Name,Date);
	}
}

	/* OpenAutoCaptureFile(STRPTR SomeName):
	 *
	 *	Open a capture file.
	 */

STATIC VOID
OpenAutoCaptureFile(STRPTR SomeName)
{
	UBYTE			SharedBuffer[MAX_FILENAME_LENGTH],
					Name[50],
					Date[20],
					Time[20];
	struct DateTime	DateTime;

		/* Get the current time and date. */

	DateStamp(&DateTime . dat_Stamp);

		/* Prepare for date conversion. */

	DateTime . dat_Format	= FORMAT_DOS;
	DateTime . dat_Flags	= 0;
	DateTime . dat_StrDay	= NULL;
	DateTime . dat_StrDate	= Date;
	DateTime . dat_StrTime	= Time;

		/* Convert the date. */

	if(DateToStr(&DateTime))
	{
			/* Remember the BBS name. */

		strcpy(Name,SomeName);

			/* Append the creation date if necessary. */

		if(Config -> CaptureConfig -> AutoCaptureDate == AUTOCAPTURE_DATE_NAME)
			BuildName(Name,Date);

			/* Make it a reasonable name. */

		FixName(Name);

			/* Get the capture file path. */

		strcpy(SharedBuffer,Config -> CaptureConfig -> CapturePath);

			/* Try to build a valid file and path name. */

		if(AddPart(SharedBuffer,Name,MAX_FILENAME_LENGTH))
		{
				/* Is the capture file still open? */

			if(FileCapture)
			{
					/* Close the file. */

				BufferClose(FileCapture);

				FileCapture = NULL;

					/* Any data written? */

				if(!GetFileSize(CaptureName))
					DeleteFile(CaptureName);
				else
				{
					AddProtection(CaptureName,FIBF_EXECUTE);

					if(Config -> MiscConfig -> CreateIcons)
						AddIcon(CaptureName,FILETYPE_TEXT,TRUE);
				}
			}

				/* Try to append the new data. */

			if(FileCapture = BufferOpen(SharedBuffer,"a"))
			{
					/* Set the menu checkmark. */

				CheckItem(MEN_CAPTURE_TO_FILE,TRUE);

					/* Remember the current capture file name. */

				strcpy(CaptureName,SharedBuffer);

					/* Add the creation date if necessary. */

				if(Config -> CaptureConfig -> AutoCaptureDate == AUTOCAPTURE_DATE_INCLUDE)
				{
					UBYTE DateTimeBuffer[256];

					if(FormatStamp(&DateTime . dat_Stamp,NULL,NULL,DateTimeBuffer,FALSE))
						BPrintf(FileCapture,LocaleString(MSG_DIALPANEL_FILE_CREATED_TXT),DateTimeBuffer);
				}
			}
			else
				CheckItem(MEN_CAPTURE_TO_FILE,FALSE);

			ConOutputUpdate();
		}
	}
}

	/* Connect(struct PhoneNode *DialNode,STRPTR NumberBuffer):
	 *
	 *	Perform connect action(s).
	 */

STATIC VOID
Connect(struct PhoneNode *DialNode,STRPTR NumberBuffer)
{
	ULONG OnlinePlus;

	if(DialNode -> Entry)
	{
		UpdateConfig(DialNode -> Entry -> Config,Config);

		ConfigChanged = FALSE;

		MakeCall(DialNode -> Entry -> Header -> Name,NumberBuffer);

		ObtainSemaphoreShared(&PatternSemaphore);

		ChosenPattern	= FindTimeDate(PatternList,NumberBuffer);
		ChosenEntry		= DialNode -> Entry;

		SendStartup		= TRUE;

		ReleaseSemaphore(&PatternSemaphore);

		strcpy(Password,DialNode -> Entry -> Header -> Password);
		strcpy(UserName,DialNode -> Entry -> Header -> UserName);

		strcpy(CurrentBBSName,DialNode -> Entry -> Header -> Name);
		strcpy(CurrentBBSComment,DialNode -> Entry -> Header -> Comment);

		strcpy(CurrentBBSNumber,NumberBuffer);

		if(DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
		{
			OnlinePlus = DialNode -> Entry -> Config -> ModemConfig -> TimeToConnect;

			if(DialNode -> Entry -> Config -> ModemConfig -> ConnectLimit > 0 && DialNode -> Entry -> Config -> ModemConfig -> ConnectLimitMacro[0])
			{
				LimitCount = DialNode -> Entry -> Config -> ModemConfig -> ConnectLimit;

				strcpy(LimitMacro,DialNode -> Entry -> Config -> ModemConfig -> ConnectLimitMacro);
			}
			else
				LimitCount = -1;
		}
		else
		{
			OnlinePlus = Config -> ModemConfig -> TimeToConnect;

			if(Config -> ModemConfig -> ConnectLimit > 0 && Config -> ModemConfig -> ConnectLimitMacro[0])
			{
				LimitCount = Config -> ModemConfig -> ConnectLimit;

				strcpy(LimitMacro,Config -> ModemConfig -> ConnectLimitMacro);
			}
			else
				LimitCount = -1;
		}

		LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),DialNode -> Entry -> Header -> Name,NumberBuffer);
	}
	else
	{
		OnlinePlus = Config -> ModemConfig -> TimeToConnect;

		MakeCall("???",NumberBuffer);

		ObtainSemaphoreShared(&PatternSemaphore);

		ChosenPattern	= FindTimeDate(PatternList,NumberBuffer);
		ChosenEntry		= NULL;

		ReleaseSemaphore(&PatternSemaphore);

		Password[0]	= 0;
		UserName[0]	= 0;
		SendStartup	= FALSE;

		CurrentBBSName[0]	= 0;
		CurrentBBSComment[0]	= 0;

		strcpy(CurrentBBSNumber,NumberBuffer);

		if(Config -> ModemConfig -> ConnectLimit > 0 && Config -> ModemConfig -> ConnectLimitMacro[0])
		{
			LimitCount = Config -> ModemConfig -> ConnectLimit;

			strcpy(LimitMacro,Config -> ModemConfig -> ConnectLimitMacro);
		}
		else
			LimitCount = -1;

		LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),NumberBuffer);
	}

		/* We are now online. */

	SetOnlineState(TRUE);

		// Start the accounting process

	StartAccountant(OnlinePlus);

		/* Open auto-capture file. */

	if(Config -> CaptureConfig -> ConnectAutoCapture && Config -> CaptureConfig -> CapturePath[0])
	{
		if(DialNode -> Entry)
			OpenAutoCaptureFile(DialNode -> Entry -> Header -> Name);
		else
			OpenAutoCaptureFile(LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT));
	}

		/* Remove node from
		 * dialing list and
		 * perform system
		 * setup.
		 */

	if(DialNode -> Entry)
		RemoveDialNode(DialNode);

	Remove(&DialNode -> VanillaNode);

	FreeVecPooled(DialNode);

	if(PrivateConfig -> MiscConfig -> BackupConfig)
	{
		if(!BackupConfig)
		{
			if(BackupConfig = CreateConfiguration(TRUE))
				SaveConfig(PrivateConfig,BackupConfig);
		}
	}

		/* Make sure that the following
		 * setup/initialization will not
		 * touch the serial configuration.
		 */

	CopyMem(Config -> SerialConfig,PrivateConfig -> SerialConfig,sizeof(struct SerialSettings));

	ConfigSetup();

		/* Reset the scanner. */

	FlowInit(TRUE);
}

	/* OpenDialPanel(BOOL *Record):
	 *
	 *	Open the dialing panel.
	 */

STATIC LayoutHandle *
OpenDialPanel(BOOL *Record)
{
	LayoutHandle *Handle;

	if(Handle = LT_CreateHandleTags(Window -> WScreen,
		LH_LocaleHook,	&LocaleHook,
	TAG_DONE))
	{
		LT_New(Handle,
			LA_Type,	VERTICAL_KIND,
		TAG_DONE);
		{
			LT_New(Handle,
				LA_Type,	VERTICAL_KIND,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,			BOX_KIND,
						LA_ID,				GAD_CALLING,
						LA_Chars,			45,
						LA_Lines,			4,
						LABX_ReserveSpace,	TRUE,
						LABX_FirstLabel,	MSG_DIALPANEL_CALLING_TXT,
						LABX_LastLabel,		MSG_DIALPANEL_NEXT_TXT,
					TAG_DONE);

					LT_New(Handle,
						LA_Type,			BOX_KIND,
						LA_ID,				GAD_TIME,
						LA_Chars,			45,
						LA_Lines,			2,
						LABX_ReserveSpace,	TRUE,
						LABX_FirstLabel,	MSG_DIALPANEL_TIMEOUT_TXT,
						LABX_LastLabel,		MSG_DIALPANEL_ATTEMPT_TXT,
					TAG_DONE);

					LT_New(Handle,
						LA_Type,			BOX_KIND,
						LA_ID,				GAD_NOTE,
						LA_Chars,			45,
						LA_Lines,			1,
						LABX_ReserveSpace,	TRUE,
						LABX_FirstLabel,	MSG_DIALPANEL_MESSAGE_TXT,
						LABX_LastLabel,		MSG_DIALPANEL_MESSAGE_TXT,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,		XBAR_KIND,
					TAG_DONE);

					LT_New(Handle,
						LA_Type,		CHECKBOX_KIND,
						LA_LabelID,		MSG_DIALPANEL_RECORD_ON_CONNECTION_TXT,
						LA_BOOL,		Record,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_EndGroup(Handle);
			}

			LT_New(Handle,
				LA_Type,VERTICAL_KIND,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,		XBAR_KIND,
					LAXB_FullSize,	TRUE,
				TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_New(Handle,LA_Type,HORIZONTAL_KIND,
				LAGR_Spread,	TRUE,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,		BUTTON_KIND,
					LA_LabelID,		MSG_DIALPANEL_SKIP_GAD,
					LA_ID,			GAD_SKIP,
					LABT_ExtraFat,	TRUE,
					GA_Disabled,	TRUE,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,		BUTTON_KIND,
					LA_LabelID,		MSG_GLOBAL_REMOVE_GAD,
					LA_ID,			GAD_REMOVE,
					LABT_ExtraFat,	TRUE,
					GA_Disabled,	TRUE,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,		BUTTON_KIND,
					LA_LabelID,		MSG_DIALPANEL_GO_TO_ONLINE_GAD,
					LA_ID,			GAD_ONLINE,
					LABT_ReturnKey,	TRUE,
					LABT_ExtraFat,	TRUE,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,		BUTTON_KIND,
					LA_LabelID,		MSG_GLOBAL_ABORT_GAD,
					LA_ID,			GAD_ABORT,
					LABT_ExtraFat,	TRUE,
				TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_EndGroup(Handle);
		}

		if(LT_Build(Handle,
			LAWN_TitleID,		MSG_DIALPANEL_DIALING_TXT,
			LAWN_IDCMP,			IDCMP_CLOSEWINDOW,
			LAWN_HelpHook,		&GuideHook,
			LAWN_Parent,		Window,
			WA_DepthGadget,		TRUE,
			WA_CloseGadget,		TRUE,
			WA_DragBar,			TRUE,
			WA_RMBTrap,			TRUE,
			WA_Activate,		TRUE,
/*			WA_SimpleRefresh,	TRUE,*/
		TAG_DONE))
			return(Handle);
		else
			LT_DeleteHandle(Handle);
	}

	return(NULL);
}

	/* DialPanel():
	 *
	 *	This routine opens a small window in the middle of the
	 *	console window and walks down the list of numbers to
	 *	dial.
	 */

BOOL
DialPanel()
{
	LayoutHandle	*Handle;
	BOOL			 Result = FALSE,
					 Record = FALSE,
					 DropIt = FALSE;

	BlockWindows();

	if(Handle = OpenDialPanel(&Record))
	{
		STATIC struct SerialSettings OriginalSerialConfig;

		struct Window		*PanelWindow = Handle -> Window;

		UBYTE				 ExitCommand[80],
							 ExitBuffer[80],
						 	 InitBuffer[80],
						 	 PrefixBuffer[80],
						 	 NumberBuffer[100];

		UBYTE				 DialBuffer[300];

		STRPTR				 NextExit,
							 NextInit,
							 NextPrefix,
							 NextNumber;

		LONG				 NumberCount,
							 NumberCurrent;

		LONG				 DialTimeout,
							 DialRetries	= 0,
							 DialAttempt	= 0;
		struct PhoneNode	*DialNode		= NULL;

		LONG				 RedialTimeout;

		STRPTR				 CallingName;
		UBYTE				 CallingBuffer[80];

		BOOL				 Dialing	= FALSE,
							 Calling	= FALSE,
							 Waiting	= FALSE,
							 Skipping	= FALSE,
							 Aborting	= FALSE,
							 Error		= FALSE,
							 Done		= FALSE,
							 NeedHangUp	= TRUE;

		LONG				 RunCount	= 0;

		ULONG				 ODUMask;

			// Don't mix up the line send stuff with the default sending routine

		BOOL				(* LocalSendLine)(register STRPTR,register LONG);

		LocalSendLine	= SendLine;
		SendLine		= SendLineDial;

			// Set up the ODU stuff

		if(OwnDevUnitBase && Config -> SerialConfig -> ReleaseODUWhenDialing && Config -> SerialConfig -> SatisfyODURequests != ODU_KEEP && !(Config -> SerialConfig -> Shared && Config -> SerialConfig -> NoODUIfShared) && OwnDevBit != -1)
			ODUMask = (1L << OwnDevBit);
		else
			ODUMask = NULL;

			/* Reset the area code scanner data. */

		ObtainSemaphore(&PatternSemaphore);

		ChosenEntry		= NULL;
		ChosenPattern	= NULL;

		ReleaseSemaphore(&PatternSemaphore);

			/* We are now dialing. */

		Status = STATUS_DIALING;

			/* Remember the original serial settings, so we
			 * can return to them later.
			 */

		CopyMem(Config -> SerialConfig,&OriginalSerialConfig,sizeof(struct SerialSettings));

			/* Set up the AmigaGuide help context. */

		GuideContext(CONTEXT_DIAL);

			/* No exit command is defined yet. */

		ExitCommand[0] = 0;

			/* Make the current one the active one. */

		LT_ShowWindow(Handle,TRUE);

		PushWindow(PanelWindow);

			/* Make a backup of the current configuration. */

		SaveConfig(Config,PrivateConfig);

			/* Don't echo serial output unless requested by the user. */

		if(!Config -> ModemConfig -> VerboseDialing)
			Quiet = TRUE;

			/* Perform full sequence check. */

		FullCheck = TRUE;

			/* Reset the scanner. */

		FlowInit(TRUE);

			/* Clear the signals. */

		SetSignal(0,SIG_SKIP | SIG_BREAK);

			/* The big dialing loop. */

		do
		{
				/* Abort the process? */

			if(SetSignal(0,SIG_BREAK) & SIG_BREAK)
			{
				if(!Done)
					Aborting = Done = TRUE;
			}

				// Check if we should let go of the device

			if(ODUMask)
			{
				if(SetSignal(0,0) & ODUMask)
				{
					if(!Done)
					{
						Aborting = Done = DropIt = TRUE;

						SetSignal(0,ODUMask);
					}
				}
			}

				/* Any window input? */

			if(!Done && (SetSignal(0,PORTMASK(PanelWindow -> UserPort)) & PORTMASK(PanelWindow -> UserPort)))
			{
				struct IntuiMessage	*Msg;
				ULONG				 MsgClass,
									 MsgQualifier;
				UWORD				 MsgCode;
				struct Gadget		*MsgGadget;

				while(Msg = LT_GetIMsg(Handle))
				{
					MsgClass		= Msg -> Class;
					MsgCode			= Msg -> Code;
					MsgQualifier	= Msg -> Qualifier;
					MsgGadget		= Msg -> IAddress;

					LT_ReplyIMsg(Msg);

						/* Convert the space keypress into a
						 * skip command.
						 */

					if(MsgClass == IDCMP_RAWKEY)
					{
						if((Dialing || Waiting) && LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
						{
							LT_PressButton(Handle,GAD_SKIP);

							Skipping = TRUE;
						}
					}

						/* Close the window, hang up the line,
						 * return to the phone book.
						 */

					if(MsgClass == IDCMP_CLOSEWINDOW)
						Aborting = Done = Result = TRUE;

						/* So a button was pressed. */

					if(MsgClass == IDCMP_GADGETUP)
					{
						switch(MsgGadget -> GadgetID)
						{
								/* Remove the currently active dialing
								 * list entry.
								 */

							case GAD_REMOVE:

									/* This makes sense only while
									 * we are dialing.
									 */

								if(Dialing)
								{
									struct PhoneNode	*NextNode = NULL;
									BOOL				 UseHangUp;

										/* If still dialing, hang up first. */

									if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
										UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
									else
										UseHangUp = Config -> ModemConfig -> AbortHangsUp;

									if(UseHangUp)
										HangUp();
									else
									{
										SerWrite("\r",1);

										DelayTime(1,0);
									}

										/* Ignore the response of the modem. */

									HandleSerial();

									FlowInit(TRUE);

										/* Is there another entry in the list? */

									if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
										NextNode = (struct PhoneNode *)DialNode -> VanillaNode . ln_Succ;
									else
									{
											/* No, there isn't; do we have a list with
											 * at least two entries in it?
											 */

										if(DialList -> lh_Head -> ln_Succ -> ln_Succ)
										{
												/* Yet another dialing attempt coming up... */

											DialAttempt++;

												/* Check for dial retry limit. */

											if(DialRetries >= 0 && DialAttempt >= DialRetries)
											{
												DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

												WakeUp(PanelWindow,SOUND_BELL);

												DelayTime(2,0);

												Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

												Done = TRUE;
											}
											else
											{
													/* Grab first list entry and continue. */

												NextNode = (struct PhoneNode *)DialList -> lh_Head;
											}
										}
										else
										{
												/* That's all, folks! */

											DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_LIST_IS_EMPTY_TXT));

											DelayTime(2,0);

											Done = TRUE;
										}
									}

										/* Remove dial entry from list. */

									if(DialNode -> Entry)
										RemoveDialNode(DialNode);

									Remove(&DialNode -> VanillaNode);

									FreeVecPooled(DialNode);

										/* Is there an entry to proceed with? */

									if(DialNode = NextNode)
									{
										NextNumber = NULL;

										Calling = TRUE;
									}
								}

								break;

							case GAD_SKIP:

								if(Dialing || Waiting)
									Skipping = TRUE;

								break;

							case GAD_ONLINE:

									/* Go online so soon? */

								if(!DialNode)
								{
									DialNode = (struct PhoneNode *)DialList -> lh_Head;

									if(DialNode -> Entry)
										ExtractString(DialNode -> Entry -> Header -> Number,NumberBuffer,TRUE);
									else
										ExtractString(DialNode -> VanillaNode . ln_Name,NumberBuffer,TRUE);
								}

								Connect(DialNode,NumberBuffer);

								Done = TRUE;

								break;

								/* Abort the dialing process. */

							case GAD_ABORT:

								Aborting = Done = TRUE;

								break;
						}
					}

					if(Done)
						break;
				}
			}

				/* Skip the current action? */

			if(SetSignal(0,SIG_SKIP) & SIG_SKIP)
			{
				if((Dialing || Waiting) && !Done)
					Skipping = TRUE;
			}

				/* Are we to abort? */

			if(Aborting)
			{
					/* Hang up if necessary. */

				if(Dialing)
				{
					BOOL UseHangUp;

					DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ABORTING_TXT));

					if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
						UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
					else
						UseHangUp = Config -> ModemConfig -> AbortHangsUp;

					if(UseHangUp)
						HangUp();
					else
					{
						SerWrite("\r",1);
						DelayTime(1,0);
					}

						/* Ignore the response of the modem. */

					HandleSerial();

					FlowInit(TRUE);
				}
			}

				/* Start at the beginning. */

			if(!DialNode && !Done)
			{
				DialNode = (struct PhoneNode *)DialList -> lh_Head;

				LT_SetAttributes(Handle,GAD_SKIP,
					GA_Disabled,	FALSE,
				TAG_DONE);

				LT_SetAttributes(Handle,GAD_REMOVE,
					GA_Disabled,	FALSE,
				TAG_DONE);

				Calling = TRUE;

				NextNumber = NULL;
			}

				/* Are we to start a call? */

			if(Calling && !Done)
			{
					/* Reset the sequence scanner, the user may have skipped
					 * the previous dial attempt causing the modem to return
					 * `NO CARRIER'. To prevent the dialer from skipping the
					 * next dial entry as well as the previous we have to
					 * flush any data pending on the serial line.
					 */

				FlowInit(TRUE);

					/* Is this the first number for this dial entry? */

				if(!NextNumber)
				{
					STRPTR	PhoneNumber;
					LONG	i,Len;

						/* Does this entry have a configuration attached? */

					if(DialNode -> Entry)
					{
							/* Get the phone number. */

						PhoneNumber = DialNode -> Entry -> Header -> Number;

							/* Pick up the modem configuration. */

						if(DialNode -> Entry -> Config -> ModemConfig)
						{
							NextInit	= ExtractString(DialNode -> Entry -> Config -> ModemConfig -> ModemInit,	InitBuffer,		FALSE);
							NextExit	= ExtractString(DialNode -> Entry -> Config -> ModemConfig -> ModemExit,	ExitBuffer,		FALSE);
							NextPrefix	= ExtractString(DialNode -> Entry -> Config -> ModemConfig -> DialPrefix,	PrefixBuffer,	FALSE);
						}
						else
						{
							NextInit	= ExtractString(Config -> ModemConfig -> ModemInit,		InitBuffer,		FALSE);
							NextExit	= ExtractString(Config -> ModemConfig -> ModemExit,		ExitBuffer,		FALSE);
							NextPrefix	= ExtractString(Config -> ModemConfig -> DialPrefix,	PrefixBuffer,	FALSE);
						}
					}
					else
					{
							/* Get the phone number. */

						PhoneNumber = DialNode -> VanillaNode . ln_Name;

							/* Pick up the modem configuration. */

						if(Config -> ModemConfig -> DoNotSendMainModemCommands)
							InitBuffer[0] = ExitBuffer[0] = 0;
						else
						{
							NextInit	= ExtractString(Config -> ModemConfig -> ModemInit,		InitBuffer,		FALSE);
							NextExit	= ExtractString(Config -> ModemConfig -> ModemExit,		ExitBuffer,		FALSE);
						}

						NextPrefix = ExtractString(Config -> ModemConfig -> DialPrefix,	PrefixBuffer,	FALSE);
					}

							/* Extract the phone number. */

					NextNumber = ExtractString(PhoneNumber,NumberBuffer,TRUE);

						/* Count the number of phone numbers separated
						 * by "|" characters.
						 */

					Len = strlen(PhoneNumber);

					for(i = 0, NumberCount = 0 ; i < Len ; i++)
					{
						if(PhoneNumber[i] == '|')
						{
							LONG j;

							for(j = i + 1 ; j <= Len ; j++)
							{
								if(PhoneNumber[j] != ' ' && PhoneNumber[j] != 0)
								{
									if(PhoneNumber[j] != '|')
										NumberCount++;

									break;
								}
							}
						}
					}

						/* This is the first one. */

					NumberCurrent = 0;
				}
				else
				{
						/* Now for multiple phone numbers separated
						 * by `|' characters. If `NextNumber' happens
						 * to be zero, we will prepare to extract
						 * the first phone number from the list.
						 * In any other case we will try to obtain
						 * the next number.
						 */

					NextNumber	= ExtractString(NextNumber,	NumberBuffer,	TRUE);
					NextPrefix	= ExtractString(NextPrefix,	PrefixBuffer,	FALSE);

					if(!DialNode -> Entry && Config -> ModemConfig -> DoNotSendMainModemCommands)
						InitBuffer[0] = ExitBuffer[0] = 0;
					else
					{
						NextInit	= ExtractString(NextInit,	InitBuffer,		FALSE);
						NextExit	= ExtractString(NextExit,	ExitBuffer,		FALSE);
					}

					NumberCurrent++;
				}

					/* Send the modem exit string before we
					 * will need to reconfigure the serial
					 * device driver.
					 */

				if(ExitCommand[0])
					Error |= Done |= SendSomeCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));

					/* We will need to change the serial parameters
					 * in order to establish a connection.
					 */

				if(!Done)
				{
					if(DialNode -> Entry && DialNode -> Entry -> Config -> SerialConfig)
					{
						if(ReconfigureSerial(PanelWindow,DialNode -> Entry -> Config -> SerialConfig) == RECONFIGURE_FAILURE)
						{
							WakeUp(PanelWindow,SOUND_ERROR);

							Error = Done = TRUE;
						}
					}
					else
					{
						if(ReconfigureSerial(PanelWindow,&OriginalSerialConfig) == RECONFIGURE_FAILURE)
						{
							WakeUp(PanelWindow,SOUND_ERROR);

							Error = Done = TRUE;
						}
					}
				}

				if(!Done)
				{
						// Update the ODU stuff

					if(OwnDevUnitBase && Config -> SerialConfig -> ReleaseODUWhenDialing && Config -> SerialConfig -> SatisfyODURequests != ODU_KEEP && !(Config -> SerialConfig -> Shared && Config -> SerialConfig -> NoODUIfShared) && OwnDevBit != -1)
						ODUMask = (1L << OwnDevBit);
					else
						ODUMask = NULL;

						/* Send the modem init command. */

					if(InitBuffer[0])
						Error |= Done |= SendSomeCommand(Handle,InitBuffer,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
				}

				if(!Done)
				{
						/* Remember the new exit command. */

					strcpy(ExitCommand,ExitBuffer);

					if(DialNode -> Entry)
						CallingName = DialNode -> Entry -> Header -> Name;
					else
						CallingName = LocaleString(MSG_GLOBAL_UNKNOWN_TXT);

						/* If there is more than one number to follow, say so. */

					if(NumberCount)
					{
						UBYTE LocalBuffer[40];

						SPrintf(LocalBuffer,LocaleString(MSG_DIALPANEL_ATTEMPT_OF_TXT),NumberCurrent + 1,NumberCount + 1);

						SPrintf(CallingBuffer,"%s (%s)",CallingName,LocalBuffer);

						CallingName = CallingBuffer;
					}

					DialPrintBox(Handle,GAD_CALLING,0,CallingName);

						/* Show the comment if any. */

					if(DialNode -> Entry && DialNode -> Entry -> Header -> Comment[0])
						DialPrintBox(Handle,GAD_CALLING,1,DialNode -> Entry -> Header -> Comment);
					else
						DialPrintBox(Handle,GAD_CALLING,1,"-");

						/* Display the number being called. */

					if(DialNode -> Entry)
						Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),DialNode -> Entry -> Header -> Name);
					else
						Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),NumberBuffer);

					DialPrintBox(Handle,GAD_CALLING,2,NumberBuffer);

						/* Display the name of the service to call next. */

					if(NextNumber)
					{
						if(DialNode -> Entry)
							CallingName = DialNode -> Entry -> Header -> Name;
						else
							CallingName = DialNode -> VanillaNode . ln_Name;
					}
					else
					{
						if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
						{
							if(DialNode -> Entry)
								CallingName = ((struct PhoneNode *)DialNode -> VanillaNode . ln_Succ) -> Entry -> Header -> Name;
							else
								CallingName = DialNode -> VanillaNode . ln_Succ -> ln_Name;
						}
						else
							CallingName = "-";
					}

					DialPrintBox(Handle,GAD_CALLING,3,CallingName);

						/* Right now we're dialing. */

					DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_TXT));

						/* Build the dialing command. */

					strcpy(DialBuffer,PrefixBuffer);

					if(DialNode -> Entry && DialNode -> Entry -> Config -> ModemConfig)
					{
						if(DialNode -> Entry -> Config -> ModemConfig -> PBX_Mode && DialNode -> Entry -> Config -> ModemConfig -> PBX_Prefix[0])
							strcat(DialBuffer,DialNode -> Entry -> Config -> ModemConfig -> PBX_Prefix);
					}
					else
					{
						if(Config -> ModemConfig -> PBX_Mode && Config -> ModemConfig -> PBX_Prefix[0])
							strcat(DialBuffer,Config -> ModemConfig -> PBX_Prefix);
					}

					strcat(DialBuffer,NumberBuffer);

					if(DialNode -> Entry)
					{
						if(DialNode -> Entry -> Config -> ModemConfig)
							strcat(DialBuffer,DialNode -> Entry -> Config -> ModemConfig -> DialSuffix);
						else
							strcat(DialBuffer,Config -> ModemConfig -> DialSuffix);
					}
					else
						strcat(DialBuffer,Config -> ModemConfig -> DialSuffix);

						/* Pick up dial timeout and dial retries. */

					if(DialNode -> Entry && DialNode -> Entry -> Config -> ModemConfig)
					{
						DialTimeout	= DialNode -> Entry -> Config -> ModemConfig -> DialTimeout;
						DialRetries	= DialNode -> Entry -> Config -> ModemConfig -> DialRetries;
					}
					else
					{
						DialTimeout	= Config -> ModemConfig -> DialTimeout;
						DialRetries	= Config -> ModemConfig -> DialRetries;
					}

						/* Dial the number. */

					SerialCommand(DialBuffer);

						/* Now we should be dialing. */

					Calling = FALSE;
					Dialing = TRUE;

						/* For the sake of precision. */

					RunCount = 0;
				}
			}

				/* Are we to skip the current assignment? */

			if(Skipping && !Done)
			{
				Skipping = FALSE;

					/* Are we currently dialing? */

				if(Dialing)
				{
						/* Hang up if necessary. */

					if(NeedHangUp)
					{
						BOOL UseHangUp;

						if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
							UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
						else
							UseHangUp = Config -> ModemConfig -> AbortHangsUp;

						if(UseHangUp)
							HangUp();
						else
						{
							SerWrite("\r",1);
							DelayTime(1,0);
						}
					}
					else
						NeedHangUp = TRUE;

						/* Ignore the response of the modem. */

					HandleSerial();

					FlowInit(TRUE);

						/* Did we dial all the numbers available? */

					if(!NextNumber)
					{
							/* Is this one the last entry? */

						if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
						{
							LONG InterDialDelay;

								/* There is still another entry. */

							DialNode = (struct PhoneNode *)DialNode -> VanillaNode . ln_Succ;

								/* Get the inter-dial delay. */

							if(DialNode -> Entry)
							{
								if(DialNode -> Entry -> Config -> ModemConfig)
									InterDialDelay = DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
								else
									InterDialDelay = Config -> ModemConfig -> InterDialDelay;
							}
							else
								InterDialDelay = Config -> ModemConfig -> InterDialDelay;

								/* Check if we should wait before we fire off another dial command. */

							if(InterDialDelay)
							{
									/* Wait until the inter-dial delay has elapsed. */

								RedialTimeout = InterDialDelay;

								DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_WAITING_TO_CALL_TXT));

								Dialing = FALSE;
								Waiting = TRUE;

									/* For the sake of precision. */

								RunCount = 0;

								Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));

									/* No entry is currently being called. */

								DialPrintBox(Handle,GAD_CALLING,0,"-");
								DialPrintBox(Handle,GAD_CALLING,1,"-");
								DialPrintBox(Handle,GAD_CALLING,2,"-");

								LT_SetAttributes(Handle,GAD_REMOVE,
									GA_Disabled,	TRUE,
								TAG_DONE);

									/* Display name of entry to call next. */

								if(DialNode -> Entry)
									DialPrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
								else
									DialPrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
							}
							else
							{
								Dialing = FALSE;
								Calling = TRUE;
							}
						}
						else
						{
								/* Yet another dial attempt coming up. */

							DialAttempt++;

								/* Is this one the last dial
								 * attempt to be made?
								 */

							if(DialAttempt >= DialRetries && DialRetries >= 0)
							{
								DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

								WakeUp(PanelWindow,SOUND_BELL);

								DelayTime(2,0);

								Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

								Done = TRUE;
							}
							else
							{
								LONG InterDialDelay;

									/* Get the first list entry. */

								DialNode = (struct PhoneNode *)DialList -> lh_Head;

								NextNumber = NULL;

									/* Get the redial delay. */

								if(DialNode -> Entry)
								{
									if(DialNode -> Entry -> Config -> ModemConfig)
									{
										RedialTimeout	= DialNode -> Entry -> Config -> ModemConfig -> RedialDelay;
										InterDialDelay	= DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
									}
									else
									{
										RedialTimeout	= Config -> ModemConfig -> RedialDelay;
										InterDialDelay	= Config -> ModemConfig -> InterDialDelay;
									}
								}
								else
								{
									RedialTimeout	= Config -> ModemConfig -> RedialDelay;
									InterDialDelay	= Config -> ModemConfig -> InterDialDelay;
								}

									/* Check if the inter-dial delay is larger than
									 * the redial delay. If so, use the inter-dial delay.
									 */

								if(InterDialDelay > RedialTimeout)
									RedialTimeout = InterDialDelay;

									/* No redial delay? Restart dialing... */

								if(!RedialTimeout)
								{
									Dialing = FALSE;
									Calling = TRUE;

									DelayTime(1,0);
								}
								else
								{
										/* Go into redial delay. */

									DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_REDIAL_DELAY_TXT));

									Dialing = FALSE;
									Waiting = TRUE;

										/* For the sake of precision. */

									RunCount = 0;

									Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));

										/* No entry is currently being called. */

									DialPrintBox(Handle,GAD_CALLING,0,"-");
									DialPrintBox(Handle,GAD_CALLING,1,"-");
									DialPrintBox(Handle,GAD_CALLING,2,"-");

									LT_SetAttributes(Handle,GAD_REMOVE,
										GA_Disabled,	TRUE,
									TAG_DONE);

										/* Display name of entry to call next. */

									if(DialNode -> Entry)
										DialPrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
									else
										DialPrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
								}
							}
						}
					}
					else
					{
						LONG InterDialDelay;

							/* Get the inter-dial delay. */

						if(DialNode -> Entry)
						{
							if(DialNode -> Entry -> Config -> ModemConfig)
								InterDialDelay = DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
							else
								InterDialDelay = Config -> ModemConfig -> InterDialDelay;
						}
						else
							InterDialDelay = Config -> ModemConfig -> InterDialDelay;

							/* Check if we should wait before we fire off another dial command. */

						if(InterDialDelay)
						{
								/* Wait until the inter-dial delay has elapsed. */

							RedialTimeout = InterDialDelay;

							DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_WAITING_TO_CALL_TXT));

							Dialing = FALSE;
							Waiting = TRUE;

								/* For the sake of precision. */

							RunCount = 0;

							Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));

								/* No entry is currently being called. */

							DialPrintBox(Handle,GAD_CALLING,0,"-");
							DialPrintBox(Handle,GAD_CALLING,1,"-");
							DialPrintBox(Handle,GAD_CALLING,2,"-");

							LT_SetAttributes(Handle,GAD_REMOVE,
								GA_Disabled,	TRUE,
							TAG_DONE);

								/* Display name of entry to call next. */

							if(DialNode -> Entry)
								DialPrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
							else
								DialPrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
						}
						else
						{
							Dialing = FALSE;
							Calling = TRUE;
						}
					}
				}
				else
				{
						/* Stop waiting. */

					if(Waiting)
					{
						LT_SetAttributes(Handle,GAD_REMOVE,
							GA_Disabled,	FALSE,
						TAG_DONE);

						Waiting = FALSE;
						Calling = TRUE;
					}
				}
			}

				/* Take care of serial input. */

			if(!Done)
				HandleSerial();

				/* Any news from the modem? */

			if(!Done && FlowInfo . Changed)
			{
					/* Current number is busy. */

				if(FlowInfo . Busy || (FlowInfo . NoCarrier && Config -> ModemConfig -> NoCarrierIsBusy))
				{
					FlowInit(TRUE);

					if(Dialing && !Done)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

						Say(LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

						DelayTime(1,0);

						Skipping = TRUE;

						NeedHangUp = FALSE;
					}
				}

					/* Line does not feature a dialtone. */

				if(FlowInfo . NoDialTone)
				{
					FlowInit(TRUE);

					if(Dialing && !Done)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						WakeUp(PanelWindow,SOUND_ERROR);

						Say(LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						Error = Done = TRUE;
					}
				}

					/* Somebody tries to call us. */

				if(FlowInfo . Ring)
				{
					FlowInit(TRUE);

					if(!Done)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));

						WakeUp(PanelWindow,SOUND_RING);

						Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));

						Error = Done = TRUE;
					}
				}

					/* Somebody's talking. */

				if(FlowInfo . Voice)
				{
					FlowInit(TRUE);

					if(!Done)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));

						WakeUp(PanelWindow,SOUND_VOICE);

						Say(LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));

						Error = Done = TRUE;
					}
				}

					/* We got a connect. */

				if(FlowInfo . Connect)
				{
					FlowInit(TRUE);

					if(Dialing && !Done)
					{
							/* Make the connection. */

						Connect(DialNode,NumberBuffer);

						Done = TRUE;

							/* Wake the user up. */

						if(BaudBuffer[0])
						{
							DialPrintBox(Handle,GAD_NOTE,0,"CONNECT %s",BaudBuffer);

							WakeUp(PanelWindow,SOUND_CONNECT);

							DelayTime(2,0);

								/* Install new baud rate if desired. */

							if(Config -> ModemConfig -> ConnectAutoBaud && DTERate > 110)
							{
								Config -> SerialConfig -> BaudRate = DTERate;

								ReconfigureSerial(PanelWindow,NULL);
							}
						}
						else
						{
							DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));

							WakeUp(PanelWindow,SOUND_CONNECT);
						}

						Say(LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));
					}
				}

					/* Looks like an error. */

				if(FlowInfo . Error)
				{
					FlowInit(TRUE);

					if(Dialing && !Done)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));

						WakeUp(PanelWindow,SOUND_ERROR);

						Error = Done = TRUE;
					}
				}

					/* In any other case, reset the scanner. */

				FlowInit(TRUE);
			}

				/* If nothing special's up... */

			if(!Done && !Skipping && (Dialing || Waiting))
			{
					/* Wait half a second. */

				DelayTime(0,MILLION / 2);

				if(Dialing)
				{
					DialPrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",DialTimeout / 60,DialTimeout % 60);

					if(DialRetries < 0)
						DialPrintBox(Handle,GAD_TIME,1,LocaleString(MSG_DIAL_RETRIES_UNLIMITED_TXT));
					else
						DialPrintBox(Handle,GAD_TIME,1,LocaleString(MSG_DIALPANEL_ATTEMPT_OF_TXT),DialAttempt + 1,DialRetries);
				}

				if(Waiting)
					DialPrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",RedialTimeout / 60,RedialTimeout % 60);

					/* The following instructions are executed each second */

				if(RunCount++)
				{
					RunCount = 0;

						/* Are we dialing? */

					if(Dialing)
					{
							/* Yet another second has elapsed. */

						if(DialTimeout > 0)
							DialTimeout--;

							/* Has the dial timeout elapsed without
							 * a connection being made?
							 */

						if(!DialTimeout)
						{
							DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIAL_ATTEMPT_TIMEOUT_TXT));

							Skipping = TRUE;
						}
					}

						/* Are we waiting? */

					if(Waiting)
					{
							/* Yet another second has elapsed. */

						if(RedialTimeout > 0)
							RedialTimeout--;

							/* The redial delay has elapsed,
							 * start dialing again.
							 */

						if(!RedialTimeout)
							Skipping = TRUE;
					}
				}
			}
		}
		while(!Done);

			/* Are we online or not? */

		if(!Online)
		{
			BOOL SendCommands = TRUE;

				/* Is the serial setup different? */

			if(memcmp(Config -> SerialConfig,&OriginalSerialConfig,sizeof(struct SerialSettings)))
			{
					/* Set up the old serial configuration. */

				if(ReconfigureSerial(PanelWindow,&OriginalSerialConfig) == RECONFIGURE_FAILURE)
					SendCommands = FALSE;
			}

			if(SendCommands)
			{
					/* Send the exit command if necessary. */

				if(ExitCommand[0])
					Error |= SendSomeCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));

					/* Take care of the init command if necessary. */

				if(Config -> ModemConfig -> ModemInit[0] && !Error)
					Error |= SendSomeCommand(Handle,Config -> ModemConfig -> ModemInit,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
			}
		}

			/* Make sure the error gets displayed. */

		if(Error && !DropIt)
		{
			struct IntuiMessage	*Msg;
			ULONG				 MsgClass;
			LONG				 i;

			for(i = GAD_SKIP ; i <= GAD_REMOVE ; i++)
				LT_SetAttributes(Handle,i,GA_Disabled,TRUE,TAG_DONE);

			Done = FALSE;

			do
			{
				if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
					break;

				while(Msg = LT_GetIMsg(Handle))
				{
					MsgClass = Msg -> Class;

					LT_ReplyIMsg(Msg);

					if(MsgClass == IDCMP_CLOSEWINDOW || MsgClass == IDCMP_GADGETUP)
						Done = TRUE;
				}
			}
			while(!Done);
		}

			// Put back the old routine if necessary

		if(SendLine == SendLineDial)
			SendLine = LocalSendLine;

		PopWindow();

		LT_DeleteHandle(Handle);

			/* Reset the scanner. */

		FullCheck = FALSE;

		FlowInit(TRUE);

			/* We are done now, restart echoing serial */

		Quiet = FALSE;

		ReleaseWindows();

			/* Reset the display if necessary. */

		if(ResetDisplay)
		{
			if(!DisplayReset())
				return(FALSE);
		}

			/* Handle online jobs. */

		if(Online)
		{
			SetDialMenu(FALSE);

				/* Send the startup macro if necessary. */

			if(SendStartup)
			{
				if(Config -> CommandConfig -> LoginMacro[0])
					SerialCommand(Config -> CommandConfig -> LoginMacro);

				if(Config -> CommandConfig -> StartupMacro[0])
					SerialCommand(Config -> CommandConfig -> StartupMacro);

				SendStartup = FALSE;
			}

				/* Take care of the recording feature. */

			if(Record)
			{
				if(CreateRecord(CurrentBBSName[0] ? CurrentBBSName : CurrentBBSNumber))
				{
					RememberResetOutput();
					RememberResetInput();

					RememberOutput = TRUE;

					Recording = TRUE;
					RecordingLine = FALSE;

					OnItem(MEN_RECORD_LINE);

					CheckItem(MEN_RECORD,TRUE);
					CheckItem(MEN_RECORD_LINE,FALSE);
				}
			}
		}
		else
			SetDialMenu(TRUE);
	}
	else
		ReleaseWindows();

		/* Reply to the message that started the
		 * dialing process.
		 */

	Forbid();

	if(DialMsg)
	{
		if(Online)
			DialMsg -> rm_Result1 = RC_OK;
		else
			DialMsg -> rm_Result1 = RC_WARN;

		DialMsg -> rm_Result2 = 0;

		ReplyMsg(DialMsg);

		DialMsg = NULL;
	}

	Permit();

	if(DropIt)
		HandleOwnDevUnit();

	return(Result);
}
