{
 SIDEPRNT ... sideways (rotated) printing ...
 Author --- John T. Bagwell, Jr.

Uses Character tables in the BIOS ROM sto do a simple form of
sideways printing. Character values above 127 aren't supported.

Formfeed acts as a 'page' eject, even in the middle of a line;
a line ends at CR/LF, FF, or end-of-file.

This program is designed for the Epson FX-80 or FX-85 printer.

}


program SidePrint;

const
  PrintMultipleSpacing = #27'3';
  JiggleDown = #13#27'J'#1;
  NormalSpacing = #27'2';
  GraphicsPrint = #27'*';
  LineFeed = ^J;
  FormFeed = ^L;
                            { possible choices }
  BitsPerChar =      9;   { 9  8  9  8  9  8  9  8 }
  ModeCode =        #0;   {#0 #0 #4 #4 #5 #5 #6 #6 }
  MaxLinesPerPage = 53;   {53 61 71 80 64 72 80 90 }
  MaxLineLen =    1000;   {adjust to match max lines and available space}

type
  BitMap = array[0..7] of Char;
  Line = array[1..MaxLineLen] of Char;

var
  Paper: array[1..MaxLinesPerPage] of Line;
  InFile: Text;
  InChar: Char;
  LineNo,CharNo,i,j,k,BitsPerPage,LineLen: Integer;
  Cindex,PrintMultiple: Byte;
  CharTable: array[0..127] of BitMap absolute $F000:$FA6E;  {BIOS Table}

(*---------------------------------*)
(*         READ ONE PAGE           *)
(*---------------------------------*)

procedure ReadOnePage;

var
  LineSize: array[1..91] of Integer;    {big enough for all options}
  eject: Boolean;

begin
  LineNo:=1;
  CharNo:=0;
  LineLen:=0;
  eject:=False;

  For i:=1 to MaxLinesPerPage do     {erase old lines}
    LineSize[i]:=0;

repeat
        {accumulate a line ...}
  While (not eoln(InFile)) AND (not eject) do
    begin
      Read(InFile,InChar);
      If InChar=FormFeed then          {watch for page ejects}
        If (LineNo=1) AND (CharNo=0) then
            {Ignore redundant page ejects}
        else
          eject:=True
      else
        If CharNo <= MaxLineLen then       {build a line}
          begin
            CharNo:=CharNo+1;
            Paper[LineNo,CharNo]:=InChar;
          end;
    end;

          {at end of each line ...}

    If CharNo > LineLen then             {save longest line length}
      LineLen:=CharNo;
    LineSize[LineNo]:=CharNo;
    LineNo:=LineNo+1;
    CharNo:=0;
    If eoln(InFile) then
      ReadLn(InFile);                    {get the end-of-line mark}

      {force eject when page is full ...}

    If LineNo > MaxLinesPerPage then
      eject:=True;

until eof(InFile) OR (eject);

(*  make each line the same length *)

For i:=1 to MaxLinesPerPage do
  For j:=LineSize[i]+1 to LineLen do
    Paper[i,j]:=' ';

end;   {procedure ReadOnePage}

(*--------------------------------*)
(*        PRINT ONE PAGE          *)
(*--------------------------------*)

procedure PrintOnePage;

begin
  For j:=1 to LineLen do   {each rotated 'line'... actually, each character}
    begin
      For LineNo:=1 to PrintMultiple do
        begin
          Write(Lst,GraphicsPrint,ModeCode,
            Char(Lo(BitsPerPage)),Char(Hi(BitsPerPage)));
          For i:=MaxLinesPerPage downto 1 do    {lines in reverse order}
            begin
              Cindex:=Ord(Paper[i,j]);
              If BitsPerChar = 9 then {For loop (9 to ...) req'd if it is >9}
                Write(Lst,#0);
              For k:=7 downto 0 do
                Write(Lst,CharTable[Cindex][k]);   {bottom up each char}
            end;
          Write(Lst,JiggleDown);      {C/R + microspace down}
        end;
      Write(Lst,LineFeed);            {next 'line'}
    end;
end;    {procedure PrintOnePage}


(* -------- MAIN PROGRAM -------- *)


begin

    (*  GET FILE PARAMETERS *)

  If Paramcount < 1 then
    begin
      WriteLn(^G'Missing file name on command line');
      Halt;
    end;
  Assign(InFile,Paramstr(1));     {OPEN the file}
  {$I-}
  Reset(InFile);
  {$I+}
  If IOResult <> 0 then
    begin
      WriteLn('File "',Paramstr(1),'" not found.');
      Halt;
    end;

    (*  GET /D DOUBLE-PRINT OPTION  *)

  PrintMultiple:=1;
  If Paramcount >= 2 then
    If (Paramstr(2) = '/d') OR (paramstr(2) = '/D') then
      PrintMultiple:=2;

    (*  SET UP *)

  BitsPerPage:=BitsPerChar * MaxLinesPerPage;
  Write(Lst,PrintMultipleSpacing,Char(24-PrintMultiple));   {nn/216th inch}

    (*  MAIN LOOP  *)

  Repeat       {do one "page" at a time}
    ReadOnePage;
    PrintOnePage;
    Write(Lst,FormFeed);      {do a page eject to line up properly}
  until eof(InFile);

    (*  ALL DONE  *)

  Close(InFile);
  Write(Lst,NormalSpacing);        {resume normal spacing vertically}
end.   {main program}

