/*
**	$Id: DialPanel.c,v 1.12 92/08/18 16:11:10 olsen Sta Locker: olsen $
**	$Revision: 1.12 $
**	$Date: 92/08/18 16:11:10 $
**
**	The dialing routine as called by the phonebook
**
**	Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* Panel gadget IDs. */

enum	{	GAD_SKIP,GAD_REMOVE,GAD_ONLINE,GAD_ABORT,
		GADGET_COUNT };

	/* Panel box IDs. */

enum	{	BOX_CALL_NUMBER_NEXT,BOX_TIME_TRY,BOX_MESSAGE,
		BOX_COUNT };

	/* CreateAllGadgets():
	 *
	 *	Create all gadgets required by the dial panel.
	 */

STATIC struct Gadget *
CreateAllGadgets(struct TextBox **BoxArray,struct TextBox **BoxList,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
{
	struct Gadget		*Gadget;
	struct NewGadget	 NewGadget;
	UWORD			 Counter = 0,BoxCounter = 0;
	struct TextBox		*Box;

	memset(&NewGadget,0,sizeof(struct NewGadget));

	SZ_SizeSetup(Screen,&UserFont,TRUE);

	if(Gadget = CreateContext(GadgetList))
	{
		LONG ButtonWidth;

		SZ_AddLeftOffset(SZ_LeftOffsetN(MSG_DIALPANEL_CALLING_TXT,MSG_DIALPANEL_NUMBER_TXT,MSG_DIALPANEL_NEXT_TXT,MSG_DIALPANEL_TIMEOUT_TXT,MSG_DIALPANEL_ATTEMPT_TXT,MSG_DIALPANEL_MESSAGE_TXT,-1));

		SZ_ResetMaxWidth();

		SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_DIALPANEL_SKIP_GAD),0,NULL);
		SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_REMOVE_GAD),0,NULL);
		SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_DIALPANEL_GO_TO_ONLINE_GAD),0,NULL);
		SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_ABORT_GAD),0,NULL);

		ButtonWidth = SZ_ResetMaxWidth();

		if(ButtonWidth * 4 + 3 * InterWidth > SZ_BoxWidth(45))
			SZ_SetWidth(ButtonWidth * 4 + 3 * InterWidth);
		else
			SZ_SetWidth(SZ_BoxWidth(45));

		BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
			SZ_Chars,	45,
			SZ_Lines,	3,
			SZ_AutoWidth,	TRUE,
		TAG_DONE);

		SZ_SetBoxTitles(Box,LocaleString(MSG_DIALPANEL_CALLING_TXT),LocaleString(MSG_DIALPANEL_NUMBER_TXT),LocaleString(MSG_DIALPANEL_NEXT_TXT),NULL);

		BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
			SZ_Chars,	45,
			SZ_Lines,	2,
			SZ_AutoWidth,	TRUE,
		TAG_DONE);

		SZ_SetBoxTitles(Box,LocaleString(MSG_DIALPANEL_TIMEOUT_TXT),LocaleString(MSG_DIALPANEL_ATTEMPT_TXT),NULL);

		BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
			SZ_Chars,	45,
			SZ_Lines,	1,
			SZ_AutoWidth,	TRUE,
		TAG_DONE);

		SZ_SetBoxTitles(Box,LocaleString(MSG_DIALPANEL_MESSAGE_TXT),NULL);

		if(!Box)
			return(NULL);

		NewGadget . ng_TextAttr		= &UserFont;
		NewGadget . ng_VisualInfo	= VisualInfo;
		NewGadget . ng_GadgetText	= LocaleString(MSG_DIALPANEL_SKIP_GAD);
		NewGadget . ng_GadgetID		= Counter;

		SZ_SetWidth(ButtonWidth);

		GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
			SZ_Adjust,	TRUE,
			SZ_AutoWidth,	TRUE,
			SZ_AlignExtra,	TRUE,
			SZ_AlignBottom,	TRUE,
			SZ_GroupCount,	4,

			GT_Underscore,	'_',
		TAG_DONE);

		NewGadget . ng_GadgetText	= LocaleString(MSG_GLOBAL_REMOVE_GAD);
		NewGadget . ng_GadgetID		= Counter;

		GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
			SZ_Adjust,	TRUE,
			SZ_AutoWidth,	TRUE,
			SZ_GroupNext,	TRUE,

			GT_Underscore,	'_',
		TAG_DONE);

		NewGadget . ng_GadgetText	= LocaleString(MSG_DIALPANEL_GO_TO_ONLINE_GAD);
		NewGadget . ng_GadgetID		= Counter;

		GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
			SZ_Adjust,	TRUE,
			SZ_AutoWidth,	TRUE,
			SZ_GroupNext,	TRUE,

			GT_Underscore,	'_',
		TAG_DONE);

		NewGadget . ng_GadgetText	= LocaleString(MSG_GLOBAL_ABORT_GAD);
		NewGadget . ng_GadgetID		= Counter;

		GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
			SZ_Adjust,	TRUE,
			SZ_AutoWidth,	TRUE,
			SZ_GroupNext,	TRUE,

			GT_Underscore,	'_',
		TAG_DONE);
	}

	return(Gadget);
}

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

