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