/*
**	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
		};

	/* Local copy of the global serial and modem settings. */

STATIC struct SerialSettings	*OriginalSerialConfig;
STATIC struct ModemSettings		*OriginalModemConfig;

	/* Local routines. */

STATIC VOID QuickHangup(struct DialNode *DialNode);
STATIC VOID DialPrintBox(LayoutHandle *Handle, LONG Box, LONG Line, STRPTR String, ...);
STATIC BOOL SendLocalModemCommand(LayoutHandle *Handle, STRPTR Command, STRPTR Message, STRPTR ErrorMessage);
STATIC VOID BuildName(STRPTR Name, LONG MaxNameLen, STRPTR Date);
STATIC VOID OpenAutoCaptureFile(STRPTR SomeName);
STATIC VOID Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode);
STATIC LayoutHandle *OpenDialPanel(BOOL *Record,BOOL *SkipLoginMacro);

	/* GetCurrentSettings():
	 *
	 *	Get the settings corresponding to a dial node.*/

STATIC VOID
GetCurrentSettings(struct DialNode *DialNode,struct SerialSettings **SerialPtr,struct ModemSettings **ModemPtr)
{
	*SerialPtr	= OriginalSerialConfig;
	*ModemPtr	= OriginalModemConfig;

	if(DialNode && DialNode->Entry && DialNode->Entry->Config)
	{
		if(DialNode->Entry->Config->SerialConfig)
			*SerialPtr = DialNode->Entry->Config->SerialConfig;

		if(DialNode->Entry->Config->ModemConfig)
			*ModemPtr = DialNode->Entry->Config->ModemConfig;
	}
}

	/* QuickHangup(struct DialNode *DialNode):
	 *
	 *	Stop dialing by hanging up or sending a return character to the modem.
	 */

STATIC VOID
QuickHangup(struct DialNode *DialNode)
{
	BOOL UseHangUp;

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

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

		StartTime(1,0);

			/* Wait for the modem to respond or the timer to elapse. */

		Wait(GetJobMask(SerialJob) | SIG_TIMER);

		StopTime();
	}

		/* Ignore the response of the modem. */

	while(RunJob(SerialJob));

	ResetDataFlowFilter();
}

	/* DialPrintBox():
	 *
	 *	Render text into one of the display box lines.
	 */

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

	va_start(VarArgs,String);
	LimitedVSPrintf(sizeof(LocalBuffer),LocalBuffer,String,VarArgs);
	va_end(VarArgs);

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

	/* SendModemCommandGetResponse(LayoutHandle *Handle,STRPTR Command):
	 *
	 *	Send a modem command and wait for a response.
	 */

STATIC BOOL
SendModemCommandGetResponse(LayoutHandle *Handle,STRPTR Command)
{
	ULONG Signals,SerialMask,WindowMask;
	ULONG LastBytesOut;
	BOOL Done;

		/* Reset the data flow scanner. */

	ResetDataFlowFilter();

		/* Send the modem command, but first remember how many
		 * bytes were sent yet.
		 */

	LastBytesOut = BytesOut;

	SerialCommand(Command);

		/* If no serial output took place, we'll return
		 * immediately.
		 */

	if(BytesOut == LastBytesOut)
		return(TRUE);

		/* Get the two wait masks. */

	SerialMask = GetJobMask(SerialJob);
	WindowMask = PORTMASK(Handle->Window->UserPort);

		/* Start the timer. We will wait up to ten seconds for
		 * the modem to respond.
		 */

	StartTime(10,0);

	Done = FALSE;

	do
	{
			/* Wait for something to happen. */

		Signals = Wait(SerialMask | WindowMask | SIG_TIMER);

			/* Any window signal? */

		if(Signals & WindowMask)
		{
			struct IntuiMessage	*Message;
			ULONG MsgClass,MsgQualifier;
			struct Gadget *MsgGadget;
			UWORD MsgCode;

				/* Check if we are to skip or abort. */

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

				LT_ReplyIMsg(Message);

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

				if(MsgClass == IDCMP_RAWKEY)
				{
					if(LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
						Done = TRUE;
				}

					/* So a button was pressed. */

				if(MsgClass == IDCMP_GADGETUP)
				{
					switch(MsgGadget->GadgetID)
					{
						case GAD_SKIP:
						case GAD_ABORT:

							Done = TRUE;
							break;
					}
				}
			}
		}

			/* Any modem signal? */

		if(Signals & SerialMask)
		{
				/* Handle the serial input. */

			while(RunJob(SerialJob));

				/* Exit if the modem said something sensible. */

			if(FlowInfo.Changed)
				Done = TRUE;
		}

			/* Did the bell ring? */

		if(Signals & SIG_TIMER)
			Done = TRUE;
	}
	while(!Done);

		/* Stop the timer. */

	StopTime();

		/* Did the modem respond? */

	return(FlowInfo.Changed);
}

	/* SendLocalModemCommand():
	 *
	 *	Send a command to the modem and display an error message if necessary.
	 */

