[Back to PRINTING SWAG index]  [Back to Main SWAG index]  [Original]

UNIT ConPrnIO;
{ UNIT TO WRITE TO SCREEN AND PRINTER AT THE SAME TIME }

INTERFACE

  USES DOS;
  VAR
    ConPrn : Text;

  PROCEDURE SetLptNbr(PrinterPort: Byte);

IMPLEMENTATION

  VAR
    IOBuffer : ARRAY[0..255] OF Char;
    OldExitProc : Pointer;

{$F+}
  PROCEDURE ExitConPrn;
  BEGIN
    ExitProc := OldExitProc;
    Close(ConPrn)
  END;

{------------------------------}

  PROCEDURE SetLptNbr;

      FUNCTION NbrLpts: Integer;
      VAR
        Regs : Registers;
      BEGIN
        Intr($11,Regs);
        NbrLpts := Regs.AH SHR 6
      END;


  BEGIN
    IF NbrLpts = 0 THEN
      BEGIN
        WriteLn('No printer port installed');
        Halt(1)
      END;

    WITH TextRec(ConPrn) DO
      BEGIN
        IF PrinterPort <= NbrLpts THEN
          UserData[1] := PrinterPort - 1
        ELSE
          UserData[1] := 0  {Default to LPT1}
      END
  END;

{------------------------------}

  FUNCTION OutPrn(VAR F: TextRec; ch : Char):
                                         Integer;
    FUNCTION GetPrnStatus(PrnPort: Byte): Boolean;

      VAR
        Regs : Registers;
        NbrPasses : Byte;
      CONST
        Retries : Byte = 100;

      BEGIN

        NbrPasses := 0;
        GetPrnStatus := TRUE;

        WITH Regs DO
          BEGIN
            REPEAT
               AH := $02;
               DX := F.UserData[1];
               Intr($17,Regs);
               AH := AH AND $90;
               IF (AH <> $90) AND
                  (NbrPasses < Retries) THEN
                 Inc(NbrPasses)
            UNTIL (NbrPasses > Retries) OR
                  (AH = $90);
            IF AH <> $90 THEN
               GetPrnStatus := FALSE;
          END
      END;


    VAR
      Regs : Registers;
      ChByte : Byte;

    BEGIN
      ChByte := Ord(ch);
      WITH Regs DO
        BEGIN
          IF GetPrnStatus(F.UserData[1]) THEN
            BEGIN
              AH := $00;
              AL := ChByte;
              DX := F.UserData[1];
              Intr($17,Regs);
              OutPrn := 0;
            END
          ELSE
            OutPrn := 160
        END
      END;

{------------------------------}

  FUNCTION InOutConPrn(VAR F: TextRec): Integer;


    PROCEDURE OutCon(ch : Char; DspPage : Byte);
    VAR
      Regs : Registers;
    BEGIN
      Regs.AH := $0E;        {Write TTY character}
      Regs.AL := Byte(ch);
      Regs.BH := DspPage;
      Intr($10,Regs)
    END;


  VAR
    OutputPos, DspPage : Byte;
    Regs               : Registers;
    Status               : Integer;

  BEGIN
    WITH F DO
      BEGIN
        Regs.AH := $0F; {Get Current Display Page}
        Intr($10,Regs);
        DspPage := Regs.BH;
        OutputPos := 0;
        Status := 0;
        InOutConPrn := 0;
        WHILE (OutputPos < BufPos) AND
              (Status = 0) DO
          BEGIN
            OutCon(BufPtr^[OutputPos],DspPage);
            Status := OutPrn(F,BufPtr^[OutputPos]);
            Inc(OutputPos);
            IF Status <> 0 THEN
              InOutConPrn := 160;
          END;
        BufPos := 0;
      END
  END;

{------------------------------}

  FUNCTION FlushConPrn(VAR F: TextRec): Integer;
  BEGIN
    WITH F DO
      BEGIN
        IF BufPos <> 0 THEN
          FlushConPrn := InOutConPrn(F)
        ELSE
          FlushConPrn := 0
      END
  END;

{------------------------------}

  FUNCTION CloseConPrn(VAR F: TextRec): Integer;
  {print a ff on printer when closing device}
  BEGIN
    IF F.UserData[1] < 3 THEN
       CloseConPrn := OutPrn(F,Chr(12))
  END;

{------------------------------}

  FUNCTION OpenConPrn(VAR F: TextRec): Integer;
  BEGIN
    WITH F DO
      BEGIN
        IF Mode = fmOutput THEN
          BEGIN
            InOutFunc        := @InOutConPrn;
            FlushFunc        := @FlushConPrn;
            CloseFunc        := @CloseConPrn;
            FillChar(IOBuffer,SizeOf(IOBuffer),#0);
            OpenConPrn        := 0
          END
        ELSE
          OpenConPrn := 104 {file not open
                             for input or Append}
      END
  END;

{$F-}

{------------------------------}


  PROCEDURE AssignConPrn(VAR F : Text);

  BEGIN
     WITH TextRec(F) DO
       BEGIN
         Mode             := fmClosed;
         BufSize     := SizeOf(IOBuffer);
         BufPtr             := @IOBuffer;
         OpenFunc    := @OpenConPrn;
         Name[0]     := #0
       END
  END;

{-------- UNIT INITIALIZATION SECTION ---------}


BEGIN
  AssignConPrn(ConPrn);
  Rewrite(ConPrn);

  OldExitProc := ExitProc;
  ExitProc := @ExitConPrn;

  SetLptNbr(1);               {default to LPT1}
END.

{ ------------------    TEST PROGRAM ------------------------}

PROGRAM TestConPrn;


USES DOS,CRT,Printer,ConPrnIO;


BEGIN
  ClrScr;
  WriteLn('Written to screen');
  WriteLn(ConPrn,'Written to both');
  WriteLn('Written to screen');
  WriteLn(Lst,'Written to printer only')
END.


[Back to PRINTING SWAG index]  [Back to Main SWAG index]  [Original]