home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / TUFPRINT.ZIP / TUFPRINT.PAS
Encoding:
Pascal/Delphi Source File  |  1985-12-28  |  6.2 KB  |  197 lines

  1. PROGRAM Printer;
  2.     {-demonstrate print error control}
  3.  
  4.     {***********************************************************************
  5.     the following can be included verbatim into a program}
  6.  
  7.   TYPE
  8.     Printers = (LPT1, LPT2, LPT3, LPT4, NoPrinter);
  9.   CONST
  10.     ActivePrinter : Printers = NoPrinter;
  11.   VAR
  12.     SavePrintTimeOut : Byte;
  13.     {
  14.     the following bytes normally equal $14, providing 20 retries on printer
  15.     busy calls. Set to 1 for a single retry (timeout takes about 2 seconds).
  16.     Do not set to 0 or system will retry forever.
  17.     }
  18.     PrintTimeOut : ARRAY[Printers] OF Byte ABSOLUTE $40 : $78;
  19.  
  20.  
  21.   PROCEDURE PrintChar(ch : Char);
  22.       {-print the character ch, handle errors and loop when busy}
  23.       {
  24.       **********************************************************************
  25.       CANNOT USE TURBO I/O FUNCTIONS INSIDE HERE DUE TO RE-ENTRANCY PROBLEMS
  26.       **********************************************************************
  27.       }
  28.  
  29.     TYPE
  30.       PrintErrors =
  31.       (TimeOut, unused1, unused2, IOerror, Selected,
  32.       OutOfPaper, Acknowledge, Busy, NoError);
  33.  
  34.       DisplayString = STRING[80];
  35.  
  36.       registers =
  37.       RECORD
  38.         CASE Integer OF
  39.           1 : (ax, bx, cx, dx, bp, si, di, ds, es, flags : Integer);
  40.           2 : (al, ah, bl, bh, cl, ch, dl, dh : Byte);
  41.       END;
  42.  
  43.     CONST
  44.       PrintErrorMsg : ARRAY[PrintErrors] OF DisplayString =
  45.       ('Printer Timeout Error', '', '', 'Printer Not Selected',
  46.       'Printer Not Selected', 'Printer Out of Paper',
  47.       'Printer Acknowledge Error', 'Printer Busy', '');
  48.  
  49.       EndStr : DisplayString = #13#10#36;
  50.  
  51.       {maximum number of replies with busy before calling it a timeout error.
  52.       may need to be adjusted empirically to avoid false timeouts}
  53.       BusyMax = 100;
  54.  
  55.     VAR
  56.       reg : registers;
  57.       Error : PrintErrors;
  58.       BusyCount : Integer;
  59.  
  60.     PROCEDURE writestring(s : DisplayString);
  61.         {-write string to standard output}
  62.       VAR
  63.         reg : registers;
  64.       BEGIN
  65.         reg.ah := 9;
  66.         reg.ds := Seg(s);
  67.         reg.dx := Ofs(s[1]);
  68.         MsDos(reg);
  69.       END;                    {displaystring}
  70.  
  71.     PROCEDURE getchar(VAR response : Char);
  72.         {-get a character from the keyboard}
  73.       VAR
  74.         reg : registers;
  75.       BEGIN
  76.         reg.ah := 0;
  77.         Intr($16, reg);
  78.         response := Chr(reg.al);
  79.       END;                    {getchar}
  80.  
  81.     FUNCTION AnyError(VAR Error : PrintErrors)
  82.         : Boolean;
  83.         {-check all the possible printer errors}
  84.         {-return TRUE and error if any found}
  85.  
  86.       FUNCTION SingleError(check : PrintErrors; VAR Error : PrintErrors)
  87.           : Boolean;
  88.           {-return true if specified error was found, setting error}
  89.         BEGIN
  90.           SingleError := ((1 SHL Ord(check)) AND reg.ah) <> 0;
  91.           Error := check;
  92.         END;                  {singleerror}
  93.  
  94.       BEGIN
  95.         AnyError := True;
  96.         IF SingleError(Busy, Error) THEN Exit;
  97.         IF SingleError(OutOfPaper, Error) THEN Exit;
  98.         IF SingleError(IOerror, Error) THEN Exit;
  99.         {polarity of "selected" flag is opposite of others}
  100.         IF NOT(SingleError(Selected, Error)) THEN Exit;
  101.         {made it through with no errors}
  102.         Error := NoError;
  103.         AnyError := False;
  104.       END;                    {anyerror}
  105.  
  106.     PROCEDURE HandleError(VAR Error : PrintErrors);
  107.         {-handle user-oriented error conditions}
  108.       VAR
  109.         response : Char;
  110.       BEGIN
  111.         IF (Error = NoError) THEN Exit;
  112.         IF (Error = Busy) THEN BEGIN
  113.           BusyCount := Succ(BusyCount);
  114.           IF BusyCount < BusyMax THEN Exit;
  115.           {busy too long, call it a timeout}
  116.           Error := TimeOut;
  117.         END;
  118.         {
  119.         prompt user to correct the error condition. screen handling could
  120.         be much fancier here but it cannot use Turbo I/O functions.
  121.         }
  122.         writestring(PrintErrorMsg[Error]+EndStr);
  123.         writestring('Correct condition and then press <ENTER> '+#36);
  124.         REPEAT
  125.           getchar(response);
  126.         UNTIL (response IN [#13, #3]);
  127.         writestring(EndStr);
  128.         IF response = #3 THEN Halt; {Ctrl-C}
  129.         BusyCount := 0;
  130.       END;                    {handleerror}
  131.  
  132.     BEGIN
  133.       IF ActivePrinter = NoPrinter THEN BEGIN
  134.         writestring('program error: no printer is selected'+EndStr);
  135.         Exit;
  136.       END;
  137.       reg.dx := Ord(ActivePrinter); {equals 0..3}
  138.       BusyCount := 0;
  139.  
  140.       REPEAT
  141.         {check printer status}
  142.         reg.ah := 2;
  143.         Intr($17, reg);
  144.  
  145.         {check for errors}
  146.         IF AnyError(Error) AND (Error <> Busy) THEN
  147.           HandleError(Error)
  148.         ELSE BEGIN
  149.           {print the character}
  150.           reg.ax := Ord(ch);
  151.           Intr($17, reg);
  152.           {check for errors again}
  153.           IF AnyError(Error) THEN
  154.             HandleError(Error);
  155.         END;
  156.       UNTIL Error = NoError;
  157.  
  158.     END;                      {printchar}
  159.  
  160.   PROCEDURE ProtectPrinter(Printer : Printers);
  161.       {-define the Lst device to print to the specified printer}
  162.     BEGIN
  163.       IF ActivePrinter = NoPrinter THEN BEGIN
  164.         ActivePrinter := Printer;
  165.         LstOutPtr := Ofs(PrintChar);
  166.         {save current printer timeout}
  167.         SavePrintTimeOut := PrintTimeOut[Printer];
  168.         {set to minimum timeout period}
  169.         PrintTimeOut[Printer] := 1;
  170.       END ELSE
  171.         WriteLn(Con,
  172.         'program error: only one printer can be protected at a time');
  173.     END;                      {protectprinter}
  174.  
  175.   PROCEDURE RestorePrinter;
  176.       {-deassign the Lst device and restore the printer timeout}
  177.     BEGIN
  178.       IF ActivePrinter <> NoPrinter THEN BEGIN
  179.         PrintTimeOut[ActivePrinter] := SavePrintTimeOut;
  180.         ActivePrinter := NoPrinter;
  181.       END;
  182.     END;                      {restoreprinter}
  183.  
  184.     {end of include portion
  185.     ***********************************************************************}
  186.  
  187.     {demonstration follows}
  188.   VAR
  189.     i : Integer;
  190.   BEGIN
  191.     ProtectPrinter(LPT1);
  192.     FOR i := 1 TO 5 DO
  193.       {any writes to the Lst device are now protected}
  194.       WriteLn(Lst, 'hello hello hello hello');
  195.     RestorePrinter;
  196.   END.
  197.