home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / CUNIT_20 / ANSIUNIT.PAS next >
Pascal/Delphi Source File  |  1992-03-18  |  15KB  |  463 lines

  1. Unit AnsiUnit;
  2.  
  3. Interface
  4.  
  5. Uses  Dos, Crt;
  6.  
  7. Var
  8.   Ansi                : Text;     { Ansi is the name of the device }
  9.   Wrap                : Boolean;  { True if Cursor should wrap }
  10.   ReportedX,
  11.   ReportedY           : Word;     { X,Y reported }
  12.  
  13.   { Hook for handling control chars i.e. Ch < Space }
  14.   WriteHook           : Procedure(Ch : Char);
  15.  
  16.   { hook for implementing Your own Device Status Report procedure }
  17.   ReplyHook           : Procedure(St : String);
  18.  
  19.   { Hook for handling simultaneous writes to ComPort and Screen }
  20.   BBsHook       : Procedure (Ch : Char);
  21.  
  22. Function In_Ansi    : Boolean;    { True if a sequence is pending }
  23. Procedure AnsiWrite(Ch: Char);
  24.  
  25. Procedure AssignAnsi(Var f : Text); { use like AssignCrt }
  26.  
  27. Implementation
  28.  
  29. Type
  30.   States              = (Waiting, Bracket, Get_Args, Get_Param, Eat_Semi,
  31.                          Get_String, In_Param, Get_Music);
  32. Const
  33.   St                  : String = '';
  34.   ParamArr            : Array[1..10] Of Word = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  35.   Params              : Word = 0; { number of parameters }
  36.   NextState           : States = Waiting; { next state for the parser }
  37.   Reverse             : Boolean = False; { true if text attributes are reversed }
  38.  
  39. Var
  40.   Quote               : Char;
  41.   SavedX, SavedY      : Word;
  42.  
  43.   Function In_Ansi    : Boolean;  { True if a sequence is pending }
  44.   Begin
  45.     In_Ansi := (NextState <> Waiting) And (NextState <> Bracket);
  46.   End {In_Ansi} ;
  47.  
  48.   Function ms(w: word): string;
  49.  
  50.     var s: string;
  51.  
  52.     begin
  53.       str(w,s);
  54.       Ms := s;
  55.     end;
  56.  
  57.  
  58.   {$F+}
  59.   Procedure Report(St : String);
  60.     {$F-}
  61.   Begin
  62.     {StuffString(St);}
  63.   End;
  64.  
  65.   {$F+}
  66.   Procedure WriteChar(Ch : Char);
  67.     {$F-}
  68.   Begin
  69.     Case Ch Of
  70.       #7 :
  71.         Begin
  72.           NoSound;
  73.           Sound(500);
  74.           Delay(50);
  75.           NoSound;
  76.           Delay(50);
  77.         End;
  78.       #8 : If (WhereX > 1) Then Write(#8' '#8);
  79.       #9 : If (WhereX < 71) Then
  80.            Repeat
  81.              GotoXy(WhereX + 1, Wherey);
  82.            Until (WhereX Mod 8 = 1);
  83.       Else
  84.         Write(Ch);
  85.     End {Case} ;
  86.   End {WriteChar} ;
  87.  
  88.   {$F+}
  89.   Procedure Dummy(St : String);
  90.     {$F-}
  91.   Begin
  92.   End;
  93.  
  94.   Procedure AnsiWrite(Ch: Char);
  95.  
  96.   Var
  97.     i                   : Word;
  98.  
  99.   Label Command;
  100.  
  101.   Begin
  102.     If Ch = #27 Then
  103.     Begin
  104.       NextState := Bracket;
  105.       Exit;
  106.     End;
  107.     Case NextState Of
  108.       Waiting : If (Ch > ' ') Then Write(Ch)
  109.                 Else WriteHook(Ch);
  110.       Bracket :
  111.         Begin
  112.           If Ch <> '[' Then
  113.           Begin
  114.             NextState := Waiting;
  115.             If (Ch > ' ') Then Write(Ch)
  116.             Else WriteHook(Ch);
  117.             Exit;
  118.           End;
  119.           St := '';
  120.           Params := 1;
  121.           FillChar(ParamArr, 10, 0);
  122.           NextState := Get_Args;
  123.         End;
  124.       Get_Args, Get_Param, Eat_Semi :
  125.         Begin
  126.           {$IFNDEF Music}
  127.           If (NextState = Get_Args) And ((Ch = '=') Or (Ch = '?')) Then
  128.           Begin
  129.             NextState := Get_Param;
  130.             Exit;
  131.           End;
  132.           {$ELSE}
  133.           If (NextState = Get_Args) Then
  134.             Case Ch Of
  135.               '=', '?' :
  136.                 Begin
  137.                   NextState := Get_Param;
  138.                   Exit;
  139.                 End;
  140.               'M' :
  141.                 Begin
  142.                   NextState := Get_Music;
  143.                   Exit;
  144.                 End;
  145.             End {Case} ;
  146.           {$ENDIF}
  147.           If (NextState = Eat_Semi) And (Ch = ';') Then
  148.           Begin
  149.             If Params < 10 Then Inc(Params);
  150.             NextState := Get_Param;
  151.             Exit;
  152.           End;
  153.           Case Ch Of
  154.             '0'..'9' :
  155.               Begin
  156.                 ParamArr[Params] := Ord(Ch) - Ord('0');
  157.                 NextState := In_Param;
  158.               End;
  159.             ';' :
  160.               Begin
  161.                 If Params < 10 Then Inc(Params);
  162.                 NextState := Get_Param;
  163.               End;
  164.             '"', '''' :
  165.               Begin
  166.                 Quote := Ch;
  167.                 St := St + Ch;
  168.                 NextState := Get_String;
  169.               End;
  170.             Else
  171.               GoTo Command;
  172.           End {Case Ch} ;
  173.         End;
  174.       Get_String :
  175.         Begin
  176.           St := St + Ch;
  177.           If Ch <> Quote
  178.           Then NextState := Get_String
  179.           Else NextState := Eat_Semi;
  180.         End;
  181.       In_Param :                  { last char was a digit }
  182.         Begin
  183.           { looking for more digits, a semicolon, or a command char }
  184.           Case Ch Of
  185.             '0'..'9' :
  186.               Begin
  187.                 ParamArr[Params] := ParamArr[Params] * 10 + Ord(Ch) - Ord('0');
  188.                 NextState := In_Param;
  189.                 Exit;
  190.               End;
  191.             ';' :
  192.               Begin
  193.                 If Params < 10 Then Inc(Params);
  194.                 NextState := Eat_Semi;
  195.                 Exit;
  196.               End;
  197.           End {Case Ch} ;
  198. Command:
  199.           NextState := Waiting;
  200.           Case Ch Of
  201.             { Note: the order of commands is optimized for execution speed }
  202.             'm' :                 {sgr}
  203.               Begin
  204.                 For i := 1 To Params Do
  205.                 Begin
  206.                   If Reverse Then TextAttr := TextAttr Shr 4 + TextAttr Shl 4;
  207.                   Case ParamArr[i] Of
  208.                     0 :
  209.                       Begin
  210.                         Reverse := False;
  211.                         TextAttr := 7;
  212.                       End;
  213.                     1 : TextAttr := TextAttr And $FF Or $08;
  214.                     2 : TextAttr := TextAttr And $F7 Or $00;
  215.                     4 : TextAttr := TextAttr And $F8 Or $01;
  216.                     5 : TextAttr := TextAttr Or $80;
  217.                     7 : If Not Reverse Then
  218.                         Begin
  219.                       {
  220.                       TextAttr := TextAttr shr 4 + TextAttr shl 4;
  221.                       }
  222.                           Reverse := True;
  223.                         End;
  224.                     22 : TextAttr := TextAttr And $F7 Or $00;
  225.                     24 : TextAttr := TextAttr And $F8 Or $04;
  226.                     25 : TextAttr := TextAttr And $7F Or $00;
  227.                     27 : If Reverse Then
  228.                          Begin
  229.                            Reverse := False;
  230.                       {
  231.                       TextAttr := TextAttr shr 4 + TextAttr shl 4;
  232.                       }
  233.                          End;
  234.                     30 : TextAttr := TextAttr And $F8 Or $00;
  235.                     31 : TextAttr := TextAttr And $F8 Or $04;
  236.                     32 : TextAttr := TextAttr And $F8 Or $02;
  237.                     33 : TextAttr := TextAttr And $F8 Or $06;
  238.                     34 : TextAttr := TextAttr And $F8 Or $01;
  239.                     35 : TextAttr := TextAttr And $F8 Or $05;
  240.                     36 : TextAttr := TextAttr And $F8 Or $03;
  241.                     37 : TextAttr := TextAttr And $F8 Or $07;
  242.                     40 : TextAttr := TextAttr And $8F Or $00;
  243.                     41 : TextAttr := TextAttr And $8F Or $40;
  244.                     42 : TextAttr := TextAttr And $8F Or $20;
  245.                     43 : TextAttr := TextAttr And $8F Or $60;
  246.                     44 : TextAttr := TextAttr And $8F Or $10;
  247.                     45 : TextAttr := TextAttr And $8F Or $50;
  248.                     46 : TextAttr := TextAttr And $8F Or $30;
  249.                     47 : TextAttr := TextAttr And $8F Or $70;
  250.                   End {Case} ;
  251.                   { fixup for reverse }
  252.                   If Reverse Then TextAttr := TextAttr Shr 4 + TextAttr Shl 4;
  253.                 End;
  254.               End;
  255.             'A' :                 {cuu}
  256.               Begin
  257.                 If ParamArr[1] = 0 Then ParamArr[1] := 1;
  258.                 If (Wherey - ParamArr[1] >= 1)
  259.                 Then GotoXy(WhereX, Wherey - ParamArr[1])
  260.                 Else GotoXy(WhereX, Hi(WindMax));
  261.               End;
  262.             'B' :                 {cud}
  263.               Begin
  264.                 If ParamArr[1] = 0 Then ParamArr[1] := 1;
  265.                 If (Wherey + ParamArr[1] <= Hi(WindMax))
  266.                 Then GotoXy(WhereX, Wherey + ParamArr[1])
  267.                 Else GotoXy(WhereX, 1);
  268.               End;
  269.             'C' :                 {cuf}
  270.               Begin
  271.                 If ParamArr[1] = 0 Then ParamArr[1] := 1;
  272.                 If WhereX + ParamArr[1] <= Lo(WindMax)
  273.                 Then GotoXy(WhereX + ParamArr[1], Wherey)
  274.                 Else GotoXy(Lo(WindMax), Wherey);
  275.               End;
  276.             'D' :                 {cub}
  277.               Begin
  278.                 If ParamArr[1] = 0 Then ParamArr[1] := 1;
  279.                 If (WhereX - ParamArr[1] >= 1)
  280.                 Then GotoXy(WhereX - ParamArr[1], Wherey)
  281.                 Else GotoXy(1, Wherey);
  282.               End;
  283.             'H', 'f' :            {cup,hvp}
  284.               Begin
  285.                 If ParamArr[1] = 0 Then ParamArr[1] := 1;
  286.                 If ParamArr[2] = 0 Then ParamArr[2] := 1;
  287.                 GotoXy(ParamArr[2], ParamArr[1]);
  288.               End;
  289.             'J' :                 {EID}
  290.               Case ParamArr[1] Of
  291.                 2 : ClrScr;
  292.              (*
  293.                 0 :               {ClrEos}
  294.                   Begin
  295.                     ClrEol;
  296.                     ScrollWindowDown(Lo(WindMin) + 1, Hi(WindMin) + Wherey + 1,
  297.                                      Lo(WindMax) + 1, Hi(WindMax) + 1, 0);
  298.                   End;
  299.                 1 :               {Clear from beginning of screen}
  300.                   Begin
  301.                     ScrollWindowDown(Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  302.                                      Lo(WindMin) + WhereX,
  303.                                      Hi(WindMin) + Wherey, 0);
  304.                     ScrollWindowDown(Lo(WindMin) + 1, Hi(WindMin) + 1,
  305.                                      Lo(WindMax) + 1, Hi(WindMin) + Wherey - 1, 0);
  306.                   End;
  307.               *)
  308.               End {Case} ;
  309.             'K' :                 {eil}
  310.               Case ParamArr[1] Of
  311.                 0 : ClrEol;
  312.               (*
  313.                 1 :               { clear from beginning of line to cursor }
  314.                   ScrollWindowDown(Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  315.                                    Lo(WindMin) + WhereX - 1,
  316.                                    Hi(WindMin) + Wherey, 0);
  317.                 2 :               { clear entire line }
  318.                   ScrollWindowDown(Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  319.                                    Lo(WindMax) + 1,
  320.                                    Hi(WindMin) + Wherey, 0);
  321.                *)
  322.               End {Case ParamArr} ;
  323.             'L' : {il } For i := 1 To ParamArr[1] Do InsLine; { must not move cursor }
  324.             'M' : {d_l} For i := 1 To ParamArr[1] Do DelLine; { must not move cursor }
  325.             'P' :                 {dc }
  326.               Begin
  327.               End;
  328.             'R' :                 {cpr}
  329.               Begin
  330.                 ReportedY := ParamArr[1];
  331.                 ReportedX := ParamArr[2];
  332.               End;
  333.             '@' :                 {ic}
  334.               Begin
  335.                 { insert blank chars }
  336.               End;
  337.             'h', 'l' :            {sm/rm}
  338.               Case ParamArr[1] Of
  339.                 0 : TextMode(BW40);
  340.                 1 : TextMode(CO40);
  341.                 2 : TextMode(BW80);
  342.                 3 : TextMode(CO80);
  343.                 4 : {GraphMode(320x200 col)} ;
  344.                 5 : {GraphMode(320x200 BW)} ;
  345.                 6 : {GraphMode(640x200 BW)} ;
  346.                 7 : Wrap := Ch = 'h';
  347.               End {case} ;
  348.             'n' :                 {dsr}
  349.               If (ParamArr[1] = 6) Then
  350.                 ReplyHook(#27'[' + ms(Wherey) + ';' +
  351.                           ms(WhereX) + 'R');
  352.             's' :                 {scp}
  353.               Begin
  354.                 SavedX := WhereX;
  355.                 SavedY := Wherey;
  356.               End;
  357.             'u' : {rcp} GotoXy(SavedX, SavedY);
  358.             Else
  359.               Begin
  360.                 If (Ch > ' ') Then Write(Ch)
  361.                 Else WriteHook(Ch);
  362.                 Exit;
  363.               End;
  364.           End {Case Ch} ;
  365.         End;
  366.       {$IFDEF Music}
  367.       Get_Music :
  368.         Begin
  369.           If Ch <> #3             {Ctrl-C}
  370.           Then St := St + Ch
  371.           Else
  372.           Begin
  373.             NextState := Waiting;
  374.           End;
  375.         End;
  376.       {$ENDIF}
  377.     End {Case NextState} ;
  378.   End {AnsiWrite} ;
  379.  
  380.   {$IFNDEF Small}
  381.  
  382.   {$F+}                           { All Driver function must be far }
  383.  
  384.   Function Nothing(Var f : TextRec) : Integer;
  385.   Begin
  386.     Nothing := 0;
  387.   End {Nothing} ;
  388.  
  389.   Procedure Null(Ch : Char);
  390.   Begin
  391.     {}
  392.   End {Null} ;
  393.  
  394.   Function DevOutput(Var f : TextRec) : Integer;
  395.   Var
  396.     i                   : Integer;
  397.   Begin
  398.     With f Do
  399.     Begin
  400.       { f.BufPos contains the number of chars in the buffer }
  401.       { f.BufPtr^ is your buffer                            }
  402.       { Any variable conversion done by writeln is already  }
  403.       { done by now.                                        }
  404.       i := 0;
  405.       While i < BufPos Do
  406.       Begin
  407.         AnsiWrite(BufPtr^[i]);
  408.         {$IFDEF BBS}
  409.         BBSHook(BufPtr^[i]);
  410.         {$ENDIF}
  411.         Inc(i);
  412.       End;
  413.       BufPos := 0;
  414.     End;
  415.     DevOutput := 0;               { return IOResult Error codes here }
  416.   End {DevOutput} ;
  417.  
  418.   Function DevOpen(Var f : TextRec) : Integer;
  419.   Begin
  420.     With f Do
  421.     Begin
  422.       If Mode = FmInput Then
  423.       Begin
  424.         InOutFunc := @Nothing;
  425.         FlushFunc := @Nothing;
  426.       End
  427.       Else
  428.       Begin
  429.         Mode := FmOutput;         { in case it was FmInOut }
  430.         InOutFunc := @DevOutput;
  431.         FlushFunc := @DevOutput;
  432.       End;
  433.       CloseFunc := @Nothing;
  434.     End;
  435.     DevOpen := 0;                 { return IOResult error codes here }
  436.   End {DevOpen} ;
  437.  
  438.   Procedure AssignAnsi(Var f : Text);
  439.   Begin
  440.     FillChar(f, SizeOf(f), #0);   { init file var }
  441.     With TextRec(f) Do
  442.     Begin
  443.       Handle := $ffff;
  444.       Mode := FmClosed;
  445.       BufSize := SizeOf(Buffer);
  446.       BufPtr := @Buffer;
  447.       OpenFunc := @DevOpen;
  448.       Name[0] := #0;
  449.     End;
  450.   End {AssignAnsi} ;
  451.   {$ENDIF}
  452.  
  453. Begin
  454.  
  455.   AssignAnsi(Ansi);               { set up the variable }
  456.   Rewrite(Ansi);                  { open it for output  }
  457.  
  458.   Wrap := True;
  459.   ReplyHook := Report;
  460.   WriteHook := WriteChar;
  461.  
  462. End.
  463.