STATIC BOOL
SendLocalModemCommand(LayoutHandle *Handle,STRPTR Command,STRPTR Message,STRPTR ErrorMessage)
{
		/* Show the message. */

	DialPrintBox(Handle,GAD_NOTE,0,Message);

		/* Send the command and check if the modem did respond. */

	if(SendModemCommandGetResponse(Handle,Command))
	{
			/* No news is good news. */

		if(!FlowInfo.Error)
			return(TRUE);
		else
			DialPrintBox(Handle,GAD_NOTE,0,ErrorMessage);
	}
	else
		DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_MODEM_NOT_RESPONDING_TXT));

	WakeUp(Handle->Window,SOUND_ERROR);
	return(FALSE);
}

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

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

		NameLen = strlen(Name);
		DateLen = strlen(Date);

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

		LimitedStrcat(MaxNameLen,Name,"_");
		LimitedStrcat(MaxNameLen,Name,Date);
	}
}

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

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

		/* Get the current time and date. */

	DateStamp(&DateTime.dat_Stamp);

		/* Prepare for date conversion. */

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

		/* Convert the date. */

	if(DateToStr(&DateTime))
	{
		UBYTE LocalBuffer[MAX_FILENAME_LENGTH],Name[MAX_FILENAME_LENGTH];

			/* Remember the BBS name. */

		LimitedStrcpy(sizeof(Name),Name,SomeName);

			/* Append the creation date if necessary. */

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

			/* Make it a reasonable name. */

		FixName(Name);

			/* Get the capture file path. */

		LimitedStrcpy(sizeof(LocalBuffer),LocalBuffer,Config->CaptureConfig->CapturePath);

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

		if(AddPart(LocalBuffer,Name,sizeof(LocalBuffer)))
		{
				/* 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(LocalBuffer,"a"))
			{
					/* Set the menu checkmark. */

				CheckItem(MEN_CAPTURE_TO_FILE,TRUE);

					/* Remember the current capture file name. */

				strcpy(CaptureName,LocalBuffer);

					/* Add the creation date if necessary. */

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

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

			ConOutputUpdate();
		}
	}
}

	/* Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode):
	 *
	 *	Perform connect action(s).
	 */

