home *** CD-ROM | disk | FTP | other *** search
/ Point Programming 1 / PPROG1.ISO / pascal / swag / printing.swg / 0028_PRINTER Unit Replacement.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-26  |  7.3 KB  |  248 lines

  1. { Can be used as a TOTAL replacement for the PRINTER UNIT }
  2. { You'll need to replace the PRINTER unit in the TURBO.TPL to use this }
  3. {$S-,R-,V-,I-,N-,B-,F-}
  4.  
  5. {$IFNDEF Ver40}
  6. {$F+,O-,X+,A-}
  7. {$ENDIF}
  8.  
  9. {$DEFINE AssignLstDevice}
  10. {$DEFINE DoErrorChecking}   { undefine this to eliminate error checking }
  11.  
  12. UNIT Printer;
  13.  
  14. INTERFACE
  15.  
  16. {$IFDEF DoErrorChecking}
  17. USES CRT;
  18. {$ENDIF}
  19.  
  20. CONST
  21.  
  22.   fmClosed = $D7B0;               { magic numbers for Turbo }
  23.   fmInput = $D7B1;
  24.   fmOutput = $D782;
  25.   fmInOut = $D7B3;
  26.  
  27.   IO_Invalid = $FC;               { invalid operation eg. attempt to write }
  28.   { to a file opened in fmInput mode       }
  29.  
  30.   LPTNames : ARRAY [0..2] OF STRING [4] = ('LPT1', 'LPT2', 'LPT3');
  31.  
  32.   LPTPort : BYTE = 0;
  33.  
  34. VAR
  35.   Lst : TEXT;                     { for source compatability with TP3 }
  36.  
  37. FUNCTION GetROMPrinterStatus (LPTNo : WORD) : BYTE;
  38.   { status of LPTNo via ROM BIOS int 17h func 2h }
  39.   INLINE (
  40.     $5A /                         {  pop     DX    ; get printer number}
  41.     $B4 / $02 /                   {  mov     AH,02 ; set AH for BIOS int 17h function 0}
  42.     $CD / $17 /                   {  int     $17   ; do an int 17h}
  43.     $86 / $E0);                   {  xchg    AL,AH ; put byte result in AL}
  44.  
  45. FUNCTION DoInt17 (Ch : CHAR; LPTNo : WORD) : BYTE;
  46.   { send a character to LPTNo via ROM BIOS int 17h func 0h }
  47.   INLINE (
  48.     $5A /                         {  pop     DX    ; get printer number}
  49.     $58 /                         {  pop     AX    ; get char}
  50.     $B4 / $00 /                   {  mov     AH,00 ; set AH for BIOS int 17h function 0}
  51.     $CD / $17 /                   {  int     $17   ; do an int 17h}
  52.     $86 / $E0);                   {  xchg    AL,AH ; put byte result in AL}
  53.  
  54. PROCEDURE AssignLst (VAR F : TEXT; LPTNumber : WORD);
  55.   { like Turbo's assign, except associates Text variable with one of the LPTs }
  56.  
  57. PROCEDURE OutputToFile (FName : STRING);
  58.   {redirect printer output to file }
  59.  
  60. FUNCTION  PrinterStatus (LPTNum : BYTE) : BYTE;
  61.  
  62. FUNCTION  Printer_OK : BOOLEAN;
  63.  
  64. PROCEDURE SelectPrinter (LPTNum : BYTE);
  65.  
  66. PROCEDURE ResetPrinter;           { only resets printer 0 }
  67.  
  68. IMPLEMENTATION
  69.  
  70. TYPE
  71.   TextBuffer = ARRAY [0..127] OF CHAR;
  72.  
  73.   TextRec = RECORD
  74.               Handle   : WORD;
  75.               Mode     : WORD;
  76.               BufSize  : WORD;
  77.               Private  : WORD;
  78.               BufPos   : WORD;
  79.               BufEnd   : WORD;
  80.               BufPtr   : ^TextBuffer;
  81.               OpenFunc : POINTER;
  82.               InOutFunc : POINTER;
  83.               FlushFunc : POINTER;
  84.               CloseFunc : POINTER;
  85.               { 16 byte user data area, I use 4 bytes }
  86.               PrintMode : WORD;   { not currently used}
  87.               LPTNo : WORD;       { LPT number in [0..2] }
  88.               UserData : ARRAY [1..12] OF CHAR;
  89.               Name : ARRAY [0..79] OF CHAR;
  90.               Buffer : TextBuffer;
  91.             END;
  92. CONST
  93.   LPTFileopen : BOOLEAN = FALSE;
  94.  
  95. VAR
  96.   LPTExitSave : POINTER;
  97.  
  98.   PROCEDURE Out_Char (Ch : CHAR; LPTNo : WORD; VAR ErrorCode : INTEGER);
  99.     { call macro to send char to LPTNo.  If bit 4, the Printer Selected bit }
  100.     { is not set upon return, it is assumed that an error has occurred.     }
  101.  
  102.   BEGIN
  103.     ErrorCode := DoInt17 (Ch, LPTNo);
  104.     IF (ErrorCode AND $10) = $10 THEN { if bit 4 is set }
  105.       ErrorCode := 0              { no error }
  106.       { if bit 4 is not set, error is passed untouched and placed in IOResult }
  107.   END;
  108.  
  109.   FUNCTION LstIgnore (VAR F : TextRec) : INTEGER;
  110.     { A do nothing, no error routine }
  111.   BEGIN
  112.     LstIgnore := 0                { return 0 for IOResult }
  113.   END;
  114.  
  115.   FUNCTION LstOutput (VAR F : TextRec) : INTEGER;
  116.     { Send whatever has accumulated in the Buffer to int 17h   }
  117.     { If error occurs, return in IOResult.  See Inside Turbo   }
  118.     { Pascal chapter of TP4 manual for more info on TFDD       }
  119.   VAR
  120.     I : WORD;
  121.     ErrorCode : INTEGER;
  122.  
  123.   BEGIN
  124.     LstOutput := 0;
  125.  
  126.     {$IFDEF DOERRORCHECKING}
  127.     WHILE NOT Printer_OK DO
  128.     BEGIN
  129.     GotoXY(1,23);ClrEol;
  130.     Write('Please check Printer, and press any key when ready...');
  131.     Readkey;
  132.     END;
  133.     {$ENDIF}
  134.  
  135.     WITH F DO BEGIN
  136.       FOR I := 0 TO PRED (BufPos) DO
  137.       BEGIN
  138.         Out_Char (BufPtr^ [I], LPTNo, ErrorCode); { send each char to printer }
  139.         IF ErrorCode <> 0 THEN BEGIN { if error }
  140.           LstOutput := ErrorCode; { return errorcode in IOResult }
  141.           EXIT                    { return from function }
  142.         END
  143.       END;
  144.       BufPos := 0
  145.     END;
  146.   END;
  147.  
  148.   PROCEDURE AssignLst (VAR F : TEXT; LPTNumber : WORD);
  149.     { like Turbo's assign, except associates Text variable with one of the LPTs }
  150.  
  151.   BEGIN
  152.     WITH TextRec (F) DO
  153.       BEGIN
  154.         Mode := fmClosed;
  155.         BufSize := SIZEOF (Buffer);
  156.         BufPtr := @Buffer;
  157.         OpenFunc := @LstIgnore;   { you don't open the BIOS printer functions }
  158.         CloseFunc := @LstIgnore;  { nor do you close them }
  159.         InOutFunc := @LstOutput;  { but you can Write to them }
  160.         FlushFunc := @LstOutput;  { and you can WriteLn to them }
  161.         LPTNo := LPTNumber;       { user selected printer num (in [0..2]) }
  162.         MOVE (LPTNames [LPTNumber], Name, 4); { set name of device }
  163.         BufPos := 0;              { reset BufPos }
  164.       END;
  165.   END;
  166.  
  167.   PROCEDURE OutputToFile (FName : STRING);
  168.   BEGIN
  169.     ASSIGN (Lst, FName);
  170.     REWRITE (Lst);
  171.     LPTFileopen := TRUE;
  172.   END;
  173.  
  174.   FUNCTION PrinterStatus (LPTNum : BYTE) : BYTE;
  175.   VAR
  176.     Status : BYTE;
  177.   BEGIN
  178.     Status := GetROMPrinterStatus (LPTNum);
  179.     IF (Status AND $B8) = $90 THEN
  180.       PrinterStatus := 0          {all's well}
  181.     ELSE IF (Status AND $20) = $20 THEN
  182.       PrinterStatus := 1          {no Paper}
  183.     ELSE IF (Status AND $10) = $00 THEN
  184.       PrinterStatus := 2          {off line}
  185.     ELSE IF (Status AND $80) = $00 THEN
  186.       PrinterStatus := 3          {busy}
  187.     ELSE IF (Status AND $08) = $08 THEN
  188.       PrinterStatus := 4;         {undetermined error}
  189.   END;
  190.  
  191.   FUNCTION Printer_OK : BOOLEAN;
  192.   VAR
  193.     Retry : BYTE;
  194.   BEGIN
  195.     Retry := 0;
  196.     WHILE (PrinterStatus (LPTPort) <> 0) AND (Retry < 255) DO INC (Retry);
  197.     Printer_OK := (PrinterStatus (LPTPort) = 0);
  198.   END;                            {PrinterReady}
  199.  
  200.   PROCEDURE SelectPrinter (LPTNum : BYTE);
  201.   BEGIN
  202.     IF (LPTNum >= 0) AND (LPTNum <= 3) THEN
  203.       LPTPort := LPTNum;
  204.     AssignLst (Lst, LPTPort);      { set up turbo 3 compatable Lst device }
  205.     REWRITE (Lst);
  206.   END;
  207.  
  208.   PROCEDURE ResetPrinter;
  209.   VAR
  210.     address : INTEGER ABSOLUTE $0040 : $0008;
  211.     portno, DELAY : INTEGER;
  212.   BEGIN
  213.     portno := address + 2;
  214.     Port [portno] := 232;
  215.     FOR DELAY := 1 TO 2000 DO {nothing} ;
  216.     Port [portno] := 236;
  217.   END;                            {ResetPrinter}
  218.  
  219.   PROCEDURE LptExitHandler; FAR;
  220.   BEGIN
  221.     IF LPTFileopen THEN CLOSE (Lst);
  222.     ExitProc := LPTExitSave;
  223.   END;
  224.  
  225. BEGIN
  226.  
  227.   LPTExitSave := ExitProc;
  228.   ExitProc := @LptExitHandler;
  229.  
  230.   {$IFDEF AssignLstDevice}
  231.  
  232.   LPTPort := 0;
  233.   AssignLst (Lst, LPTPort);        { set up turbo 3 compatable Lst device }
  234.   REWRITE (Lst);
  235.  
  236.   {$ENDIF}
  237.  
  238.   {$IFDEF DOERRORCHECKING}
  239.   WHILE NOT Printer_OK DO
  240.   BEGIN
  241.   GotoXY(1,23);ClrEol;
  242.   Write('Please check Printer, and press any key when ready...');
  243.   Readkey;
  244.   END;
  245.   {$ENDIF}
  246.  
  247. END.
  248.