home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / internet / Term / Source / term-4.7a / Dial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  40.1 KB  |  1,856 lines

  1. /*
  2. **    Dial.c
  3. **
  4. **    The dialing routine as called by the phonebook
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Panel gadget IDs. */
  17.  
  18. enum    {    GAD_CALLING=1,GAD_TIME,GAD_NOTE,
  19.             GAD_SKIP,GAD_REMOVE,GAD_ONLINE,GAD_ABORT
  20.         };
  21.  
  22.     /* Local copy of the global serial and modem settings. */
  23.  
  24. STATIC struct SerialSettings    *OriginalSerialConfig;
  25. STATIC struct ModemSettings        *OriginalModemConfig;
  26.  
  27.     /* Local routines. */
  28.  
  29. STATIC VOID QuickHangup(struct DialNode *DialNode);
  30. STATIC VOID DialPrintBox(LayoutHandle *Handle, LONG Box, LONG Line, STRPTR String, ...);
  31. STATIC BOOL SendLocalModemCommand(LayoutHandle *Handle, STRPTR Command, STRPTR Message, STRPTR ErrorMessage);
  32. STATIC VOID BuildName(STRPTR Name, LONG MaxNameLen, STRPTR Date);
  33. STATIC VOID OpenAutoCaptureFile(STRPTR SomeName);
  34. STATIC VOID Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode);
  35. STATIC LayoutHandle *OpenDialPanel(BOOL *Record,BOOL *SkipLoginMacro);
  36.  
  37.     /* GetCurrentSettings():
  38.      *
  39.      *    Get the settings corresponding to a dial node.*/
  40.  
  41. STATIC VOID
  42. GetCurrentSettings(struct DialNode *DialNode,struct SerialSettings **SerialPtr,struct ModemSettings **ModemPtr)
  43. {
  44.     *SerialPtr    = OriginalSerialConfig;
  45.     *ModemPtr    = OriginalModemConfig;
  46.  
  47.     if(DialNode && DialNode->Entry && DialNode->Entry->Config)
  48.     {
  49.         if(DialNode->Entry->Config->SerialConfig)
  50.             *SerialPtr = DialNode->Entry->Config->SerialConfig;
  51.  
  52.         if(DialNode->Entry->Config->ModemConfig)
  53.             *ModemPtr = DialNode->Entry->Config->ModemConfig;
  54.     }
  55. }
  56.  
  57.     /* QuickHangup(struct DialNode *DialNode):
  58.      *
  59.      *    Stop dialing by hanging up or sending a return character to the modem.
  60.      */
  61.  
  62. STATIC VOID
  63. QuickHangup(struct DialNode *DialNode)
  64. {
  65.     BOOL UseHangUp;
  66.  
  67.     if(DialNode->Entry && DialNode->Entry->Config->ModemConfig)
  68.         UseHangUp = DialNode->Entry->Config->ModemConfig->AbortHangsUp;
  69.     else
  70.         UseHangUp = OriginalModemConfig->AbortHangsUp;
  71.  
  72.     if(UseHangUp)
  73.         HangUp();
  74.     else
  75.     {
  76.         SerWrite("\r",1);
  77.  
  78.         StartTime(1,0);
  79.  
  80.             /* Wait for the modem to respond or the timer to elapse. */
  81.  
  82.         Wait(GetJobMask(SerialJob) | SIG_TIMER);
  83.  
  84.         StopTime();
  85.     }
  86.  
  87.         /* Ignore the response of the modem. */
  88.  
  89.     while(RunJob(SerialJob));
  90.  
  91.     ResetDataFlowFilter();
  92. }
  93.  
  94.     /* DialPrintBox():
  95.      *
  96.      *    Render text into one of the display box lines.
  97.      */
  98.  
  99. STATIC VOID
  100. DialPrintBox(LayoutHandle *Handle,LONG Box,LONG Line,STRPTR String,...)
  101. {
  102.     UBYTE LocalBuffer[256];
  103.     va_list VarArgs;
  104.  
  105.     va_start(VarArgs,String);
  106.     LimitedVSPrintf(sizeof(LocalBuffer),LocalBuffer,String,VarArgs);
  107.     va_end(VarArgs);
  108.  
  109.     LT_SetAttributes(Handle,Box,
  110.         LABX_Index,    Line,
  111.         LABX_Text,    LocalBuffer,
  112.     TAG_DONE);
  113. }
  114.  
  115.     /* SendModemCommandGetResponse(LayoutHandle *Handle,STRPTR Command):
  116.      *
  117.      *    Send a modem command and wait for a response.
  118.      */
  119.  
  120. STATIC BOOL
  121. SendModemCommandGetResponse(LayoutHandle *Handle,STRPTR Command)
  122. {
  123.     ULONG Signals,SerialMask,WindowMask;
  124.     ULONG LastBytesOut;
  125.     BOOL Done;
  126.  
  127.         /* Reset the data flow scanner. */
  128.  
  129.     ResetDataFlowFilter();
  130.  
  131.         /* Send the modem command, but first remember how many
  132.          * bytes were sent yet.
  133.          */
  134.  
  135.     LastBytesOut = BytesOut;
  136.  
  137.     SerialCommand(Command);
  138.  
  139.         /* If no serial output took place, we'll return
  140.          * immediately.
  141.          */
  142.  
  143.     if(BytesOut == LastBytesOut)
  144.         return(TRUE);
  145.  
  146.         /* Get the two wait masks. */
  147.  
  148.     SerialMask = GetJobMask(SerialJob);
  149.     WindowMask = PORTMASK(Handle->Window->UserPort);
  150.  
  151.         /* Start the timer. We will wait up to ten seconds for
  152.          * the modem to respond.
  153.          */
  154.  
  155.     StartTime(10,0);
  156.  
  157.     Done = FALSE;
  158.  
  159.     do
  160.     {
  161.             /* Wait for something to happen. */
  162.  
  163.         Signals = Wait(SerialMask | WindowMask | SIG_TIMER);
  164.  
  165.             /* Any window signal? */
  166.  
  167.         if(Signals & WindowMask)
  168.         {
  169.             struct IntuiMessage    *Message;
  170.             ULONG MsgClass,MsgQualifier;
  171.             struct Gadget *MsgGadget;
  172.             UWORD MsgCode;
  173.  
  174.                 /* Check if we are to skip or abort. */
  175.  
  176.             while(Message = LT_GetIMsg(Handle))
  177.             {
  178.                 MsgClass        = Message->Class;
  179.                 MsgCode            = Message->Code;
  180.                 MsgQualifier    = Message->Qualifier;
  181.                 MsgGadget        = Message->IAddress;
  182.  
  183.                 LT_ReplyIMsg(Message);
  184.  
  185.                     /* Convert the space keypress into a
  186.                      * skip command.
  187.                      */
  188.  
  189.                 if(MsgClass == IDCMP_RAWKEY)
  190.                 {
  191.                     if(LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
  192.                         Done = TRUE;
  193.                 }
  194.  
  195.                     /* So a button was pressed. */
  196.  
  197.                 if(MsgClass == IDCMP_GADGETUP)
  198.                 {
  199.                     switch(MsgGadget->GadgetID)
  200.                     {
  201.                         case GAD_SKIP:
  202.                         case GAD_ABORT:
  203.  
  204.                             Done = TRUE;
  205.                             break;
  206.                     }
  207.                 }
  208.             }
  209.         }
  210.  
  211.             /* Any modem signal? */
  212.  
  213.         if(Signals & SerialMask)
  214.         {
  215.                 /* Handle the serial input. */
  216.  
  217.             while(RunJob(SerialJob));
  218.  
  219.                 /* Exit if the modem said something sensible. */
  220.  
  221.             if(FlowInfo.Changed)
  222.                 Done = TRUE;
  223.         }
  224.  
  225.             /* Did the bell ring? */
  226.  
  227.         if(Signals & SIG_TIMER)
  228.             Done = TRUE;
  229.     }
  230.     while(!Done);
  231.  
  232.         /* Stop the timer. */
  233.  
  234.     StopTime();
  235.  
  236.         /* Did the modem respond? */
  237.  
  238.     return(FlowInfo.Changed);
  239. }
  240.  
  241.     /* SendLocalModemCommand():
  242.      *
  243.      *    Send a command to the modem and display an error message if necessary.
  244.      */
  245.  
  246. STATIC BOOL
  247. SendLocalModemCommand(LayoutHandle *Handle,STRPTR Command,STRPTR Message,STRPTR ErrorMessage)
  248. {
  249.         /* Show the message. */
  250.  
  251.     DialPrintBox(Handle,GAD_NOTE,0,Message);
  252.  
  253.         /* Send the command and check if the modem did respond. */
  254.  
  255.     if(SendModemCommandGetResponse(Handle,Command))
  256.     {
  257.             /* No news is good news. */
  258.  
  259.         if(!FlowInfo.Error)
  260.             return(TRUE);
  261.         else
  262.             DialPrintBox(Handle,GAD_NOTE,0,ErrorMessage);
  263.     }
  264.     else
  265.         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_MODEM_NOT_RESPONDING_TXT));
  266.  
  267.     WakeUp(Handle->Window,SOUND_ERROR);
  268.     return(FALSE);
  269. }
  270.  
  271.     /* BuildName(STRPTR Name):
  272.      *
  273.      *    Build a file name from a BBS name and the current date.
  274.      */
  275.  
  276. STATIC VOID
  277. BuildName(STRPTR Name,LONG MaxNameLen,STRPTR Date)
  278. {
  279.     if(Date[0])
  280.     {
  281.         LONG NameLen,DateLen,Delta;
  282.  
  283.         NameLen = strlen(Name);
  284.         DateLen = strlen(Date);
  285.  
  286.         if((Delta = NameLen + 1 + DateLen - 32) > 0)
  287.             Name[NameLen - Delta] = 0;
  288.  
  289.         LimitedStrcat(MaxNameLen,Name,"_");
  290.         LimitedStrcat(MaxNameLen,Name,Date);
  291.     }
  292. }
  293.  
  294.     /* OpenAutoCaptureFile(STRPTR SomeName):
  295.      *
  296.      *    Open a capture file.
  297.      */
  298.  
  299. STATIC VOID
  300. OpenAutoCaptureFile(STRPTR SomeName)
  301. {
  302.     struct DateTime    DateTime;
  303.     UBYTE Date[20],Time[20];
  304.  
  305.         /* Get the current time and date. */
  306.  
  307.     DateStamp(&DateTime.dat_Stamp);
  308.  
  309.         /* Prepare for date conversion. */
  310.  
  311.     DateTime.dat_Format        = FORMAT_DEF;
  312.     DateTime.dat_Flags        = 0;
  313.     DateTime.dat_StrDay        = NULL;
  314.     DateTime.dat_StrDate    = Date;
  315.     DateTime.dat_StrTime    = Time;
  316.  
  317.         /* Convert the date. */
  318.  
  319.     if(DateToStr(&DateTime))
  320.     {
  321.         UBYTE LocalBuffer[MAX_FILENAME_LENGTH],Name[MAX_FILENAME_LENGTH];
  322.  
  323.             /* Remember the BBS name. */
  324.  
  325.         LimitedStrcpy(sizeof(Name),Name,SomeName);
  326.  
  327.             /* Append the creation date if necessary. */
  328.  
  329.         if(Config->CaptureConfig->AutoCaptureDate == AUTOCAPTURE_DATE_NAME)
  330.             BuildName(Name,sizeof(Name),Date);
  331.  
  332.             /* Make it a reasonable name. */
  333.  
  334.         FixName(Name);
  335.  
  336.             /* Get the capture file path. */
  337.  
  338.         LimitedStrcpy(sizeof(LocalBuffer),LocalBuffer,Config->CaptureConfig->CapturePath);
  339.  
  340.             /* Try to build a valid file and path name. */
  341.  
  342.         if(AddPart(LocalBuffer,Name,sizeof(LocalBuffer)))
  343.         {
  344.                 /* Is the capture file still open? */
  345.  
  346.             if(FileCapture)
  347.             {
  348.                     /* Close the file. */
  349.  
  350.                 BufferClose(FileCapture);
  351.  
  352.                 FileCapture = NULL;
  353.  
  354.                     /* Any data written? */
  355.  
  356.                 if(!GetFileSize(CaptureName))
  357.                     DeleteFile(CaptureName);
  358.                 else
  359.                 {
  360.                     AddProtection(CaptureName,FIBF_EXECUTE);
  361.  
  362.                     if(Config->MiscConfig->CreateIcons)
  363.                         AddIcon(CaptureName,FILETYPE_TEXT,TRUE);
  364.                 }
  365.             }
  366.  
  367.                 /* Try to append the new data. */
  368.  
  369.             if(FileCapture = BufferOpen(LocalBuffer,"a"))
  370.             {
  371.                     /* Set the menu checkmark. */
  372.  
  373.                 CheckItem(MEN_CAPTURE_TO_FILE,TRUE);
  374.  
  375.                     /* Remember the current capture file name. */
  376.  
  377.                 strcpy(CaptureName,LocalBuffer);
  378.  
  379.                     /* Add the creation date if necessary. */
  380.  
  381.                 if(Config->CaptureConfig->AutoCaptureDate == AUTOCAPTURE_DATE_INCLUDE)
  382.                 {
  383.                     UBYTE DateTimeBuffer[256];
  384.  
  385.                     if(FormatStamp(&DateTime.dat_Stamp,DateTimeBuffer,sizeof(DateTimeBuffer),FALSE))
  386.                         BPrintf(FileCapture,LocaleString(MSG_DIALPANEL_FILE_CREATED_TXT),DateTimeBuffer);
  387.                 }
  388.             }
  389.             else
  390.                 CheckItem(MEN_CAPTURE_TO_FILE,FALSE);
  391.  
  392.             ConOutputUpdate();
  393.         }
  394.     }
  395. }
  396.  
  397.     /* Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode):
  398.      *
  399.      *    Perform connect action(s).
  400.      */
  401.  
  402. STATIC VOID
  403. Connect(PhonebookHandle *PhoneHandle,struct DialNode *DialNode)
  404. {
  405.     struct ModemSettings *ModemConfig;
  406.     ULONG RateIs;
  407.     STRPTR Name;
  408.  
  409.         /* Check which modem configuration to use later. */
  410.  
  411.     if(DialNode->Entry && DialNode->Entry->Config->ModemConfig)
  412.         ModemConfig = DialNode->Entry->Config->ModemConfig;
  413.     else
  414.         ModemConfig = OriginalModemConfig;
  415.  
  416.         /* Get the current area code settings. */
  417.  
  418.     SetActivePattern(FindTimeDate(PatternList,DialNode->Number));
  419.  
  420.         /* Mark the active phonebook entry, if any. */
  421.  
  422.     SetActiveEntry(PhoneHandle,DialNode->Entry);
  423.  
  424.         /* Get the DTE rate ready. */
  425.  
  426.     if(DTERate > 0)
  427.         RateIs = DTERate;
  428.     else
  429.         RateIs = Config->SerialConfig->BaudRate;
  430.  
  431.         /* Does the node have a phonebook entry attached? */
  432.  
  433.     if(DialNode->Entry)
  434.     {
  435.         SaveConfig(DialNode->Entry->Config,Config);
  436.         ConfigChanged = FALSE;
  437.  
  438.         Name = DialNode->Entry->Header->Name;
  439.  
  440.         strcpy(Password,DialNode->Entry->Header->Password);
  441.         strcpy(UserName,DialNode->Entry->Header->UserName);
  442.  
  443.         SendStartup = TRUE;
  444.  
  445.         strcpy(CurrentBBSName,DialNode->Entry->Header->Name);
  446.         strcpy(CurrentBBSComment,DialNode->Entry->Header->Comment);
  447.  
  448.         LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),Name,DialNode->Number,RateIs);
  449.     }
  450.     else
  451.     {
  452.         Name = LocaleString(MSG_GLOBAL_UNKNOWN_TXT);
  453.  
  454.         Password[0]    = 0;
  455.         UserName[0]    = 0;
  456.  
  457.         SendStartup    = FALSE;
  458.  
  459.         CurrentBBSName[0]        = 0;
  460.         CurrentBBSComment[0]    = 0;
  461.  
  462.         LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),DialNode->Number,RateIs);
  463.     }
  464.  
  465.         /* Register the call. */
  466.  
  467.     MakeCall(Name,DialNode->Number,ModemConfig->TimeToConnect);
  468.  
  469.         /* Store the current phone number. */
  470.  
  471.     strcpy(CurrentBBSNumber,DialNode->Number);
  472.  
  473.         /* Get the online time limit and the macro to execute when the limit is reached. */
  474.  
  475.     if(ModemConfig->ConnectLimit > 0 && ModemConfig->ConnectLimitMacro[0])
  476.     {
  477.         ArmLimit(ModemConfig->ConnectLimit);
  478.  
  479.         strcpy(LimitMacro,ModemConfig->ConnectLimitMacro);
  480.     }
  481.     else
  482.         DisarmLimit();
  483.  
  484.         /* We are now online. */
  485.  
  486.     SetOnlineState(TRUE,ModemConfig->TimeToConnect);
  487.  
  488.         /* Start the accounting process */
  489.  
  490.     StartAccountant(ModemConfig->TimeToConnect);
  491.  
  492.         /* Open auto-capture file. */
  493.  
  494.     if(Config->CaptureConfig->ConnectAutoCapture && Config->CaptureConfig->CapturePath[0])
  495.     {
  496.         STRPTR FileName;
  497.  
  498.         if(DialNode->Entry)
  499.             FileName = DialNode->Entry->Header->Name;
  500.         else
  501.             FileName = LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT);
  502.  
  503.         OpenAutoCaptureFile(FileName);
  504.     }
  505.  
  506.         /* Remove node from dialing list and perform system setup. */
  507.  
  508.     RemoveAndDeleteRelatedDialNodes(PhoneHandle,DialNode);
  509.  
  510.         /* Make a backup of the old settings. */
  511.  
  512.     if(PrivateConfig->MiscConfig->BackupConfig && !BackupConfig)
  513.     {
  514.         if(BackupConfig = CreateConfiguration(TRUE))
  515.             SaveConfig(PrivateConfig,BackupConfig);
  516.     }
  517.  
  518.         /* Make sure that the following
  519.          * setup/initialization will not
  520.          * touch the serial configuration.
  521.          */
  522.  
  523.     PutConfigEntry(PrivateConfig,Config->SerialConfig,PREF_SERIAL);
  524.  
  525.     ConfigSetup();
  526.  
  527.         /* Reset the scanner. */
  528.  
  529.     ResetDataFlowFilter();
  530. }
  531.  
  532.     /* OpenDialPanel(BOOL *Record):
  533.      *
  534.      *    Open the dialing panel.
  535.      */
  536.  
  537. STATIC LayoutHandle *
  538. OpenDialPanel(BOOL *Record,BOOL *SkipLoginMacro)
  539. {
  540.     LayoutHandle *Handle;
  541.  
  542.     if(Handle = LT_CreateHandleTags(Window->WScreen,
  543.         LAHN_LocaleHook,    &LocaleHook,
  544.     TAG_DONE))
  545.     {
  546.         LT_New(Handle,
  547.             LA_Type,    VERTICAL_KIND,
  548.         TAG_DONE);
  549.         {
  550.             LT_New(Handle,
  551.                 LA_Type,    VERTICAL_KIND,
  552.             TAG_DONE);
  553.             {
  554.                 LT_New(Handle,
  555.                     LA_Type,    VERTICAL_KIND,
  556.                 TAG_DONE);
  557.                 {
  558.                     LT_New(Handle,
  559.                         LA_Type,            BOX_KIND,
  560.                         LA_ID,                GAD_CALLING,
  561.                         LABX_Chars,            40,
  562.                         LABX_Rows,            4,
  563.                         LABX_ReserveSpace,    TRUE,
  564.                         LABX_FirstLabel,    MSG_DIALPANEL_CALLING_TXT,
  565.                         LABX_LastLabel,        MSG_DIALPANEL_NEXT_TXT,
  566.                     TAG_DONE);
  567.  
  568.                     LT_New(Handle,
  569.                         LA_Type,            BOX_KIND,
  570.                         LA_ID,                GAD_TIME,
  571.                         LABX_Chars,            40,
  572.                         LABX_Rows,            2,
  573.                         LABX_ReserveSpace,    TRUE,
  574.                         LABX_FirstLabel,    MSG_DIALPANEL_TIMEOUT_TXT,
  575.                         LABX_LastLabel,        MSG_DIALPANEL_ATTEMPT_TXT,
  576.                     TAG_DONE);
  577.  
  578.                     LT_New(Handle,
  579.                         LA_Type,            BOX_KIND,
  580.                         LA_ID,                GAD_NOTE,
  581.                         LABX_Chars,            40,
  582.                         LABX_Rows,            1,
  583.                         LABX_ReserveSpace,    TRUE,
  584.                         LABX_FirstLabel,    MSG_DIALPANEL_MESSAGE_TXT,
  585.                         LABX_LastLabel,        MSG_DIALPANEL_MESSAGE_TXT,
  586.                     TAG_DONE);
  587.  
  588.                     LT_EndGroup(Handle);
  589.                 }
  590.  
  591.                 LT_New(Handle,
  592.                     LA_Type,    VERTICAL_KIND,
  593.                 TAG_DONE);
  594.                 {
  595.                     LT_New(Handle,
  596.                         LA_Type,        XBAR_KIND,
  597.                     TAG_DONE);
  598.  
  599.                     LT_New(Handle,
  600.                         LA_Type,        CHECKBOX_KIND,
  601.                         LA_LabelID,        MSG_DIALPANEL_RECORD_ON_CONNECTION_TXT,
  602.                         LA_BOOL,        Record,
  603.                     TAG_DONE);
  604.  
  605.                     LT_New(Handle,
  606.                         LA_Type,        CHECKBOX_KIND,
  607.                         LA_LabelID,        MSG_SKIP_LOGIN_MACRO_GAD,
  608.                         LA_BOOL,        SkipLoginMacro,
  609.                     TAG_DONE);
  610.  
  611.                     LT_EndGroup(Handle);
  612.                 }
  613.  
  614.                 LT_EndGroup(Handle);
  615.             }
  616.  
  617.             LT_New(Handle,
  618.                 LA_Type,VERTICAL_KIND,
  619.             TAG_DONE);
  620.             {
  621.                 LT_New(Handle,
  622.                     LA_Type,        XBAR_KIND,
  623.                     LAXB_FullSize,    TRUE,
  624.                 TAG_DONE);
  625.  
  626.                 LT_EndGroup(Handle);
  627.             }
  628.  
  629.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  630.                 LAGR_Spread,    TRUE,
  631.             TAG_DONE);
  632.             {
  633.                 LT_New(Handle,
  634.                     LA_Type,        BUTTON_KIND,
  635.                     LA_LabelID,        MSG_DIALPANEL_SKIP_GAD,
  636.                     LA_ID,            GAD_SKIP,
  637.                     LABT_ExtraFat,    TRUE,
  638.                     GA_Disabled,    TRUE,
  639.                 TAG_DONE);
  640.  
  641.                 LT_New(Handle,
  642.                     LA_Type,        BUTTON_KIND,
  643.                     LA_LabelID,        MSG_GLOBAL_REMOVE_GAD,
  644.                     LA_ID,            GAD_REMOVE,
  645.                     LABT_ExtraFat,    TRUE,
  646.                     GA_Disabled,    TRUE,
  647.                 TAG_DONE);
  648.  
  649.                 LT_New(Handle,
  650.                     LA_Type,        BUTTON_KIND,
  651.                     LA_LabelID,        MSG_DIALPANEL_GO_TO_ONLINE_GAD,
  652.                     LA_ID,            GAD_ONLINE,
  653.                     LABT_ReturnKey,    TRUE,
  654.                     LABT_ExtraFat,    TRUE,
  655.                 TAG_DONE);
  656.  
  657.                 LT_New(Handle,
  658.                     LA_Type,        BUTTON_KIND,
  659.                     LA_LabelID,        MSG_GLOBAL_ABORT_GAD,
  660.                     LA_ID,            GAD_ABORT,
  661.                     LABT_ExtraFat,    TRUE,
  662.                 TAG_DONE);
  663.  
  664.                 LT_EndGroup(Handle);
  665.             }
  666.  
  667.             LT_EndGroup(Handle);
  668.         }
  669.  
  670.         if(LT_Build(Handle,
  671.             LAWN_TitleID,        MSG_DIALPANEL_DIALING_TXT,
  672.             LAWN_IDCMP,            IDCMP_CLOSEWINDOW,
  673.             LAWN_HelpHook,        &GuideHook,
  674.             LAWN_Parent,        Window,
  675.             WA_DepthGadget,        TRUE,
  676.             WA_CloseGadget,        TRUE,
  677.             WA_DragBar,            TRUE,
  678.             WA_RMBTrap,            TRUE,
  679.             WA_Activate,        TRUE,
  680.         /*    WA_SimpleRefresh,    TRUE, */
  681.         TAG_DONE))
  682.             return(Handle);
  683.         else
  684.             LT_DeleteHandle(Handle);
  685.     }
  686.  
  687.     return(NULL);
  688. }
  689.  
  690.     /* DialPanel():
  691.      *
  692.      *    This routine opens a small window in the middle of the
  693.      *    console window and walks down the list of numbers to
  694.      *    dial.
  695.      */
  696.  
  697. BOOL
  698. DialPanel(PhonebookHandle *PhoneHandle)
  699. {
  700.     enum { STOP_Not,STOP_Abort,STOP_Skip };
  701.     enum { START_Dial,START_Call,START_Wait };
  702.  
  703.     BOOL ReturnToPhonebook,RecordOnConnection,ReleaseSerialDevice,SkipLoginMacro;
  704.     LayoutHandle *Handle;
  705.  
  706.             /* Remember the original modem and serial settings, so we
  707.              * can return to them later.
  708.              */
  709.  
  710.     OriginalSerialConfig    = CreateNewConfigEntry(PREF_SERIAL);
  711.     OriginalModemConfig        = CreateNewConfigEntry(PREF_MODEM);
  712.  
  713.     if(!OriginalSerialConfig || !OriginalModemConfig)
  714.     {
  715.         FreeVecPooled(OriginalSerialConfig);
  716.         OriginalSerialConfig = NULL;
  717.  
  718.         FreeVecPooled(OriginalModemConfig);
  719.         OriginalModemConfig = NULL;
  720.  
  721.         DisplayBeep(NULL);
  722.  
  723.         return(FALSE);
  724.     }
  725.  
  726.     ReturnToPhonebook = RecordOnConnection = ReleaseSerialDevice = SkipLoginMacro = FALSE;
  727.  
  728.     if(Handle = OpenDialPanel(&RecordOnConnection,&SkipLoginMacro))
  729.     {
  730.         struct SerialSettings *    CurrentSerialConfig;
  731.         struct ModemSettings *    CurrentModemConfig;
  732.  
  733.         struct Window *            PanelWindow;
  734.  
  735.         UBYTE                    NoteText[80];
  736.  
  737.         UBYTE                    ExitCommand[80];
  738.  
  739.         UBYTE                    ExitBuffer[80],
  740.                                  InitBuffer[80];
  741.  
  742.         UBYTE                     PrefixBuffer[80],
  743.                                  SuffixBuffer[80];
  744.  
  745.         UBYTE                    DialBuffer[300];
  746.  
  747.         LONG                    DialTimeout,DialRetries,DialAttempt;
  748.  
  749.         struct DialNode *        DialNode;
  750.  
  751.         LONG                    RedialTimeout;
  752.  
  753.         WORD                    Start,Stop;
  754.  
  755.         BOOL                    DoNotHangUp,ErrorHasOccured,ModemNotResponding,Done;
  756.  
  757.         BOOL                    OldQuietSettings;
  758.  
  759.         ULONG                    ODUMask,WindowMask,Signals;
  760.  
  761.         SENDLINE                OriginalSendLine;
  762.  
  763.         struct timeval            LastTimeCheck;
  764.  
  765.             /* Start from scratch. */
  766.  
  767.         PanelWindow         = Handle->Window;
  768.  
  769.         DialRetries            = 0;
  770.         DialAttempt            = 0;
  771.         DialNode            = NULL;
  772.  
  773.         ErrorHasOccured        = FALSE;
  774.         ModemNotResponding    = FALSE;
  775.         DoNotHangUp         = FALSE;
  776.  
  777.         Done                = FALSE;
  778.  
  779.         Start                = START_Call;
  780.         Stop                = STOP_Not;
  781.  
  782.         GetCurrentSettings(NULL,&CurrentSerialConfig,&CurrentModemConfig);
  783.  
  784.         GetSysTime(&LastTimeCheck);
  785.  
  786.             /* Don't mix up the line send stuff with the default sending routine */
  787.  
  788.         OriginalSendLine = ChangeSendLine(SendLineDial);
  789.  
  790.             /* Set up the ODU stuff */
  791.  
  792.         if(OwnDevUnitBase && Config->SerialConfig->ReleaseODUWhenDialing && Config->SerialConfig->SatisfyODURequests != ODU_KEEP && !(Config->SerialConfig->Shared && Config->SerialConfig->NoODUIfShared))
  793.             ODUMask = SIG_OWNDEVUNIT;
  794.         else
  795.             ODUMask = NULL;
  796.  
  797.             /* And get the window port mask ready */
  798.  
  799.         WindowMask = PORTMASK(Handle->Window->UserPort);
  800.  
  801.             /* Reset the area code scanner data. */
  802.  
  803.         SetActivePattern(NULL);
  804.         SetActiveEntry(PhoneHandle,NULL);
  805.  
  806.             /* We are now dialing. */
  807.  
  808.         PushStatus(STATUS_DIALING);
  809.  
  810.             /* Set up the AmigaGuide help context. */
  811.  
  812.         GuideContext(CONTEXT_DIAL);
  813.  
  814.             /* No exit command is defined yet. */
  815.  
  816.         ExitCommand[0] = 0;
  817.  
  818.             /* Make the current one the active one. */
  819.  
  820.         LT_ShowWindow(Handle,TRUE);
  821.  
  822.         PushWindow(PanelWindow);
  823.  
  824.             /* Make a backup of the current configuration. */
  825.  
  826.         SaveConfig(Config,PrivateConfig);
  827.  
  828.             /* Don't echo serial output unless requested by the user. */
  829.  
  830.         OldQuietSettings = SetConsoleQuiet((BOOL)(Config->ModemConfig->VerboseDialing == FALSE));
  831.  
  832.             /* Reset the scanner. */
  833.  
  834.         ResetDataFlowFilter();
  835.  
  836.             /* Get the entry signals ready and clear those we do not yet care about. */
  837.  
  838.         Signals = SetSignal(0,SIG_BREAK | SIG_SKIP | ODUMask | WindowMask) & (ODUMask | WindowMask);
  839.  
  840.             /* The big dialing loop. */
  841.  
  842.         do
  843.         {
  844.                 /* Abort the process? */
  845.  
  846.             if(!Done && (Signals & SIG_BREAK))
  847.             {
  848.                 Stop = STOP_Abort;
  849.                 Done = TRUE;
  850.             }
  851.  
  852.                 /* Check if we should let go of the device */
  853.  
  854.             if(!Done && (Signals & ODUMask))
  855.             {
  856.                 Stop = STOP_Abort;
  857.                 Done = TRUE;
  858.  
  859.                 ReleaseSerialDevice = TRUE;
  860.             }
  861.  
  862.                 /* Any window input? */
  863.  
  864.             if(!Done && (Signals & WindowMask))
  865.             {
  866.                 struct IntuiMessage    *Message;
  867.                 ULONG MsgClass,MsgQualifier;
  868.                 struct Gadget *MsgGadget;
  869.                 UWORD MsgCode;
  870.  
  871.                 while(Message = LT_GetIMsg(Handle))
  872.                 {
  873.                     MsgClass        = Message->Class;
  874.                     MsgCode            = Message->Code;
  875.                     MsgQualifier    = Message->Qualifier;
  876.                     MsgGadget        = Message->IAddress;
  877.  
  878.                     LT_ReplyIMsg(Message);
  879.  
  880.                         /* Convert the space keypress into a
  881.                          * skip command.
  882.                          */
  883.  
  884.                     if(MsgClass == IDCMP_RAWKEY)
  885.                     {
  886.                         if(LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
  887.                         {
  888.                             if(Stop == STOP_Not && Start != START_Call)
  889.                             {
  890.                                 LT_PressButton(Handle,GAD_SKIP);
  891.  
  892.                                 Stop = STOP_Skip;
  893.                             }
  894.                         }
  895.                     }
  896.  
  897.                         /* Close the window, hang up the line,
  898.                          * return to the phone book.
  899.                          */
  900.  
  901.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  902.                     {
  903.                         Stop = STOP_Abort;
  904.                         Done = TRUE;
  905.                         ReturnToPhonebook = TRUE;
  906.                     }
  907.  
  908.                         /* So a button was pressed. */
  909.  
  910.                     if(MsgClass == IDCMP_GADGETUP)
  911.                     {
  912.                         switch(MsgGadget->GadgetID)
  913.                         {
  914.                                 /* Remove the currently active dialing
  915.                                  * list entry.
  916.                                  */
  917.  
  918.                             case GAD_REMOVE:
  919.  
  920.                                     /* This makes sense only while
  921.                                      * we are dialing.
  922.                                      */
  923.  
  924.                                 if(Start == START_Dial)
  925.                                 {
  926.                                     struct DialNode    *NextNode;
  927.  
  928.                                     NextNode = NULL;
  929.  
  930.                                         /* If still dialing, hang up first. */
  931.  
  932.                                     if(DoNotHangUp)
  933.                                         DoNotHangUp = FALSE;
  934.                                     else
  935.                                         QuickHangup(DialNode);
  936.  
  937.                                         /* Is there another entry in the list? */
  938.  
  939.                                     if(DialNode->Node.ln_Succ->ln_Succ)
  940.                                         NextNode = (struct DialNode *)DialNode->Node.ln_Succ;
  941.                                     else
  942.                                     {
  943.                                             /* No, there isn't; do we have a list with
  944.                                              * at least two entries in it?
  945.                                              */
  946.  
  947.                                         if(PhoneHandle->DialList->lh_Head->ln_Succ->ln_Succ)
  948.                                         {
  949.                                                 /* Yet another dialing attempt coming up... */
  950.  
  951.                                             DialAttempt++;
  952.  
  953.                                                 /* Check for dial retry limit. */
  954.  
  955.                                             if(DialRetries >= 0 && DialAttempt >= DialRetries)
  956.                                             {
  957.                                                 DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  958.  
  959.                                                 WakeUp(PanelWindow,SOUND_BELL);
  960.  
  961.                                                 DelayTime(2,0);
  962.  
  963.                                                 Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  964.  
  965.                                                 Done = TRUE;
  966.                                             }
  967.                                             else
  968.                                             {
  969.                                                     /* Grab first list entry and continue. */
  970.  
  971.                                                 NextNode = (struct DialNode *)PhoneHandle->DialList->lh_Head;
  972.                                             }
  973.                                         }
  974.                                         else
  975.                                         {
  976.                                                 /* That's all, folks! */
  977.  
  978.                                             DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_LIST_IS_EMPTY_TXT));
  979.  
  980.                                             DelayTime(2,0);
  981.  
  982.                                             Done = TRUE;
  983.                                         }
  984.                                     }
  985.  
  986.                                         /* Remove dial entry from list. */
  987.  
  988.                                     RemoveDialNode(PhoneHandle,DialNode);
  989.                                     DeleteDialNode(DialNode);
  990.  
  991.                                         /* Is there an entry to proceed with? */
  992.  
  993.                                     if(DialNode = NextNode)
  994.                                         Start = START_Call;
  995.  
  996.                                     GetCurrentSettings(DialNode,&CurrentSerialConfig,&CurrentModemConfig);
  997.                                 }
  998.  
  999.                                 break;
  1000.  
  1001.                             case GAD_SKIP:
  1002.  
  1003.                                 if(Stop == STOP_Not && Start != START_Call)
  1004.                                     Stop = STOP_Skip;
  1005.  
  1006.                                 break;
  1007.  
  1008.                             case GAD_ONLINE:
  1009.  
  1010.                                     /* Go online so soon? */
  1011.  
  1012.                                 if(!DialNode)
  1013.                                 {
  1014.                                     if(!IsListEmpty(PhoneHandle->DialList))
  1015.                                         DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head;
  1016.                                 }
  1017.  
  1018.                                 if(DialNode)
  1019.                                     Connect(PhoneHandle,DialNode);
  1020.  
  1021.                                 GetCurrentSettings(DialNode,&CurrentSerialConfig,&CurrentModemConfig);
  1022.  
  1023.                                 Done = TRUE;
  1024.  
  1025.                                 break;
  1026.  
  1027.                                 /* Abort the dialing process. */
  1028.  
  1029.                             case GAD_ABORT:
  1030.  
  1031.                                 Stop = STOP_Abort;
  1032.                                 Done = TRUE;
  1033.  
  1034.                                 break;
  1035.                         }
  1036.                     }
  1037.  
  1038.                     if(Done)
  1039.                         break;
  1040.                 }
  1041.             }
  1042.  
  1043.                 /* Skip the current action? */
  1044.  
  1045.             if(!Done && (Signals & SIG_SKIP))
  1046.             {
  1047.                 if(Stop == STOP_Not && Start != START_Call)
  1048.                     Stop = STOP_Skip;
  1049.             }
  1050.  
  1051.                 /* Are we to abort? */
  1052.  
  1053.             if(Stop == STOP_Abort)
  1054.             {
  1055.                 Stop = STOP_Not;
  1056.  
  1057.                     /* Hang up if necessary. */
  1058.  
  1059.                 if(Start == START_Dial)
  1060.                 {
  1061.                     DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ABORTING_TXT));
  1062.  
  1063.                         /* Hang up if necessary. */
  1064.  
  1065.                     if(DoNotHangUp)
  1066.                         DoNotHangUp = FALSE;
  1067.                     else
  1068.                         QuickHangup(DialNode);
  1069.                 }
  1070.             }
  1071.  
  1072.                 /* Start at the beginning. */
  1073.  
  1074.             if(!Done && !DialNode)
  1075.             {
  1076.                 GetCurrentSettings(DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head,&CurrentSerialConfig,&CurrentModemConfig);
  1077.  
  1078.                 LT_SetAttributes(Handle,GAD_SKIP,
  1079.                     GA_Disabled,    FALSE,
  1080.                 TAG_DONE);
  1081.  
  1082.                 LT_SetAttributes(Handle,GAD_REMOVE,
  1083.                     GA_Disabled,    FALSE,
  1084.                 TAG_DONE);
  1085.  
  1086.                 Start = START_Call;
  1087.             }
  1088.  
  1089.                 /* Are we to start a call? */
  1090.  
  1091.             if(!Done && Start == START_Call)
  1092.             {
  1093.                     /* Reset the sequence scanner, the user may have skipped
  1094.                      * the previous dial attempt causing the modem to return
  1095.                      * `NO CARRIER'. To prevent the dialer from skipping the
  1096.                      * next dial entry as well as the previous we have to
  1097.                      * flush any data pending on the serial line.
  1098.                      */
  1099.  
  1100.                 ResetDataFlowFilter();
  1101.  
  1102.                     /* Does this entry have a configuration attached? */
  1103.  
  1104.                 if(DialNode->Entry == NULL && Config->ModemConfig->DoNotSendMainModemCommands)
  1105.                     InitBuffer[0] = ExitBuffer[0] = 0;
  1106.                 else
  1107.                 {
  1108.                     LimitedStrcpy(sizeof(InitBuffer),InitBuffer,DialNode->InitCommand ? DialNode->InitCommand : CurrentModemConfig->ModemInit);
  1109.                     LimitedStrcpy(sizeof(ExitBuffer),ExitBuffer,DialNode->ExitCommand ? DialNode->ExitCommand : CurrentModemConfig->ModemExit);
  1110.                 }
  1111.  
  1112.                 LimitedStrcpy(sizeof(PrefixBuffer),PrefixBuffer,DialNode->DialPrefix ? DialNode->DialPrefix : CurrentModemConfig->DialPrefix);
  1113.                 LimitedStrcpy(sizeof(SuffixBuffer),SuffixBuffer,DialNode->DialSuffix ? DialNode->DialSuffix : CurrentModemConfig->DialSuffix);
  1114.  
  1115.                     /* Send the modem exit string before we
  1116.                      * will need to reconfigure the serial
  1117.                      * device driver.
  1118.                      */
  1119.  
  1120.                 if(ExitCommand[0])
  1121.                 {
  1122.                     if(!SendLocalModemCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
  1123.                     {
  1124.                         if(!FlowInfo.Changed)
  1125.                             ModemNotResponding = TRUE;
  1126.  
  1127.                         ErrorHasOccured = TRUE;
  1128.                         Done = TRUE;
  1129.                     }
  1130.  
  1131.                     ExitCommand[0] = 0;
  1132.                 }
  1133.  
  1134.                     /* We will need to change the serial and modem parameters
  1135.                      * in order to establish a connection.
  1136.                      */
  1137.  
  1138.                 if(!Done)
  1139.                 {
  1140.                     PutConfigEntry(Config,CurrentModemConfig,PREF_MODEM);
  1141.  
  1142.                     if(ReconfigureSerial(PanelWindow,CurrentSerialConfig) == RECONFIGURE_FAILURE)
  1143.                     {
  1144.                         WakeUp(PanelWindow,SOUND_ERROR);
  1145.  
  1146.                         ErrorHasOccured = TRUE;
  1147.                         Done = TRUE;
  1148.                     }
  1149.                 }
  1150.  
  1151.                     /* Update the ODU bits and send the modem init command, if any. */
  1152.  
  1153.                 if(!Done)
  1154.                 {
  1155.                         /* Update the ODU stuff */
  1156.  
  1157.                     if(OwnDevUnitBase && CurrentSerialConfig->ReleaseODUWhenDialing && CurrentSerialConfig->SatisfyODURequests != ODU_KEEP && !(CurrentSerialConfig->Shared && CurrentSerialConfig->NoODUIfShared))
  1158.                         ODUMask = SIG_OWNDEVUNIT;
  1159.                     else
  1160.                         ODUMask = NULL;
  1161.  
  1162.                         /* Send the modem init command. */
  1163.  
  1164.                     if(InitBuffer[0])
  1165.                     {
  1166.                         if(!SendLocalModemCommand(Handle,InitBuffer,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
  1167.                         {
  1168.                             if(!FlowInfo.Changed)
  1169.                                 ModemNotResponding = TRUE;
  1170.  
  1171.                             ErrorHasOccured = TRUE;
  1172.                             Done = TRUE;
  1173.                         }
  1174.  
  1175.                         InitBuffer[0] = 0;
  1176.                     }
  1177.                 }
  1178.  
  1179.                     /* Get on with the rest. */
  1180.  
  1181.                 if(!Done)
  1182.                 {
  1183.                     STRPTR Comment;
  1184.  
  1185.                         /* Remember the new exit command. */
  1186.  
  1187.                     LimitedStrcpy(sizeof(ExitCommand),ExitCommand,ExitBuffer);
  1188.  
  1189.                     DialPrintBox(Handle,GAD_CALLING,0,DialNode->Node.ln_Name);
  1190.  
  1191.                         /* Show the comment, if any. */
  1192.  
  1193.                     if(DialNode->Entry && DialNode->Entry->Header->Comment[0])
  1194.                         Comment = DialNode->Entry->Header->Comment;
  1195.                     else
  1196.                         Comment = "-";
  1197.  
  1198.                     DialPrintBox(Handle,GAD_CALLING,1,Comment);
  1199.  
  1200.                         /* Display the number being called. */
  1201.  
  1202.                     DialPrintBox(Handle,GAD_CALLING,2,DialNode->Number);
  1203.  
  1204.                         /* Display the name of the service to call next. */
  1205.  
  1206.                     DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Succ->ln_Succ ? DialNode->Node.ln_Succ->ln_Name : "-");
  1207.  
  1208.                         /* Right now we're dialing. */
  1209.  
  1210.                     if(DialNode->Node.ln_Succ->ln_Succ)
  1211.                     {
  1212.                         LimitedSPrintf(sizeof(NoteText),NoteText,LocaleString(MSG_DIALER_NOTE_TXT),LocaleString(MSG_DIALPANEL_DIALING_TXT),GetListSize((struct List *)DialNode));
  1213.  
  1214.                         DialPrintBox(Handle,GAD_NOTE,0,NoteText);
  1215.                     }
  1216.                     else
  1217.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_TXT));
  1218.  
  1219.                         /* Say what we are dialing. */
  1220.  
  1221.                     Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),DialNode->Node.ln_Name);
  1222.  
  1223.                         /* Pick up dial timeout and dial retries. */
  1224.  
  1225.                     DialTimeout    = CurrentModemConfig->DialTimeout;
  1226.                     DialRetries    = CurrentModemConfig->DialRetries;
  1227.  
  1228.                         /* Build the dialing command. */
  1229.  
  1230.                     LimitedStrcpy(sizeof(DialBuffer),DialBuffer,PrefixBuffer);
  1231.  
  1232.                     if(CurrentModemConfig->PBX_Mode && CurrentModemConfig->PBX_Prefix[0])
  1233.                         LimitedStrcat(sizeof(DialBuffer),DialBuffer,CurrentModemConfig->PBX_Prefix);
  1234.  
  1235.                     LimitedStrcat(sizeof(DialBuffer),DialBuffer,DialNode->Number);
  1236.                     LimitedStrcat(sizeof(DialBuffer),DialBuffer,SuffixBuffer);
  1237.  
  1238.                         /* Dial the number. */
  1239.  
  1240.                     SerialCommand(DialBuffer);
  1241.  
  1242.                         /* Now we should be dialing. */
  1243.  
  1244.                     Start = START_Dial;
  1245.  
  1246.                         /* For the sake of precision. */
  1247.  
  1248.                     GetSysTime(&LastTimeCheck);
  1249.                 }
  1250.             }
  1251.  
  1252.                 /* Are we to skip the current assignment? */
  1253.  
  1254.             if(!Done && Stop == STOP_Skip)
  1255.             {
  1256.                 Stop = STOP_Not;
  1257.  
  1258.                 switch(Start)
  1259.                 {
  1260.                         /* Are we currently dialing? */
  1261.  
  1262.                     case START_Dial:
  1263.  
  1264.                             /* Hang up if necessary. */
  1265.  
  1266.                         if(DoNotHangUp)
  1267.                             DoNotHangUp = FALSE;
  1268.                         else
  1269.                             QuickHangup(DialNode);
  1270.  
  1271.                             /* Is this one the last entry? */
  1272.  
  1273.                         if(DialNode->Node.ln_Succ->ln_Succ)
  1274.                         {
  1275.                                 /* There is still another entry. */
  1276.  
  1277.                             GetCurrentSettings(DialNode = (struct DialNode *)DialNode->Node.ln_Succ,&CurrentSerialConfig,&CurrentModemConfig);
  1278.  
  1279.                                 /* Check if we should wait before we fire off another dial command. */
  1280.  
  1281.                             if(CurrentModemConfig->InterDialDelay)
  1282.                             {
  1283.                                     /* Wait until the inter-dial delay has elapsed. */
  1284.  
  1285.                                 RedialTimeout = CurrentModemConfig->InterDialDelay;
  1286.  
  1287.                                 DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_WAITING_TO_CALL_TXT));
  1288.  
  1289.                                 Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
  1290.  
  1291.                                     /* No entry is currently being called. */
  1292.  
  1293.                                 DialPrintBox(Handle,GAD_CALLING,0,"-");
  1294.                                 DialPrintBox(Handle,GAD_CALLING,1,"-");
  1295.                                 DialPrintBox(Handle,GAD_CALLING,2,"-");
  1296.  
  1297.                                 LT_SetAttributes(Handle,GAD_REMOVE,
  1298.                                     GA_Disabled,    TRUE,
  1299.                                 TAG_DONE);
  1300.  
  1301.                                     /* Display name of entry to call next. */
  1302.  
  1303.                                 DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Name);
  1304.  
  1305.                                 Start = START_Wait;
  1306.  
  1307.                                     /* For the sake of precision. */
  1308.  
  1309.                                 GetSysTime(&LastTimeCheck);
  1310.                             }
  1311.                             else
  1312.                                 Start = START_Call;
  1313.                         }
  1314.                         else
  1315.                         {
  1316.                                 /* Yet another dial attempt coming up. */
  1317.  
  1318.                             DialAttempt++;
  1319.  
  1320.                                 /* Is this one the last dial
  1321.                                  * attempt to be made?
  1322.                                  */
  1323.  
  1324.                             if(DialAttempt >= DialRetries && DialRetries >= 0)
  1325.                             {
  1326.                                 DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  1327.  
  1328.                                 WakeUp(PanelWindow,SOUND_BELL);
  1329.  
  1330.                                 DelayTime(2,0);
  1331.  
  1332.                                 Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  1333.  
  1334.                                 Done = TRUE;
  1335.                             }
  1336.                             else
  1337.                             {
  1338.                                 LONG InterDialDelay;
  1339.  
  1340.                                     /* Get the first list entry. */
  1341.  
  1342.                                 GetCurrentSettings(DialNode = (struct DialNode *)PhoneHandle->DialList->lh_Head,&CurrentSerialConfig,&CurrentModemConfig);
  1343.  
  1344.                                     /* Get the redial delay. */
  1345.  
  1346.                                 RedialTimeout    = CurrentModemConfig->RedialDelay;
  1347.                                 InterDialDelay    = CurrentModemConfig->InterDialDelay;
  1348.  
  1349.                                     /* Check if the inter-dial delay is larger than
  1350.                                      * the redial delay. If so, use the inter-dial delay.
  1351.                                      */
  1352.  
  1353.                                 if(InterDialDelay > RedialTimeout)
  1354.                                     RedialTimeout = InterDialDelay;
  1355.  
  1356.                                     /* No redial delay? Restart dialing... */
  1357.  
  1358.                                 if(!RedialTimeout)
  1359.                                 {
  1360.                                     Start = START_Call;
  1361.  
  1362.                                     DelayTime(1,0);
  1363.                                 }
  1364.                                 else
  1365.                                 {
  1366.                                         /* Go into redial delay. */
  1367.  
  1368.                                     DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_REDIAL_DELAY_TXT));
  1369.  
  1370.                                     Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
  1371.  
  1372.                                         /* No entry is currently being called. */
  1373.  
  1374.                                     DialPrintBox(Handle,GAD_CALLING,0,"-");
  1375.                                     DialPrintBox(Handle,GAD_CALLING,1,"-");
  1376.                                     DialPrintBox(Handle,GAD_CALLING,2,"-");
  1377.  
  1378.                                     LT_SetAttributes(Handle,GAD_REMOVE,
  1379.                                         GA_Disabled,    TRUE,
  1380.                                     TAG_DONE);
  1381.  
  1382.                                         /* Display name of entry to call next. */
  1383.  
  1384.                                     DialPrintBox(Handle,GAD_CALLING,3,DialNode->Node.ln_Name);
  1385.  
  1386.                                     Start = START_Wait;
  1387.  
  1388.                                         /* For the sake of precision. */
  1389.  
  1390.                                     GetSysTime(&LastTimeCheck);
  1391.                                 }
  1392.                             }
  1393.                         }
  1394.  
  1395.                         break;
  1396.  
  1397.                         /* Stop waiting. */
  1398.  
  1399.                     case START_Wait:
  1400.  
  1401.                         if(Start == START_Wait)
  1402.                         {
  1403.                             LT_SetAttributes(Handle,GAD_REMOVE,
  1404.                                 GA_Disabled,    FALSE,
  1405.                             TAG_DONE);
  1406.  
  1407.                             Start = START_Call;
  1408.                         }
  1409.  
  1410.                         break;
  1411.                 }
  1412.             }
  1413.  
  1414.                 /* Take care of serial input. */
  1415.  
  1416.             if(!Done)
  1417.                 RunJob(SerialJob);
  1418.  
  1419.                 /* Any news from the modem? */
  1420.  
  1421.             if(!Done && FlowInfo.Changed)
  1422.             {
  1423.                     /* Current number is busy. */
  1424.  
  1425.                 if(FlowInfo.Busy || (FlowInfo.NoCarrier && CurrentModemConfig->NoCarrierIsBusy))
  1426.                 {
  1427.                     if(!Done && Start == START_Dial)
  1428.                     {
  1429.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));
  1430.  
  1431.                         Say(LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));
  1432.  
  1433.                         DelayTime(1,0);
  1434.  
  1435.                         Stop = STOP_Skip;
  1436.  
  1437.                         DoNotHangUp = TRUE;
  1438.                     }
  1439.  
  1440.                     ResetDataFlowFilter();
  1441.                 }
  1442.  
  1443.                     /* Line does not feature a dialtone. */
  1444.  
  1445.                 if(FlowInfo.NoDialTone)
  1446.                 {
  1447.                     if(!Done && Start == START_Dial)
  1448.                     {
  1449.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));
  1450.  
  1451.                         WakeUp(PanelWindow,SOUND_ERROR);
  1452.  
  1453.                         Say(LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));
  1454.  
  1455.                         ErrorHasOccured = TRUE;
  1456.                         Done = TRUE;
  1457.                     }
  1458.  
  1459.                     ResetDataFlowFilter();
  1460.                 }
  1461.  
  1462.                     /* Somebody tries to call us. */
  1463.  
  1464.                 if(FlowInfo.Ring)
  1465.                 {
  1466.                     if(!Done)
  1467.                     {
  1468.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));
  1469.  
  1470.                         WakeUp(PanelWindow,SOUND_RING);
  1471.  
  1472.                         Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));
  1473.  
  1474.                         ErrorHasOccured = TRUE;
  1475.                         Done = TRUE;
  1476.                     }
  1477.  
  1478.                     ResetDataFlowFilter();
  1479.                 }
  1480.  
  1481.                     /* Somebody's talking. */
  1482.  
  1483.                 if(FlowInfo.Voice)
  1484.                 {
  1485.                     if(!Done)
  1486.                     {
  1487.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));
  1488.  
  1489.                         WakeUp(PanelWindow,SOUND_VOICE);
  1490.  
  1491.                         Say(LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));
  1492.  
  1493.                         ErrorHasOccured = TRUE;
  1494.                         Done = TRUE;
  1495.                     }
  1496.  
  1497.                     ResetDataFlowFilter();
  1498.                 }
  1499.  
  1500.                     /* We got a connect. */
  1501.  
  1502.                 if(FlowInfo.Connect)
  1503.                 {
  1504.                     if(!Done && Start == START_Dial)
  1505.                     {
  1506.                             /* Make the connection. */
  1507.  
  1508.                         Connect(PhoneHandle,DialNode);
  1509.  
  1510.                         Done = TRUE;
  1511.  
  1512.                             /* Wake the user up. */
  1513.  
  1514.                         if(BaudBuffer[0])
  1515.                         {
  1516.                             DialPrintBox(Handle,GAD_NOTE,0,"CONNECT %s",BaudBuffer);
  1517.  
  1518.                             WakeUp(PanelWindow,SOUND_CONNECT);
  1519.  
  1520.                             DelayTime(2,0);
  1521.  
  1522.                                 /* Install new baud rate if desired. */
  1523.  
  1524.                             if(Config->ModemConfig->ConnectAutoBaud && DTERate > 110)
  1525.                             {
  1526.                                 Config->SerialConfig->BaudRate = DTERate;
  1527.  
  1528.                                 ReconfigureSerial(PanelWindow,NULL);
  1529.                             }
  1530.                         }
  1531.                         else
  1532.                         {
  1533.                             DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));
  1534.  
  1535.                             WakeUp(PanelWindow,SOUND_CONNECT);
  1536.                         }
  1537.  
  1538.                         Say(LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));
  1539.                     }
  1540.  
  1541.                     ResetDataFlowFilter();
  1542.                 }
  1543.  
  1544.                     /* Looks like an error. */
  1545.  
  1546.                 if(FlowInfo.Error)
  1547.                 {
  1548.                     if(!Done && Start == START_Dial)
  1549.                     {
  1550.                         DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  1551.  
  1552.                         WakeUp(PanelWindow,SOUND_ERROR);
  1553.  
  1554.                         ErrorHasOccured = TRUE;
  1555.                         Done = TRUE;
  1556.                     }
  1557.  
  1558.                     ResetDataFlowFilter();
  1559.                 }
  1560.  
  1561.                     /* In any other case, reset the scanner. */
  1562.  
  1563.                 ResetDataFlowFilter();
  1564.             }
  1565.  
  1566.                 /* If nothing special's up... */
  1567.  
  1568.             if(!Done && Stop == STOP_Not && Start != START_Call)
  1569.             {
  1570.                 struct timeval Now,Then;
  1571.  
  1572.                     /* Give a brief report. */
  1573.  
  1574.                 switch(Start)
  1575.                 {
  1576.                     case START_Dial:
  1577.  
  1578.                         DialPrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",DialTimeout / 60,DialTimeout % 60);
  1579.                         DialPrintBox(Handle,GAD_TIME,1,LocaleString(DialRetries < 0 ? MSG_DIAL_RETRIES_UNLIMITED_TXT : MSG_DIALPANEL_ATTEMPT_OF_TXT),DialAttempt + 1,DialRetries);
  1580.  
  1581.                         break;
  1582.  
  1583.                     case START_Wait:
  1584.  
  1585.                         DialPrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",RedialTimeout / 60,RedialTimeout % 60);
  1586.                         break;
  1587.                 }
  1588.  
  1589.                     /* Wait a second or until something interesting happens. */
  1590.  
  1591.                 StartTime(1,0);
  1592.  
  1593.                 Signals = Wait(SIG_TIMER | SIG_BREAK | SIG_SKIP | ODUMask | WindowMask);
  1594.  
  1595.                 StopTime();
  1596.  
  1597.                     /* Get the current time. */
  1598.  
  1599.                 GetSysTime(&Now);
  1600.  
  1601.                     /* Check if the current time is "later" than the last time check.
  1602.                      * This is to avoid embarrassing situations such as could take
  1603.                      * place if the the user resets the operating system time.
  1604.                      */
  1605.  
  1606.                 if(-CmpTime(&Now,&LastTimeCheck) >= 0)
  1607.                 {
  1608.                     CopyMem(&Now,&Then,sizeof(struct timeval));
  1609.                     SubTime(&Now,&LastTimeCheck);
  1610.                 }
  1611.                 else
  1612.                 {
  1613.                     CopyMem(&Now,&LastTimeCheck,sizeof(struct timeval));
  1614.                     Now.tv_secs = 0;
  1615.                 }
  1616.  
  1617.                     /* The following instructions are executed as time passes by. */
  1618.  
  1619.                 if(Now.tv_secs > 0)
  1620.                 {
  1621.                     LONG Seconds = Now.tv_secs;
  1622.  
  1623.                         /* Remember the last time we went through. */
  1624.  
  1625.                     CopyMem(&Then,&LastTimeCheck,sizeof(struct timeval));
  1626.  
  1627.                     switch(Start)
  1628.                     {
  1629.                             /* Are we dialing? */
  1630.  
  1631.                         case START_Dial:
  1632.  
  1633.                             if(DialTimeout > Seconds)
  1634.                                 DialTimeout -= Seconds;
  1635.                             else
  1636.                             {
  1637.                                 DialTimeout = 0;
  1638.  
  1639.                                     /* The dial timeout has elapsed without
  1640.                                      * a connection being made.
  1641.                                      */
  1642.  
  1643.                                 Stop = STOP_Skip;
  1644.  
  1645.                                 DialPrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIAL_ATTEMPT_TIMEOUT_TXT));
  1646.                             }
  1647.  
  1648.                             break;
  1649.  
  1650.                             /* Are we waiting? */
  1651.  
  1652.                         case START_Wait:
  1653.  
  1654.                             if(RedialTimeout > Seconds)
  1655.                                 RedialTimeout -= Seconds;
  1656.                             else
  1657.                             {
  1658.                                 RedialTimeout = 0;
  1659.  
  1660.                                     /* The redial delay has elapsed,
  1661.                                      * start dialing again.
  1662.                                      */
  1663.  
  1664.                                 Stop = STOP_Skip;
  1665.                             }
  1666.  
  1667.                             break;
  1668.                     }
  1669.                 }
  1670.             }
  1671.         }
  1672.         while(!Done);
  1673.  
  1674.             /* Reset the status */
  1675.  
  1676.         PopStatus();
  1677.  
  1678.             /* Are we online or not? */
  1679.  
  1680.         if(!Online)
  1681.         {
  1682.             BOOL SendCommands;
  1683.  
  1684.                 /* If the modem is not responding anyway, don't bother
  1685.                  * sending any commands.
  1686.                  */
  1687.  
  1688.             SendCommands = (BOOL)(ModemNotResponding == FALSE);
  1689.  
  1690.                 /* Is the serial setup different? */
  1691.  
  1692.             if(CompareConfigEntries(Config->SerialConfig,OriginalSerialConfig,PREF_SERIAL))
  1693.             {
  1694.                     /* Set up the old serial configuration. */
  1695.  
  1696.                 if(ReconfigureSerial(PanelWindow,OriginalSerialConfig) == RECONFIGURE_FAILURE)
  1697.                     SendCommands = FALSE;
  1698.             }
  1699.  
  1700.                 /* Put back the original modem settings. */
  1701.  
  1702.             PutConfigEntry(Config,OriginalModemConfig,PREF_MODEM);
  1703.  
  1704.             if(SendCommands)
  1705.             {
  1706.                     /* Send the exit command if necessary. */
  1707.  
  1708.                 if(ExitCommand[0])
  1709.                 {
  1710.                     if(!SendLocalModemCommand(Handle,ExitCommand,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
  1711.                         ErrorHasOccured = TRUE;
  1712.                 }
  1713.  
  1714.                     /* Take care of the init command if necessary. */
  1715.  
  1716.                 if(Config->ModemConfig->ModemInit[0] && !ErrorHasOccured)
  1717.                 {
  1718.                     if(!SendLocalModemCommand(Handle,Config->ModemConfig->ModemInit,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT),LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT)))
  1719.                         ErrorHasOccured = TRUE;
  1720.                 }
  1721.             }
  1722.         }
  1723.  
  1724.             /* Make sure the error gets displayed. */
  1725.  
  1726.         if(ErrorHasOccured && !ReleaseSerialDevice)
  1727.         {
  1728.             LONG i;
  1729.  
  1730.             for(i = GAD_SKIP ; i <= GAD_REMOVE ; i++)
  1731.                 LT_SetAttributes(Handle,i,GA_Disabled,TRUE,TAG_DONE);
  1732.  
  1733.             Done = FALSE;
  1734.  
  1735.             do
  1736.             {
  1737.                 if(Wait(WindowMask | SIG_BREAK) & SIG_BREAK)
  1738.                     break;
  1739.                 else
  1740.                 {
  1741.                     struct IntuiMessage    *Message;
  1742.  
  1743.                     while(Message = LT_GetIMsg(Handle))
  1744.                     {
  1745.                         if(Message->Class == IDCMP_CLOSEWINDOW || Message->Class == IDCMP_GADGETUP)
  1746.                             Done = TRUE;
  1747.  
  1748.                         LT_ReplyIMsg(Message);
  1749.                     }
  1750.                 }
  1751.             }
  1752.             while(!Done);
  1753.         }
  1754.  
  1755.             /* Put back the old routine if necessary */
  1756.  
  1757.         RestoreSendLine(SendLineDial,OriginalSendLine);
  1758.  
  1759.         PopWindow();
  1760.  
  1761.         LT_DeleteHandle(Handle);
  1762.  
  1763.             /* Reset the scanner. */
  1764.  
  1765.         ResetDataFlowFilter();
  1766.  
  1767.             /* We are done now, restart echoing serial input. */
  1768.  
  1769.         SetConsoleQuiet(OldQuietSettings);
  1770.  
  1771.             /* Reset the display if necessary. */
  1772.  
  1773.         if(ResetDisplay)
  1774.         {
  1775.             if(!DisplayReset())
  1776.             {
  1777.                 FreeVecPooled(OriginalSerialConfig);
  1778.                 OriginalSerialConfig = NULL;
  1779.  
  1780.                 FreeVecPooled(OriginalModemConfig);
  1781.                 OriginalModemConfig = NULL;
  1782.  
  1783.                 return(FALSE);
  1784.             }
  1785.         }
  1786.  
  1787.             /* Handle online jobs. */
  1788.  
  1789.         SetDialMenu(Online == FALSE);
  1790.  
  1791.         if(Online)
  1792.         {
  1793.                 /* Send the startup macro if necessary. */
  1794.  
  1795.             if(SendStartup && !SkipLoginMacro)
  1796.             {
  1797.                 if(Config->CommandConfig->LoginMacro[0])
  1798.                     SerialCommand(Config->CommandConfig->LoginMacro);
  1799.  
  1800.                 if(Config->CommandConfig->StartupMacro[0])
  1801.                     SerialCommand(Config->CommandConfig->StartupMacro);
  1802.  
  1803.                 SendStartup = FALSE;
  1804.             }
  1805.  
  1806.                 /* Take care of the recording feature. */
  1807.  
  1808.             if(RecordOnConnection)
  1809.             {
  1810.                 if(CreateRecord(CurrentBBSName[0] ? CurrentBBSName : CurrentBBSNumber))
  1811.                 {
  1812.                     RememberResetOutput();
  1813.                     RememberResetInput();
  1814.  
  1815.                     RememberOutput    = TRUE;
  1816.  
  1817.                     Recording        = TRUE;
  1818.                     RecordingLine    = FALSE;
  1819.  
  1820.                     PushStatus(STATUS_RECORDING);
  1821.  
  1822.                     OnItem(MEN_RECORD_LINE);
  1823.  
  1824.                     CheckItem(MEN_RECORD,TRUE);
  1825.                     CheckItem(MEN_RECORD_LINE,FALSE);
  1826.                 }
  1827.             }
  1828.         }
  1829.     }
  1830.  
  1831.         /* Reply to the messages that started the
  1832.          * dialing process.
  1833.          */
  1834.  
  1835.     DispatchRexxDialMsgList(Online);
  1836.  
  1837.         /* Release the serial device driver if necessary. */
  1838.  
  1839.     if(ReleaseSerialDevice)
  1840.         RunJob(OwnDevUnitJob);
  1841.  
  1842.         /* Release the backup data. */
  1843.  
  1844.     FreeVecPooled(OriginalSerialConfig);
  1845.     OriginalSerialConfig = NULL;
  1846.  
  1847.     FreeVecPooled(OriginalModemConfig);
  1848.     OriginalModemConfig = NULL;
  1849.  
  1850.         /* Exit and tell the caller if control should pass
  1851.          * back to the phonebook control panel.
  1852.          */
  1853.  
  1854.     return(ReturnToPhonebook);
  1855. }
  1856.