home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / MISC.ZIP / TUFPRT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-02-09  |  6.2 KB  |  210 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.   err : Byte;
  60.  
  61.   PROCEDURE writestring(s : DisplayString);
  62.    {-write string to standard output}
  63.   VAR
  64.    reg : registers;
  65.   BEGIN
  66.    reg.ah := 9;
  67.    reg.ds := Seg(s);
  68.    reg.dx := Ofs(s[1]);
  69.    MsDos(reg);
  70.   END;                        {displaystring}
  71.  
  72.   PROCEDURE getchar(VAR response : Char);
  73.    {-get a character from the keyboard}
  74.   VAR
  75.    reg : registers;
  76.   BEGIN
  77.    reg.ah := 0;
  78.    Intr($16, reg);
  79.    response := Chr(reg.al);
  80.   END;                        {getchar}
  81.  
  82.   FUNCTION AnyError(VAR Error : PrintErrors)
  83.    : Boolean;
  84.    {-check all the possible printer errors}
  85.    {-return TRUE and error if any found}
  86.  
  87.    FUNCTION SingleError(check : PrintErrors; VAR Error : PrintErrors)
  88.     : Boolean;
  89.     {-return true if specified error was found, setting error}
  90.    BEGIN
  91.     SingleError := ((1 SHL Ord(check)) AND err) <> 0;
  92.     Error := check;
  93.    END;                       {singleerror}
  94.  
  95.   BEGIN
  96.    AnyError := True;
  97.    IF SingleError(Busy, Error) THEN Exit;
  98.    IF SingleError(OutOfPaper, Error) THEN Exit;
  99.    IF SingleError(IOerror, Error) THEN Exit;
  100.    {polarity of "selected" flag is opposite of others}
  101.    IF NOT(SingleError(Selected, Error)) THEN Exit;
  102.    {made it through with no errors}
  103.    Error := NoError;
  104.    AnyError := False;
  105.   END;                        {anyerror}
  106.  
  107.   PROCEDURE HandleError(VAR Error : PrintErrors);
  108.    {-handle user-oriented error conditions}
  109.   VAR
  110.    response : Char;
  111.   BEGIN
  112.    IF (Error = NoError) THEN Exit;
  113.    IF (Error = Busy) THEN BEGIN
  114.     BusyCount := Succ(BusyCount);
  115.     IF BusyCount < BusyMax THEN Exit;
  116.     {busy too long, call it a timeout}
  117.     Error := TimeOut;
  118.    END;
  119.    {
  120.    prompt user to correct the error condition. screen handling could
  121.    be much fancier here but it cannot use Turbo I/O functions.
  122.    }
  123.    writestring(PrintErrorMsg[Error]+EndStr);
  124.    writestring('Correct condition and then press <ENTER> '+#36);
  125.    REPEAT
  126.     getchar(response);
  127.    UNTIL (response IN [#13, #3]);
  128.    writestring(EndStr);
  129.    IF response = #3 THEN Halt; {Ctrl-C}
  130.    BusyCount := 0;
  131.   END;                        {handleerror}
  132.  
  133.   PROCEDURE int17(printer : printers; func : Byte; chartoprint : Byte; VAR err : Byte);
  134.    {-call the printer interrupt and return error information}
  135.   BEGIN
  136.    INLINE(
  137.     $8B/$56/$0C/              {MOV    DX,[BP+0C] - get printer number}
  138.     $8A/$66/$0A/              {MOV    AH,[BP+0A] - get printer function}
  139.     $8A/$46/$08/              {MOV    AL,[BP+08] - get character to print}
  140.     $CD/$17/                  {INT    17}
  141.     $C4/$7E/$04/              {LES    DI,[BP+04] - get address of error}
  142.     $26/                      {ES:    }
  143.     $88/$25                   {MOV    [DI],AH - return error if any}
  144.     );
  145.   END;                        {int17}
  146.  
  147.  BEGIN
  148.   IF ActivePrinter = NoPrinter THEN BEGIN
  149.    writestring('program error: no printer is selected'+EndStr);
  150.    Exit;
  151.   END;
  152.   reg.dx := Ord(ActivePrinter); {equals 0..3}
  153.   BusyCount := 0;
  154.  
  155.   REPEAT
  156.    {check printer status}
  157.    int17(activeprinter, 2, 0, err);
  158.  
  159.    {check for errors}
  160.    IF AnyError(Error) AND (Error <> Busy) THEN
  161.     HandleError(Error)
  162.    ELSE BEGIN
  163.     {print the character}
  164.     int17(activeprinter, 0, Ord(ch), err);
  165.     {check for errors again}
  166.     IF AnyError(Error) THEN
  167.      HandleError(Error);
  168.    END;
  169.   UNTIL Error = NoError;
  170.  
  171.  END;                         {printchar}
  172.  
  173.  PROCEDURE ProtectPrinter(Printer : Printers);
  174.   {-define the Lst device to print to the specified printer}
  175.  BEGIN
  176.   IF ActivePrinter = NoPrinter THEN BEGIN
  177.    ActivePrinter := Printer;
  178.    LstOutPtr := Ofs(PrintChar);
  179.    {save current printer timeout}
  180.    SavePrintTimeOut := PrintTimeOut[Printer];
  181.    {set to minimum timeout period}
  182.    PrintTimeOut[Printer] := 1;
  183.   END ELSE
  184.    WriteLn(Con,
  185.    'program error: only one printer can be protected at a time');
  186.  END;                         {protectprinter}
  187.  
  188.  PROCEDURE RestorePrinter;
  189.   {-deassign the Lst device and restore the printer timeout}
  190.  BEGIN
  191.   IF ActivePrinter <> NoPrinter THEN BEGIN
  192.    PrintTimeOut[ActivePrinter] := SavePrintTimeOut;
  193.    ActivePrinter := NoPrinter;
  194.   END;
  195.  END;                         {restoreprinter}
  196.  
  197.  {end of include portion
  198.  ***********************************************************************}
  199.  
  200.  {demonstration follows}
  201. VAR
  202.  i : Integer;
  203. BEGIN
  204.  ProtectPrinter(LPT1);
  205.  FOR i := 1 TO 5 DO
  206.   {any writes to the Lst device are now protected}
  207.   WriteLn(Lst, 'hello hello hello hello');
  208.  RestorePrinter;
  209. END.
  210.