(*----------------------------------------------------------------------*)
(*                PibDialer --- Dialing Management                      *)
(*----------------------------------------------------------------------*)

OVERLAY PROCEDURE PibDialer( ReDial         : BOOLEAN;
                             Dialing_String : AnyStr );

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  PibDialer                                            *)
(*                                                                      *)
(*     Purpose:    Main routine for dials/redials                       *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        PibDialer( ReDial         : BOOLEAN;                          *)
(*                   Dialing_String : AnyStr );                         *)
(*                                                                      *)
(*           ReDial --- TRUE for redial, FALSE for ordinary dial        *)
(*           Dialing_String --- if not null, use this as number to      *)
(*                              be dialed.                              *)
(*                                                                      *)
(*     Calls:                                                           *)
(*                                                                      *)
(*           Dial_A_Number                                              *)
(*           Redial_A_Number                                            *)
(*                                                                      *)
(*    Remarks:                                                          *)
(*                                                                      *)
(*        This routine exists solely to route calls to Dial_A_Number    *)
(*        and Redial_A-Number.  This setup is used so that the Turbo    *)
(*        Pascal overlay scheme will work correctly.                    *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   Local_Save_4   : Saved_Screen_Ptr;
   Session_Active : BOOLEAN;
   Xpos1          : INTEGER;
   Manual_Dial    : BOOLEAN;
   Quit           : BOOLEAN;

(*----------------------------------------------------------------------*)
(*          Dialer_Carrier_Detect --- Look for carrier detect           *)
(*----------------------------------------------------------------------*)

FUNCTION Dialer_Carrier_Detect : BOOLEAN;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Function:  Dialer_Carrier_Detect                                 *)
(*                                                                      *)
(*     Purpose:   Looks for a carrier detect                            *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Carrier := Dialer_Carrier_Detect;                             *)
(*                                                                      *)
(*           Carrier  --- TRUE if carrier detect found                  *)
(*                                                                      *)
(*     Calls:                                                           *)
(*                                                                      *)
(*        Async_Carrier_Detect;                                         *)
(*                                                                      *)
(*     Remarks:                                                         *)
(*                                                                      *)
(*        This routine is essentially a filter for Async_Carrier_Detect *)
(*        except that if the global flag Modem_Carrier_High is set, it  *)
(*        returns FALSE.  This is to support modems which always keep   *)
(*        the carrier detect line high.                                 *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

BEGIN (* Dialer_Carrier_Detect *)

   IF Modem_Carrier_High THEN
      Dialer_Carrier_Detect := FALSE
   ELSE
      Dialer_Carrier_Detect := Async_Carrier_Detect;

END   (* Dialer_Carrier_Detect *);

(*----------------------------------------------------------------------*)
(*          Read_Number_Or_ESC --- Read in number or get escape         *)
(*----------------------------------------------------------------------*)

PROCEDURE Read_Number_Or_ESC(     Ch        : CHAR;
                                  Xpos      : INTEGER;
                              VAR SNumber   : AnyStr;
                              VAR P_Str     : AnyStr;
                              VAR Esc_Found : BOOLEAN;
                              VAR Number    : INTEGER );

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Read_Number_Or_ESC                                   *)
(*                                                                      *)
(*     Purpose:    Reads in number and reports if escape hit.           *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Read_Number_Or_ESC(     Ch        : CHAR;                     *)
(*                                Xpos      : INTEGER;                  *)
(*                            VAR Snumber   : AnyStr;                   *)
(*                            VAR P_Str     : AnyStr;                   *)
(*                            VAR Esc_Found : BOOLEAN;                  *)
(*                            VAR Number    : INTEGER );                *)
(*                                                                      *)
(*           Ch        --- First character in number (input)            *)
(*           XPos      --- First column of answer                       *)
(*           Snumber   --- Full number if found                         *)
(*           P_Str     --- Prefix string if any found                   *)
(*           Esc_Found --- Escape encountered                           *)
(*           Number    --- Resultant number                             *)
(*                                                                      *)
(*     Calls:                                                           *)
(*                                                                      *)
(*        Menu_Beep                                                     *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   IX      : INTEGER;
   IY      : INTEGER;
   Ierr    : INTEGER;

BEGIN (* Read_Number_Or_ESC *)

                                   (* Initialize arguments         *)
   ESC_Found := FALSE;
   SNumber   := '';
   P_Str     := '';
   Number    := 0;
                                   (* Loop over input and pick up   *)
                                   (* number, possibly with dialing *)
                                   (* prefix, or ESC.               *)
   REPEAT

      IF ( Ch <> CHR( CR ) ) AND ( Ch <> ';' ) THEN
         BEGIN (* Not CR *)

            IF Ch = ^H THEN
               BEGIN  (* Backspace *)
                  IF WhereX > Xpos THEN
                     BEGIN
                        IY := WhereX;
                        GoToXY( IY - 1 , WhereY );
                        WRITE(' ');
                        GoToXY( IY - 1 , WhereY );
                        IF LENGTH( Snumber ) > 1 THEN
                           Snumber := COPY( Snumber, 2, LENGTH( Snumber ) - 1 )
                        ELSE
                           Snumber := '';
                     END;
               END   (* Backspace *)
            ELSE IF ( Ch = CHR( ESC ) ) THEN
               BEGIN  (* Escape found *)
                  ESC_Found := TRUE;
                  Snumber   := '';
               END    (* Escape found *)
            ELSE
               BEGIN
                  Snumber := Snumber + Ch;
                  WRITE( Ch );
               END;

            IF ( NOT ESC_Found ) THEN
               READ( Kbd, Ch );

         END (* Not CR *);

   UNTIL ( Ch = CHR( CR ) ) OR ( Ch = ';' ) OR ESC_Found;

                                   (* No number entered -- quit *)

   IF ( LENGTH( Snumber ) <= 0 ) OR ( ESC_Found ) THEN EXIT;

                                   (* Remove prefix if any *)

   IF Snumber[1] IN ['+','-','!','@','#'] THEN
      BEGIN
         P_Str      := Phone_Prefix_Nos[ POS( Snumber[1], '+-!@#' ) ];
         Snumber    := COPY( Snumber, 2, LENGTH( Snumber ) - 1 );
      END;
                                   (* Convert number *)
   Number := 0;
   Ierr   := 0;

   FOR IX := 1 TO LENGTH( Snumber ) DO
      IF Snumber[IX] IN ['0'..'9'] THEN
         Number := Number * 10 + ORD( Snumber[IX] ) - ORD('0')
      ELSE IF UpCase( Snumber[IX] ) <> 'M' THEN
         Ierr := 1;
                                   (* If bad, beep and ignore. *)
   IF ( Ierr > 0 ) THEN
      BEGIN
         Menu_Beep;
         EXIT;
      END;

END   (* Read_Number_Or_ESC *);

(*----------------------------------------------------------------------*)
(*    Reset_Comm_Params --- Reset comm. parms. from dialing entry       *)
(*----------------------------------------------------------------------*)

PROCEDURE Reset_Comm_Params( Phone_Entry_Data: Phone_Number_Record ) ;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Reset_Comm_Params                                    *)
(*                                                                      *)
(*     Purpose:    Resets communications parameters (baud,parity,bits)  *)
(*                 according to selected dialing directory entry.       *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Reset_Comm_Params( Phone_Entry_Data: Phone_Number_Record );   *)
(*                                                                      *)
(*           Phone_Entry_Data --- data record for a dialing entry       *)
(*                                                                      *)
(*     Calls:                                                           *)
(*                                                                      *)
(*        Async_Reset_Port                                              *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   Qerr: BOOLEAN;
   S:    ShortStr;
   I:    INTEGER;
   J:    INTEGER;

BEGIN (* Reset_Comm_Params *)

   WITH Phone_Entry_Data DO
      BEGIN

         S := Phone_Baud;

         I := 0;

         FOR J := 1 TO LENGTH( S ) DO
            IF S[J] IN ['0'..'9'] THEN
               I := I * 10 + ORD( S[J] ) - ORD('0');

         Baud_Rate := I;

         Parity := Phone_Parity;

         Data_Bits := ORD( Phone_DataBits ) - ORD('0');

         Stop_Bits := ORD( Phone_StopBits ) - ORD('0');

         Async_Reset_Port( Comm_Port, Baud_Rate,
                           Parity, Data_Bits, Stop_Bits );

      END;

END   (* Reset_Comm_Params *);

(*----------------------------------------------------------------------*)
(*         Display_Phone_Numbers --- display dialing directory          *)
(*----------------------------------------------------------------------*)

PROCEDURE Display_Phone_Numbers( VAR Phone_Number: AnyStr;
                                 VAR Prefix_Str  : AnyStr;
                                 VAR Esc_Hit     : BOOLEAN );

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Display_Phone_Numbers                                *)
(*                                                                      *)
(*     Purpose:    Displays dialing directory and prompts for # to dial *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Display_Phone_Numbers( VAR Phone_Number: AnyStr;              *)
(*                               VAR Prefix_Str  : AnyStr;              *)
(*                               VAR Esc_Hit     : BOOLEAN );           *)
(*                                                                      *)
(*           Phone_Number --- phone number to dial (if any)             *)
(*           Prefix_Str   --- prefix string to use                      *)
(*           Esc_Hit      --- TRUE if ESC hit to exit dialing           *)
(*                                                                      *)
(*     Calls:   Display_Directory_Page                                  *)
(*              Save_Screen                                             *)
(*              Restore_Screen                                          *)
(*              Draw_Menu_Frame                                         *)
(*              Reset_Global_Colors                                     *)
(*              Dialer_Carrier_Detect                                   *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

CONST
   N_nos = 15                      (* No. of phone numbers displayed *);

VAR
   Phone_Entries: ARRAY[ 1 .. N_Nos ] OF Phone_Number_Record;
   Fixed_Entry  : Phone_Number_Record;
   Low_Num      : INTEGER;
   Hi_Num       : INTEGER;
   Done         : BOOLEAN;
   I            : INTEGER;
   J            : INTEGER;
   L            : INTEGER;
   Dial_Func    : CHAR;
   Snumber      : STRING[40];
   Local_Save   : Saved_Screen_Ptr;
   Local_Save_2 : Saved_Screen_Ptr;
   Local_Save_3 : Saved_Screen_Ptr;
   Qerr         : BOOLEAN;
   XPos         : INTEGER;
   YPos         : INTEGER;
   ReDraw       : BOOLEAN;

(*----------------------------------------------------------------------*)
(*   Display_Directory_Page --- display a page of phone directory       *)
(*----------------------------------------------------------------------*)

PROCEDURE Display_Directory_Page;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Display_Directory_Page                               *)
(*                                                                      *)
(*     Purpose:    Displays one page of dialing directory               *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Display_Directory_Page;                                       *)
(*                                                                      *)
(*     Calls:   None                                                    *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

BEGIN (* Display_Directory_Page *)
                                   (* Get to first line of display *)
   GoToXY( 1 , 1 );
                                   (* Pick up phone numbers        *)
   L      := 0;

   FOR I := Low_Num TO Hi_Num DO
      BEGIN
            (*$I-*)
         SEEK( Phone_File , I - 1 );
            (*$I+*)
         IF Int24Result = 0 THEN
            BEGIN
               L      := L + 1;
               READ( Phone_File , Phone_Entries[ L ] );
            END;
      END;

                                   (* Display entries              *)

   RvsVideoOn( ForeGround_Color , BackGround_Color );

   FOR I := 1 TO L DO
      WITH Phone_Entries[I] DO
         BEGIN
            J := Low_Num + I - 1;
            WRITELN( J:3, '  ',  Phone_Name:25,  '  ',  Phone_Number:15,
                          '   ', Phone_Baud:5,   '    ', Phone_DataBits:1,
                          '      ', Phone_Parity:1, '     ', Phone_StopBits:1 );
            RvsVideoOff( ForeGround_Color , BackGround_Color );
         END;
                                   (* Blank out any remaining lines *)
   FOR I := ( L + 1 ) TO N_Nos DO
      BEGIN
         GoToXY( 1 , I );
         ClrEol;
      END;

END   (* Display_Directory_Page *);

(*----------------------------------------------------------------------*)
(*          Revise_Phone_Entry --- Revise phone directory entry         *)
(*----------------------------------------------------------------------*)

PROCEDURE Revise_Phone_Entry;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Revise_Phone_Entry                                   *)
(*                                                                      *)
(*     Purpose:    Handles revision of dialing directory entry          *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Revise_Phone_Entry;                                           *)
(*                                                                      *)
(*     Calls:   Save_Screen                                             *)
(*              Draw_Menu_Frame                                         *)
(*              Save_Screen                                             *)
(*              Restore_Screen                                          *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   J:    INTEGER;
   Quit: BOOLEAN;
   Ch  : CHAR;

BEGIN (* Revise_Phone_Entry *)
                                   (* Get number to revise *)
   Save_Screen( Local_Save_2 );

   Window( 1, 1, 80, 25 );

   Draw_Menu_Frame( 10, 2, 51, 6, Menu_Frame_Color,
                    Menu_Text_Color, 'Revise Dialing Entry');

   Quit := FALSE;
                                   (* Request the entry number *)

   WRITE('Entry to revise ? ');
   READ( Kbd , Ch );

   Read_Number_Or_ESC( Ch , WhereX - 1, SNumber, Prefix_Str, Quit, J );

                                   (* Exit if none entered *)
   IF  ( Quit OR ( J <= 0 ) ) THEN
      BEGIN
         Restore_Screen( Local_Save_2 );
         EXIT;
      END;
                                   (* Look for it on file  *)
       (*$I-*)
   SEEK( Phone_File , J - 1 );
       (*$I+*)
                                   (* If not found, quit revision *)
   IF Int24Result <> 0 THEN
      BEGIN
         WRITELN;
         WRITELN('No such entry.');
         DELAY( Two_Second_Delay );
      END
   ELSE                            (* Otherwise pick up entry's data *)
      BEGIN (* Entry exists *)

         READ( Phone_File , Fixed_Entry );

         Restore_Screen( Local_Save_2 );

                                   (* Bring up revision window *)
         Save_Screen( Local_Save_2 );

         Window( 1, 1, 80, 25 );

         Draw_Menu_Frame( 10, 2, 51, 23, Menu_Frame_Color,
                          Menu_Text_Color, 'Revise Dialing Entry ');

         Window( 11, 3, 50, 22 );
                                   (* Read in revisions *)
         WITH Fixed_Entry DO
            BEGIN  (* Get revisions *)

               GoToXY ( 2 , 2 );
               WRITELN('Old Name: ', Phone_Name );

               GoToXY( 2 , 3 );
               WRITE ('New Name: ');
               READLN( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  CopyStoA( Snumber , Phone_Name , 25 );

               GoToXY ( 2 , 5 );
               WRITELN('Old Number: ', Phone_Number );

               GoToXY( 2 , 6 );
               WRITE ('New Number: ');
               READLN( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  CopyS2AR( Snumber , Phone_Number , 15 );

               GoToXY( 2 , 8 );
               WRITELN('Old Baud Rate: ', Phone_Baud );

               GoToXY( 2 , 9 );
               WRITE ('New Baud Rate: ');
               READLN( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  CopyS2AR( Snumber , Phone_Baud, 5 );

               GoToXY( 2 , 11 );
               WRITELN('Old Parity: ', Phone_Parity );

               GoToXY( 2 , 12 );
               WRITE ('New Parity: ');
               READLN( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  IF UpCase( Snumber[1] ) IN ['E','O','N'] THEN
                     Phone_Parity := UpCase(Snumber[1]);

               GoToXY ( 2 , 14 );
               WRITELN('Old Data Bits: ', Phone_DataBits );

               GoToXY ( 2 , 15 );
               WRITE  ('New Data Bits: ');
               READLN ( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  IF Snumber[1] IN ['5'..'8'] THEN
                     Phone_DataBits := Snumber[1];

               GoToXY( 2 , 17 );
               WRITELN('Old Stop Bits: ', Phone_StopBits );

               GoToXY( 2 , 18 );
               WRITE  ('New Stop Bits: ');
               READLN( Snumber );

               IF LENGTH( Snumber ) > 0 THEN
                  IF Snumber[1] IN ['1'..'2'] THEN
                     Phone_StopBits := Snumber[1];

                                   (* Write revised entry back to *)
                                   (* phone directory file        *)

               SEEK ( Phone_File , J - 1 );
               WRITE( Phone_File , Fixed_Entry );

               Restore_Screen( Local_Save_2 );

            END (* Get Revisions *);

      END (* Entry exists *);

END   (* Revise_Phone_Entry *);

(*----------------------------------------------------------------------*)
(*            Revise_Dialing_Prefix --- Revise dialing prefix           *)
(*----------------------------------------------------------------------*)

PROCEDURE Revise_Dialing_Prefix;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Revise_Dialing_Prefix                                *)
(*                                                                      *)
(*     Purpose:    Handles revision of dialing prefix or setting of     *)
(*                 default prefix.                                      *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Revise_Dialing_Prefix;                                        *)
(*                                                                      *)
(*     Calls:   Save_Screen                                             *)
(*              Draw_Menu_Frame                                         *)
(*              Save_Screen                                             *)
(*              Restore_Screen                                          *)
(*              Get_New_Dialing_Prefix                                  *)
(*              Get_New_Default_Prefix                                  *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   Prefix_Menu  : Menu_Type;

(*----------------------------------------------------------------------*)

PROCEDURE Get_New_Dialing_Prefix;

VAR
   I:       INTEGER;
   Done:    BOOLEAN;
   Pchar:   CHAR;
   Changed: BOOLEAN;

BEGIN (* Get_New_Dialing_Prefix *)

                                   (* Bring up revision window *)
   Save_Screen( Local_Save_2 );

   Window( 1, 1, 80, 25 );

   Draw_Menu_Frame( 10, 2, 65, 10, Menu_Frame_Color,
                    Menu_Text_Color, 'Revise Dialing Prefix');

   Window( 11, 3, 64, 9 );

   Done    := FALSE;
   Changed := FALSE;

   REPEAT

      GoToXY( 1 , 2 );

      FOR I := 1 TO Max_Phone_Prefixes DO
         BEGIN
            ClrEol;
            WRITELN( ' ', Phone_Prefix_Chars[I], ' = ', Phone_Prefix_Nos[I] );
         END;

      WRITELN(' ');

      REPEAT
         GoToXY( 2 , WhereY );
         WRITE('Enter prefix character to revise: ');
         ClrEol;
         READ( Kbd, Pchar );
         IF NOT ( Pchar IN ['+','-','!','@','#',CHR(CR)] ) THEN
            Menu_Beep;
      UNTIL( Pchar IN ['+','-','!','@','#',CHR(CR)] );

      IF Pchar <> CHR(CR) THEN
         BEGIN

            GoToXY( 2 , WhereY );
            WRITE('Enter new prefix for ',Pchar,':');
            ClrEol;

            READLN( Snumber );

            Phone_Prefix_Nos[ POS( Pchar , '+-!@#' ) ] := Snumber;

            Changed := TRUE;

         END
      ELSE
         Done := TRUE;

   UNTIL( Done );
                                   (* Rewrite prefix file if changed *)

   IF Changed THEN
      BEGIN

         ASSIGN( Phone_Prefix_File , Home_Dir + 'PIBTERM.PRE' );
                   (*$I-*)
         REWRITE( Phone_Prefix_File );
                   (*$I+*)

         ClrScr;

         IF Int24Result <> 0 THEN
            WRITELN(' Can''t create revised PIBTERM.PRE')
         ELSE
            BEGIN

               WRITELN(' Writing revised PIBTERM.PRE -- phone prefix file.');

               FOR I := 1 TO Max_Phone_Prefixes DO
                  WRITELN( Phone_Prefix_File , Phone_Prefix_Nos[ I ] );

               CLOSE( Phone_Prefix_File );

            END;

         DELAY( Two_Second_Delay );

      END;

   Restore_Screen( Local_Save_2 );

END   (* Get_New_Dialing_Prefix *);

(*----------------------------------------------------------------------*)

PROCEDURE Get_New_Default_Prefix;

VAR
   Done:  BOOLEAN;
   Pchar: CHAR;

BEGIN (* Get_New_Default_Prefix *)
                                   (* Bring up revision window *)
   Save_Screen( Local_Save_2 );

   Window( 1, 1, 80, 25 );

   Draw_Menu_Frame( 10, 10, 65, 15, Menu_Frame_Color,
                    Menu_Text_Color, 'Set Default Dialing Prefix');

   Window( 11, 11, 64, 14 );

   Done := FALSE;

   REPEAT
      GoToXY( 1 , WhereY );
      WRITE('Enter default prefix character: ');
      ClrEol;
      READ( Kbd, Pchar );
      WRITE( Pchar );
      IF NOT ( Pchar IN ['+','-','!','@','#',CHR(CR)] ) THEN
         Menu_Beep;
   UNTIL( Pchar IN ['+','-','!','@','#',CHR(CR)] );

   IF Pchar <> CHR(CR) THEN
      Default_Prefix := Pchar
   ELSE
      Default_Prefix := ' ';

   DELAY( One_Second_Delay );

   Restore_Screen( Local_Save_2 );

END   (* Get_New_Default_Prefix *);

(*----------------------------------------------------------------------*)

BEGIN (* Revise_Dialing_Prefix *)
                                   (* Bring up revision menu *)
   WITH Prefix_Menu DO
      BEGIN

         Menu_Size    := 2;
         Menu_Default := 1;
         Menu_Row     := 11;
         Menu_Column  := 30;
         Menu_Tcolor  := Menu_Text_Color;
         Menu_Bcolor  := BackGround_Color;
         Menu_Fcolor  := Menu_Frame_Color;
         Menu_Width   := 0;
         Menu_Height  := 0;

      END (* WITH Prefix_Menu *);

   FOR I := 1 TO 2 DO
      WITH Prefix_Menu.Menu_Entries[I] DO
      BEGIN
         Menu_Item_Row    := I;
         Menu_Item_Column := 2;
         CASE I OF
            1:  Menu_Item_Text := 'Revise prefix string';
            2:  Menu_Item_Text := 'Set default prefix';
         END (* CASE *);
      END;

   Prefix_Menu.Menu_Title := 'Choose prefix revision function:';

   Menu_Display_Choices( Prefix_Menu );

   CASE Menu_Get_Choice( Prefix_Menu , Erase_Menu ) OF
      1: Get_New_Dialing_Prefix;
      2: Get_New_Default_Prefix;
   END (* Case *);

END   (* Revise_Dialing_Prefix *);

(*----------------------------------------------------------------------*)
(*            Clear_Dialing_Entry --- Clear dialing entry               *)
(*----------------------------------------------------------------------*)

PROCEDURE Clear_Dialing_Entry;

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Clear_Dialing_Entry                                  *)
(*                                                                      *)
(*     Purpose:    Clear out entry in dialing directory                 *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Clear_Dialing_Entry;                                          *)
(*                                                                      *)
(*     Calls:   CopySToA                                                *)
(*              Menu_Beep                                               *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

BEGIN (* Clear_Dialing_Entry *)

                                   (* Bring up clear entry window *)
   Save_Screen( Local_Save_2 );

   Window( 1, 1, 80, 25 );

   Draw_Menu_Frame( 10, 2, 65, 5, Menu_Frame_Color,
                    Menu_Text_Color, 'Clear Entry');

   Window( 11, 3, 64, 4 );

   GoToXY( 1 , 1 );
                                   (* Get entry to clear out *)

   WRITE('Enter # of entry to clear: ');
      (*$I-*)
   READLN( Snumber );
      (*$I+*)

   VAL( Snumber, I, J );
                                   (* Check if legitimate *)
   IF ( J = 0 ) AND
      ( I > 0 ) AND ( I < Default_Phone_Number_Size ) THEN
      BEGIN
                                   (* If so, clear it     *)
         WITH Phone_Entry_Data DO
            BEGIN

               CopyStoA( Dupl( '-' , 25 ) , Phone_Name ,   25 );
               CopyStoA( ' # ### ###-####' , Phone_Number , 15 );

               Phone_Parity   := ' ';
               Phone_Baud     := ' ----';
               Phone_DataBits := ' ';
               Phone_StopBits := ' ';

            END;

         SEEK ( Phone_File , I - 1 );
         WRITE( Phone_File , Phone_Entry_Data );

      END
   ELSE
      Menu_Beep;

   Restore_Screen( Local_Save_2 );

END   (* Clear_Dialing_Entry *);

(*----------------------------------------------------------------------*)
(*            Extract_Dialing_Entry --- Get number to dial              *)
(*----------------------------------------------------------------------*)

PROCEDURE Extract_Dialing_Entry( I: INTEGER );

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Procedure:  Extract_Dialing_Entry                                *)
(*                                                                      *)
(*     Purpose:    Read entry from dialing directory file               *)
(*                                                                      *)
(*     Calling Sequence:                                                *)
(*                                                                      *)
(*        Extract_Dialing_Entry( I : INTEGER );                         *)
(*                                                                      *)
(*           I --- If  > 0, then entry to dial;                         *)
(*                 If <= 0, then get entry from input.                  *)
(*                                                                      *)
(*     Calls:   Reset_Comm_Params                                       *)
(*                                                                      *)
(*     Remarks:                                                         *)
(*                                                                      *)
(*        The current communications parameters are reset to match      *)
(*        present in the selected dialing directory entry.              *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

VAR
   OK_Number: BOOLEAN;
   Ch       : CHAR;
   IX       : INTEGER;
   IY       : INTEGER;
   Quit     : BOOLEAN;
   Use_DP   : BOOLEAN;

BEGIN (* Extract_Dialing_Entry *)
                                   (* Initialize dialing entry *)
   Snumber    := '';
   Prefix_Str := '';

   Quit       := FALSE;
   Use_DP     := FALSE;
                                   (* We entered with first character *)
                                   (* in Dial_Func if I <= 0.         *)

   IF I <= 0 THEN
      Read_Number_Or_ESC( Dial_Func, Xpos, SNumber, Prefix_Str, Quit, I )
   ELSE
      Use_DP := Default_Prefix <> ' ';


                                   (* No number entered -- quit *)
   IF ( Quit OR ( I <= 0 ) ) THEN EXIT;

                                   (* Extract phone number from directory *)
      (*$I-*)
   SEEK( Phone_File , I - 1 );
      (*$I+*)

   IF ( Int24Result <> 0 ) THEN EXIT;

   READ( Phone_File , Phone_Entry_Data );

   Phone_Number := Phone_Entry_Data.Phone_Number;

                                   (* Use default dialing prefix if       *)
                                   (* number is > 7 digits.               *)
   IF Use_DP THEN
      BEGIN
         IX := 0;
         FOR I := 1 TO LENGTH( Phone_Number ) DO
            IF ( Phone_Number[I] IN ['0'..'9'] ) THEN
               IX := IX + 1;
         IF ( IX > 7 ) THEN
            Prefix_Str := Phone_Prefix_Nos[ POS( Default_Prefix, '+-!@#' ) ];
      END;

   Done := TRUE;
                                   (* If session not already in progress, *)
                                   (* change comm parms to match dialing  *)
                                   (* directory entry.                    *)

   IF ( NOT Dialer_Carrier_Detect ) THEN
      Reset_Comm_Params( Phone_Entry_Data );

END   (* Extract_Dialing_Entry *);

(*----------------------------------------------------------------------*)
(*     Do_Manual_Dial --- Get number to dial from keyboard entry        *)
(*----------------------------------------------------------------------*)

FUNCTION Do_Manual_Dial : BOOLEAN;

VAR
   Local_Save_5 : Saved_Screen_Ptr;
   Ch           : CHAR;
   Quit         : BOOLEAN;
   J            : INTEGER;

BEGIN (* Do_Manual_Dial *)

   Save_Screen( Local_Save_5 );

   Window( 1, 1, 80, 25 );

   Draw_Menu_Frame( 10, 10, 65, 13, Menu_Frame_Color,
                    Menu_Text_Color, 'Manual Dial');

   Window( 11, 11, 64, 12 );

   GoToXY( 1 , 1 );

   Prefix_Str := '';
   SNumber    := '';

   WRITE('Number to dial? ');
   READ( Kbd , Ch );

   Read_Number_Or_ESC( Ch , WhereX - 1, SNumber, Prefix_Str, Quit, J );

   Restore_Screen( Local_Save_5 );

   IF ( NOT Quit ) AND ( LENGTH( Snumber ) > 0 ) THEN
      BEGIN
         Phone_Number   := SNumber;
         Do_Manual_Dial := TRUE;
         Manual_Dial    := TRUE;
      END
   ELSE
      Do_Manual_Dial := FALSE;

END   (* Do_Manual_Dial *);


(*----------------------------------------------------------------------*)
(*     Get_List_Of_Phone_Numbers --- Get up to 5 entries to dial        *)
(*----------------------------------------------------------------------*)

PROCEDURE Get_List_Of_Phone_Numbers;

VAR
   No_Num  : BOOLEAN;
   N_Nos   : INTEGER;

BEGIN (* Get_List_Of_Phone_Numbers *)

   N_Nos := 1;

   WHILE ( ( N_Nos < Max_Dial_Numbers ) AND ( NOT No_Num ) ) DO
      BEGIN
         N_Nos := N_Nos + 1;
         WRITE('Enter phone number ',N_Nos,': ');
         GoToXY( 25, WhereY );
         Extract_Dialing_Entry( -1 );
         No_Num := ( Snumber = '' );
      END;

END   (* Get_List_Of_Phone_Numbers *);

(*----------------------------------------------------------------------*)


BEGIN (* Display_Phone_Numbers *)

                                   (* Save dialing box screen *)
   Save_Screen( Local_Save );
                                   (* Get back whole screen as window *)
                                   (* for dialing display             *)
   Window( 1, 1, 80, 25 );

   ClrScr;

   Draw_Menu_Frame( 1, 1, 79, 25, Menu_Frame_Color,
                    Menu_Text_Color, 'Dialing Directory' );

   Window( 2, 2, 78, 24 );
                                   (* Display title                *)

   WRITELN('No.  --------- Name ----------',
           '  --- Number ---    -Baud- -Bits- -Par- -Stp- ');
   WRITELN(' ');

   Window( 2, 4, 78, 24 );

   GoToXY( 1 , N_Nos + 2 );
   TextColor( Menu_Frame_Color );
   WRITE  (' -->    R');
   TextColor( Menu_Text_Color );
   WRITE  (' Revise entry   ');
   TextColor( Menu_Frame_Color );
   WRITE  (' P');
   TextColor( Menu_Text_Color );
   WRITE  (' Revise prefix   ');
   TextColor( Menu_Frame_Color );
   WRITE  (' C');
   TextColor( Menu_Text_Color );
   WRITE  (' Clear entry');
   TextColor( Menu_Frame_Color );
   WRITE  ('    Q');
   TextColor( Menu_Text_Color );
   WRITELN(' Redial');

   TextColor( Menu_Frame_Color );
   WRITE  ('        PgUp/PgDn');
   TextColor( Menu_Text_Color );
   WRITE  (' Page');
   TextColor( Menu_Frame_Color );
   WRITE  ('    Esc');
   TextColor( Menu_Text_Color );
   WRITE  (' Exit        ');
   TextColor( Menu_Frame_Color );
   WRITE  ('   /');
   TextColor( Menu_Text_Color );
   WRITE  (' Scroll');
   TextColor( Menu_Frame_Color );
   WRITE  ('       H');
   TextColor( Menu_Text_Color );
   WRITELN(' Hang up');

   TextColor( Menu_Frame_Color );
   WRITE  ('        M ');
   TextColor( Menu_Text_Color );
   WRITE  ('Manual dial');
   TextColor( Menu_Frame_Color );
   WRITE  ('     Home ');
   TextColor( Menu_Text_Color );
   WRITE  ('First page ');
   TextColor( Menu_Frame_Color );
   WRITE  ('   End');
   TextColor( Menu_Text_Color );
   WRITELN(' Last page');

   WRITE  ('        Entry');
   WRITE  (' to dial     ');
   TextColor( Menu_Frame_Color );
   WRITE  ('ENTER ');
   TextColor( Menu_Text_Color );
   WRITELN('dials highlighted entry');

   Low_Num      := MIN( MAX( Phone_Entry_Page , 1 ) ,
                             Default_Phone_Number_Size );
   Hi_Num       := MIN( Low_Num + N_Nos - 1 , Default_Phone_Number_Size );
   Done         := FALSE;

   Esc_Hit      := FALSE;
   ReDraw       := TRUE;
                                   (* Display dialing directory until    *)
                                   (* explicit exit requested or a       *)
                                   (* phone number selected for dialing  *)
   REPEAT

      IF ReDraw THEN
         BEGIN
            Display_Directory_Page;
            GoToXY( 5 , N_Nos + 2 );
            XPos      := WhereX;
            YPos      := WhereY;
            Dial_Func := ' ';
         END;

      ReDraw    := TRUE;
                                   (* Read in dialing command *)
      GoToXY( Xpos, Ypos );

      FOR I := 1 TO 4 DO
         WRITE(' ');

      GoToXY( Xpos, Ypos );
                                   (* Get function to perform *)
      READ( KBD , Dial_Func );
      Dial_Func := UpCase( Dial_Func );

                                   (* Check for keypad key *)

      IF ( ORD( Dial_Func ) = ESC ) AND KeyPressed THEN
         BEGIN

            READ( KBD , Dial_Func );

            CASE ORD( Dial_Func ) OF

               PgUp:    Dial_Func := 'B';
               PgDn:    Dial_Func := 'F';
               U_Arrow: Dial_Func := 'U';
               D_Arrow: Dial_Func := 'D';
               End_Key: Dial_Func := 'E';
               Home:    Dial_Func := 'T';
               ELSE     Dial_Func := 'Z';

            END (* CASE *)

         END
                                   (* flag invalid letters *)

      ELSE IF( NOT ( Dial_Func IN ['C','R','P',^[,^H,'0'..'9','+','-','!','@',
                                   '#',' ',^M, 'M',';','H','Q' ] ) ) THEN
         Dial_Func := 'Z';

                                   (* Perform requested dialing command *)

      CASE Dial_Func OF

                                   (* Clear dialing entry        *)
         'C':     Clear_Dialing_Entry;

                                   (* Exit without dialing anything *)
         ^[ :     BEGIN
                     Done    := TRUE;
                     Esc_Hit := TRUE;
                  END;

                                   (* Display next page in directory *)

         'F':     IF Hi_Num < Default_Phone_Number_Size THEN
                     BEGIN
                        Low_Num := Hi_Num + 1;
                        Hi_Num  := MIN( Low_Num + N_Nos - 1 ,
                                        Default_Phone_Number_Size );
                     END;

                                   (* Display previous page in directory *)

         'B':     IF Low_Num > 1 THEN
                     BEGIN
                        Low_Num := MAX( Low_Num - N_Nos , 1 );
                        Hi_Num  := MIN( Low_Num + N_Nos - 1 ,
                                        Default_Phone_Number_Size );
                     END;

                                   (* Display first page in directory *)

         'T':     BEGIN
                     Low_Num := 1;
                     Hi_Num  := N_Nos;
                  END;

                                   (* Display last page in directory *)

         'E':     BEGIN
                     Hi_Num  := Default_Phone_Number_Size;
                     Low_Num := MAX( Hi_Num - N_Nos + 1 , 1 );
                  END;

         'U':     BEGIN (* Scroll up one line *)

                     Redraw := FALSE;

                     IF Low_Num > 1 THEN
                        BEGIN

                           Window( 2, 4, 78, N_Nos + 3 );

                                   (* Remove highlight from top line *)

                           GoToXY( 1 , 1 );

                           WITH Phone_Entries[1] DO
                              WRITELN( Low_Num:3, '  ',     Phone_Name:25,
                                                  '  ',     Phone_Number:15,
                                                  '   ',    Phone_Baud:5,
                                                  '    ',   Phone_DataBits:1,
                                                  '      ', Phone_Parity:1,
                                                  '     ',  Phone_StopBits:1 );

                                   (* Make room for new line *)

                           GoToXY( 1 , 1 );
                           InsLine;

                           Low_Num  := Low_Num  - 1;
                           Hi_Num   := Hi_Num   - 1;

                                   (* Move current entries up *)

                           MOVE( Phone_Entries[1], Phone_Entries[2],
                                 ( N_Nos - 1 ) * SizeOf( Phone_Entries[1] ) );

                                   (* Get data for new line *)

                              (*$I-*)
                           SEEK( Phone_File , Low_Num - 1 );
                              (*$I+*)
                           IF Int24Result = 0 THEN
                              READ( Phone_File , Phone_Entries[ 1 ] );

                                   (* Draw new line *)

                           RvsVideoOn( ForeGround_Color , BackGround_Color );

                           WITH Phone_Entries[1] DO
                              WRITELN( Low_Num:3, '  ',     Phone_Name:25,
                                                  '  ',     Phone_Number:15,
                                                  '   ',    Phone_Baud:5,
                                                  '    ',   Phone_DataBits:1,
                                                  '      ', Phone_Parity:1,
                                                  '     ',  Phone_StopBits:1 );
                           Window( 2, 4, 78, 24 );

                           RvsVideoOff( ForeGround_Color , BackGround_Color );

                        END;

                  END   (* Scroll up one line *);

         'D':     BEGIN (* Scroll down one line *)

                     Redraw := FALSE;

                     IF Hi_Num < Default_Phone_Number_Size THEN
                        BEGIN
                                   (* Make room for new line *)

                           Window( 2, 4, 78, N_Nos + 4 );

                           GoToXY( 1 , 1 );
                           DelLine;

                           Low_Num  := Low_Num + 1;
                           Hi_Num   := Hi_Num  + 1;

                                   (* Move current entries down *)

                           MOVE( Phone_Entries[2], Phone_Entries[1],
                                 ( N_Nos - 1 ) * SizeOf( Phone_Entries[1] ) );

                              (*$I-*)
                           SEEK( Phone_File , Hi_Num - 1 );
                              (*$I+*)
                           IF Int24Result = 0 THEN
                              READ( Phone_File , Phone_Entries[ N_Nos ] );

                           GoToXY( 1 , Hi_Num - Low_Num + 1 );

                           WITH Phone_Entries[ N_Nos ] DO
                              WRITELN( Hi_Num:3, '  ',     Phone_Name:25,
                                                 '  ',     Phone_Number:15,
                                                 '   ',    Phone_Baud:5,
                                                 '    ',   Phone_DataBits:1,
                                                 '      ', Phone_Parity:1,
                                                 '     ',  Phone_StopBits:1 );

                           RvsVideoOn( ForeGround_Color , BackGround_Color );

                           GoToXY( 1 , 1 );

                           WITH Phone_Entries[ 1 ] DO
                              WRITELN( Low_Num:3, '  ',     Phone_Name:25,
                                                  '  ',     Phone_Number:15,
                                                  '   ',    Phone_Baud:5,
                                                  '    ',   Phone_DataBits:1,
                                                  '      ', Phone_Parity:1,
                                                  '     ',  Phone_StopBits:1 );

                           RvsVideoOff( ForeGround_Color , BackGround_Color );

                           Window( 2, 4, 78, 23 );

                        END;

                  END   (* Scroll down one line *);

                                   (* Entry to dial *)

         '0'..'9', '+','-','!','@','#':

                  IF ( NOT Dialer_Carrier_Detect ) THEN
                     Extract_Dialing_Entry( -1 )
                  ELSE
                     BEGIN
                        Save_Screen( Local_Save_3 );
                        Window( 1, 1, 80, 25 );
                        Draw_Menu_Frame( 10, 10, 60, 14, Menu_Frame_Color,
                                         Menu_Text_Color + Blink, '' );
                        WRITELN('Session already in progress.');
                        WRITE  ('Dialing request ignored.');
                        DELAY( Two_Second_Delay );
                        Restore_Screen( Local_Save_3 );
                        TextColor( Menu_Text_Color );
                        ReDraw    := FALSE;
                     END;
                                   (* Revise/add a dialing entry *)

         'R':     Revise_Phone_Entry;

                                   (* Revise dialing prefix      *)

         'P':     BEGIN
                     Revise_Dialing_Prefix;
                     Redraw := FALSE;
                  END;
                                   (* Start a redial             *)

         'Q':     BEGIN
                     IF Phone_Number = '' THEN
                        Extract_Dialing_Entry( Low_Num );
                     Done   := TRUE;
                     ReDial := TRUE;
                  END;

                                   (* Ignore extraneous backspace *)
         ^H:      BEGIN
                     Redraw := FALSE;
                  END;

                                   (* Hang up the phone *)
         'H':     BEGIN

                     Redraw := FALSE;

                     Save_Screen( Local_Save_2 );

                     Draw_Menu_Frame( 10, 10, 60, 15, Menu_Frame_Color,
                                      Menu_Text_Color, '' );

                     WRITELN;
                     WRITELN('*** Hanging up the phone ***');

                                   (* Hang up the phone *)

                     HangUpPhone;

                     IF Async_Carrier_Detect THEN
                        WRITELN('*** Phone not hung up, try again ***')
                     ELSE
                        BEGIN
                           WRITELN('*** Phone hung up ***');
                           Qerr := Async_Open( Comm_Port, Baud_Rate,
                                               Parity, Data_Bits,
                                               Stop_Bits );
                        END;

                     DELAY( Two_Second_Delay );

                     Restore_Screen( Local_Save_2 );
                     TextColor( Menu_Text_Color );

                  END;

                                   (* Dial top number on screen *)
         ^M,
         ' ':     IF ( NOT Dialer_Carrier_Detect ) THEN
                     Extract_Dialing_Entry( Low_Num )
                  ELSE
                     BEGIN
                        Save_Screen( Local_Save_3 );
                        Window( 1, 1, 80, 25 );
                        Draw_Menu_Frame( 10, 10, 60, 14, Menu_Frame_Color,
                                         Menu_Text_Color + Blink, '' );
                        WRITELN('Session already in progress.');
                        WRITE  ('Dialing request ignored.');
                        DELAY( Two_Second_Delay );
                        Restore_Screen( Local_Save_3 );
                        TextColor( Menu_Text_Color );
                        ReDraw    := FALSE;
                     END;

                                   (* Manual dial *)
         'M':     BEGIN
                     Done   := Do_Manual_Dial;
                     ReDraw := FALSE;
                  END;

                                   (* ';' -- list of numbers given *)
         ';':     BEGIN
                     Save_Screen( Local_Save_3 );
                     Window( 1, 1, 80, 25 );
                     Draw_Menu_Frame( 10, 10, 60, 18, Menu_Frame_Color,
                                      Menu_Text_Color, 'Numbers to Dial' );
                     Get_List_Of_Phone_Numbers;
                     Restore_Screen( Local_Save_3 );
                     TextColor( Menu_Text_Color );
                     ReDraw    := FALSE;
                  END;
                                   (* Beep on anything else -- bad *)
         ELSE
            Menu_Beep;
            ReDraw := FALSE;

      END (* CASE *);

   UNTIL Done;
                                   (* Remember current dialing page *)

   Phone_Entry_Page := Low_Num;

                                   (* Restore dialing box *)
   Restore_Screen( Local_Save );
   Reset_Global_Colors;

END   (* Display_Phone_Numbers *);