STATIC VOID
Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode)
{
	struct ModemSettings *ModemConfig;
	ULONG RateIs;
	STRPTR Name;

		/* Check which modem configuration to use later. */

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

		/* Get the current area code settings. */

	SetActivePattern(FindTimeDate(PatternList,DialNode->Number));

		/* Mark the active phonebook entry, if any. */

	SetActiveEntry(PhoneHandle,DialNode->Entry);

		/* Get the DTE rate ready. */

	if(DTERate > 0)
		RateIs = DTERate;
	else
		RateIs = Config->SerialConfig->BaudRate;

		/* Does the node have a phonebook entry attached? */

	if(DialNode->Entry)
	{
		SaveConfig(DialNode->Entry->Config,Config);
		ConfigChanged = FALSE;

		Name = DialNode->Entry->Header->Name;

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

		SendStartup = TRUE;

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

		LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),Name,DialNode->Number,RateIs);
	}
	else
	{
		Name = LocaleString(MSG_GLOBAL_UNKNOWN_TXT);

		Password[0]	= 0;
		UserName[0]	= 0;

		SendStartup	= FALSE;

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

		LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),DialNode->Number,RateIs);
	}

		/* Register the call. */

	MakeCall(Name,DialNode->Number);

		/* Store the current phone number. */

	strcpy(CurrentBBSNumber,DialNode->Number);

		/* Get the online time limit and the macro to execute when the limit is reached. */

	if(ModemConfig->ConnectLimit > 0 && ModemConfig->ConnectLimitMacro[0])
	{
		ArmLimit(ModemConfig->ConnectLimit);

		strcpy(LimitMacro,ModemConfig->ConnectLimitMacro);
	}
	else
		DisarmLimit();

		/* We are now online. */

	SetOnlineState(TRUE);

		/* Start the accounting process */

	StartAccountant(ModemConfig->TimeToConnect);

		/* Open auto-capture file. */

	if(Config->CaptureConfig->ConnectAutoCapture && Config->CaptureConfig->CapturePath[0])
	{
		STRPTR FileName;

		if(DialNode->Entry)
			FileName = DialNode->Entry->Header->Name;
		else
			FileName = LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT);

		OpenAutoCaptureFile(FileName);
	}

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

	RemoveAndDeleteRelatedDialNodes(PhoneHandle,DialNode);

		/* Make a backup of the old settings. */

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

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

	PutConfigEntry(PrivateConfig,Config->SerialConfig,PREF_SERIAL);

	ConfigSetup();

		/* Reset the scanner. */

	ResetDataFlowFilter();
}

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

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

	if(Handle = LT_CreateHandleTags(Window->WScreen,
		LAHN_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,			40,
						LABX_Rows,			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,
						LABX_Rows,			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,
						LABX_Rows,			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_New(Handle,
						LA_Type,		CHECKBOX_KIND,
						LA_LabelID,		MSG_SKIP_LOGIN_MACRO_GAD,
						LA_BOOL,		SkipLoginMacro,
					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(PhonebookHandle *PhoneHandle)
{
	enum { STOP_Not,STOP_Abort,STOP_Skip };
	enum { START_Dial,START_Call,START_Wait };

	BOOL ReturnToPhonebook,RecordOnConnection,ReleaseSerialDevice,SkipLoginMacro;
	LayoutHandle *Handle;

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

	OriginalSerialConfig	= CreateNewConfigEntry(PREF_SERIAL);
	OriginalModemConfig		= CreateNewConfigEntry(PREF_MODEM);

	if(!OriginalSerialConfig || !OriginalModemConfig)
	{
		FreeVecPooled(OriginalSerialConfig);
		OriginalSerialConfig = NULL;

		FreeVecPooled(OriginalModemConfig);
		OriginalModemConfig = NULL;

		DisplayBeep(NULL);

		return(FALSE);
	}

	ReturnToPhonebook = RecordOnConnection = ReleaseSerialDevice = SkipLoginMacro = FALSE;

	if(Handle = OpenDialPanel(&RecordOnConnection,&SkipLoginMacro))
	{
		struct SerialSettings *	CurrentSerialConfig;
		struct ModemSettings *	CurrentModemConfig;

		struct Window *			PanelWindow;

		UBYTE					NoteText[80];

		UBYTE					ExitCommand[80];

		UBYTE					ExitBuffer[80],
						 		InitBuffer[80];

		UBYTE			 		PrefixBuffer[80],
						 		SuffixBuffer[80];

		UBYTE					DialBuffer[300];

		LONG					DialTimeout,DialRetries,DialAttempt;

		struct DialNode *		DialNode;

		LONG					RedialTimeout;

		WORD					Start,Stop;

		BOOL					DoNotHangUp,ErrorHasOccured,ModemNotResponding,Done;

		BOOL					OldQuietSettings;

		ULONG					ODUMask,WindowMask,Signals;

		SENDLINE				OriginalSendLine;

		struct timeval			LastTimeCheck;

			/* Start from scratch. */

		PanelWindow 		= Handle->Window;

		DialRetries			= 0;
		DialAttempt			= 0;
		DialNode			= NULL;

		ErrorHasOccured		= FALSE;
		ModemNotResponding	= FALSE;
		DoNotHangUp 		= FALSE;

		Done				= FALSE;

		Start				= START_Call;
		Stop				= STOP_Not;

		GetCurrentSettings(NULL,&CurrentSerialConfig,&CurrentModemConfig);

		GetSysTime(&LastTimeCheck);

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

		OriginalSendLine = ChangeSendLine(SendLineDial);

			/* Set up the ODU stuff */

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

			/* And get the window port mask ready */

		WindowMask = PORTMASK(Handle->Window->UserPort);

			/* Reset the area code scanner data. */

		SetActivePattern(NULL);
		SetActiveEntry(PhoneHandle,NULL);

			/* We are now dialing. */

		PushStatus(STATUS_DIALING);

			/* 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. */

		OldQuietSettings = SetConsoleQuiet((BOOL)(Config->ModemConfig->VerboseDialing == FALSE));

			/* Reset the scanner. */

		ResetDataFlowFilter();

			/* Get the entry signals ready and clear those we do not yet care about. */

		Signals = SetSignal(0,SIG_BREAK | SIG_SKIP | ODUMask | WindowMask) & (ODUMask | WindowMask);

			/* The big dialing loop. */

		do
		{
				/* Abort the process? */

			if(!Done && (Signals & SIG_BREAK))
			{
				Stop = STOP_Abort;
				Done = TRUE;
			}

				/* Check if we should let go of the device */

			if(!Done && (Signals & ODUMask))
			{
				Stop = STOP_Abort;
				Done = TRUE;

				ReleaseSerialDevice = TRUE;
			}

				/* Any window input? */

			if(!Done && (Signals & WindowMask))
			{
				struct IntuiMessage	*Message;
				ULONG MsgClass,MsgQualifier;
				struct Gadget *MsgGadget;
				UWORD MsgCode;

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

					LT_ReplyIMsg(Message);

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

					if(MsgClass == IDCMP_RAWKEY)
					{
						if(LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
						{
							if(Stop == STOP_Not && Start != START_Call)
							{
								LT_PressButton(Handle,GAD_SKIP);

								Stop = STOP_Skip;
							}
						}
					}

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

					if(MsgClass == IDCMP_CLOSEWINDOW)
					{
						Stop = STOP_Abort;
						Done = TRUE;
						ReturnToPhonebook = 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(Start == START_Dial)
								{
									struct DialNode	*NextNode;

									NextNode = NULL;

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

									if(DoNotHangUp)
										DoNotHangUp = FALSE;
									else
										QuickHangup(DialNode);

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

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

										if(PhoneHandle->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 DialNode *)PhoneHandle->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. */

									RemoveDialNode(PhoneHandle,DialNode);
									DeleteDialNode(DialNode);

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

									if(DialNode = NextNode)
										Start = START_Call;

									GetCurrentSettings(DialNode,&CurrentSerialConfig,&CurrentModemConfig);
								}

								break;

							case GAD_SKIP:

								if(Stop == STOP_Not && Start != START_Call)
									Stop = STOP_Skip;

								break;

							case GAD_ONLINE:

									/* Go online so soon? */

								if(!DialNode)
								{
									if(!IsListEmpty(PhoneHandle->DialList))
										DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head;
								}

								if(DialNode)
									Connect(PhoneHandle,DialNode);

								GetCurrentSettings(DialNode,&CurrentSerialConfig,&CurrentModemConfig);

								Done = TRUE;

								break;

								/* Abort the dialing process. */

							case GAD_ABORT:

								Stop = STOP_Abort;
								Done = TRUE;

								break;
						}
					}

					if(Done)
						break;
				}
			}

				/* Skip the current action? */

			if(!Done && (Signals & SIG_SKIP))
			{
				if(Stop == STOP_Not && Start != START_Call)
					Stop = STOP_Skip;
			}

				/* Are we to abort? */

			if(Stop == STOP_Abort)
			{
				Stop = STOP_Not;

					/* Hang up if necessary. */

				if(Start == START_Dial)
				{
					DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ABORTING_TXT));

						/* Hang up if necessary. */

					if(DoNotHangUp)
						DoNotHangUp = FALSE;
					else
						QuickHangup(DialNode);
				}
			}

				/* Start at the beginning. */

			if(!Done && !DialNode)
			{
				GetCurrentSettings(DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head,&CurrentSerialConfig,&CurrentModemConfig);

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

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

				Start = START_Call;
			}

				/* Are we to start a call? */

			if(!Done && Start == START_Call)
			{
					/* 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.
					 */

				ResetDataFlowFilter();

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

				if(DialNode->Entry == NULL && Config->ModemConfig->DoNotSendMainModemCommands)
					InitBuffer[0] = ExitBuffer[0] = 0;
				else
				{
					LimitedStrcpy(sizeof(InitBuffer),InitBuffer,DialNode->InitCommand ? DialNode->InitCommand : CurrentModemConfig->ModemInit);
					LimitedStrcpy(sizeof(ExitBuffer),ExitBuffer,DialNode->ExitCommand ? DialNode->ExitCommand : CurrentModemConfig->ModemExit);
				}

				LimitedStrcpy(sizeof(PrefixBuffer),PrefixBuffer,DialNode->DialPrefix ? DialNode->DialPrefix : CurrentModemConfig->DialPrefix);
				LimitedStrcpy(sizeof(SuffixBuffer),SuffixBuffer,DialNode->DialSuffix ? DialNode->DialSuffix : CurrentModemConfig->DialSuffix);

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

				if(ExitCommand[0])
				{
					if(!SendLocalModemCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
					{
						if(!FlowInfo.Changed)
							ModemNotResponding = TRUE;

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}

					ExitCommand[0] = 0;
				}

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

				if(!Done)
				{
					PutConfigEntry(Config,CurrentModemConfig,PREF_MODEM);

					if(ReconfigureSerial(PanelWindow,CurrentSerialConfig) == RECONFIGURE_FAILURE)
					{
						WakeUp(PanelWindow,SOUND_ERROR);

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}
				}

					/* Update the ODU bits and send the modem init command, if any. */

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

					if(OwnDevUnitBase && CurrentSerialConfig->ReleaseODUWhenDialing && CurrentSerialConfig->SatisfyODURequests != ODU_KEEP && !(CurrentSerialConfig->Shared && CurrentSerialConfig->NoODUIfShared))
						ODUMask = SIG_OWNDEVUNIT;
					else
						ODUMask = NULL;

						/* Send the modem init command. */

					if(InitBuffer[0])
					{
						if(!SendLocalModemCommand(Handle,InitBuffer,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
						{
							if(!FlowInfo.Changed)
								ModemNotResponding = TRUE;

							ErrorHasOccured = TRUE;
							Done = TRUE;
						}

						InitBuffer[0] = 0;
					}
				}

					/* Get on with the rest. */

				if(!Done)
				{
					STRPTR Comment;

						/* Remember the new exit command. */

					LimitedStrcpy(sizeof(ExitCommand),ExitCommand,ExitBuffer);

					DialPrintBox(Handle,GAD_CALLING,0,DialNode->Node.ln_Name);

						/* Show the comment, if any. */

					if(DialNode->Entry && DialNode->Entry->Header->Comment[0])
						Comment = DialNode->Entry->Header->Comment;
					else
						Comment = "-";

					DialPrintBox(Handle,GAD_CALLING,1,Comment);

						/* Display the number being called. */

					DialPrintBox(Handle,GAD_CALLING,2,DialNode->Number);

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

					DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Succ->ln_Succ ? DialNode->Node.ln_Succ->ln_Name : "-");

						/* Right now we're dialing. */

					if(DialNode->Node.ln_Succ->ln_Succ)
					{
						LimitedSPrintf(sizeof(NoteText),NoteText,LocaleString(MSG_DIALER_NOTE_TXT),LocaleString(MSG_DIALPANEL_DIALING_TXT),GetListSize((struct List *)DialNode));

						DialPrintBox(Handle,GAD_NOTE,0,NoteText);
					}
					else
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_TXT));

						/* Say what we are dialing. */

					Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),DialNode->Node.ln_Name);

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

					DialTimeout	= CurrentModemConfig->DialTimeout;
					DialRetries	= CurrentModemConfig->DialRetries;

						/* Build the dialing command. */

					LimitedStrcpy(sizeof(DialBuffer),DialBuffer,PrefixBuffer);

					if(CurrentModemConfig->PBX_Mode && CurrentModemConfig->PBX_Prefix[0])
						LimitedStrcat(sizeof(DialBuffer),DialBuffer,CurrentModemConfig->PBX_Prefix);

					LimitedStrcat(sizeof(DialBuffer),DialBuffer,DialNode->Number);
					LimitedStrcat(sizeof(DialBuffer),DialBuffer,SuffixBuffer);

						/* Dial the number. */

					SerialCommand(DialBuffer);

						/* Now we should be dialing. */

					Start = START_Dial;

						/* For the sake of precision. */

					GetSysTime(&LastTimeCheck);
				}
			}

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

			if(!Done && Stop == STOP_Skip)
			{
				Stop = STOP_Not;

				switch(Start)
				{
						/* Are we currently dialing? */

					case START_Dial:

							/* Hang up if necessary. */

						if(DoNotHangUp)
							DoNotHangUp = FALSE;
						else
							QuickHangup(DialNode);

							/* Is this one the last entry? */

						if(DialNode->Node.ln_Succ->ln_Succ)
						{
								/* There is still another entry. */

							GetCurrentSettings(DialNode = (struct DialNode *)DialNode->Node.ln_Succ,&CurrentSerialConfig,&CurrentModemConfig);

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

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

								RedialTimeout = CurrentModemConfig->InterDialDelay;

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

								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. */

								DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Name);

								Start = START_Wait;

									/* For the sake of precision. */

								GetSysTime(&LastTimeCheck);
							}
							else
								Start = START_Call;
						}
						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. */

								GetCurrentSettings(DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head,&CurrentSerialConfig,&CurrentModemConfig);

									/* Get the redial delay. */

								RedialTimeout	= CurrentModemConfig->RedialDelay;
								InterDialDelay	= CurrentModemConfig->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)
								{
									Start = START_Call;

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

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

									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. */

									DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Name);

									Start = START_Wait;

										/* For the sake of precision. */

									GetSysTime(&LastTimeCheck);
								}
							}
						}

						break;

						/* Stop waiting. */

					case START_Wait:

						if(Start == START_Wait)
						{
							LT_SetAttributes(Handle,GAD_REMOVE,
								GA_Disabled,	FALSE,
							TAG_DONE);

							Start = START_Call;
						}

						break;
				}
			}

				/* Take care of serial input. */

			if(!Done)
				RunJob(SerialJob);

				/* Any news from the modem? */

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

				if(FlowInfo.Busy || (FlowInfo.NoCarrier && CurrentModemConfig->NoCarrierIsBusy))
				{
					if(!Done && Start == START_Dial)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

						Say(LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

						DelayTime(1,0);

						Stop = STOP_Skip;

						DoNotHangUp = TRUE;
					}

					ResetDataFlowFilter();
				}

					/* Line does not feature a dialtone. */

				if(FlowInfo.NoDialTone)
				{
					if(!Done && Start == START_Dial)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						WakeUp(PanelWindow,SOUND_ERROR);

						Say(LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}

					ResetDataFlowFilter();
				}

					/* Somebody tries to call us. */

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

						WakeUp(PanelWindow,SOUND_RING);

						Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}

					ResetDataFlowFilter();
				}

					/* Somebody's talking. */

				if(FlowInfo.Voice)
				{
					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));

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}

					ResetDataFlowFilter();
				}

					/* We got a connect. */

				if(FlowInfo.Connect)
				{
					if(!Done && Start == START_Dial)
					{
							/* Make the connection. */

						Connect(PhoneHandle,DialNode);

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

					ResetDataFlowFilter();
				}

					/* Looks like an error. */

				if(FlowInfo.Error)
				{
					if(!Done && Start == START_Dial)
					{
						DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));

						WakeUp(PanelWindow,SOUND_ERROR);

						ErrorHasOccured = TRUE;
						Done = TRUE;
					}

					ResetDataFlowFilter();
				}

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

				ResetDataFlowFilter();
			}

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

			if(!Done && Stop == STOP_Not && Start != START_Call)
			{
				struct timeval Now,Then;

					/* Give a brief report. */

				switch(Start)
				{
					case START_Dial:

						DialPrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",DialTimeout / 60,DialTimeout % 60);
						DialPrintBox(Handle,GAD_TIME,1,LocaleString(DialRetries < 0 ? MSG_DIAL_RETRIES_UNLIMITED_TXT : MSG_DIALPANEL_ATTEMPT_OF_TXT),DialAttempt + 1,DialRetries);

						break;

					case START_Wait:

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

					/* Wait a second or until something interesting happens. */

				StartTime(1,0);

				Signals = Wait(SIG_TIMER | SIG_BREAK | SIG_SKIP | ODUMask | WindowMask);

				StopTime();

					/* Get the current time. */

				GetSysTime(&Now);

					/* Check if the current time is "later" than the last time check.
					 * This is to avoid embarrassing situations such as could take
					 * place if the the user resets the operating system time.
					 */

				if(-CmpTime(&Now,&LastTimeCheck) >= 0)
				{
					CopyMem(&Now,&Then,sizeof(struct timeval));
					SubTime(&Now,&LastTimeCheck);
				}
				else
				{
					CopyMem(&Now,&LastTimeCheck,sizeof(struct timeval));
					Now.tv_secs = 0;
				}

					/* The following instructions are executed as time passes by. */

				if(Now.tv_secs > 0)
				{
					LONG Seconds = Now.tv_secs;

						/* Remember the last time we went through. */

					CopyMem(&Then,&LastTimeCheck,sizeof(struct timeval));

					switch(Start)
					{
							/* Are we dialing? */

						case START_Dial:

							if(DialTimeout > Seconds)
								DialTimeout -= Seconds;
							else
							{
								DialTimeout = 0;

									/* The dial timeout has elapsed without
									 * a connection being made.
									 */

								Stop = STOP_Skip;

								DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIAL_ATTEMPT_TIMEOUT_TXT));
							}

							break;

							/* Are we waiting? */

						case START_Wait:

							if(RedialTimeout > Seconds)
								RedialTimeout -= Seconds;
							else
							{
								RedialTimeout = 0;

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

								Stop = STOP_Skip;
							}

							break;
					}
				}
			}
		}
		while(!Done);

			/* Reset the status */

		PopStatus();

			/* Are we online or not? */

		if(!Online)
		{
			BOOL SendCommands;

				/* If the modem is not responding anyway, don't bother
				 * sending any commands.
				 */

			SendCommands = (BOOL)(ModemNotResponding == FALSE);

				/* Is the serial setup different? */

			if(CompareConfigEntries(Config->SerialConfig,OriginalSerialConfig,PREF_SERIAL))
			{
					/* Set up the old serial configuration. */

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

				/* Put back the original modem settings. */

			PutConfigEntry(Config,OriginalModemConfig,PREF_MODEM);

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

				if(ExitCommand[0])
				{
					if(!SendLocalModemCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
						ErrorHasOccured = TRUE;
				}

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

				if(Config->ModemConfig->ModemInit[0] && !ErrorHasOccured)
				{
					if(!SendLocalModemCommand(Handle,Config->ModemConfig->ModemInit,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
						ErrorHasOccured = TRUE;
				}
			}
		}

			/* Make sure the error gets displayed. */

		if(ErrorHasOccured && !ReleaseSerialDevice)
		{
			LONG i;

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

			Done = FALSE;

			do
			{
				if(Wait(WindowMask | SIG_BREAK) & SIG_BREAK)
					break;
				else
				{
					struct IntuiMessage	*Message;

					while(Message = LT_GetIMsg(Handle))
					{
						if(Message->Class == IDCMP_CLOSEWINDOW || Message->Class == IDCMP_GADGETUP)
							Done = TRUE;

						LT_ReplyIMsg(Message);
					}
				}
			}
			while(!Done);
		}

			/* Put back the old routine if necessary */

		RestoreSendLine(SendLineDial,OriginalSendLine);

		PopWindow();

		LT_DeleteHandle(Handle);

			/* Reset the scanner. */

		ResetDataFlowFilter();

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

		SetConsoleQuiet(OldQuietSettings);

			/* Reset the display if necessary. */

		if(ResetDisplay)
		{
			if(!DisplayReset())
			{
				FreeVecPooled(OriginalSerialConfig);
				OriginalSerialConfig = NULL;

				FreeVecPooled(OriginalModemConfig);
				OriginalModemConfig = NULL;

				return(FALSE);
			}
		}

			/* Handle online jobs. */

		SetDialMenu(Online == FALSE);

		if(Online)
		{
				/* Send the startup macro if necessary. */

			if(SendStartup && !SkipLoginMacro)
			{
				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(RecordOnConnection)
			{
				if(CreateRecord(CurrentBBSName[0] ? CurrentBBSName : CurrentBBSNumber))
				{
					RememberResetOutput();
					RememberResetInput();

					RememberOutput	= TRUE;

					Recording		= TRUE;
					RecordingLine	= FALSE;

					PushStatus(STATUS_RECORDING);

					OnItem(MEN_RECORD_LINE);

					CheckItem(MEN_RECORD,TRUE);
					CheckItem(MEN_RECORD_LINE,FALSE);
				}
			}
		}
	}

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

	DispatchRexxDialMsgList(Online);

		/* Release the serial device driver if necessary. */

	if(ReleaseSerialDevice)
		RunJob(OwnDevUnitJob);

		/* Release the backup data. */

	FreeVecPooled(OriginalSerialConfig);
	OriginalSerialConfig = NULL;

	FreeVecPooled(OriginalModemConfig);
	OriginalModemConfig = NULL;

		/* Exit and tell the caller if control should pass
		 * back to the phonebook control panel.
		 */

	return(ReturnToPhonebook);
}
