home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s4.arc / SENDKER2.MOD < prev    next >
Text File  |  1988-02-15  |  32KB  |  800 lines

  1. (*----------------------------------------------------------------------*)
  2. (*              Kermit_Send_File --- send file data itself              *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Kermit_Send_File;
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Kermit_Send_File                                     *)
  10. (*                                                                      *)
  11. (*     Purpose:    Sends file data packets to remote Kermit.            *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Kermit_Send_File;                                             *)
  16. (*                                                                      *)
  17. (*     Calls:                                                           *)
  18. (*                                                                      *)
  19. (*        Build_And_Send_Packet_With_Retry                              *)
  20. (*                                                                      *)
  21. (*----------------------------------------------------------------------*)
  22.  
  23. (*----------------------------------------------------------------------*)
  24. (*              Send_Normal --- Send file without windowing             *)
  25. (*----------------------------------------------------------------------*)
  26.  
  27. PROCEDURE Send_Normal;
  28.  
  29. VAR
  30.    Prev_Packet_Num : INTEGER;
  31.  
  32. BEGIN (* Send_Normal *)
  33.                                    (* Set address to build packets    *)
  34.  
  35.    Send_Packet_Ptr := ADDR( Sector_Data[Send_Offset] );
  36.  
  37.                                    (* Loop over file contents         *)
  38.  
  39.    IF ( NOT Kermit_Abort ) THEN
  40.       REPEAT
  41.                                    (* Increment packet number         *)
  42.  
  43.          Prev_Packet_Num      := Packet_Num;
  44.          Packet_Num           := SUCC( Packet_Num ) MOD 64;
  45.          Kermit_Window_Top    := Packet_Num;
  46.          Kermit_Window_Bottom := Packet_Num;
  47.  
  48.                                     (* Get next block of data from file *)
  49.          Get_File_Data;
  50.                                     (* Construct and send data packet   *)
  51.  
  52.          IF ( Send_Packet_Length > 0 ) THEN
  53.             Build_And_Send_Packet_With_Retry
  54.          ELSE
  55.             Packet_Num := Prev_Packet_Num;
  56.  
  57.       UNTIL File_Done OR Kermit_Abort;
  58.  
  59. END   (* Send_Normal *);
  60.  
  61. (*----------------------------------------------------------------------*)
  62. (*              Send_Windowing --- Send file with windowing             *)
  63. (*----------------------------------------------------------------------*)
  64.  
  65. PROCEDURE Send_Windowing;
  66.  
  67. VAR
  68.    Data_Place  : INTEGER;
  69.    Save_Retry  : INTEGER;
  70.    Slow_Count  : INTEGER;
  71.  
  72. BEGIN  (* Send_Windowing *)
  73.                                    (* Set window size                  *)
  74.  
  75.    Window_Size_Used := MAX( His_Kermit_Window_Size , 1 );
  76.  
  77.                                    (* Slow count is used to send the   *)
  78.                                    (* first few data blocks slowly,    *)
  79.                                    (* so that PCKermit and other       *)
  80.                                    (* programs won't be unhappy.       *)
  81.  
  82.    Slow_Count       := MIN( Window_Size_Used , 3 );
  83.  
  84.                                    (* Need more retries with windows   *)
  85.    Save_Retry    := Kermit_MaxTry;
  86.    Kermit_MaxTry := Kermit_MaxTry + Window_Size_Used;
  87.  
  88.                                    (* Empty window at this point       *)
  89.    Kermit_Window_Used   := 0;
  90.    Kermit_Window_Top    := Packet_Num;
  91.    Kermit_Window_Bottom := SUCC( Kermit_Window_Top ) MOD 64;
  92.    Data_Place           := Send_Offset;
  93.    Kermit_Window_Errors := 0;
  94. {
  95.    IF Kermit_Debug THEN
  96.       BEGIN
  97.          Write_Log( 'Window_Size   = ' + IToS( Window_Size_Used ) , FALSE, FALSE );
  98.          Write_Log( 'Window_Used   = ' + IToS( Kermit_Window_Used ) , FALSE, FALSE );
  99.          Write_Log( 'Window_Top    = ' + IToS( Kermit_Window_Top  ) , FALSE, FALSE );
  100.          Write_Log( 'Window_Bottom = ' + IToS( Kermit_Window_Bottom ) , FALSE, FALSE );
  101.          Write_Log( 'Data_Place    = ' + IToS( Data_Place         ) , FALSE, FALSE );
  102.       END;
  103. }
  104.                                    (* Loop over file contents          *)
  105.    IF ( NOT Kermit_Abort ) THEN
  106.       REPEAT
  107.                                    (* If window full, wait for ACK/NAK *)
  108.  
  109.          IF ( Kermit_Window_Used >= Window_Size_Used ) THEN
  110.             Check_Sliding_ACK( TRUE )
  111.  
  112.          ELSE                      (* Window not full -- construct and *)
  113.                                    (* send next packet.                *)
  114.             BEGIN
  115.                                    (* Increment packet number          *)
  116.  
  117.                Packet_Num := SUCC( Kermit_Window_Top ) MOD 64;
  118.  
  119.                                    (* Increment window used count      *)
  120.  
  121.                INC( Kermit_Window_Used );
  122.                Kermit_Window_Top  := Packet_Num;
  123.  
  124.                                    (* Set window data                  *)
  125.  
  126.                Data_Place      := Data_Place + 96;
  127.                IF ( ( Data_Place + 96 ) > MaxSectorLength ) THEN
  128.                   Data_Place := Send_Offset;
  129.  
  130.                Send_Packet_Ptr := ADDR( Sector_Data[Data_Place] );
  131. {
  132.                IF Kermit_Debug THEN
  133.                   Write_Log( 'Data_Place = ' + IToS( Data_Place          ) , FALSE, FALSE );
  134. }
  135.                WITH Kermit_Queue[Kermit_Window_Top] DO
  136.                   BEGIN
  137.                      Data_Slot       := Data_Place;
  138. {
  139.                      IF Kermit_Debug THEN
  140.                         Write_Log( 'Data_Slot = ' + IToS( Data_Slot          ) , FALSE, FALSE );
  141. }
  142.                      ACK_Flag        := FALSE;
  143.                      Retry_Count     := 0;
  144.                   END;
  145. {
  146.    IF Kermit_Debug THEN
  147.       BEGIN
  148.          Write_Log( '---------------', FALSE, FALSE );
  149.          Write_Log( 'Window_Used   = ' + IToS( Kermit_Window_Used ) , FALSE, FALSE );
  150.          Write_Log( 'Packet_Num    = ' + IToS( Packet_Num         ) , FALSE, FALSE );
  151.          Write_Log( 'Window_Top    = ' + IToS( Kermit_Window_Top  ) , FALSE, FALSE );
  152.          Write_Log( 'Window_Bottom = ' + IToS( Kermit_Window_Bottom ) , FALSE, FALSE );
  153.       END;
  154. }
  155.                                    (* Get next block of data from file *)
  156.                Get_File_Data;
  157.                                    (* Construct and send data packet   *)
  158. {
  159.                IF Kermit_Debug THEN
  160.                   Write_Log( 'Found length  = ' + IToS( Send_Packet_Length   ) , FALSE, FALSE );
  161. }
  162.                IF ( Send_Packet_Length > 0 ) THEN
  163.                   BEGIN
  164.                      Build_Packet;
  165.                      Kermit_Queue[Kermit_Window_Top].Data_Length :=
  166.                         Send_Packet_Length;
  167.                      Send_Packet;
  168.                      IF ( Slow_Count > 0 ) THEN
  169.                         BEGIN
  170.                            DEC( Slow_Count );
  171.                            Async_Drain_Output_Buffer( Five_Seconds );
  172.                         END;
  173.                   END
  174.                                    (* Nothing left to send -- back up *)
  175.                                    (* window pointers.                *)
  176.                ELSE
  177.                   BEGIN
  178.                      DEC( Kermit_Window_Used );
  179.                      Kermit_Window_Top  := PRED( Kermit_Window_Top ) MOD 64;
  180.                   END;
  181.                                    (* Check if any ACK/NAKs have arrived *)
  182. {
  183.                Check_Sliding_ACK( FALSE );
  184. }
  185.             END;
  186.  
  187.       UNTIL File_Done OR Kermit_Abort;
  188.  
  189. {
  190.    IF Kermit_Debug THEN
  191.       BEGIN
  192.          Write_Log( '---File Done---', FALSE, FALSE );
  193.          Write_Log( 'Window_Used   = ' + IToS( Kermit_Window_Used ) , FALSE, FALSE );
  194.          Write_Log( 'Window_Top    = ' + IToS( Kermit_Window_Top  ) , FALSE, FALSE );
  195.          Write_Log( 'Window_Bottom = ' + IToS( Kermit_Window_Bottom ) , FALSE, FALSE );
  196.          Write_Log( 'Packet_Num    = ' + IToS( Packet_Num           ) , FALSE, FALSE );
  197.       END;
  198. }
  199.    IF ( NOT Kermit_Abort ) THEN
  200.       BEGIN
  201.                                    (* If entire file done and windowing,   *)
  202.                                    (* wait for ACK of all outstanding      *)
  203.                                    (* packets.                             *)
  204.  
  205.          IF ( Kermit_Window_Used > 0 ) THEN
  206.             REPEAT
  207.                Check_Sliding_Ack( TRUE )
  208.             UNTIL ( Kermit_Abort OR ( Kermit_Window_Used = 0 ) );
  209.  
  210.                                    (* Make sure current packet number is   *)
  211.                                    (* correct.                             *)
  212.  
  213.          Packet_Num    := Kermit_Window_Top;
  214.  
  215.       END;
  216.                                    (* Restore old MaxTry *)
  217.    Kermit_MaxTry := Save_Retry;
  218.  
  219. END    (* Send_Windowing *);
  220.  
  221. (*----------------------------------------------------------------------*)
  222.  
  223. BEGIN  (* Kermit_Send_File *)
  224.                                    (* Send file packets until entire  *)
  225.                                    (* file is sent OR transfer aborts *)
  226.  
  227.    Display_Kermit_Message('Sending ' + FileName);
  228.  
  229.                                    (* Send attribute packet if remote *)
  230.                                    (* Kermit understands it.          *)
  231.    IF Kermit_Attributes THEN
  232.       BEGIN
  233.          Kermit_Send_Attributes;
  234.          IF ( NOT ACK_OK ) THEN
  235.             BEGIN
  236.                Kermit_State          := Send_Break;
  237.                Kermit_Abort          := TRUE;
  238.                Kermit_Abort_Level    := One_File;
  239.                Kermit_Doing_Transfer := FALSE;
  240.                EXIT;
  241.             END;
  242.       END;
  243.                                    (* Choose transfer routine based upon *)
  244.                                    (* windowing/no windowing             *)
  245.    Kermit_Doing_Transfer := TRUE;
  246.  
  247.    IF Kermit_Do_Sliding_Win THEN
  248.       Send_Windowing
  249.    ELSE
  250.       Send_Normal;
  251.                                    (* If entire file done, prepare to send *)
  252.                                    (* EOF packet.                          *)
  253.  
  254.    Kermit_Doing_Transfer := FALSE;
  255.  
  256.    IF ( File_Done OR Kermit_Abort ) THEN
  257.       Kermit_State := Send_EOF;
  258.  
  259. END   (* Kermit_Send_File *);
  260.  
  261. (*----------------------------------------------------------------------*)
  262. (*              Kermit_Send_EOF --- send end of file packet             *)
  263. (*----------------------------------------------------------------------*)
  264.  
  265. PROCEDURE Kermit_Send_EOF;
  266.  
  267. (*----------------------------------------------------------------------*)
  268. (*                                                                      *)
  269. (*     Procedure:  Kermit_Send_EOF                                      *)
  270. (*                                                                      *)
  271. (*     Purpose:    Sends end of file packet to remote Kermit marking    *)
  272. (*                 no more data in current file being transferred.      *)
  273. (*                                                                      *)
  274. (*     Calling Sequence:                                                *)
  275. (*                                                                      *)
  276. (*        Kermit_Send_EOF;                                              *)
  277. (*                                                                      *)
  278. (*     Calls:                                                           *)
  279. (*                                                                      *)
  280. (*        Build_And_Send_Packet_With_Retry                              *)
  281. (*                                                                      *)
  282. (*----------------------------------------------------------------------*)
  283.  
  284. BEGIN (* Kermit_Send_EOF *)
  285.  
  286.                                    (* Prepare EOF packet *)
  287.  
  288.    Packet_Num          := SUCC( Packet_Num ) MOD 64;
  289.    Send_Packet_Ptr^[4] := EOF_Packet;
  290.    Send_Packet_Length  := 4;
  291.                                    (* Add discard indicator if needed *)
  292.    IF ( Kermit_Abort ) THEN
  293.       BEGIN
  294.          Send_Packet_Ptr^[5] := 'D';
  295.          Send_Packet_Length  := 5;
  296.       END;
  297.                                    (* Send EOF Packet *)
  298.  
  299.    Build_And_Send_Packet_With_Retry;
  300.  
  301.                                    (* If OK then prepare to try *)
  302.                                    (* for another file, if any  *)
  303.    Kermit_State := Send_Break;
  304.  
  305.    Kermit_Abort := Kermit_Abort OR ( NOT ACK_OK );
  306.  
  307. END   (* Kermit_Send_EOF *);
  308.  
  309. (*----------------------------------------------------------------------*)
  310. (*                 Kermit_Send_Break --- send break packet              *)
  311. (*----------------------------------------------------------------------*)
  312.  
  313. PROCEDURE Kermit_Send_Break;
  314.  
  315. (*----------------------------------------------------------------------*)
  316. (*                                                                      *)
  317. (*     Procedure:  Kermit_Send_Break                                    *)
  318. (*                                                                      *)
  319. (*     Purpose:    Sends break packet to remote Kermit.                 *)
  320. (*                                                                      *)
  321. (*     Calling Sequence:                                                *)
  322. (*                                                                      *)
  323. (*        Kermit_Send_Break;                                            *)
  324. (*                                                                      *)
  325. (*     Calls:                                                           *)
  326. (*                                                                      *)
  327. (*        Build_And_Send_Packet_With_Retry                              *)
  328. (*                                                                      *)
  329. (*----------------------------------------------------------------------*)
  330.  
  331. BEGIN (* Kermit_Send_Break *)
  332.                                    (* Construct break packet *)
  333.  
  334.    Kermit_State        := Send_Break;
  335.    Packet_Num          := SUCC( Packet_Num ) MOD 64;
  336.    Send_Packet_Ptr^[4] := Break_Packet;
  337.    Send_Packet_Length  := 4;
  338.                                    (* Send the break packet *)
  339.  
  340.    Build_And_Send_Packet_With_Retry;
  341.  
  342.                                    (* If OK, then sending of file complete *)
  343.    IF ACK_OK THEN
  344.       Send_Done := TRUE
  345.    ELSE
  346.       Kermit_Abort := TRUE;
  347.  
  348. END    (* Kermit_Send_Break *);
  349.  
  350. (*----------------------------------------------------------------------*)
  351. (*       Kermit_Send_One_File --- Controls sending of a single file     *)
  352. (*----------------------------------------------------------------------*)
  353.  
  354. PROCEDURE Kermit_Send_One_File;
  355.  
  356. (*----------------------------------------------------------------------*)
  357. (*                                                                      *)
  358. (*     Procedure:  Kermit_Send_One_File                                 *)
  359. (*                                                                      *)
  360. (*     Purpose:    Sends a single file to remote Kermit.                *)
  361. (*                                                                      *)
  362. (*     Calling Sequence:                                                *)
  363. (*                                                                      *)
  364. (*        Kermit_Send_One_File;                                         *)
  365. (*                                                                      *)
  366. (*     Calls:                                                           *)
  367. (*                                                                      *)
  368. (*        Draw_Menu_Frame                                               *)
  369. (*        Initialize_Display                                            *)
  370. (*        Open_File                                                     *)
  371. (*                                                                      *)
  372. (*----------------------------------------------------------------------*)
  373.  
  374. BEGIN  (* Kermit_Send_One_File *)
  375.                                    (* Open file transfer display window *)
  376.  
  377.    Kermit_Menu_Title := 'Send file ' + FileName + ' using Kermit';
  378.  
  379.    Initialize_Display;
  380.                                    (* Display init packet parameters   *)
  381.    Display_Kermit_Init_Params;
  382.                                    (* Try opening file to be sent      *)
  383.  
  384.    Open_File( Read_Open, FileName , Full_Name );
  385.  
  386.                                    (* If open went OK, then do transfer. *)
  387.    IF ( Open_OK ) THEN
  388.       BEGIN
  389.                                    (* Ensure record read first time by *)
  390.                                    (* pointing buffer pointer past end *)
  391.                                    (* of file buffer.                  *)
  392.  
  393.          Buffer_Pos := Buffer_Size + 1;
  394.  
  395.                                    (* Loop over states in transfer until     *)
  396.                                    (* transfer aborted OR file is completely *)
  397.                                    (* sent.                                  *)
  398.  
  399.          Kermit_Transfer_Start := TimeOfDay;
  400.  
  401.          REPEAT
  402.  
  403.             CASE Kermit_State OF
  404.                Send_Init        : Kermit_Send_Init;
  405.                Send_File_Header : Kermit_Send_Header;
  406.                Send_File        : BEGIN
  407.                                      Kermit_Transfer_Start := TimeOfDay;
  408.                                      Kermit_Send_File;
  409.                                   END;
  410.                Send_EOF         : Kermit_Send_EOF;
  411.                Send_Break       : Send_Done := TRUE;
  412.             END  (* CASE *);
  413.  
  414.          UNTIL Send_Done;
  415.                                    (* Accumulate time for this transfer *)
  416.  
  417.          Kermit_Transfer_End  := TimeOfDay;
  418.          Total_Time           := Total_Time + TimeDiff( Kermit_Transfer_Start,
  419.                                                         Kermit_Transfer_End    );
  420.  
  421.       END  (* IF Open_OK *);
  422.  
  423. END    (* Kermit_Send_One_File *);
  424.  
  425. (*----------------------------------------------------------------------*)
  426. (*   Do_Kermit_Send --- Controls sending of list of files in Kermit     *)
  427. (*----------------------------------------------------------------------*)
  428.  
  429. PROCEDURE Do_Kermit_Send;
  430.  
  431. (*----------------------------------------------------------------------*)
  432. (*                                                                      *)
  433. (*     Procedure:  Do_Kermit_Send                                       *)
  434. (*                                                                      *)
  435. (*     Purpose:    Controls sending of list of files in Kermit          *)
  436. (*                                                                      *)
  437. (*     Calling Sequence:                                                *)
  438. (*                                                                      *)
  439. (*        Do_Kermit_Send;                                               *)
  440. (*                                                                      *)
  441. (*     Calls:                                                           *)
  442. (*                                                                      *)
  443. (*        Save_Screen                                                   *)
  444. (*        Restore_Screen                                                *)
  445. (*        Initialize_Display                                            *)
  446. (*        Display_Kermit_Message                                        *)
  447. (*        FindFirst                                                     *)
  448. (*        FindNext                                                      *)
  449. (*        Get_Kermit_File_Name                                          *)
  450. (*        Kermit_Send_One_File                                          *)
  451. (*        Reset_Global_Colors                                           *)
  452. (*                                                                      *)
  453. (*----------------------------------------------------------------------*)
  454.  
  455. VAR
  456.    S_Baud_Rate    : STRING[5];
  457.    W_Str          : STRING[3];
  458.    Send_Str       : AnyStr;
  459.    Save_Close     : BOOLEAN;
  460.    C_Trans_Rate_E : ShortStr;
  461.    C_Trans_Rate_A : ShortStr;
  462.    I              : INTEGER;
  463.  
  464. BEGIN  (* Do_Kermit_Send *)
  465.                                    (* Hide cursor *)
  466.    CursorOff;
  467.                                    (* Save current screen             *)
  468.  
  469.    Save_Screen( Kermit_Local_Save );
  470.  
  471.                                    (* Open display window for transfer  *)
  472.                                    (* Initialize status display information *)
  473.    Packets_Sent      := 0;
  474.    Packets_Received  := 0;
  475.    Packets_Bad       := 0;
  476.    Buffer_Num        := 0;
  477.    Buffer_Num_Actual := 0;
  478.    Buffer_Total      := 0;
  479.    Kermit_MaxTry     := 5;
  480.    Total_Time        := 0;
  481.                                    (* Prepare Kermit to send initialization *)
  482.                                    (* packet.                               *)
  483.    Kermit_State := Send_Init;
  484.                                    (* Not transferring file data yet *)
  485.    Kermit_Doing_Transfer := FALSE;
  486.  
  487.                                    (* Display transfer headings      *)
  488.  
  489.    Kermit_Menu_Title := 'Send file using Kermit';
  490.  
  491.    Write_Log( Kermit_Menu_Title, FALSE, FALSE );
  492.  
  493.    Initialize_Display;
  494.                                    (* See if we can find anything to *)
  495.                                    (* be sent.                       *)
  496.  
  497.    FindFirst( File_Pattern, AnyFile, File_Entry );
  498.  
  499.    Stop_Send  := ( DosError <> 0 );
  500.  
  501.    IF Stop_Send THEN
  502.       BEGIN
  503.          Display_Kermit_Message('  No files found to send.');
  504.          Window_Delay;
  505.          Restore_Screen_And_Colors( Kermit_Local_Save );
  506.          CursorOn;
  507.          EXIT;
  508.       END
  509.    ELSE                            (* Wait for delay time to expire in *)
  510.                                    (* host mode.                       *)
  511.       IF Host_Mode THEN
  512.          DELAY( 1000 * Kermit_Delay_Time );
  513.  
  514.                                    (* Allocate buffer for file       *)
  515.  
  516.    Buffer_Length  := Max_Write_Buffer;
  517.    GetMem( Read_Buffer , Buffer_Length );
  518.  
  519.    IF ( Read_Buffer = NIL ) THEN
  520.       BEGIN
  521.          Display_Kermit_Message('  Not enough memory to perform send.');
  522.          Press_Any;
  523.          Restore_Screen_And_Colors( Kermit_Local_Save );
  524.          CursorOn;
  525.          EXIT;
  526.       END;
  527.                                    (* Loop over file names         *)
  528.    WHILE( NOT Stop_Send ) DO
  529.       BEGIN
  530.                                    (* Initialize    *)
  531.  
  532.          Send_Done          := FALSE;
  533.          File_Done          := FALSE;
  534.          Kermit_Abort       := FALSE;
  535.          Kermit_Retry       := FALSE;
  536.          Buffer_Size        := Buffer_Length;
  537.          Kermit_Abort_Level := No_Abort;
  538.  
  539.          Kermit_Clear_Message_Lines;
  540.  
  541.                                    (* Get file name *)
  542.  
  543.          Get_Kermit_File_Name( OK_File );
  544.  
  545.                                    (* If file can be sent, do it   *)
  546.          IF OK_File THEN
  547.             BEGIN
  548.                Kermit_Send_One_File;
  549.                Kermit_State := Send_File_Header;
  550.             END;
  551.                                    (* See if transfer loop should be *)
  552.                                    (* stopped.                       *)
  553.  
  554.          Stop_Send := Stop_Send OR
  555.                       ( Kermit_Abort_Level IN [All_Files, Entire_Protocol] );
  556.  
  557.                                    (* See if more files to transfer  *)
  558.  
  559.          FindNext( File_Entry );
  560.  
  561.          Stop_Send := Stop_Send OR ( DosError <> 0 );
  562.  
  563.                                    (* Send break packet if no more files *)
  564.  
  565.          IF ( Stop_Send AND ( NOT Kermit_Abort ) ) THEN
  566.             Kermit_Send_Break;
  567.  
  568.       END (* WHILE *);
  569.                                    (* Display transfer time *)
  570.  
  571.       IF ( Send_Done AND ( NOT Kermit_Abort ) ) THEN
  572.          BEGIN
  573.  
  574.             Display_Kermit_Message('Send completed.');
  575.  
  576.             IF ( Total_Time = 0 ) THEN
  577.                Total_Time := 1;
  578.  
  579.             Kermit_Transfer_Rate := Buffer_Total / ( Total_Time * 1.0 );
  580.  
  581.             STR( Kermit_Transfer_Rate:10:0 , C_Trans_Rate_E );
  582.  
  583.             Display_Kermit_Message_2('Effective transfer rate was ' +
  584.                                      LTrim( C_Trans_Rate_E ) + ' CPS.');
  585.  
  586.             Kermit_Transfer_Rate := Buffer_Num_Actual / ( Total_Time * 1.0 );
  587.  
  588.             STR( Kermit_Transfer_Rate:10:0 , C_Trans_Rate_A );
  589.  
  590.             Display_Kermit_Message_3('Actual transfer rate was ' +
  591.                                      LTrim( C_Trans_Rate_A ) + ' CPS.');
  592.  
  593.          END
  594.       ELSE
  595.          BEGIN
  596.             Display_Kermit_Message('Send Cancelled.');
  597.          END;
  598.                                    (* Ensure entire protocol aborted   *)
  599.                                    (* if requested.                    *)
  600.  
  601.    Kermit_Done := ( Kermit_Abort_Level = Entire_Protocol );
  602.  
  603.    Window_Delay;
  604.                                    (* Remove download buffer           *)
  605.  
  606.    IF ( Read_Buffer <> NIL ) THEN
  607.       MyFreeMem( Read_Buffer , Buffer_Length );
  608.  
  609.                                    (* Remove Kermit window             *)
  610.  
  611.    Restore_Screen_And_Colors( Kermit_Local_Save );
  612.  
  613.                                    (* Restore cursor *)
  614.    CursorOn;
  615.                                    (* Signal transfer done *)
  616.    IF ( NOT Silent_Mode ) THEN
  617.       FOR I := 1 TO Transfer_Bells DO
  618.          Menu_Beep;
  619.  
  620. END    (* Do_Kermit_Send *);
  621.  
  622. (*----------------------------------------------------------------------*)
  623. (*   Get_File_Pattern --- get wildcard specification for files to send  *)
  624. (*----------------------------------------------------------------------*)
  625.  
  626. PROCEDURE Get_File_Pattern;
  627.  
  628. VAR
  629.    I    : INTEGER;
  630.    Done : BOOLEAN;
  631.  
  632. BEGIN (* Get_File_Pattern *)
  633.                                    (* Get file name from kbd/screen *)
  634.  
  635.    IF ( LENGTH( FileName ) = 0 ) THEN
  636.       IF Auto_Find_FileNames THEN
  637.          Get_Auto_File_Name( Saved_Kbd_File_Name , FileName );
  638.  
  639.    Draw_Titled_Box( Local_Save, 10, 5, 78, 8, '' );
  640.  
  641.    PibTerm_Window( 11, 6, 77, 7 );
  642.  
  643.    GoToXY( 2 , 1 );
  644.  
  645.    WRITE('File to send: ');
  646.                                    (* Read in wildcard spec *)
  647.  
  648.    IF ( ( NOT ( Host_Mode OR Script_Transfer ) ) OR ( LENGTH( FileName ) = 0 ) ) THEN
  649.       BEGIN
  650.          File_Pattern := FileName;
  651.          Read_Edited_String( File_Pattern );
  652.          IF ( File_Pattern = CHR( ESC ) ) THEN
  653.             File_Pattern := '';
  654.       END
  655.    ELSE
  656.       BEGIN
  657.          WRITE( FileName );
  658.          File_Pattern := FileName;
  659.       END;
  660.                                    (* Exit if no file name specified *)
  661.  
  662.    IF ( LENGTH( File_Pattern ) = 0 ) THEN
  663.       BEGIN
  664.          Restore_Screen_And_Colors( Local_Save );
  665.          EXIT;
  666.       END;
  667.                                    (* Get upload directory spec *)
  668.    IF ( NOT Host_Mode ) THEN
  669.       BEGIN
  670.  
  671.          I    := LENGTH( File_Pattern ) + 1;
  672.          Done := FALSE;
  673.  
  674.          WHILE ( NOT Done ) DO
  675.             BEGIN
  676.                I    := I - 1;
  677.                Done := ( File_Pattern[I] = ':' ) OR
  678.                        ( File_Pattern[I] = '\' ) OR
  679.                        ( I = 1 );
  680.             END;
  681.  
  682.          IF ( I > 1 ) THEN
  683.             Upload_Dir_Path := COPY( File_Pattern, 1, I )
  684.          ELSE
  685.             Upload_Dir_Path := '';
  686.  
  687.          IF ( POS( '\', Upload_Dir_Path ) <> 0 ) THEN
  688.             IF ( Upload_Dir_Path[LENGTH( Upload_Dir_Path )] <> '\' ) THEN
  689.                Upload_Dir_Path := Upload_Dir_Path + '\';
  690.  
  691.       END;
  692.  
  693.    Restore_Screen_And_Colors( Local_Save );
  694.  
  695. END   (* Get_File_Pattern *);
  696.  
  697. (*----------------------------------------------------------------------*)
  698.  
  699. BEGIN (* Send_Kermit_File *)
  700.                                    (* Get Kermit menu *)
  701.  
  702.    Make_A_Menu( Kermit_Menu, Send_Quit_Item, 6, 20, 40, 6, Send_Quit_Item,
  703.                 'Choose Kermit function: ',
  704.                 'a) Send Text File;b) Send Binary file;' +
  705.                 'f) Finish Remote Server;l) Logout Remote Server;' +
  706.                 't) Transfer to Receive File Menu;' +
  707.                 'q) Quit Kermit',
  708.                 FALSE );
  709.  
  710.    Kermit_Screen_Write    := FALSE;
  711.    Kermit_Done            := FALSE;
  712.    Sending_File           := TRUE;
  713.    Host_Count             := 0;
  714.    FileName               := UpperCase( FileName );
  715.    Send_Packet_Ptr        := ADDR( Sector_Data[Send_Offset] );
  716.    Send_Packet_Ptr^[2]    := CHR( 0 );
  717.    Send_Packet_Ptr^[3]    := CHR( 0 );
  718.    Send_Packet_Ptr^[4]    := CHR( 0 );
  719.  
  720.                                    (* Begin loop over send choices *)
  721.    REPEAT
  722.                                    (* Reinitialize global Kermit variables *)
  723.       Kermit_Init;
  724.                                    (* Display send menu *)
  725.  
  726.       IF ( NOT ( Host_Mode OR Script_Transfer ) ) THEN
  727.          BEGIN
  728.             Menu_Display_Choices( Kermit_Menu );
  729.             Menu_Choice := Menu_Get_Choice( Kermit_Menu , Erase_Menu );
  730.          END
  731.       ELSE
  732.          BEGIN
  733.             INC( Host_Count );
  734.             IF ( Host_Count = 1 ) THEN
  735.                BEGIN
  736.  
  737.                   IF Kermit_File_Type_Var <> Kermit_Binary THEN
  738.                      Menu_Choice := 1
  739.                   ELSE
  740.                      Menu_Choice := 2;
  741.  
  742.                   IF ( LENGTH( FileName ) > 0 ) THEN
  743.                      IF ( FileName = '/FINISH' ) THEN
  744.                         Menu_Choice := 3
  745.                      ELSE IF ( FileName = '/LOGOUT' ) THEN
  746.                         Menu_Choice := 4;
  747.  
  748.                END
  749.             ELSE
  750.                Menu_Choice := Send_Quit_Item;
  751.          END;
  752.                                    (* Choose function to perform *)
  753.       CASE Menu_Choice OF
  754.  
  755.          1: BEGIN (* Send Ascii text file *)
  756.                Kermit_File_Type_Var := Kermit_Ascii;
  757.                Get_File_Pattern;
  758.                IF LENGTH( File_Pattern ) > 0 THEN
  759.                   Do_Kermit_Send;
  760.             END;
  761.  
  762.          2: BEGIN (* Send binary file *)
  763.                Kermit_File_Type_Var := Kermit_Binary;
  764.                Get_File_Pattern;
  765.                IF LENGTH( File_Pattern ) > 0 THEN
  766.                   Do_Kermit_Send;
  767.             END;
  768.                                    (* Finish remote Kermit server *)
  769.          3: BEGIN
  770.                Kermit_Finish_Server('F');
  771.             END;
  772.                                    (* Logout remote Kermit server *)
  773.          4: BEGIN
  774.                Kermit_Finish_Server('L');
  775.             END;
  776.                                    (* Set up transfer to receive menu *)
  777.          5: BEGIN
  778.                Kermit_Done := TRUE;
  779.                Sending_File := FALSE;
  780.             END;
  781.                                    (* Stop sends *)
  782.          ELSE
  783.             BEGIN
  784.                Kermit_Done := TRUE;
  785.             END;
  786.  
  787.       END (* CASE *);
  788.  
  789.    UNTIL Kermit_Done;
  790.                                    (* Ensure status window restored *)
  791.    IF Do_Status_Line THEN
  792.       PibTerm_Window( 1, 1, Max_Screen_Col, Max_Screen_Line - 1 );
  793.  
  794.                                    (* Ensure switch to receive if needed *)
  795.  
  796.    Kermit_Really_Done := Sending_File;
  797.    FileName           := '';
  798.  
  799. END   (* Send_Kermit_File *);
  800.