BYTE
DialPanel()
{
	STATIC WORD		 PositionX = -1,
				 PositionY = -1;

	struct Gadget		*GadgetList = NULL;
	struct Gadget		*GadgetArray[GADGET_COUNT];
	struct TextBox		*BoxList = NULL;
	struct TextBox		*BoxArray[BOX_COUNT];
	struct Window		*PanelWindow;
	struct PhoneNode	*DialNode;
	BYTE			 Result = FALSE;

	ChosenEntry	= NULL;

		/* We are dialing. */

	Status = STATUS_DIALING;

		/* Create the gadgets. */

	if(CreateAllGadgets(&BoxArray[0],&BoxList,&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
	{
			/* At last, open the window. */

		if(PanelWindow = OpenWindowTags(NULL,
			WA_Left,	(Screen -> Width	- SZ_GetWindowWidth())	/ 2,
			WA_Top,		(Screen -> Height	- SZ_GetWindowHeight())	/ 2,
			WA_Width,	SZ_GetWindowWidth(),
			WA_Height,	SZ_GetWindowHeight(),

			WA_Activate,	TRUE,
			WA_DragBar,	TRUE,
			WA_DepthGadget,	TRUE,
			WA_CloseGadget,	TRUE,
			WA_RMBTrap,	TRUE,
			WA_CustomScreen,Screen,

			WA_IDCMP,	IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | BUTTONIDCMP,

			WA_Title,	LocaleString(MSG_DIALPANEL_DIALING_TXT),
		TAG_DONE))
		{
			struct IntuiMessage	*Massage;
			ULONG			 Class,Code;
			struct Gadget		*Gadget;
			LONG			 RedialDelay = 0,DialTimeout,DialRetries,DialAttempt;
			BYTE			 Dialing,Terminated = FALSE;

			UBYTE			 SomeBuffer[300],ExitString[80];
			BYTE			 RunCount = 0;

			UBYTE			 NumberBuffer[40],	*NextNumber	= NULL,
						 InitBuffer[80],	*NextInit	= NULL,
						 ExitBuffer[80],	*NextExit	= NULL,
						 PrefixBuffer[80],	*NextPrefix	= NULL;

			ExitString[0] = 0;

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

			PushWindow(PanelWindow);

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

			CopyMem(&Config,&PrivateConfig,sizeof(struct Configuration));

				/* Add the gadgets and refresh them. */

			AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
			RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
			GT_RefreshWindow(PanelWindow,NULL);

			SZ_DrawBoxes(PanelWindow -> RPort,BoxList);

				/* Don't echo serial output. */

			Quiet		= TRUE;

				/* Perform full sequence check. */

			FullCheck	= TRUE;

				/* Reset the number of dial attempts. */

			DialAttempt	= 0;

				/* Get the first dial list entry. */

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

				/* The big dialing loop, implemented as a goto -> mark
				 * loop rather than one of those classical while .. do
				 * loops.
				 */

Dial:			Dialing		= TRUE;

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

			HandleSerial();

			FlowInit();

			FullCheck = TRUE;

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

			if(NextNumber)
			{
				NextNumber	= ExtractString(NextNumber,	NumberBuffer,TRUE);
				NextInit	= ExtractString(NextInit,	InitBuffer,FALSE);
				NextExit	= ExtractString(NextExit,	ExitBuffer,FALSE);
				NextPrefix	= ExtractString(NextPrefix,	PrefixBuffer,FALSE);
			}
			else
			{
				if(DialNode -> Entry)
				{
					NextNumber	= ExtractString(DialNode -> Entry -> Number,NumberBuffer,TRUE);
					NextInit	= ExtractString(DialNode -> Entry -> Config . ModemInit,InitBuffer,FALSE);
					NextExit	= ExtractString(DialNode -> Entry -> Config . ModemExit,ExitBuffer,FALSE);
					NextPrefix	= ExtractString(DialNode -> Entry -> Config . DialPrefix,PrefixBuffer,FALSE);
				}
				else
				{
					NextNumber	= ExtractString(DialNode -> VanillaNode . ln_Name,NumberBuffer,TRUE);
					NextInit	= ExtractString(Config . ModemInit,InitBuffer,FALSE);
					NextExit	= ExtractString(Config . ModemExit,ExitBuffer,FALSE);
					NextPrefix	= ExtractString(Config . DialPrefix,PrefixBuffer,FALSE);
				}
			}

				/* If DialNode -> Entry is nonzero it has
				 * a configuration attached.
				 */

			if(DialNode -> Entry)
			{
				DialTimeout	= DialNode -> Entry -> Config . DialTimeout;
				DialRetries	= DialNode -> Entry -> Config . DialRetries;

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

				if(memcmp(&Config,&DialNode -> Entry -> Config,offsetof(struct Configuration,ModemInit)))
				{
					BYTE SameDevice = TRUE;

					CopyMem(&DialNode -> Entry -> Config,&Config,offsetof(struct Configuration,ModemInit));

					Config . SerBuffSize = DialNode -> Entry -> Config . SerBuffSize;

						/* Any device name change? */

					if(strcmp(PrivateConfig . SerialDevice,Config . SerialDevice))
						SameDevice = FALSE;
					else
					{
						if(PrivateConfig . SerBuffSize != Config . SerBuffSize)
							SameDevice = FALSE;

							/* Handshaking mode changed to RTS/CTS protocol? */

						if(PrivateConfig . HandshakingProtocol == HANDSHAKING_NONE && PrivateConfig . HandshakingProtocol != HANDSHAKING_NONE)
							SameDevice = FALSE;
					}

						/* Stop any IO activity. */

					if(ReadRequest)
						ClearSerial();
					else
						SameDevice = FALSE;

						/* No dramatic changes? Simply change the parameters. */

					if(SameDevice)
					{
						LONG Error;

							/* Use new parameters... */

						SetFlags(WriteRequest);
						SetFlags(ReadRequest);

							/* ...and set them. */

						WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;

						if(Error = DoIO(WriteRequest))
						{
							STRPTR	String;
							BYTE	Reset;

							if(!(String = GetSerialError(Error,&Reset)))
								String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);

							SPrintf(SharedBuffer,String,Config . SerialDevice,Config . UnitNumber);

							BlockWindow(PanelWindow);

							MyEasyRequest(PanelWindow,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SharedBuffer);

							ReleaseWindow(PanelWindow);

							if(Reset)
							{
								WriteRequest -> IOSer . io_Command = CMD_RESET;

								DoIO(WriteRequest);

								GetFlags(&Config,WriteRequest);
								SetFlags(ReadRequest);
							}
						}

							/* Restart read request. */

						ReadRequest -> IOSer . io_Command	= CMD_READ;
						ReadRequest -> IOSer . io_Data		= ReadBuffer;
						ReadRequest -> IOSer . io_Length	= 1;

						SetSignal(0,SIG_SERIAL);

						SendIO(ReadRequest);
					}
					else
					{
						UBYTE *Error;

						DeleteSerial();

						if(!(Error = CreateSerial()))
						{
							if(StripBuffer)
								FreeVec(StripBuffer);

							if(!(StripBuffer = (UBYTE *)AllocVec(Config . SerBuffSize,MEMF_ANY)))
								Error = LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT);
						}

						if(Error)
						{
							BlockWindow(PanelWindow);

							MyEasyRequest(PanelWindow,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error);

							DeleteSerial();

							ReleaseWindow(PanelWindow);

							SerialSet = FALSE;

							goto Quit;
						}
						else
						{
							if(SerialMessage)
							{
								MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage);

								SerialMessage = NULL;
							}
						}
					}

					if(!Terminated)
					{
						SerWrite("\rAT\r",4);
						WaitTime(1,0);
					}

						/* Don't reinitialize serial driver in ConfigSetup()! */

					SerialSet = TRUE;
				}

				if(ExitString[0])
				{
					SerialCommand(ExitString);

					WaitTime(1,0);
				}

				if(InitBuffer[0])
				{
					SerialCommand(InitBuffer);

					WaitTime(1,0);
				}

				strcpy(ExitString,ExitBuffer);

				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],0,DialNode -> Entry -> Name);

				Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),DialNode -> Entry -> Name);

				strcpy(SomeBuffer,PrefixBuffer);

				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],1,NumberBuffer);
				strcat(SomeBuffer,NumberBuffer);
			}
			else
			{
				DialTimeout	= Config . DialTimeout;
				DialRetries	= Config . DialRetries;

				if(ExitString[0])
				{
					SerialCommand(ExitString);

					WaitTime(1,0);
				}

				strcpy(ExitString,ExitBuffer);

				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],0,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));

				Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),NumberBuffer);

				strcpy(SomeBuffer,PrefixBuffer);

				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],1,NumberBuffer);
				strcat(SomeBuffer,NumberBuffer);
			}

			if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],2,((struct PhoneNode *)DialNode -> VanillaNode . ln_Succ) -> Entry -> Name);
			else
				SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_CALL_NUMBER_NEXT],2,LocaleString(MSG_GLOBAL_NONE_TXT));

			if(DialNode -> Entry)
				strcat(SomeBuffer,DialNode -> Entry -> Config . DialSuffix);
			else
				strcat(SomeBuffer,Config . DialSuffix);

			SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_DIALING_TXT));

				/* Dial the number. */

			SerialCommand(SomeBuffer);

				/* Reset the signal. */

			SetSignal(NULL,SIGBREAKF_CTRL_F);

			while(!Terminated)
			{
				if(Dialing)
				{
					SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_TIME_TRY],0,"%2ld:%02ld",DialTimeout / 60,DialTimeout % 60);
					SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_TIME_TRY],1,LocaleString(MSG_DIALPANEL_ATTEMPT_OF_TXT),DialAttempt + 1,DialRetries);
				}
				else
					SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_TIME_TRY],0,"%2ld:%02ld",RedialDelay / 60,RedialDelay % 60);

				WaitTime(0,MILLION / 2);

					/* The following commands are executed each second */

				if((RunCount++) && !Terminated)
				{
					RunCount = 0;

						/* Are we dialing or waiting? */

					if(Dialing)
					{
							/* No chance, the dial timeout
							 * has elapsed and no connection
							 * was made.
							 */

						if(!(--DialTimeout))
						{
							SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_DIAL_ATTEMPT_TIMEOUT_TXT));

Skip1:							SerWrite("\r",1);
							WaitTime(1,0);

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

							if(NextNumber)
								goto Dial;

								/* Is this one the last entry? */

							if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
							{
									/* Proceed to the next entry. */

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

								goto Dial;
							}
							else
							{
									/* Is this one the last dial
									 * attempt to be made?
									 */

								if(++DialAttempt >= DialRetries)
								{
									SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

									WakeUp(PanelWindow);

									WaitTime(2,0);

									Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

									Terminated = TRUE;
								}
								else
								{
										/* Get the first list entry. */

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

										/* Get the redial delay. */

									if(DialNode -> Entry)
										RedialDelay = 10 * DialNode -> Entry -> Config . RedialDelay;
									else
										RedialDelay = 10 * Config . RedialDelay;

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

									if(!RedialDelay)
									{
										WaitTime(1,0);

										goto Dial;
									}
									else
									{
											/* Go into redial delay. */

										SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_REDIAL_DELAY_TXT));

										Dialing = FALSE;

										Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
									}
								}
							}
						}
					}
					else
					{
						if(!(--RedialDelay))
						{
								/* Get the first list entry. */

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

								/* We are once again dialing. */

							Dialing = TRUE;

							goto Dial;
						}
					}
				}

					/* Handle serial data flow. */

				HandleSerial();

					/* Something has changed in the flow
					 * info structure.
					 */

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

					if(FlowInfo . Busy || FlowInfo . NoCarrier)
					{
						FlowInit();

						FullCheck = TRUE;

						FlowInfo . Busy		= FALSE;
						FlowInfo . NoCarrier	= FALSE;
						FlowInfo . Changed	= FALSE;

						if(Dialing)
						{
							SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

							Say(LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));

							WaitTime(1,0);

							goto Skip1;
						}
					}

						/* Line does not feature a dialtone. */

					if(FlowInfo . NoDialTone)
					{
						FlowInit();

						SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						WakeUp(PanelWindow);

						WaitTime(1,0);

						Say(LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));

						Terminated = TRUE;
					}

						/* Somebody tries to call us. */

					if(FlowInfo . Ring && !Terminated)
					{
						FlowInit();

						SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));

						WakeUp(PanelWindow);

						WaitTime(1,0);

						Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));

						Terminated = TRUE;
					}

						/* Somebody's talking. */

					if(FlowInfo . Voice && !Terminated)
					{
						FlowInit();

						SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));

						WakeUp(PanelWindow);

						WaitTime(1,0);

						Say(LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));

						Terminated = TRUE;
					}

						/* We got a connect. */

					if(FlowInfo . Connect && !Terminated)
					{
						FlowInfo . Connect = FALSE;
						FlowInfo . Changed = FALSE;

							/* Install the new configuration. */

ConnectIt:					if(DialNode -> Entry)
						{
							CopyMem(&DialNode -> Entry -> Config,&Config,sizeof(struct Configuration));

							MakeCall(DialNode -> Entry -> Name,DialNode -> Entry -> Number);
						}
						else
							MakeCall("???",DialNode -> VanillaNode . ln_Name);

								/* Convert the baud rate. */

						if(BaudBuffer[0] && Config . ConnectAutoBaud)
						{
							LONG TestRate,i,j;

							for(i = j = 0 ; i < strlen(BaudBuffer) ; i++)
							{
								if(BaudBuffer[i] == ' ')
									continue;
								else
								{
									if(BaudBuffer[i] >= '0' && BaudBuffer[i] <= '9')
										SharedBuffer[j++] = BaudBuffer[i];
									else
										break;
								}
							}

							SharedBuffer[j] = 0;

							TestRate = atol(SharedBuffer);

							if(TestRate >= 110)
								Config . BaudRate = TestRate;
						}

							/* Reset the scanner. */

						FlowInit();

							/* Copy the remaining data. */

						if(DialNode -> Entry)
						{
							SelectTime(DialNode -> Entry);

							ChosenEntry	= DialNode -> Entry;
							WhichUnit	= DT_FIRST_UNIT;
							CurrentPay	= 0;
							SendStartup	= TRUE;

							strcpy(Password,DialNode -> Entry -> Password);
							strcpy(UserName,DialNode -> Entry -> UserName);
						}
						else
						{
							CurrentPay	= 0;

							ChosenEntry	= NULL;

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

							SendStartup	= FALSE;
						}

							/* We are now online. */

						Online		= TRUE;
						Terminated	= TRUE;

							/* Add another logfile entry. */

						if(DialNode -> Entry)
							LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),DialNode -> Entry -> Name,NumberBuffer);
						else
							LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),NumberBuffer);

							/* Open auto-capture file if necessary. */

						if(Config . ConnectAutoCapture && Config . CapturePath[0])
						{
							UBYTE		SharedBuffer[256],Name[50],Date[20];
							struct DateTime	DateTime;

							DateStamp(&DateTime . dat_Stamp);

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

							strcpy(SharedBuffer,Config . CapturePath);

							if(DateToStr(&DateTime))
							{
								if(DialNode -> Entry)
								{
									WORD i;

									strcpy(Name,DialNode -> Entry -> Name);

									for(i = 0 ; i < strlen(Name) ; i++)
									{
										if(Name[i] == ' ')
											Name[i] = '_';
									}
								}
								else
									strcpy(Name,LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT));

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

								if(AddPart(SharedBuffer,Name,256))
								{
									struct MenuItem *Item;

									Item = FindThisItem(MEN_CAPTURE_TO_FILE);

									Item -> Flags &= ~CHECKED;

									if(FileCapture)
									{
										BufferClose(FileCapture);

										if(!GetFileSize(CaptureName))
											DeleteFile(CaptureName);
										else
											SetProtection(CaptureName,FIBF_EXECUTE);
									}

									if(FileCapture = BufferOpen(SharedBuffer,"a"))
									{
										Item -> Flags |= CHECKED;

										strcpy(CaptureName,SharedBuffer);
									}
								}
							}
						}

							/* Remove the node from the
							 * dialing list.
							 */

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

						Remove(&DialNode -> VanillaNode);

						FreeVec(DialNode);

							/* Wake the user up. */

						SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));

						WakeUp(PanelWindow);

						if(PrivateConfig . BackupConfig)
						{
							if(!BackupConfig)
							{
								if(BackupConfig = (struct Configuration *)AllocVec(sizeof(struct Configuration),MEMF_ANY))
									memcpy(BackupConfig,&PrivateConfig,sizeof(struct Configuration));
							}
						}

						Say(LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));

							/* Don't process any data until the screen
							 * is set up correctly.
							 */

						Blocking = TRUE;

							/* Perform system initialization. */

						ConfigSetup();
					}
				}

					/* Look for the hotkey. */

				if(SetSignal(NULL,NULL) & SIGBREAKF_CTRL_F)
				{
					SetSignal(NULL,SIGBREAKF_CTRL_F);

						/* Are we dialing or waiting? */

					if(Dialing)
					{
						DialTimeout = 0;

						goto Skip1;
					}
					else
					{
						RedialDelay = 0;

						goto Skip2;
					}
				}

					/* Pick up the window input. */

				while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
				{
					Class	= Massage -> Class;
					Code	= Massage -> Code;
					Gadget	= (struct Gadget *)Massage -> IAddress;

					GT_ReplyIMsg(Massage);

					if(Class == IDCMP_VANILLAKEY)
					{
						if(Code == ' ')
						{
							Class	= IDCMP_GADGETUP;
							Code	= 0;
							Gadget	= GadgetArray[GAD_SKIP];
						}
						else
							KeySelect(GadgetArray,GAD_ABORT,Code,PanelWindow,&Gadget,&Class,&Code);
					}

						/* Close the window, hang up the line. */

					if(Class == IDCMP_CLOSEWINDOW)
					{
						Class	= IDCMP_GADGETUP;
						Gadget	= GadgetArray[GAD_ABORT];

						Result = TRUE;
					}

					if(Class == IDCMP_GADGETUP)
					{
						switch(Gadget -> GadgetID)
						{
									/* Don't proceed to the next number in the buffer! */

							case GAD_REMOVE:NextNumber = NULL;

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

											/* 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)
											{
													/* There is just a single entry
													 * available, check for dial retry
													 * limit.
													 */

												if(++DialAttempt >= DialRetries)
												{
													SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

													WakeUp(PanelWindow);

													WaitTime(1,0);

													Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));

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

													NextNode = (struct PhoneNode *)DialList -> lh_Head;
												}
											}
											else
											{
												Terminated = TRUE;

												SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_DIALING_LIST_IS_EMPTY_TXT));

												WaitTime(1,0);
											}
										}

										DialTimeout = 0;

										SerWrite("\r",1);
										WaitTime(1,0);

											/* Remove dial entry from list. */

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

										Remove(&DialNode -> VanillaNode);

										FreeVec(DialNode);

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

										if(NextNode)
										{
											DialNode = NextNode;

											goto Dial;
										}
									}
									else
									{
										struct PhoneNode *LastNode;

											/* We are to leave the redial delay loop,
											 * are there at least two entries in
											 * the list?
											 */

										if(!DialList -> lh_Head -> ln_Succ -> ln_Succ)
										{
												/* No, there is just a single entry in
												 * the list.
												 */

											Terminated = TRUE;

											SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_DIALING_LIST_IS_EMPTY_TXT));

											SerWrite("\r",1);
											WaitTime(2,0);
										}

											/* Remove last dial entry from list. */

										LastNode = (struct PhoneNode *)DialList -> lh_TailPred;

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

										Remove(&LastNode -> VanillaNode);

										FreeVec(LastNode);

											/* Get back to first list entry. */

										if(!Terminated)
										{
											RedialDelay = 0;

											goto Skip2;
										}
									}

									break;

							case GAD_SKIP:	if(Dialing)
									{
										DialTimeout = 0;

										goto Skip1;
									}
									else
									{
										RedialDelay = 0;

										goto Skip2;
									}

										/* Forced online,
										 * install new configuration
										 * first.
										 */

							case GAD_ONLINE:if(DialNode -> Entry)
									{
										CopyMem(&DialNode -> Entry -> Config,&Config,sizeof(struct Configuration));

										MakeCall(DialNode -> Entry -> Name,DialNode -> Entry -> Number);

										SelectTime(DialNode -> Entry);

										ChosenEntry	= DialNode -> Entry;
										WhichUnit	= DT_FIRST_UNIT;
										CurrentPay	= 0;
										SendStartup	= TRUE;

										strcpy(Password,DialNode -> Entry -> Password);
										strcpy(UserName,DialNode -> Entry -> UserName);
									}
									else
									{
										MakeCall("???",DialNode -> VanillaNode . ln_Name);

										CurrentPay	= 0;
										ChosenEntry	= NULL;
										Password[0]	= 0;
										UserName[0]	= 0;
										SendStartup	= FALSE;
									}

										/* We are now online. */

									Online		= TRUE;
									Terminated	= TRUE;

										/* Add a new log action. */

									if(DialNode -> Entry)
										LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),DialNode -> Entry -> Name,NumberBuffer);
									else
										LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),NumberBuffer);

										/* Open auto-capture file. */

									if(Config . ConnectAutoCapture && Config . CapturePath[0])
									{
										UBYTE		SharedBuffer[256],Name[50],Date[20];
										struct DateTime	DateTime;

										DateStamp(&DateTime . dat_Stamp);

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

										strcpy(SharedBuffer,Config . CapturePath);

										if(DateToStr(&DateTime))
										{
											if(DialNode -> Entry)
											{
												WORD i;

												strcpy(Name,DialNode -> Entry -> Name);

												for(i = 0 ; i < strlen(Name) ; i++)
												{
													if(Name[i] == ' ')
														Name[i] = '_';
												}
											}
											else
												strcpy(Name,LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT));

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

											if(AddPart(SharedBuffer,Name,256))
											{
												struct MenuItem *Item;

												Item = FindThisItem(MEN_CAPTURE_TO_FILE);

												Item -> Flags &= ~CHECKED;

												if(FileCapture)
												{
													BufferClose(FileCapture);

													if(!GetFileSize(CaptureName))
														DeleteFile(CaptureName);
													else
														SetProtection(CaptureName,FIBF_EXECUTE);
												}

												if(FileCapture = BufferOpen(SharedBuffer,"a"))
												{
													Item -> Flags |= CHECKED;

													strcpy(CaptureName,SharedBuffer);
												}
											}
										}
									}

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

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

									Remove(&DialNode -> VanillaNode);

									FreeVec(DialNode);

									if(PrivateConfig . BackupConfig)
									{
										if(!BackupConfig)
										{
											if(BackupConfig = (struct Configuration *)AllocVec(sizeof(struct Configuration),MEMF_ANY))
												memcpy(BackupConfig,&PrivateConfig,sizeof(struct Configuration));
										}
									}

									Blocking = TRUE;

									ConfigSetup();

									break;

								/* Abort the dialing process. */

							case GAD_ABORT:	Terminated = TRUE;

									SZ_PrintLine(PanelWindow -> RPort,BoxArray[BOX_MESSAGE],0,LocaleString(MSG_DIALPANEL_ABORTING_TXT));

									SerWrite("\r",1);
									WaitTime(1,0);

									break;
						}
					}
				}
			}

				/* Are we online or not? */

