home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s4.arc / RECEIVX2.MOD < prev    next >
Text File  |  1988-03-23  |  28KB  |  748 lines

  1.  
  2. (*----------------------------------------------------------------------*)
  3.  
  4. BEGIN  (* Receive_Xmodem_File *)
  5.                                    (* Remember CRC checking *)
  6.    CRC_Used      := Use_CRC;
  7.                                    (* Pick up file name for title *)
  8.    XFile_Name    := FileName;
  9.                                    (* Get title for transfer *)
  10.    Get_Xmodem_Titles;
  11.                                    (* Initialize status display information *)
  12.    SOH_Errors     := 0;
  13.    BlockL_Errors  := 0;
  14.    BlockN_Errors  := 0;
  15.    Comple_Errors  := 0;
  16.    TimeOut_Errors := 0;
  17.    Resend_Errors  := 0;
  18.    CRC_Errors     := 0;
  19.    Display_Time   := FALSE;
  20.    Dup_Block      := FALSE;
  21.    G_Failure      := FALSE;
  22.  
  23.    Initialize_Receive_Display;
  24.                                    (* Current sector = 0 *)
  25.    Sector_Number  := 0;
  26.    Sector_Count   := 0;
  27.    Sector_Prev    := 0;
  28.    Sector_Length  := 128;
  29.                                    (* Overall error count = 0 *)
  30.    Error_Count    := 0;
  31.                                    (* CRC, WXModem tries *)
  32.    CRC_Tries      := 0;
  33.    WXM_Tries      := 0;
  34.                                    (* How long to wait for SOH *)
  35.  
  36.    SOH_Time       := Xmodem_Block_Wait;
  37.  
  38.                                    (* Assume file size not sent *)
  39.    Truncate_File  := FALSE;
  40.                                    (* Assume file size, date not sent *)
  41.    RFile_Size     := 0;
  42.    RFile_Size_2   := 0;
  43.    RFile_Date     := 0;
  44.    File_Date      := 0;
  45.    File_Time      := 0;
  46.                                    (* Figure if ACKs to be handled *)
  47.  
  48.    Do_ACKs        := ( Transfer_Protocol <> Ymodem_G   ) AND
  49.                      ( Transfer_Protocol <> Xmodem_1KG );
  50.  
  51.                                    (* Note if WXModem or SeaLink used *)
  52. {
  53.    Do_WXmodem     := ( Transfer_Protocol = WXModem );
  54.    Do_SeaLink     := ( Transfer_Protocol = SeaLink );
  55. }
  56.    Do_WXmodem     := FALSE;
  57.    Do_SeaLink     := FALSE;
  58.                                    (* Assume file name not sent *)
  59.    RFile_Name     := '';
  60.                                    (* Assume transfer fails *)
  61.    OK_Transfer    := FALSE;
  62.                                    (* Assume block 0 not found *)
  63.    Block_Zero     := FALSE;
  64.                                    (* Starting time  *)
  65.    Start_Time     := TimeOfDay;
  66.                                    (* User intervention flag *)
  67.    Alt_R_Pressed  := FALSE;
  68.                                    (* Serious error flag     *)
  69.    Stop_Receive   := FALSE;
  70.                                    (* Not null file name   *)
  71.    Null_File_Name := FALSE;
  72.                                    (* Allocate buffer if requested   *)
  73.                                    (* otherwise use sector data area *)
  74.                                    (* directly.                      *)
  75.  
  76.    IF ( Max_Write_Buffer > 1024 ) AND
  77.       ( Max_Write_Buffer < MaxAvail ) THEN
  78.       BEGIN
  79.          Buffer_Length  := ( ( MIN( Max_Write_Buffer , 31744 ) +
  80.                                1023 ) SHR 10 ) SHL 10;
  81.          Long_Buffer    := TRUE;
  82.          GetMem( Write_Buffer , Buffer_Length );
  83.          IF ( Write_Buffer = NIL ) THEN
  84.             BEGIN
  85.                Long_Buffer   := FALSE;
  86.                Buffer_Length := 1024;
  87.                Write_Buffer  := ADDR( Sector_Data );
  88.             END;
  89.       END
  90.    ELSE
  91.       BEGIN
  92.          Long_Buffer   := FALSE;
  93.          Buffer_Length := 1024;
  94.          Write_Buffer  := ADDR( Sector_Data );
  95.       END;
  96.                                    (* Determine block starter characters *)
  97.  
  98.    Block_Start_Set := [ ^A, ^B, ^D, ^V, ^X ];
  99.  
  100.                                    (* No blocks being flushed currently  *)
  101.    Flush_Count    := 0;
  102.                                    (* Empty write buffer   *)
  103.    Buffer_Pos     := 0;
  104.                                    (* Open reception file now if possible *)
  105.    RFile_Open     := FALSE;
  106.  
  107.    IF FileName <> '' THEN
  108.       BEGIN
  109.          Open_Receiving_File;
  110.          IF Stop_Receive THEN
  111.             BEGIN
  112.                Cancel_Transfer;
  113.                Window_Delay;
  114.                Restore_Screen_And_Colors( Saved_Screen );
  115.                EXIT;
  116.             END;
  117.       END;
  118.                                    (* Save Xon/Xoff status *)
  119.  
  120.    Save_XonXoff     := Async_Do_XonXoff;
  121.    Async_Do_XonXoff := Do_WXModem;
  122.  
  123.    Save_XonOV       := Async_OV_XonXoff;
  124.    Async_OV_XonXoff := Do_WXModem OR ( NOT Do_Acks );
  125.  
  126.                                    (* Begin XMODEM loop    *)
  127.    REPEAT
  128.                                    (* Reset error flag *)
  129.       Error_Flag := FALSE;
  130.       Dup_Block  := FALSE;
  131.                                    (* Look for SOH     *)
  132.       REPEAT
  133.  
  134.          IF ( ( Sector_Count = 0 ) AND ( WXM_Tries = 0 ) ) THEN
  135.             BEGIN  (* Initial handshake *)
  136.  
  137.                CRC_Used   := CRC_Used   AND ( CRC_Tries < 4 );
  138.                Do_WXModem := Do_WXModem AND ( WXM_Tries < 4 );
  139.  
  140.                                    (* Purge reception      *)
  141.                Async_Purge_Buffer;
  142.  
  143.                                    (* Indicate XMODEM type *)
  144.                IF Do_WXModem THEN
  145.                   BEGIN
  146.                      Async_Send( 'W' );
  147.                      INC( WXM_Tries );
  148.                   END
  149.                ELSE
  150.                   BEGIN
  151.                      IF ( NOT Do_ACKs ) THEN
  152.                         Async_Send( 'G' )
  153.                      ELSE
  154.                         IF CRC_Used THEN
  155.                            BEGIN
  156.                               Async_Send( 'C' );
  157.                            END
  158.                         ELSE
  159.                            BEGIN
  160.                               Async_Send( CHR( NAK ) );
  161.                            END;
  162.                      INC( CRC_Tries );
  163.                      IF Do_Sealink THEN
  164.                         BEGIN
  165.                            Async_Send( CHR( 1   ) );
  166.                            Async_Send( CHR( 254 ) );
  167.                         END;
  168.                   END;
  169.  
  170.                IF Display_Status THEN
  171.                   BEGIN
  172.  
  173.                      GoToXY( 1 , 8 );
  174.  
  175.                      TextColor( Menu_Text_Color_2 );
  176.  
  177.                      IF ( NOT CRC_Used ) THEN
  178.                         WRITELN(' Checksum errors      :')
  179.                      ELSE
  180.                         WRITELN(' CRC errors           :');
  181.  
  182.                      TextColor( Menu_Text_Color );
  183.  
  184.                   END;
  185.  
  186.             END   (* Initial handshake *);
  187.  
  188.          Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive );
  189.  
  190.                                    (* If CAN found, insist on    *)
  191.                                    (* at least two CANs in a row *)
  192.                                    (* before cancelling transfer *)
  193.  
  194.          IF ( Initial_Ch = CAN ) THEN
  195.             Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive )
  196.  
  197.                                    (* If EOT and windowing, insist *)
  198.                                    (* on at least two EOTs in a    *)
  199.                                    (* row before halting.          *)
  200.  
  201.          ELSE IF ( ( Initial_Ch = EOT ) AND
  202.                    ( Do_WXModem OR
  203.                      ( Do_SeaLink AND ( Sector_Count > 0 ) ) ) ) THEN
  204.             BEGIN
  205.                Async_Send( CHR( NAK ) );
  206.                Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive )
  207.             END
  208.          ELSE IF ( Initial_Ch = TimeOut ) THEN
  209.             BEGIN
  210.                IF ( Sector_Count > 0 ) THEN
  211.                   Async_Send( CHR( NAK ) );
  212.                Display_Receive_Error( 'Time out, no SOH');
  213.                INC( TimeOut_Errors );
  214.             END;
  215.                                    (* If WXmodem, leave Xon/Xoff on *)
  216.  
  217.          Async_Do_XonXoff := Do_WXModem;
  218.  
  219.                                    (* Update status display       *)
  220.          IF Display_Status THEN
  221.             Update_Xmodem_Receive_Display;
  222.  
  223.                                    (* Update status line *)
  224.          IF Do_Status_Line THEN
  225.             BEGIN
  226.                Set_Status_Line_Name( Short_Terminal_Name );
  227.                Write_To_Status_Line( Status_Line_Name, 1 );
  228.             END;
  229.  
  230.       UNTIL ( Initial_Ch = SOH                ) OR
  231.             ( Initial_Ch = EOT                ) OR
  232.             ( Initial_Ch = CAN                ) OR
  233.             ( Initial_Ch = SYN                ) OR
  234.             ( Initial_Ch = STX                ) OR
  235.             ( Error_Count > Xmodem_Max_Errors ) OR
  236.             ( Stop_Receive                    );
  237.  
  238.                                    (* Something wrong already -- *)
  239.                                    (* cancel the transfer.       *)
  240.       IF Stop_Receive THEN
  241.          BEGIN
  242.             IF NOT Async_Carrier_Detect THEN
  243.                BEGIN
  244.                   Display_Receive_Error('Carrier dropped');
  245.                   Window_Delay;
  246.                END;
  247.          END
  248.                                    (* Timed out -- no SOH found *)
  249.  
  250.       ELSE IF Initial_Ch = TimeOut THEN
  251.          BEGIN
  252.             Display_Receive_Error( 'Time out, no SOH');
  253.             INC( TimeOut_Errors );
  254.          END
  255.                                    (* SYN found -- possible Telink block *)
  256.                                    (*              or WXModem start      *)
  257.  
  258.       ELSE IF ( ( Initial_Ch = SYN ) AND Do_WXModem ) THEN
  259.          (* Do nothing and skip SYN *)
  260.  
  261.                                    (* SOH found -- start of XMODEM block *)
  262.                                    (* STX found -- start of Ymodem block *)
  263.                                    (* SYN found -- start of Telink block *)
  264.  
  265.       ELSE IF ( Initial_Ch = SOH ) OR
  266.               ( Initial_Ch = SYN ) OR
  267.               ( Initial_Ch = STX ) THEN
  268.          BEGIN (* SOH found *)
  269.                                    (* Pick up sector number *)
  270.  
  271.             IF Initial_Ch = STX THEN
  272.                Sector_Length := 1024
  273.             ELSE
  274.                Sector_Length := 128;
  275.  
  276.             IF Do_WXModem THEN
  277.                WXModem_Receive_With_TimeOut( Ch )
  278.             ELSE
  279.                Async_Receive_With_TimeOut( Xmodem_Char_Wait , Ch );
  280.  
  281.             IF Ch = TimeOut THEN
  282.                BEGIN
  283.                   INC( BlockL_Errors );
  284.                   Display_Receive_Error('Short block');
  285.                END;
  286.  
  287.             Sector_Number := Ch;
  288.  
  289.                                    (* Complement of sector number *)
  290.  
  291.             IF Do_WXModem THEN
  292.                WXModem_Receive_With_TimeOut( Ch )
  293.             ELSE
  294.                Async_Receive_With_TimeOut( Xmodem_Char_Wait , Ch );
  295.  
  296.             IF Ch = TimeOut THEN
  297.                BEGIN
  298.                   INC( BlockL_Errors );
  299.                   Display_Receive_Error('Short block');
  300.                END;
  301.  
  302.             Sector_Comp := Ch;
  303.  
  304.                                    (* See if they add up properly     *)
  305.  
  306.             IF ( ( Sector_Number + Sector_Comp ) = 255 ) THEN
  307.  
  308.                BEGIN  (* Sector number and complement match *)
  309.  
  310.                   Sector_Prev1 := SUCC( Sector_Prev );
  311.  
  312.                   Block_Zero   := ( Sector_Count  = 0 ) AND
  313.                                   ( Sector_Number = 0 ) AND
  314.                                   ( ( Initial_Ch  = SYN ) OR
  315.                                     ( Transfer_Protocol IN [Xmodem_1K,
  316.                                                             Xmodem_1KG,
  317.                                                             Ymodem_G,
  318.                                                             Ymodem_Batch
  319.                                                             {,SeaLink}] ) );
  320.  
  321.                   CRC_Used_2 := CRC_Used AND
  322.                                ( NOT ( Block_Zero AND
  323.                                        ( Transfer_Protocol = Telink ) ) );
  324.  
  325.                   IF ( Sector_Number = Sector_Prev1 ) OR Block_Zero THEN
  326.                      BEGIN  (* Correct sector found *)
  327.  
  328.                         IF Receive_Xmodem_Sector( CRC_Used_2 ) THEN
  329.                            IF ( NOT Block_Zero ) THEN
  330.                               BEGIN (* Checksum/CRC OK *)
  331.  
  332.                                  Write_File_Data;
  333.  
  334.                                  IF ( NOT Stop_Receive ) THEN
  335.                                     BEGIN
  336.  
  337.                                        Error_Count  := 0;
  338.  
  339.                                        Sector_Count := Sector_Count +
  340.                                                        ( Sector_Length SHR 7 );
  341.  
  342.                                        Sector_Prev := Sector_Number;
  343.  
  344.                                        IF Do_ACKs THEN
  345.                                           BEGIN
  346.                                              Async_Send( CHR( ACK ) );
  347.                                              IF Do_WXModem THEN
  348.                                                 Async_Send( CHR( Sector_Number AND 3 ) )
  349.                                              ELSE IF Do_SeaLink THEN
  350.                                                 BEGIN
  351.                                                    Async_Send( CHR( Sector_Number ) );
  352.                                                    Async_Send( CHR( Sector_Comp   ) );
  353.                                                 END;
  354.                                           END;
  355.  
  356.                                     END
  357.  
  358.                               END   (* Checksum/CRC OK *)
  359.                            ELSE (* Telink/Ymodem/SeaLink block 0 *)
  360.                               BEGIN
  361.  
  362.                                  IF ( Initial_Ch = SYN ) { OR
  363.                                     ( Transfer_Protocol = SeaLink ) } THEN
  364.                                     Receive_Telink_Header
  365.                                  ELSE IF ( Transfer_Protocol IN [Xmodem_1K,
  366.                                                                  Xmodem_1KG,
  367.                                                                  Ymodem_G,
  368.                                                                  Ymodem_Batch] ) THEN
  369.                                     Receive_Ymodem_Header;
  370.  
  371.                                  IF ( NOT Stop_Receive ) THEN
  372.                                     BEGIN
  373.                                        IF ( NOT Do_ACKs ) THEN
  374.                                           Async_Send( 'G' )
  375.                                        ELSE
  376.                                           Async_Send( CHR( ACK ) );
  377.                                        IF Do_WXModem THEN
  378.                                           Async_Send( CHR( Sector_Number AND 3 ) )
  379.                                        ELSE IF Do_SeaLink THEN
  380.                                           BEGIN
  381.                                              Async_Send( CHR( Sector_Number ) );
  382.                                              Async_Send( CHR( Sector_Comp   ) );
  383.                                           END;
  384.                                        Error_Count := 0;
  385.                                     END;
  386.  
  387.                               END
  388.                         ELSE
  389.                            BEGIN  (* Checksum/CRC error *)
  390.                               INC( CRC_Errors );
  391.                               IF CRC_Used THEN
  392.                                  Display_Receive_Error('CRC error')
  393.                               ELSE
  394.                                  Display_Receive_Error('Checksum error');
  395.                            END    (* Checksum/CRC error *)
  396.  
  397.                      END  (* Correct sector found *)
  398.  
  399.                   ELSE
  400.                      IF ( Sector_Number = Sector_Prev ) THEN
  401.                         BEGIN  (* Duplicate sector *)
  402.  
  403.                            BS_Flag := Receive_Xmodem_Sector( CRC_Used_2 );
  404.  
  405.                            IF Do_ACKs THEN
  406.                               BEGIN
  407.                                  Async_Send( CHR( ACK ) );
  408.                                  IF Do_WXModem THEN
  409.                                     Async_Send( CHR( Sector_Number AND 3 ) )
  410.                                  ELSE IF Do_SeaLink THEN
  411.                                     BEGIN
  412.                                        Async_Send( CHR( Sector_Number ) );
  413.                                        Async_Send( CHR( Sector_Comp   ) );
  414.                                     END;
  415.                               END;
  416.  
  417.                            Display_Receive_Error('Duplicate block');
  418.  
  419.                            INC( Resend_Errors );
  420.  
  421.                            Error_Flag := FALSE;
  422.                            Dup_Block  := TRUE;
  423.  
  424.                         END   (* Duplicate sector *)
  425.                      ELSE
  426.                         BEGIN (* Out of sequence sector *)
  427.                            BS_Flag := Receive_Xmodem_Sector( CRC_Used_2 );
  428.                            IF ( Flush_Count > 0 ) THEN
  429.                               BEGIN
  430.                                  DEC( Flush_Count );
  431.                                  Display_Receive_Error('Re-synchronizing ... ');
  432.                                  Error_Flag  := FALSE;
  433.                               END
  434.                            ELSE
  435.                               BEGIN
  436.                                  Display_Receive_Error('Synchronization error');
  437.                                  INC( BlockN_Errors );
  438.                               END;
  439.                         END   (* Out of sequence sector *);
  440.  
  441.                END   (* Sector # and complement match *)
  442.  
  443.             ELSE
  444.                BEGIN (* Sector # and complement do not match *)
  445.                   Display_Receive_Error('Sector number error');
  446.                   INC( Comple_Errors );
  447.                END   (* Sector # and complement do not match *);
  448.  
  449.          END (* SOH Found *)
  450.       ELSE IF ( Initial_Ch = EOT ) THEN
  451.          BEGIN
  452.             IF ( Do_SeaLink AND ( Sector_Count = 0 ) ) THEN
  453.                Null_File_Name := TRUE;
  454.          END
  455.       ELSE
  456.          BEGIN
  457.             Display_Receive_Error('SOH not found');
  458.             INC( SOH_Errors );
  459.          END;
  460.                                    (* Process bad blocks here *)
  461.       IF Error_Flag THEN
  462.          BEGIN
  463.                                    (* Increment error count *)
  464.             INC( Error_Count );
  465.                                    (* If not windowing, flush buffer. *)
  466.  
  467.             IF Do_Acks THEN
  468.                IF ( NOT ( Do_WXmodem OR Do_SeaLink ) ) THEN
  469.                      Async_Purge_Buffer;
  470.  
  471.                                    (* Send negative acknowledge to reject *)
  472.                                    (* bad sector.                         *)
  473.  
  474.             Async_Send( CHR( NAK ) );
  475.  
  476.                                    (* If windowing, skip remainder of this *)
  477.                                    (* sector, and set up to skip any left  *)
  478.                                    (* in this window.                      *)
  479.             IF Do_WXModem THEN
  480.                BEGIN
  481.                   Async_Send( CHR( Sector_Number AND 3 ) );
  482.                   Block_Start_Set := [ ^V ];
  483.                   Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive );
  484.                   Block_Start_Set := [ ^A, ^B, ^D, ^V, ^X ];
  485.                   Flush_Count := WXmodem_Flush;
  486.                END
  487.             ELSE IF Do_SeaLink THEN
  488.                BEGIN
  489.                   Async_Send( CHR( Sector_Number ) );
  490.                   Async_Send( CHR( 255 - Sector_Number ) );
  491.                   Flush_Count := SEALink_Flush;
  492.                END;
  493.                                    (* Cancel transfer for G-protocol guys *)
  494.  
  495.             IF ( NOT Do_ACKs ) THEN
  496.                BEGIN
  497.                   Stop_Receive := TRUE;
  498.                   G_Failure    := TRUE;
  499.                END;
  500.  
  501.          END;
  502.  
  503.       IF Display_Time THEN
  504.          BEGIN
  505.  
  506.             IF ( NOT ( Error_Flag OR Dup_Block ) ) THEN
  507.                BEGIN
  508.  
  509.                   Time_To_Send := ROUND( Saved_Time_To_Send *
  510.                                          ( 1.0 -
  511.                                            Sector_Count / Blocks_To_Send ) );
  512.  
  513.                   IF Time_To_Send < 0 THEN
  514.                      Time_To_Send := 0;
  515.  
  516.                END;
  517.  
  518.          END;
  519.                                    (* Check for keyboard entry    *)
  520.       Check_Keyboard;
  521.                                    (* Update status display       *)
  522.       IF Display_Status THEN
  523.          Update_Xmodem_Receive_Display;
  524.  
  525.    UNTIL ( Initial_Ch = EOT     ) OR
  526.          ( Initial_Ch = CAN     ) OR
  527.          ( Stop_Receive         ) OR
  528.          ( Null_File_Name       ) OR
  529.          ( Error_Count > Xmodem_Max_Errors );
  530. {
  531. IF Debug_Mode THEN
  532.    BEGIN
  533.       Write_Log('Receive_Xmodem', FALSE, FALSE );
  534.       IF Stop_Receive THEN
  535.          Write_Log('   Stop_Receive   = TRUE', FALSE, FALSE )
  536.       ELSE
  537.          Write_Log('   Stop_Receive   = FALSE', FALSE, FALSE );
  538.       IF Null_File_Name THEN
  539.          Write_Log('   Null_File_Name = TRUE', FALSE, FALSE )
  540.       ELSE
  541.          Write_Log('   Null_File_Name = FALSE', FALSE, FALSE );
  542.       IF Alt_R_Pressed THEN
  543.          Write_Log('   Alt_R_Pressed  = TRUE', FALSE, FALSE )
  544.       ELSE
  545.          Write_Log('   Alt_R_Pressed  = FALSE', FALSE, FALSE );
  546.       IF G_Failure THEN
  547.          Write_Log('   G_Failure      = TRUE', FALSE, FALSE )
  548.       ELSE
  549.          Write_Log('   G_Failure      = FALSE', FALSE, FALSE );
  550.       Write_Log('   Error_Count = ' + IToS( Error_Count ), FALSE, FALSE );
  551.       Write_Log('   Xmodem_Max  = ' + IToS( Xmodem_Max_Errors ), FALSE, FALSE );
  552.       Write_Log('   Initial_Ch  = ' + IToS( Initial_Ch ), FALSE, FALSE );
  553.    END;
  554. }
  555.                                    (* If serious error or Alt_R hit, *)
  556.                                    (* stop download.                 *)
  557.    IF ( Stop_Receive ) THEN
  558.       BEGIN
  559.  
  560.          Cancel_Transfer;
  561.  
  562.          IF Alt_R_Pressed THEN
  563.             BEGIN
  564.                IF ( NOT Display_Status ) THEN
  565.                   Flip_Display_Status;
  566.                GoToXY( 25 , 10 );
  567.                WRITE('Alt-R hit, receive cancelled.');
  568.                Write_Log('ALT-R hit, receive cancelled.', TRUE, FALSE);
  569.                ClrEol;
  570.             END
  571.          ELSE IF G_Failure THEN
  572.             BEGIN
  573.                IF ( NOT Display_Status ) THEN
  574.                   Flip_Display_Status;
  575.                GoToXY( 25 , 10 );
  576.                WRITE('Error during G protocol, receive cancelled.');
  577.                Write_Log('Error during G protocol, receive cancelled.', TRUE, FALSE);
  578.                ClrEol;
  579.             END;
  580.  
  581.       END
  582.                                    (* Null file name -- end of batch *)
  583.    ELSE IF Null_File_Name THEN
  584.       BEGIN
  585.          IF ( NOT Display_Status ) THEN
  586.             Flip_Display_Status;
  587.          GoToXY( 25 , 10 );
  588.          WRITE('Null file name received.');
  589.          Write_Log('Null file name received.', TRUE, FALSE);
  590.          ClrEol;
  591.          OK_Transfer := TRUE;
  592.       END
  593.                                    (* EOT received, error count OK *)
  594.  
  595.    ELSE IF ( ( Initial_Ch = EOT ) AND ( Error_Count <= Xmodem_Max_Errors ) ) THEN
  596.       BEGIN
  597.                                    (* Acknowledge EOT  *)
  598.          Async_Send( CHR( ACK ) );
  599.  
  600.                                    (* Write any remaining data in buffer *)
  601.          IF Buffer_Pos > 0 THEN
  602.             BEGIN
  603.  
  604.                Write_Count := Buffer_Pos;
  605.  
  606.                IF ( ( RFile_Size_2 + Write_Count ) > RFile_Size ) AND
  607.                    Truncate_File THEN
  608.                       Write_Count := TRUNC( RFile_Size - Rfile_Size_2 );
  609.  
  610.                W_Count := Write_Count;
  611.  
  612.                BlockWrite( XFile, Write_Buffer^, W_Count, Write_Count );
  613.  
  614.                IF ( Int24Result <> 0 ) OR
  615.                   ( W_Count <> Write_Count ) THEN
  616.                   BEGIN
  617.                      IF ( NOT Display_Status ) THEN
  618.                         Flip_Display_Status;
  619.                      GoToXY( 25 , 10 );
  620.                      WRITE('Error in writing to disk, file may be bad.');
  621.                      ClrEol;
  622.                      Window_Delay;
  623.                   END;
  624.  
  625.                RFile_Size_2 := RFile_Size_2 + Write_Count;
  626.  
  627.             END;
  628.  
  629.          End_Time       := TimeOfDay;
  630.  
  631.          IF ( NOT Display_Status ) THEN
  632.             Flip_Display_Status;
  633.  
  634.          OK_Transfer := TRUE;
  635.  
  636.          GoToXY( 2 , 10 );
  637.  
  638.          IF RFile_Size > 0 THEN
  639.             IF RFile_Size <= RFile_Size_2 THEN
  640.                BEGIN
  641.                   RFile_Size_2 := RFile_Size;
  642.                   WRITE('Reception complete; ');
  643.                END
  644.             ELSE
  645.                BEGIN
  646.                   WRITE('Reception appears incomplete; ');
  647.                   OK_Transfer := FALSE;
  648.                END
  649.          ELSE
  650.             WRITE('Reception complete; ');
  651.  
  652.                                    (* Fix possible wrap around midnight *)
  653.  
  654.          IF End_Time < Start_Time THEN
  655.             End_Time := End_Time + 86400;
  656.  
  657.          Effective_Rate := End_Time - Start_Time;
  658.  
  659.          IF ( Effective_Rate = 0.0 ) THEN
  660.             Effective_Rate := 1.0;
  661.  
  662.          Effective_Rate := RFile_Size_2 / Effective_Rate;
  663.  
  664.          WRITE('transfer rate ',Effective_Rate:6:1,' CPS');
  665.          ClrEol;
  666.  
  667.          IF OK_Transfer THEN
  668.             Write_Log('Received file ' + FileName , TRUE , FALSE )
  669.          ELSE
  670.             Write_Log('Received file ' + FileName + ' (appears incomplete)',
  671.                       TRUE , FALSE );
  672.  
  673.          OK_Transfer := TRUE;
  674.  
  675.          STR( RFile_Size_2 , SCps );
  676.          Write_Log('Size of file received was ' + SCps + ' bytes' , TRUE, FALSE );
  677.  
  678.          STR( Effective_Rate:6:1 , SCps );
  679.          Write_Log('Transfer rate was ' + SCps + ' CPS' , TRUE, FALSE );
  680.  
  681.       END
  682.    ELSE IF ( Initial_Ch = CAN ) THEN
  683.       BEGIN
  684.          IF ( NOT Display_Status ) THEN
  685.             Flip_Display_Status;
  686.          GoToXY( 25 , 10 );
  687.          WRITE('Transmitter cancelled file transfer.');
  688.          Write_Log('Transmitter cancelled file transfer.', TRUE, FALSE);
  689.          ClrEol;
  690.          Stop_Receive := TRUE;
  691.       END
  692.    ELSE
  693.       BEGIN  (* Too many errors -- cancel transfer *)
  694.  
  695.          Cancel_Transfer;
  696.  
  697.          IF ( NOT Display_Status ) THEN
  698.             Flip_Display_Status;
  699.          GoToXY( 25 , 10 );
  700.          WRITE('Receive cancelled -- too many errors');
  701.          Write_Log('Receive cancelled -- too many errors', TRUE, FALSE);
  702.          ClrEol;
  703.       END;
  704.                                    (* Set file time and date if Telink *)
  705.                                    (* or Ymodem                        *)
  706.  
  707.    IF ( File_Date <> 0 ) AND Use_Time_Sent THEN
  708.       Set_File_Date_And_Time;
  709.  
  710.                                    (* Close transferred file *)
  711.    CLOSE( XFile );
  712.    I := Int24Result;
  713.                                    (* Delete file if bad               *)
  714.  
  715.    IF ( Evict_Partial_Trans AND ( NOT OK_Transfer ) ) THEN
  716.       BEGIN
  717.          ASSIGN( XFile , Full_File_Name );
  718.             (*!I-*)
  719.          ERASE( XFile );
  720.             (*!I+*)
  721.          I := INT24Result;
  722.       END;
  723.  
  724.    Window_Delay;
  725.                                    (* Remove download buffer           *)
  726.    IF Long_Buffer THEN
  727.       MyFreeMem( Write_Buffer , Buffer_Length );
  728.  
  729.                                    (* Remove XMODEM window             *)
  730.  
  731.    Restore_Screen_And_Colors( Saved_Screen );
  732.  
  733.                                    (* Cursor back on *)
  734.    CursorOn;
  735.                                    (* Restore XON/XOFF status *)
  736.  
  737.    Async_Do_XonXoff := Save_XonXoff;
  738.    Async_OV_XonXoff := Save_XonOV;
  739.  
  740.                                    (* Restore status line *)
  741.    IF Do_Status_Line THEN
  742.       BEGIN
  743.          Set_Status_Line_Name( Short_Terminal_Name );
  744.          Write_To_Status_Line( Status_Line_Name, 1 );
  745.       END;
  746.  
  747. END    (* Receive_Xmodem_File *) ;
  748.