home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / perqa / kermitrecv.pas < prev    next >
Pascal/Delphi Source File  |  2020-01-01  |  23KB  |  706 lines

  1. MODULE KermitRecv ;
  2.  
  3. (* 29-Nov-83  Allow eight bit file transfer (c.f. sopen call) [pgt001] *)
  4. (* 30-Nov-83  During a receive clear the screen and show characters    *)
  5. (*            and packets received.      [pgt002]                      *)
  6.  
  7.  
  8. EXPORTS
  9.  
  10. FUNCTION ReceiveACK : (* Returning *) Boolean;
  11. PROCEDURE RecvSwitch; (* this procedure is the main receive routine *)
  12.  
  13.  
  14. PRIVATE
  15.  
  16. IMPORTS KermitGlobals   FROM KermitGlobals ;
  17. IMPORTS KermitUtils     FROM KermitUtils ;
  18. IMPORTS Stdio           FROM Stdio ;
  19. IMPORTS KermitError     FROM KermitError ;
  20. IMPORTS KermitSend      FROM KermitSend ;  (* for sending ACKs and NAKs, etc *)
  21. IMPORTS Screen          FROM Screen ;  (* screen control [pgt002] *)
  22.  
  23.  
  24. VAR
  25.    OldChInFile: Stats ;  (* Characters in file [pgt002]*)
  26.    BadPackets: Integer ; (* Bad packet count for this recv [pgt002]*)
  27.  
  28.  
  29. {$RANGE-}     (* Range checks off to see if it runs faster   (16-Jan-84)*)
  30.  
  31.  
  32. PROCEDURE Field1; (* Count *)
  33.    VAR
  34.       test: Boolean;
  35.    BEGIN
  36.       WITH Buf[NextPacket] DO
  37.          BEGIN
  38.             WITH PackControl DO
  39.                BEGIN
  40.                   Buf[InputPacket].count := t;
  41.                   count := UnChar(t);
  42.                   test := (count >= 3) OR (count <= SizeRecv-2);
  43.                   (* IF (NOT test) AND Debug THEN ErrorMsg('Bad count'); *)
  44.                   good := good AND test;
  45.                END;
  46.          END;
  47.    END;
  48.  
  49. PROCEDURE Field2; (* Packet Number *)
  50.    VAR
  51.       test : Boolean;
  52.    BEGIN
  53.       WITH Buf[NextPacket] DO
  54.          BEGIN
  55.             WITH PackControl DO
  56.                BEGIN
  57.                   Buf[InputPacket].seq := t;
  58.                   seq := UnChar(t);
  59.                   test := (seq >= 0) OR (seq <= 63);
  60.                   (* IF (NOT test) AND Debug THEN ErrorMsg('Bad seq number'); *)
  61.                   good := test AND good;
  62.                END;
  63.          END;
  64.    END;
  65.  
  66. PROCEDURE Field3; (* Packet Type *)
  67.    VAR
  68.       test : Boolean;
  69.    BEGIN
  70.       WITH Buf[NextPacket] DO
  71.          BEGIN
  72.             WITH PackControl DO
  73.                BEGIN
  74.                   ptype := t;
  75.                   Buf[InputPacket].ptype := t;
  76.                   test := IsValidPType(ptype);
  77.                   (* IF (NOT test) AND Debug THEN ErrorMsg('Bad Packet Type'); *)
  78.                   good := test AND good;
  79.                END;
  80.          END;
  81.    END;
  82.  
  83. PROCEDURE Field4; (* Data *)
  84.    BEGIN
  85.       WITH PackControl DO
  86.          BEGIN
  87.             PacketPtr := PacketPtr+1;
  88.             Buf[InputPacket].data[PacketPtr] := t;
  89.             WITH Buf[NextPacket] DO
  90.                BEGIN
  91.                   IF (t = MyQuote) THEN    (* character is quote *)
  92.                      BEGIN
  93.                         IF control THEN        (* quote ,quote  *)
  94.                            BEGIN
  95.                               data[i] := MyQuote;
  96.                               i := i+1;
  97.                               control := False;
  98.                            END
  99.                         ELSE      (* set control on *)
  100.                            control := True
  101.                      END
  102.                   ELSE                 (* not quote *)
  103.                      IF control THEN      (* convert to control *)
  104.                         BEGIN
  105.                            data[i] := ctl(t);
  106.                            i := i+1;
  107.                            control := False
  108.                         END
  109.                      ELSE      (* regular data *)
  110.                         BEGIN
  111.                            data[i] := t;
  112.                            i := i+1;
  113.                         END;
  114.                END;
  115.          END;
  116.    END;
  117.  
  118. PROCEDURE Field5; (* Check Sum *)
  119.    VAR
  120.       test : Boolean;
  121.    BEGIN
  122.       WITH PackControl DO
  123.          BEGIN
  124.             PacketPtr := PacketPtr +1;
  125.             Buf[InputPacket].data[PacketPtr] := t;
  126.             Buf[InputPacket].data[PacketPtr + 1] := ENDSTR;
  127.             check := CheckFunction(check);
  128.             check := MakeChar(check);
  129.             test := (t=check);
  130.             IF (NOT test) AND Debug THEN ErrorMsg('Bad CheckSum');
  131.             good := test AND good;
  132.             Buf[NextPacket].data[i] := ENDSTR;
  133.             finished := True;  (* set finished *)
  134.          END;
  135.    END;
  136.  
  137. PROCEDURE BuildPacket;
  138.    (* receive packet & validate checksum *)
  139.    VAR
  140.       temp : Ppack;
  141.    BEGIN
  142.       WITH PackControl DO
  143.          BEGIN
  144.             WITH Buf[NextPacket] DO
  145.                BEGIN
  146.                   IF (t <> ENDSTR) THEN
  147.                      IF restart THEN
  148.                         BEGIN
  149.                            (* read until get SOH marker *)
  150.                            IF (t = SOH) THEN
  151.                               BEGIN
  152.                                  finished := False;    (* set varibles *)
  153.                                  control := False;
  154.                                  good := True;
  155.                                  seq := -1;        (* set return values to bad packet *)
  156.                                  ptype := QUESTION;
  157.                                  data[1] := ENDSTR;
  158.                                  data[MAXSTR] := ENDSTR;
  159.                                  restart := False;
  160.                                  fld := 0;
  161.                                  i := 1;
  162.                                  PacketPtr := 0;
  163.                                  check := 0;
  164.                               END;
  165.                         END
  166.                      ELSE  (* Not restart -pt*)    (* have started packet *)
  167.                         BEGIN
  168.                            IF (t = SOH) THEN    (* check for restart or EOL *)
  169.                               restart := True
  170.                            ELSE
  171.                               IF (t = myEOL) THEN
  172.                                  BEGIN
  173.                                     finished := True;
  174.                                     good := False;
  175.                                  END
  176.                               ELSE
  177.                                  BEGIN
  178.                                     CASE fld OF
  179.                                        (* increment field number *)
  180.                                        0:   fld := 1;
  181.                                        1:   fld := 2;
  182.                                        2:   fld := 3;
  183.                                        3:
  184.                                           IF (count = 3)  (* no data *)
  185.                                           THEN fld := 5
  186.                                           ELSE fld := 4;
  187.                                        4:
  188.                                           IF (PacketPtr>=count-3) (* end of data *)
  189.                                           THEN fld := 5;
  190.                                        END (* case *);
  191.                                     IF (fld <> 5)
  192.                                     THEN  check := check+t; (* add into checksum *)
  193.  
  194.                                     CASE fld OF
  195.                                        1:      Field1;
  196.                                        2:      Field2;
  197.                                        3:      Field3;
  198.                                        4:      Field4;
  199.                                        5:      Field5;
  200.                                     END;
  201.                                     (* case *)
  202.                                  END;
  203.                         END;
  204.  
  205.                   IF finished THEN
  206.                      BEGIN
  207.                         IF (ptype = TYPEE) AND good THEN (* error_packets *)
  208.                            BEGIN
  209.                               SendACK(n);          (* send ACK *)
  210.  
  211.                               RAISE GotErrorPacket( data ) ; (* ********** *)
  212.  
  213.                            END;
  214.                         NumRecvPacks := NumRecvPacks+1;
  215.                         IF Debug THEN
  216.                            BEGIN
  217.                               DebugPacket('Received: ',InputPacket);
  218.                               IF good THEN ErrorMsg('Is Good');
  219.                            END;
  220.  
  221.                         temp := CurrentPacket;
  222.                         CurrentPacket := NextPacket;
  223.                         NextPacket := temp;
  224.                      END;
  225.                END;
  226.          END;
  227.    END;
  228.  
  229. FUNCTION ReceivePacket: Boolean;
  230.    BEGIN
  231.       WITH PackControl DO
  232.          BEGIN
  233.             StartTimer;
  234.             good := False ;
  235.             finished := False;
  236.             restart := True;
  237.             (* No Keyboard Interupt - Set by ^C handler -pt*)
  238.             FromConsole := nothing;
  239.             REPEAT
  240.                t := GetIn;
  241.  
  242.                CheckTimer ;
  243.                IF (FromConsole = abortnow) THEN
  244.                   BEGIN
  245.                      State := ABORT ;
  246.                      ReceivePacket := False ;
  247.                      EXIT( ReceivePacket )
  248.                   END;
  249.  
  250.                BuildPacket;
  251.             UNTIL finished  OR (TimeLeft <= 0);
  252.             IF (TimeLeft <= 0) THEN
  253.                BEGIN
  254.                   Buf[CurrentPacket] := TOPacket;
  255.                   restart := True;
  256.                   IF NOT ((RunType=Transmit) AND (State=Init)) THEN
  257.                      BEGIN
  258.                         ErrorInt('%Timed out ', n)
  259.                      END;
  260.                END;
  261.             StopTimer;
  262.             IF NOT good THEN BadPackets := BadPackets + 1 ;
  263.             ReceivePacket := good;
  264.          END;
  265.    END;
  266.  
  267. FUNCTION ReceiveACK : (* Returning *) Boolean;
  268.    (* receive ACK with correct number *)
  269.    VAR
  270.       Ok: Boolean;
  271.    BEGIN
  272.       Ok := ReceivePacket;
  273.       WITH Buf[CurrentPacket] DO
  274.          BEGIN
  275.             IF (ptype = TYPEY) THEN   NumACKrecv := NumACKrecv+1
  276.             ELSE
  277.                IF (ptype = TYPEN) THEN  NumNAKrecv := NumNAKrecv+1
  278.                ELSE
  279.                     NumBadrecv := NumBadrecv +1;
  280.             (* got right one ? *)
  281.             ReceiveACK := ( Ok AND (ptype=TYPEY) AND (n=seq))
  282.          END;
  283.    END;
  284.  
  285.  
  286. PROCEDURE GetFile((* Using *) data:istring);
  287.    (* create file from fileheader packet *)
  288.    VAR
  289.       len: Integer;
  290.  
  291.    PROCEDURE Strip( var name: istring ) ;
  292.    (* Strip off any blanks (usually trailing) from the file name *)
  293.    VAR i, newpos: integer ;
  294.    BEGIN (*-Strip-*)
  295.       newpos := 1 ;  (* this is the new character position for non-blanks *)
  296.       FOR i := 1 TO ilength(name) DO
  297.         IF (name[i] = blank) THEN (* skip it by not incrementing "newpos"  *)
  298.         ELSE
  299.            BEGIN (* restore character *)
  300.               name[newpos] := name[i] ;
  301.               newpos := newpos + 1
  302.            END ;
  303.  
  304.       name[newpos] := ENDSTR
  305.    END ; (*-Strip-*)
  306.  
  307.    BEGIN
  308.       WITH Buf[CurrentPacket] DO
  309.          BEGIN
  310.             IF (DiskFile = StdIOError) THEN (* check if we already have a file *)
  311.                BEGIN
  312.                   Strip( data ) ;  (* remove any blanks *)
  313.                   IF Verbosity THEN
  314.                      BEGIN
  315.                         ErrorMsg ('Creating file: ');
  316.                         ErrorStr(data);
  317.                      END;
  318.                   IF Exists(data) AND FileWarning THEN
  319.                      BEGIN
  320.                         ErrorMsg('File already exists ');
  321.                         ErrorStr(data);
  322.                         ErrorMsg('Creating: ');
  323.                         (* Make it <file>.A *)
  324.                         len := ilength(data) + 1 ; (* first free char pos *)
  325.                         data[len] := PERIOD ;
  326.                         data[len+1] := leta ;
  327.                         data[len+2] := ENDSTR;
  328.                         ErrorStr(data)
  329.                      END;
  330.                   IF EightBitFile THEN
  331.                      DiskFile := Sopen(data,StdIO8Write)
  332.                   ELSE
  333.                      DiskFile := Sopen(data,StdIOWrite);
  334.                END;
  335.             IF (Diskfile <= StdIOError) THEN ErrorPack('Cannot create file  ');
  336.          END;
  337.    END;
  338.  
  339. PROCEDURE ReceiveInit;
  340.    (* receive init packet *)
  341.    (* respond with ACK and  our parameters *)
  342.    BEGIN
  343.       IF (NumTry > MaxTry) THEN
  344.          BEGIN
  345.             State := Abort;
  346.             ErrorMsg('Cannot receive init');
  347.          END
  348.       ELSE
  349.          BEGIN
  350.             Verbose('Receiving Init');
  351.             NumTry := NumTry+1;
  352.             IF ReceivePacket
  353.                AND (Buf[CurrentPacket].ptype = TYPES) THEN
  354.                BEGIN
  355.                   WITH Buf[CurrentPacket] DO
  356.                      BEGIN
  357.                         n := seq;
  358.                         DeCodeParm(data);
  359.                      END;
  360.  
  361.                   (* now send mine *)
  362.                   WITH Buf[ThisPacket] DO
  363.                      BEGIN
  364.                         count := NUMPARAM;
  365.                         seq := n;
  366.                         Ptype := TYPEY;
  367.                         EnCodeParm(data);
  368.                      END;
  369.  
  370.                   SendPacket;
  371.  
  372.                   NumACK := NumACK+1;
  373.                   State := FileHeader;
  374.                   OldTry := NumTry;
  375.                   NumTry := 0;
  376.                   n := (n+1) MOD 64
  377.                END
  378.             ELSE
  379.                BEGIN
  380.                   IF Debug THEN ErrorMsg('Received Bad init');
  381.                   SendNAK(n);
  382.                END;
  383.          END;
  384.    END;
  385.  
  386. PROCEDURE DataToFile; (* output to file *)
  387.    VAR
  388.       len,i : Integer;
  389.       temp : istring;
  390.    BEGIN
  391.       WITH Buf[CurrentPacket] DO
  392.          BEGIN
  393.             len := ilength(data);
  394.             ChInFile := ChInFile + len ;
  395.             PutStr(data,DiskFile)
  396.          END;
  397.    END;
  398.  
  399. PROCEDURE Dodata;  (* Process Data packet *)
  400.  
  401.    BEGIN
  402.       WITH Buf[CurrentPacket] DO
  403.          BEGIN
  404.             IF ( seq = ((n + 63) MOD 64)) THEN
  405.                BEGIN                (* data last one *)
  406.                   IF (OldTry > MaxTry) THEN     (* number of tries? *)
  407.                      BEGIN
  408.                         State := Abort;
  409.                         ErrorMsg('Old data - Too many');
  410.                      END
  411.                   ELSE
  412.                      BEGIN
  413.                         SendACK(seq);
  414.                         NumTry := 0;
  415.                      END;
  416.                END
  417.             ELSE
  418.                BEGIN            (* data - this one *)
  419.                   IF (n <> seq) THEN  SendNAK(n)
  420.                   ELSE
  421.                      BEGIN
  422.                         SendACK(n); (* ACK *)
  423.                         DataToFile;
  424.                         OldTry := NumTry;
  425.                         NumTry := 0;
  426.                         n := (n+1) MOD 64;
  427.                      END;
  428.                END;
  429.          END;
  430.    END;
  431.  
  432. PROCEDURE DoFileLast;   (* Process File Packet *)
  433.    BEGIN          (* File header - last one  *)
  434.       IF (OldTry > MaxTry) THEN   (* tries ? *)
  435.          BEGIN
  436.             State := Abort;
  437.             ErrorMsg('Old file - Too many ');
  438.          END
  439.       ELSE
  440.          BEGIN
  441.             OldTry := OldTry+1;
  442.             WITH Buf[CurrentPacket] DO
  443.                BEGIN
  444.                   IF (seq = ((n + 63) MOD 64)) THEN     (* packet number *)
  445.                      BEGIN  (* send ACK *)
  446.                         SendACK(seq);
  447.                         NumTry := 0
  448.                      END
  449.                   ELSE
  450.                      BEGIN
  451.                         SendNAK(n);   (* NAK *)
  452.                      END;
  453.                END;
  454.          END;
  455.    END;
  456.  
  457. PROCEDURE DoEOF;  (* Process EOF packet *)
  458.    BEGIN                 (* EOF - this one *)
  459.       IF (Buf[CurrentPacket].seq <> n) THEN   (* packet number ? *)
  460.          SendNAK(n) (* NAK *)
  461.       ELSE
  462.          BEGIN               (* send ACK *)
  463.             SendACK(n);
  464.             Sclose(DiskFile);  (* close file *)
  465.             DiskFile := StdIOError;
  466.             OldTry := NumTry;
  467.             NumTry := 0;
  468.             n := (n+1) MOD 64; (* next packet  *)
  469.             State := FileHeader;   (* change state *)
  470.          END;
  471.    END;
  472.  
  473. PROCEDURE ReceiveData;  (* Receive data packets *)
  474.    VAR
  475.       strend: Integer;
  476.       packetnum: istring;
  477.       good : Boolean;
  478.  
  479.    BEGIN
  480.       IF (NumTry > MaxTry) THEN    (* check number of tries *)
  481.          BEGIN
  482.             State := Abort;
  483.             ErrorInt('Recv data -Too many ', n)
  484.          END
  485.       ELSE
  486.          BEGIN
  487.             NumTry := NumTry+1;                (* increase number of tries *)
  488.             good := ReceivePacket;        (* get packet *)
  489.             WITH Buf[CurrentPacket] DO
  490.                BEGIN
  491.                   IF Verbosity THEN
  492.                      BEGIN
  493.                         ErrorInt('Receiving (Data) ', Buf[CurrentPacket].seq);
  494.                      END ;
  495.  
  496.                   IF ((ptype = TYPED) OR (ptype=TYPEZ)
  497.                       OR (ptype=TYPEF)) AND good  THEN   (* check type *)
  498.                      CASE ptype OF
  499.                         TYPED:  DoData;
  500.                         TYPEF:  DoFileLast;
  501.                         TYPEZ:  DoEOF;
  502.                         END (* case *)
  503.                   ELSE
  504.                      BEGIN
  505.                         Verbose('Expected data pack');
  506.                         SendNAK(n);
  507.                      END;
  508.                END;
  509.          END;
  510.    END;
  511.  
  512. PROCEDURE DoBreak; (* Process Break packet *)
  513.    BEGIN                    (* Break transmission *)
  514.       IF (Buf[CurrentPacket].seq <> n) THEN  (* packet number ? *)
  515.          SendNAK(n) (* NAK *)
  516.       ELSE
  517.          BEGIN            (* send  ACK *)
  518.             SendACK(n) ;
  519.             State := Complete  (* change state *)
  520.          END
  521.    END;
  522.  
  523. PROCEDURE DoFile; (* Process file packet *)
  524.    BEGIN                 (* File Header *)
  525.       WITH Buf[CurrentPacket] DO
  526.          BEGIN
  527.             IF (seq <> n) THEN         (* packet number ? *)
  528.                SendNAK(n)  (* NAK *)
  529.             ELSE
  530.                BEGIN               (* send ACK *)
  531.                   SendACK(n);
  532.                   ChInFile := ChInFile + ilength(data) ;
  533.                   GetFile(data);   (* get file name *)
  534.                   OldTry := NumTry;
  535.                   NumTry := 0;
  536.                   n := (n+1) MOD 64; (* next packet  *)
  537.                   State := FileData;   (* change state *)
  538.                END;
  539.          END;
  540.    END;
  541.  
  542. PROCEDURE DoEOFLast; (* Process EOF Packet *)
  543.    BEGIN               (* End Of File Last One*)
  544.       IF (OldTry > MaxTry) THEN (* tries ? *)
  545.          BEGIN
  546.             State := Abort;
  547.             ErrorMsg('Old EOF - Too many');
  548.          END
  549.       ELSE
  550.          BEGIN
  551.             OldTry := OldTry+1;
  552.             WITH Buf[CurrentPacket] DO
  553.                BEGIN
  554.                   IF (seq =((n + 63 ) MOD 64)) THEN   (* packet number *)
  555.                      BEGIN  (* send ACK *)
  556.                         SendACK(seq);
  557.                         Numtry := 0
  558.                      END
  559.                   ELSE
  560.                      BEGIN
  561.                         SendNAK(n);  (* NAK *)
  562.                      END
  563.                END;
  564.          END;
  565.    END;
  566.  
  567. PROCEDURE DoInitLast;
  568.    BEGIN                (* Init Packet - last one *)
  569.       IF (OldTry > MaxTry) THEN  (* number of tries? *)
  570.          BEGIN
  571.             State := Abort;
  572.             ErrorMsg('Old init - Too many');
  573.          END
  574.       ELSE
  575.          BEGIN
  576.             OldTry := OldTry+1;
  577.             (* packet number *)
  578.             IF (Buf[CurrentPacket].seq = ((n + 63) MOD  64)) THEN
  579.                BEGIN   (* send ACK *)
  580.                   WITH Buf[ThisPacket] DO
  581.                      BEGIN
  582.                         count := NUMPARAM;
  583.                         seq := Buf[CurrentPacket].seq;
  584.                         ptype := TYPEY;
  585.                         EnCodeParm(data);
  586.                      END;
  587.                   SendPacket;
  588.                   NumACK := NumACK+1;
  589.                   NumTry := 0;
  590.                END
  591.             ELSE
  592.                BEGIN
  593.                   SendNAK(n);  (* NAK *)
  594.                END;
  595.          END;
  596.    END;
  597.  
  598. PROCEDURE ReceiveFile; (* receive file packet *)
  599.    VAR
  600.       good: Boolean;
  601.  
  602.    BEGIN
  603.       IF (NumTry > MaxTry) THEN     (* check number of tries *)
  604.          BEGIN
  605.             State := Abort;
  606.             ErrorMsg('Recv file - Too many');
  607.          END
  608.       ELSE
  609.          BEGIN
  610.             NumTry := NumTry+1;                (* increase number of tries *)
  611.             good := ReceivePacket;             (* get packet *)
  612.             WITH Buf[CurrentPacket] DO
  613.                BEGIN
  614.                   IF Verbosity THEN BEGIN
  615.                      ErrorInt('Receiving (File) ', seq)
  616.                   END;
  617.  
  618.                   (* Set up for new file [pgt002] *)
  619.                   OldChInFile := ChInFile ; (* Start value *)
  620.                   BadPackets := 0 ;
  621.  
  622.                   SSetCursor(250, 100) ;
  623.                   Write('File: ');
  624.                   PutStr(data,stdout);
  625.                   Write(' ':10) ; (* blank the end  of any other names *)
  626.  
  627.                   IF ((ptype = TYPES) OR (ptype=TYPEZ)
  628.                       OR (ptype=TYPEF) OR (ptype=TYPEB)) (* check type *)
  629.                   AND good    THEN
  630.                      CASE ptype OF
  631.                         TYPES:  DoInitLast;
  632.                         TYPEZ:  DoEOFLast;
  633.                         TYPEF:  DoFile;
  634.                         TYPEB:  DoBreak;
  635.                         END (* case *)
  636.                   ELSE
  637.                      BEGIN
  638.                         IF Debug THEN   ErrorMsg('Expected File Pack');
  639.                         SendNAK(n);
  640.                      END;
  641.                END;
  642.          END;
  643.    END;
  644.  
  645.  
  646. PROCEDURE RecvSwitch; (* this procedure is the main receive routine *)
  647.  
  648.    HANDLER GotErrorPacket( VAR msg: istring ) ;
  649.      (* Handle any error packets reveived. Write msg and exit *)
  650.      BEGIN
  651.         Inverse( TRUE ) ;
  652.         Writeln ;
  653.         Writeln('?RECV received error packet from other Host');
  654.         putstr(msg, STDOUT) ;
  655.         Writeln ;
  656.         Inverse( FALSE ) ;
  657.         SClose( DiskFile ) ;  (* Close the file, if open *)
  658.         State := Abort ;
  659.         EXIT( RecvSwitch )
  660.      END ;
  661.  
  662.    BEGIN
  663.       State := Init;
  664.       NumTry := 0;
  665.  
  666.       OldChInFile := ChInFile ; (* Start value *)
  667.       BadPackets := 0 ;
  668.  
  669.       (* set up the progress reports (c.f. ReceiveFile too) [pgt002] *)
  670.       IF NOT Verbosity THEN
  671.          BEGIN
  672.            SPutChr(FF) ; (* clear the screen *)
  673.            SSetCursor(200, 150);   Write( 'Current Packet' );
  674.            SSetCursor(200, 170);   Write( 'Characters received' );
  675.            SSetCursor(200, 190);   Write( 'Bad packets received' )
  676.          END ;
  677.  
  678.  
  679.       REPEAT
  680.  
  681.          (* Each time thru' the loop print the values [pgt002] *)
  682.          IF NOT Verbosity THEN
  683.             BEGIN
  684.               SSetCursor(410, 150);  Write( n:8 ) ;
  685.               SSetCursor(410, 170);  Write( (ChInFile-OldChInFile):10:0 ) ;
  686.               SSetCursor(410, 190);  Write( BadPackets:8 )
  687.             END ;
  688.  
  689.  
  690.          CASE State OF
  691.             FileData:       ReceiveData;
  692.             Init:           ReceiveInit;
  693.             Break:          (* nothing *);
  694.             FileHeader:     ReceiveFile;
  695.             EOFile:         (* nothing *);
  696.             Complete:       (* nothing *);
  697.             Abort:          (* nothing *);
  698.          END; (* case *)
  699.  
  700.       UNTIL ( State = Abort ) OR ( State = Complete );
  701.  
  702.       SSetCursor(10, 250) ;
  703.       Writeln
  704.    END.
  705.  
  706.