home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBBS / ECO_ANSI.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-03-08  |  13.3 KB  |  415 lines

  1. unit eco_ansi;
  2. interface
  3. uses
  4.   dos, crt
  5.   
  6.   ;
  7.  
  8.  
  9. var
  10.   ansi                : text;     { ansi is the name of the device }
  11.   wrap                : boolean;  { true if cursor should wrap }
  12.   reportedx,
  13.   reportedy           : word;     { x,y reported }
  14.  
  15.   { hook for handling control chars i.e. ch < space }
  16.   writehook           : procedure(ch : char);
  17.  
  18.   { hook for implementing your own device status report procedure }
  19.   replyhook           : procedure(st : string);
  20.  
  21.   { hook for handling simultaneous writes to comport and screen }
  22.   bbshook       : procedure (ch : char);
  23.  
  24. function in_ansi    : boolean;    { true if a sequence is pending }
  25. procedure ansiwrite(s: string);
  26.  
  27. procedure assignansi(var f : text); { use like assigncrt }
  28.  
  29. implementation
  30.  
  31. type
  32.   states              = (waiting, bracket, get_args, get_param, eat_semi,
  33.                          get_string, in_param, get_music);
  34. const
  35.   st                  : string = '';
  36.   paramarr            : array[1..10] of word = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  37.   params              : word = 0; { number of parameters }
  38.   nextstate           : states = waiting; { next state for the parser }
  39.   reverse             : boolean = false; { true if text attributes are reversed }
  40.  
  41. var
  42.   quote               : char;
  43.   savedx, savedy      : word;
  44.  
  45.   function in_ansi    : boolean;  { true if a sequence is pending }
  46.   begin
  47.     in_ansi := (nextstate <> waiting) and (nextstate <> bracket);
  48.   end {in_ansi} ;
  49.  
  50.  
  51.   function ms(w: word): string;
  52.   var s: string;
  53.   begin
  54.     str(w,s);
  55.     ms := s;
  56.   end;
  57.  
  58.  
  59.   {$F+}
  60.   procedure report(st : string);
  61.   {$F-}
  62.   begin
  63.     {stuffstring(st);}
  64.   end;
  65.  
  66.  
  67.   {$F+}
  68.   procedure writechar(ch : char);
  69.   {$F-}
  70.   begin
  71.     case ch of
  72.       #7 : begin
  73.         nosound;
  74.         sound(500);
  75.         delay(50);
  76.         nosound;
  77.         delay(50);
  78.       end;
  79.       #8 : if (wherex > 1) then write(#8' '#8);
  80.       #9 : if (wherex < 71) then repeat
  81.         gotoxy(wherex + 1, wherey);
  82.       until (wherex mod 8 = 1);
  83.       else write(ch);
  84.     end { case }
  85.   end; { writechar }
  86.  
  87.   {$F+}
  88.   procedure dummy(st : string);
  89.     {$F-}
  90.   begin
  91.   end;
  92.  
  93.  
  94.   
  95.   procedure ansiwrite(s: string);
  96.   var
  97.     i  : word;
  98.     j  : byte;
  99.     ch : char;
  100.  
  101.   label command, ending;
  102.  
  103.   begin
  104.     for j := 1 to length(s) do begin
  105.       ch := s[j];
  106.       if ch = #27 then begin
  107.         nextstate := bracket;
  108.         goto ending;
  109.       end;
  110.       case nextstate of
  111.         waiting : if (ch > ' ') then write(ch) else writehook(ch);
  112.         bracket : begin
  113.           if ch <> '[' then begin
  114.             nextstate := waiting;
  115.             if (ch > ' ') then write(ch)
  116.             else writehook(ch);
  117.             goto ending;
  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 : begin
  125.           {$IFNDEF Music}
  126.           if (nextstate = get_args) and ((ch = '=') or (ch = '?')) then begin
  127.             nextstate := get_param;
  128.             goto ending;
  129.           end;
  130.           {$ELSE}
  131.           if (nextstate = get_args) then case ch of
  132.             '=', '?' : begin
  133.               nextstate := get_param;
  134.               goto ending;
  135.             end;
  136.             'M' : begin
  137.               nextstate := get_music;
  138.               goto ending;
  139.             end;
  140.           end; {case}
  141.           {$ENDIF}
  142.           if (nextstate = eat_semi) and (ch = ';') then begin
  143.             if params < 10 then inc(params);
  144.             nextstate := get_param;
  145.             exit;
  146.           end;
  147.           case ch of
  148.             '0'..'9' : begin
  149.               paramarr[params] := ord(ch) - ord('0');
  150.               nextstate := in_param;
  151.             end;
  152.             ';' : begin
  153.               if params < 10 then inc(params);
  154.               nextstate := get_param;
  155.             end;
  156.             '"', '''' : begin
  157.               quote := ch;
  158.               st := st + ch;
  159.               nextstate := get_string;
  160.             end;
  161.             else goto command;
  162.           end {case ch} ;
  163.         end;
  164.         get_string : begin
  165.           st := st + ch;
  166.           if ch <> quote then nextstate := get_string else
  167.             nextstate := eat_semi;
  168.         end;
  169.         in_param : begin                 { last char was a digit }
  170.           { looking for more digits, a semicolon, or a command char }
  171.           case ch of
  172.             '0'..'9' : begin
  173.               paramarr[params] := paramarr[params] * 10 + ord(ch) - ord('0');
  174.               nextstate := in_param;
  175.               goto ending;
  176.             end;
  177.             ';' : begin
  178.               if params < 10 then inc(params);
  179.               nextstate := eat_semi;
  180.               goto ending;
  181.             end;
  182.           end; {case ch}
  183. command:
  184.           nextstate := waiting;
  185.           case ch of
  186.             { note: the order of commands is optimized for execution speed }
  187.             'm' : begin                {sgr}
  188.               for i := 1 to params do begin
  189.                 if reverse then textattr := textattr shr 4 + textattr shl 4;
  190.                 case paramarr[i] of
  191.                   0 : begin reverse := false; textattr := 7 end;
  192.                   1 : textattr := textattr and $ff or $08;
  193.                   2 : textattr := textattr and $f7 or $00;
  194.                   4 : textattr := textattr and $f8 or $01;
  195.                   5 : textattr := textattr or $80;
  196.                   7 : if not reverse then begin
  197.                     { TextAttr := TextAttr shr 4 + TextAttr shl 4;}
  198.                     reverse := true;
  199.                   end;
  200.                   22 : textattr := textattr and $f7 or $00;
  201.                   24 : textattr := textattr and $f8 or $04;
  202.                   25 : textattr := textattr and $7f or $00;
  203.                   27 : if reverse then begin
  204.                     reverse := false;
  205.                     { TextAttr := TextAttr shr 4 + TextAttr shl 4; }
  206.                   end;
  207.                   30 : textattr := textattr and $f8 or $00;
  208.                   31 : textattr := textattr and $f8 or $04;
  209.                   32 : textattr := textattr and $f8 or $02;
  210.                   33 : textattr := textattr and $f8 or $06;
  211.                   34 : textattr := textattr and $f8 or $01;
  212.                   35 : textattr := textattr and $f8 or $05;
  213.                   36 : textattr := textattr and $f8 or $03;
  214.                   37 : textattr := textattr and $f8 or $07;
  215.                   40 : textattr := textattr and $8f or $00;
  216.                   41 : textattr := textattr and $8f or $40;
  217.                   42 : textattr := textattr and $8f or $20;
  218.                   43 : textattr := textattr and $8f or $60;
  219.                   44 : textattr := textattr and $8f or $10;
  220.                   45 : textattr := textattr and $8f or $50;
  221.                   46 : textattr := textattr and $8f or $30;
  222.                   47 : textattr := textattr and $8f or $70;
  223.                 end; { case }
  224.                 { fixup for reverse }
  225.                 if reverse then textattr := textattr shr 4 + textattr shl 4;
  226.               end;
  227.             end;
  228.             'A' : begin                {cuu}
  229.               if paramarr[1] = 0 then paramarr[1] := 1;
  230.               if (wherey - paramarr[1] >= 1) then gotoxy(
  231.                 wherex, wherey - paramarr[1]
  232.               ) else gotoxy(wherex, hi(windmax));
  233.             end;
  234.             'B' : begin                {cud}
  235.               if paramarr[1] = 0 then paramarr[1] := 1;
  236.               if (wherey + paramarr[1] <= hi(windmax)) then gotoxy(
  237.                 wherex, wherey + paramarr[1]
  238.               ) else gotoxy(wherex, 1);
  239.             end;
  240.             'C' : begin                {cuf}
  241.               if paramarr[1] = 0 then paramarr[1] := 1;
  242.               if wherex + paramarr[1] <= lo(windmax) then gotoxy(
  243.                 wherex + paramarr[1], wherey
  244.               ) else gotoxy(lo(windmax), wherey);
  245.             end;
  246.             'D' : begin                 {cub}
  247.               if paramarr[1] = 0 then paramarr[1] := 1;
  248.               if (wherex - paramarr[1] >= 1) then gotoxy(
  249.                 wherex - paramarr[1], wherey
  250.               ) else gotoxy(1, wherey);
  251.             end;
  252.             'H', 'f' : begin           {cup,hvp}
  253.               if paramarr[1] = 0 then paramarr[1] := 1;
  254.               if paramarr[2] = 0 then paramarr[2] := 1;
  255.               gotoxy(paramarr[2], paramarr[1]);
  256.             end;
  257.             'J' : case paramarr[1] of   {eid}
  258.               2 : clrscr;
  259. (*
  260.                 0 : begin             {ClrEos}
  261.                   ClrEol;
  262.                   ScrollWindowDown(
  263.                     Lo(WindMin) + 1, Hi(WindMin) + Wherey + 1,
  264.                     Lo(WindMax) + 1, Hi(WindMax) + 1, 0
  265.                   );
  266.                 End;
  267.                 1 : begin              {Clear from beginning of screen}
  268.                   ScrollWindowDown(
  269.                     Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  270.                     Lo(WindMin) + WhereX, Hi(WindMin) + Wherey, 0
  271.                   );
  272.                   ScrollWindowDown(
  273.                     Lo(WindMin) + 1, Hi(WindMin) + 1,
  274.                     Lo(WindMax) + 1, Hi(WindMin) + Wherey - 1, 0
  275.                   );
  276.                 End;
  277. *)
  278.               end; { case }
  279.             'K' : case paramarr[1] of     {eil}
  280.               0 : clreol;
  281. (*
  282.               1 : ScrollWindowDown( { clear from beginning of line to cursor }
  283.                 Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  284.                 Lo(WindMin) + WhereX - 1, Hi(WindMin) + Wherey, 0
  285.               );
  286.               2 : ScrollWindowDown(              { clear entire line }
  287.                 Lo(WindMin) + 1, Hi(WindMin) + Wherey,
  288.                 Lo(WindMax) + 1, Hi(WindMin) + Wherey, 0
  289.               );
  290. *)
  291.             end {case paramarr} ;
  292.             'L' : {il } for i := 1 to paramarr[1] do insline; { must not move cursor }
  293.             'M' : {d_l} for i := 1 to paramarr[1] do delline; { must not move cursor }
  294.             'P' : begin                {dc }
  295.             end;
  296.             'R' : begin                {cpr}
  297.               reportedy := paramarr[1];
  298.               reportedx := paramarr[2];
  299.             end;
  300.             '@' : begin                {ic}
  301.               { insert blank chars }
  302.             end;
  303.             'h', 'l' : case paramarr[1] of           {sm/rm}
  304.               0 : textmode(bw40);
  305.               1 : textmode(co40);
  306.               2 : textmode(bw80);
  307.               3 : textmode(co80);
  308.               4 : {graphmode(320x200 col)} ;
  309.               5 : {graphmode(320x200 bw)} ;
  310.               6 : {graphmode(640x200 bw)} ;
  311.               7 : wrap := ch = 'h';
  312.             end {case} ;
  313.             'n' : if (paramarr[1] = 6) then                {dsr}
  314.               replyhook(#27'[' + ms(wherey) + ';' + ms(wherex) + 'R');
  315.             's' : begin                {scp}
  316.               savedx := wherex;
  317.               savedy := wherey;
  318.             end;
  319.             'u' : {rcp} gotoxy(savedx, savedy);
  320.             else begin
  321.               if (ch > ' ') then write(ch)
  322.               else writehook(ch);
  323.               goto ending;
  324.             end;
  325.           end; { case ch }
  326.         end;
  327.         {$IFDEF Music}
  328.         get_music : begin
  329.           if ch <> #3 then st := st + ch else begin           {ctrl-c}
  330.             nextstate := waiting;
  331.           end;
  332.         end;
  333.         {$ENDIF}
  334.       end; { case nextstate }
  335.       ending:
  336.     end;
  337.   end; { ansiwrite }
  338.  
  339.  
  340.   {$IFNDEF Small}
  341.  
  342.   {$F+}                           { All Driver function must be far }
  343.  
  344.   function nothing(var f : textrec) : integer;
  345.   begin
  346.     nothing := 0;
  347.   end; {nothing}
  348.  
  349.   procedure null(ch : char);
  350.   begin
  351.     {}
  352.   end; {null}
  353.  
  354.   function devoutput(var f: textrec): integer;
  355.   var i : integer;
  356.   begin
  357.     with f do begin
  358.       { f.bufpos contains the number of chars in the buffer }
  359.       { f.bufptr^ is your buffer                            }
  360.       { any variable conversion done by writeln is already  }
  361.       { done by now.                                        }
  362.       i := 0;
  363.       while i < bufpos do begin
  364.         ansiwrite(bufptr^[i]);
  365. {$IFDEF BBS}
  366.         bbshook(bufptr^[i]);
  367. {$ENDIF}
  368.         inc(i);
  369.       end;
  370.       bufpos := 0;
  371.     end;
  372.     devoutput := 0;               { return ioresult error codes here }
  373.   end; { devoutput }
  374.  
  375.  
  376.   function devopen(var f: textrec): integer;
  377.   begin
  378.     with f do begin
  379.       if mode = fminput then begin
  380.         inoutfunc := @nothing;
  381.         flushfunc := @nothing;
  382.       end else begin
  383.         mode := fmoutput;         { in case it was fminout }
  384.         inoutfunc := @devoutput;
  385.         flushfunc := @devoutput;
  386.       end;
  387.       closefunc := @nothing;
  388.     end;
  389.     devopen := 0;                 { return ioresult error codes here }
  390.   end; { devopen }
  391.  
  392.  
  393.   procedure assignansi(var f : text);
  394.   begin
  395.     fillchar(f, sizeof(f), #0);   { init file var }
  396.     with textrec(f) do begin
  397.       handle := $ffff;
  398.       mode := fmclosed;
  399.       bufsize := sizeof(buffer);
  400.       bufptr := @buffer;
  401.       openfunc := @devopen;
  402.       name[0] := #0;
  403.     end;
  404.   end; { assignansi }
  405.   {$ENDIF}
  406.  
  407.  
  408. {main}begin
  409.   assignansi(ansi);               { set up the variable }
  410.   rewrite(ansi);                  { open it for output  }
  411.   wrap := true;
  412.   replyhook := report;
  413.   writehook := writechar;
  414. {happy}end.
  415.