Quit:			if(!Online)
			{
					/* Is the serial setup different? */

				if(memcmp(&PrivateConfig,&Config,58))
				{
						/* Swap the serial data. */

					swmem(&PrivateConfig,&Config,58);

						/* Set up the old serial configuration. */

					ConfigSetup();

						/* Reinitialize... */

					SerWrite("\rAT\r",4);
					WaitTime(1,0);
				}

					/* Do we have a valid modem exit string? */

				if(ExitString[0])
				{
					SerialCommand(ExitString);

					WaitTime(1,0);
				}
			}

				/* Reset the scanner. */

			FlowInit();

			RemoveGList(PanelWindow,GadgetList,(UWORD)-1);

			PopWindow();

			PositionX = PanelWindow -> LeftEdge;
			PositionY = PanelWindow -> TopEdge;

			CloseWindow(PanelWindow);
		}
	}

	FreeGadgets(GadgetList);

	SZ_FreeBoxes(BoxList);

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

	Quiet = FALSE;

		/* Reset the display if necessary. */

	if(ResetDisplay)
		DisplayReset();

	if(Online)
		SetDialMenu(FALSE);

		/* Send the startup macro if necessary. */

	if(SendStartup && Online)
	{
		if(Config . StartupMacro[0])
			SerialCommand(Config . StartupMacro);

		SendStartup = FALSE;
	}

	return(Result);
}
