home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / MKMSG104 / MKMSGCVT / MKAVATAR.PAS next >
Pascal/Delphi Source File  |  1994-01-09  |  19KB  |  705 lines

  1. Unit MKAvatar;
  2. {$I-}
  3. {$I MKB.Def}
  4.  
  5. {
  6.      MKAvatar - Copyright 1993 by Mark May - MK Software
  7.      You are free to use this code in your programs, however
  8.      it may not be included in Source/TPU function libraries
  9.      without my permission.
  10.  
  11.      Mythical Kingom Tech BBS (513)237-7737 HST/v32
  12.      FidoNet: 1:110/290
  13.      Rime: ->MYTHKING
  14.      You may also reach me at maym@dmapub.dma.org
  15. }
  16.  
  17.  
  18. Interface
  19.  
  20. {$IFDEF WINDOWS}
  21. Uses MKWCrt;
  22. {$ELSE}
  23.   {$IfDef OPRO}
  24.     Uses OpCrt,
  25.   {$ELSE}
  26.     Uses Crt,
  27.   {$EndIf}
  28.   MKScrn;
  29. {$EndIF}
  30.  
  31.  
  32. Function InAvatar: Boolean;
  33.  
  34. Function AnsiColor (Fore:Byte;Back:Byte):String;
  35.   {return Ansi String to set color}
  36.  
  37. Function AnsiAttr(AA: Byte): String;
  38.   {return ansi string for attribute}
  39.  
  40. Function AnsiAttrDiff(OldA: Byte; NewA: Byte): String;
  41.   {return minimal ansi string to update attribute}
  42.  
  43. Procedure AvatarChar (ch:Char);
  44.   {interpret Ansi/Avatar codes and display to screen}
  45.  
  46. Function CvtColor(colr:Byte):String;
  47.   {Convert attr color codes to ansi numbers}
  48.  
  49. Procedure AVReset;
  50.  
  51. Procedure AvStr(St: String);
  52. Procedure AvStrLn(St: String);
  53.  
  54. Const AnsiSoundOn: Boolean = True;
  55.  
  56. Implementation
  57.  
  58.  
  59. Uses MKMusic;
  60.  
  61. Const
  62.   ControlCh: Set of Char = ['A','B','C','D','f','s','u','H','J','K','m',';',
  63.     'P', '@', 'M', 'L'];
  64.  
  65.   MusicCh: Set of Char = ['A','B','C','D','E','F','G','#','+','-','O','>',
  66.     '<','N','L','P','T','L','S','0','1','2','3','4','5','6','7','8','9','.',
  67.     ' '];
  68.  
  69. Const
  70.   MaxParms = 200;
  71.  
  72. Var
  73.   AvState: Word;            {0=normal, 1=esc, 2=esc[}        {Ansi}
  74.                             {5=^Y, 6=^Y#, 7=^V, 8=^V^A}      {Avatar}
  75.                             {9=^V^H 10=^V^H#}
  76.                             {11=Collect Parameters}
  77.                             {12="ansi" music, 13="ansi" music}
  78.   AvAttr: Byte;
  79.   AnsiParm: Array [1..MaxParms] of Byte;
  80.   AnsiParmNo: Byte;
  81.   SaveX: Byte;
  82.   SaveY: Byte;
  83.   InsertMode: Boolean;
  84.   CommandType: Word;
  85.   RemainingParms: Byte;
  86.   RepCount: Byte;
  87.   MusicStr: String[128];
  88.  
  89.  
  90. Function InAvatar: Boolean;
  91.   Begin
  92.   InAvatar := (AvState > 0);
  93.   End;
  94.  
  95.  
  96. Procedure AvStr(St: String);
  97.   Var
  98.     i: Word;
  99.  
  100.   Begin
  101.   For i := 1 To Length(St) Do
  102.     AvatarChar(St[i]);
  103.   End;
  104.  
  105.  
  106. Procedure AvStrLn(St: String);
  107.   Begin
  108.   AvStr(St);
  109.   AvatarChar(#13);
  110.   AvatarChar(#10);
  111.   End;
  112.  
  113.  
  114. Function CvtColor(colr:Byte):String;
  115.   Begin
  116.   Colr := Colr mod 8;
  117.   Case Colr of
  118.     0: cvtcolor := '0';
  119.     1: cvtcolor := '4';
  120.     2: cvtcolor := '2';
  121.     3: cvtcolor := '6';
  122.     4: cvtcolor := '1';
  123.     5: cvtcolor := '5';
  124.     6: cvtcolor := '3';
  125.     7: cvtcolor := '7';
  126.     End;
  127.   End;
  128.  
  129.  
  130. Function AnsiAttrDiff(OldA: Byte; NewA: Byte): String;
  131.   Var
  132.     DoReset: Boolean;
  133.     DoBlink: Boolean;
  134.     DoHigh: Boolean;
  135.     DoFore: Boolean;
  136.     DoBack: Boolean;
  137.     TmpStr: String;
  138.  
  139.   Begin
  140.   If OldA = NewA Then
  141.     AnsiAttrDiff := ''
  142.   Else
  143.     Begin
  144.     DoReset := ((OldA and $88) and (Not (NewA and $88))) <> 0;
  145.     DoBlink := ((NewA and $80) <> 0) And (DoReset or (OldA and $80 = 0));
  146.     DoHigh  := ((NewA and $08) <> 0) and (DoReset or (OldA and $08 = 0));
  147.     DoFore  := (((NewA and $07) <> (OldA and $07)) or (DoReset and ((NewA and $07) <> 7)));
  148.     DoBack  := (((NewA and $70) <> (OldA and $70)) or (DoReset and ((NewA and $70) <> 0)));
  149.     TmpStr := #27 + '[';
  150.     If DoReset Then
  151.       TmpStr := TmpStr + '0;';
  152.     If DoBlink Then
  153.       TmpStr := TmpStr + '5;';
  154.     If DoHigh Then
  155.       TmpStr := TmpStr + '1;';
  156.     If DoFore Then
  157.       TmpStr := TmpStr + '3' + CvtColor(NewA and $07) + ';';
  158.     If DoBack Then
  159.       TmpStr := TmpStr + '4' + CvtColor((NewA shr 4) and $07) + ';';
  160.     TmpStr[Length(TmpStr)] := 'm';
  161.     AnsiAttrDiff := TmpStr;
  162.     End;
  163.   End;
  164.  
  165.  
  166. Function AnsiColor(Fore:Byte;Back:Byte):String;
  167.   Var
  168.     TempStr:    String;
  169.  
  170.   Begin
  171.   TempStr := #027;
  172.   TempStr := TempStr +'['+ '0;';
  173.   If Fore > 7 Then
  174.     Begin
  175.     TempStr := TempStr + '1;';
  176.     Fore := Fore - 8;
  177.     End;
  178.   If Back > 7 Then
  179.     Begin
  180.     TempStr := TempStr + '5;';
  181.     Back := Back - 8;
  182.     End;
  183.   TempStr := TempStr + '3';
  184.   TempStr := TempStr + CvtColor(Fore) + ';' + '4' + CvtColor(Back) + 'm';
  185.   AnsiColor := TempStr;
  186.   End;
  187.  
  188.  
  189. Function AnsiAttr(AA: Byte): String;
  190.   Begin
  191.   AnsiAttr := AnsiColor(AA and $0f, AA shr 4);
  192.   End;
  193.  
  194.  
  195. Procedure AVReset;
  196.   Begin
  197.   AvState := 0;
  198.   AvAttr := 3;
  199.   TextAttr := AvAttr;
  200.   ClrScr;
  201.   InsertMode := False;
  202.   End;
  203.  
  204.  
  205. Procedure AVInit;
  206.   Begin
  207.   SaveX := 0;
  208.   SaveY := 0;
  209.   AvState := 0;
  210.   AvAttr := 3;
  211.   TextAttr := AvAttr;
  212.   InsertMode := False;
  213.   End;
  214.  
  215.  
  216. Procedure ColorParm(Parm:Byte);
  217.   Var
  218.     Temp: Word;
  219.  
  220.   Begin
  221.   Case parm of
  222.     00: AvAttr := LightGray;
  223.     01: AvAttr := AvAttr or $08;             {Hi intensity}
  224.     04: AvAttr := (AvAttr and $F8) or Blue;
  225.     05: AvAttr := AvAttr or $80;             {Blink}
  226.     07: Begin
  227.         Temp := AvAttr and $77;
  228.         AvAttr := (AvAttr and $88) or ((Temp shr 4) and $07);
  229.         AvAttr := AvAttr or ((Temp shl 4) and $70);
  230.         End;
  231.     08: AvAttr := AvAttr and $88;      {black on black}
  232.     30: AvAttr := (AvAttr and $F8) or Black;
  233.     31: AvAttr := (AvAttr and $F8) or Red;
  234.     32: AvAttr := (AvAttr and $F8) or Green;
  235.     33: AvAttr := (AvAttr and $F8) or Brown;
  236.     34: AvAttr := (AvAttr and $F8) or Blue;
  237.     35: AvAttr := (AvAttr and $F8) or Magenta;
  238.     36: AvAttr := (AvAttr and $F8) or Cyan;
  239.     37: AvAttr := (AvAttr and $F8) or LightGray;
  240.     40: AvAttr := (AvAttr and $8F) or (Black shl 4);
  241.     41: AvAttr := (AvAttr and $8F) or (Red shl 4);
  242.     42: AvAttr := (AvAttr and $8F) or (Green shl 4);
  243.     43: AvAttr := (AvAttr and $8F) or (Brown shl 4);
  244.     44: AvAttr := (AvAttr and $8F) or (Blue shl 4);
  245.     45: AvAttr := (AvAttr and $8F) or (Magenta shl 4);
  246.     46: AvAttr := (AvAttr and $8F) or (Cyan shl 4);
  247.     47: AvAttr := (AvAttr and $8F) or (LightGray shl 4);
  248.     End;
  249.   End;
  250.  
  251.  
  252. Procedure ProcCtl(ch:Char);
  253.   Var
  254.     i:  Word;
  255.  
  256.   Begin
  257.   Case ch of
  258.     ';': Begin
  259.          Ansiparmno := Ansiparmno + 1;
  260.          if Ansiparmno > 10 Then
  261.            Ansiparmno := 10;
  262.          End;
  263.     'A': Begin  {cursor up}
  264.          If Ansiparm[1] = 0 Then
  265.            Ansiparm[1] := 1;
  266.          i := WhereY;
  267.          Dec(i,AnsiParm[1]);
  268.          If i < 0 Then
  269.            i := 0;
  270.          GoToXy(WhereX, i);
  271.          AvState := 0;
  272.          End;
  273.     'B': Begin {cursor down}
  274.          If Ansiparm[1] = 0 Then
  275.            AnsiParm[1] := 1;
  276.          GoToXy(WhereX, WhereY + AnsiParm[1]);
  277.          AvState := 0;
  278.          End;
  279.     'C': Begin {cursor right}
  280.          If Ansiparm[1] = 0 Then
  281.            Ansiparm[1] := 1;
  282.          GoToXy(WhereX + AnsiParm[1], WhereY);
  283.          AvState := 0;
  284.          End;
  285.     'D': Begin {cursor left}
  286.          If AnsiParm[1] = 0 Then
  287.             AnsiParm[1] := 1;
  288.          i := WhereX;
  289.          Dec(i, AnsiParm[1]);
  290.          If i < 0 Then
  291.            i := 0;
  292.          GoToXy(i, WhereY);
  293.          AvState := 0;
  294.          End;
  295.     'H','f': {set cursor position}
  296.          Begin
  297.          if Ansiparm[1] = 0 Then
  298.            Ansiparm[1] := 1;
  299.          If Ansiparm[2] = 0 Then
  300.             Ansiparm[2] := 1;
  301.          GoToXy(Ansiparm[2],Ansiparm[1]);
  302.          AvState := 0;
  303.          End;
  304.     'J': Begin
  305.          AvState := 0;
  306.          Case AnsiParm[1] of
  307.            0: Begin {erase to end of screen}
  308.               ClrEol;
  309.               InitializeScrnRegion(1, WhereY + 1, ScrnWidth, ScrnHeight, ' ');
  310.               End;
  311.            1: Begin {erase from start of screen}
  312.               InitializeScrnRegion(1, 1, ScrnWidth, WhereY - 1, ' ');
  313.               InitializeScrnRegion(1, WhereY, WhereX - 1, WhereY, ' ');
  314.               End;
  315.            2: Begin  {clear screen}
  316.               TextAttr := AvAttr;
  317.               ClrScr;
  318.               End;
  319.            End;
  320.          End;
  321.     'K': Begin
  322.          AvState := 0;
  323.          Case AnsiParm[1] of
  324.            0: Begin {clear to end of line}
  325.               ClrEol;
  326.               End;
  327.            1: Begin {clear from start of line}
  328.               InitializeScrnRegion(1, WhereY, WhereX - 1, WhereY, ' ');
  329.               End;
  330.            2: Begin {erase whole line}
  331.               InitializeScrnRegion(1, WhereY ,ScrnWidth, WhereY, ' ');
  332.               End;
  333.            End;
  334.          End;
  335.     's': Begin {save cursor position}
  336.          SaveX := WhereX;
  337.          SaveY := WhereY;
  338.          AvState := 0;
  339.          End;
  340.     'u': Begin {restore cursor position}
  341.          GoToXy(SaveX, SaveY);
  342.          AvState := 0;
  343.          End;
  344.     'm': Begin {set color attribute}
  345.          AvState := 0;
  346.          If AnsiParmNo > 0 Then
  347.            For i := 1 to AnsiParmNo Do
  348.              ColorParm(AnsiParm[i]);
  349.          TextAttr := AvAttr;
  350.          End;
  351.     'P': Begin {delete characters}
  352.          AvState := 0;
  353.          If AnsiParm[1] = 0 Then
  354.            AnsiParm[1] := 1;
  355.          For i := 1 to AnsiParm[1] Do
  356.            DelCharInLine(WhereX, WhereY);
  357.          End;
  358.     '@': Begin {insert characters}
  359.          AvState := 0;
  360.          If AnsiParm[1] = 0 Then
  361.            AnsiParm[1] := 1;
  362.          For i := 1 to AnsiParm[1] Do
  363.            InsCharInLine(WhereX, WhereY, ' ');
  364.          End;
  365.     'M': Begin {delete lines or "ansi" music}
  366.          If ((AnsiParmNo = 1) and (AnsiParm[1] = 0)) Then
  367.            Begin
  368.            AvState := 12;
  369.            MusicStr := '';
  370.            End
  371.          Else
  372.            Begin
  373.            AvState := 0;
  374.            If AnsiParm[1] = 0 Then
  375.              AnsiParm[1] := 1;
  376.            ScrollScrnRegionUp(1, WhereY + 1, ScrnWidth, ScrnHeight, AnsiParm[1]);
  377.            End;
  378.          End;
  379.     'L': Begin {insert lines}
  380.          AvState := 0;
  381.          If AnsiParm[1] = 0 Then
  382.            AnsiParm[1] := 1;
  383.          ScrollScrnRegionDown(1, WhereY, ScrnWidth, ScrnHeight, AnsiParm[1]);
  384.          End;
  385.     Else
  386.       AvState := 0;
  387.     End;
  388.   End;
  389.  
  390.  
  391. Procedure Accum(ch: Char);
  392.   Begin
  393.   AnsiParm[AnsiParmNo] := (AnsiParm[AnsiParmNo] * 10)  + (Ord(ch) - 48);
  394.   End;
  395.  
  396.  
  397. Procedure MusicChar(ch: Char);
  398.   Begin
  399.   Case ch of
  400.     #27: AvState := 1;
  401.     #$0e: AvState := 0;
  402.     #13: Begin
  403.          If Length(MusicStr) > 0 Then
  404.            Begin
  405.            If AnsiSoundOn Then
  406.              Play(MusicStr);
  407.            MusicStr := '';
  408.            End;
  409.          End;
  410.     #10:;
  411.     Else
  412.       Begin
  413.       If ch in MusicCh Then
  414.         Begin
  415.         If Length(MusicStr) > 120 Then
  416.           Begin
  417.           If AnsiSoundOn Then
  418.             Play(MusicStr);
  419.           MusicStr := '';
  420.           End;
  421.         Inc(MusicStr[0]);
  422.         MusicStr[Length(MusicStr)] := ch;
  423.         End
  424.       Else
  425.         Begin
  426.         AVState := 0;
  427.         End;
  428.       End;
  429.     End;
  430.   If ((AvState < 12) and (Length(MusicStr) > 0)) Then
  431.     Begin
  432.     If AnsiSoundOn Then
  433.       Play(MusicStr);
  434.     MusicStr := '';
  435.     End;
  436.   End;
  437.  
  438.  
  439. Procedure AvatarChar(ch:Char);
  440.   Var
  441.     i: Word;
  442.  
  443.   Begin
  444.   Case AvState of
  445.     0: Begin
  446.        Case ch of
  447.          #027: AvState := 1;
  448.          #012: AvReset;                      {^L - Avatar}
  449.          #025: AvState := 5;                 {^Y - Avatar}
  450.          #022: AvState := 7;                 {^V - Avatar}
  451.          Else
  452.            If InsertMode Then
  453.              InsCharInLine(WhereX, WhereY, ch);
  454.            Write(ch);
  455.          End;
  456.        End;
  457.     1: Begin
  458.        Case ch of
  459.          #27: Begin
  460.               AvState := 1;
  461.               If InsertMode Then
  462.                 InsCharInLine(WhereX, WhereY, #27);
  463.               Write(#27);
  464.               End;
  465.          '[': Begin
  466.               AvState := 2;
  467.               AnsiParmNo := 1;
  468.               For i := 1 To 10 Do
  469.                 Ansiparm[i] := 0;
  470.               End;
  471.          #12: Begin
  472.               AvReset;
  473.               AvState := 0;
  474.               End;
  475.          #25: Begin
  476.               If InsertMode Then
  477.                 InsCharInLine(WhereX, WhereY, #27);
  478.               Write(#27);
  479.               AvState := 5;
  480.               End;
  481.          #22: Begin
  482.               If InsertMode Then
  483.                 InsCharInLine(WhereX, WhereY, #27);
  484.               Write(#27);
  485.               AvState := 6;
  486.               End
  487.          Else
  488.            Begin
  489.            If InsertMode Then
  490.              InsCharInLine(WhereX, WhereY, #27);
  491.            Write(#27);
  492.            If InsertMode Then
  493.              InsCharInLine(WhereX, WhereY, ch);
  494.            Write(ch);
  495.            AvState := 0;
  496.            End;
  497.          End;
  498.        End;
  499.     2: Begin
  500.        Case ch of
  501.          #27: Begin
  502.               AvState := 1;
  503.               If InsertMode Then
  504.                 InsCharInLine(WhereX, WhereY, #27);
  505.               Write(#27);
  506.               If InsertMode Then
  507.                 InsCharInLine(WhereX, WhereY, '[');
  508.               Write('[');
  509.               End;
  510.          '0' .. '9': Accum(ch);
  511.          Else
  512.            If ch in ControlCh Then
  513.              ProcCtl(ch)
  514.            Else
  515.              AvState :=0;
  516.          End;
  517.        End;
  518.     5: Begin
  519.        AnsiParm[1] := Ord(ch);
  520.        AvState := 6;
  521.        End;
  522.     6: Begin
  523.        AvState := 0;
  524.        i := 1;
  525.        While i <= Ord(ch) Do
  526.          Begin
  527.          If InsertMode Then
  528.            InsCharInLine(WhereX, WhereY, Chr(AnsiParm[1]));
  529.          Write(Chr(AnsiParm[1]));
  530.          Inc(i);
  531.          End;
  532.        End;
  533.     7: Begin
  534.        Case ch of
  535.          #001: AvState := 8;                 {^V^A}
  536.          #002: Begin
  537.                AvAttr := AvAttr or Blink;    {^B}
  538.                InsertMode := False;
  539.                AvState := 0;
  540.                End;
  541.          #003: Begin
  542.                If WhereY > 1 Then            {^C}
  543.                  GoToXy(WhereX, WhereY - 1);
  544.                InsertMode := False;
  545.                AvState := 0;
  546.                End;
  547.          #004: Begin
  548.                GoToXy(WhereX, WhereY + 1);   {^D}
  549.                InsertMode := False;
  550.                AvState := 0;
  551.                End;
  552.          #005: Begin
  553.                GoToXy(WhereX + 1, WhereY);   {^E}
  554.                InsertMode := False;
  555.                AvState := 0;
  556.                End;
  557.          #006: Begin
  558.                If WhereX > 1 Then            {^F}
  559.                  GoToXy(WhereX - 1, WhereY);
  560.                InsertMode := False;
  561.                AvState := 0;
  562.                End;
  563.          #007: Begin
  564.                ClrEol;                       {^G}
  565.                InsertMode := False;
  566.                AvState := 0;
  567.                End;
  568.          #008: AvState := 9;                 {^H}
  569.          #009: Begin
  570.                InsertMode := True;           {^I}
  571.                AvState := 0;
  572.                End;
  573.          #010: Begin                         {^J}
  574.                AvState := 11;
  575.                RemainingParms := 5;
  576.                CommandType := 1;
  577.                InsertMode := False;
  578.                AnsiParmNo := 1;
  579.                End;
  580.          #011: Begin                         {^K}
  581.                AvState := 11;
  582.                RemainingParms := 5;
  583.                CommandType := 2;
  584.                InsertMode := False;
  585.                AnsiParmNo := 1;
  586.                End;
  587.          #012: Begin                         {^L}
  588.                AvState := 11;
  589.                RemainingParms := 3;
  590.                CommandType := 3;
  591.                InsertMode := False;
  592.                AnsiParmNo := 1;
  593.                End;
  594.          #013: Begin                         {^M}
  595.                AvState := 11;
  596.                RemainingParms := 4;
  597.                CommandType := 4;
  598.                InsertMode := False;
  599.                AnsiParmNo := 1;
  600.                End;
  601.          #014: Begin
  602.                DelCharInLine(WhereX, WhereY);{^N}
  603.                InsertMode := False;
  604.                AvState := 0;
  605.                End;
  606.          #025: Begin                         {^Y}
  607.                AvState := 11;
  608.                RemainingParms := 1;
  609.                CommandType := 5;
  610.                AnsiParmNo := 1;
  611.                End;
  612.          End;
  613.        End;
  614.     8: Begin                                 {^V^A}
  615.        AvAttr := Ord(ch);
  616.        TextAttr := AvAttr;
  617.        AvState := 0;
  618.        InsertMode := False;
  619.        End;
  620.     9: Begin                                 {^V^H}
  621.        AvState := 10;
  622.        AnsiParm[1] := Ord(ch);
  623.        End;
  624.     10:Begin                                 {^V^H#}
  625.        AvState := 0;
  626.        GoToXy(Ord(ch), AnsiParm[1]);
  627.        InsertMode := False;
  628.        End;
  629.     11:Begin
  630.        AnsiParm[AnsiParmNo] := Ord(ch);
  631.        Inc(AnsiParmNo);
  632.        If AnsiParmNo > MaxParms Then
  633.          AnsiParmNo := MaxParms;
  634.        Dec(RemainingParms);
  635.        If RemainingParms < 1 Then
  636.          Begin
  637.          Case CommandType of
  638.            1: Begin                         {^V^J}
  639.               ScrollScrnRegionUp(AnsiParm[3], AnsiParm[2], AnsiParm[5],
  640.                 AnsiParm[4], AnsiParm[1]);
  641.               AvState := 0;
  642.               End;
  643.            2: Begin                         {^V^K}
  644.               ScrollScrnRegionDown(AnsiParm[3], AnsiParm[2], AnsiParm[5],
  645.                 AnsiParm[4], AnsiParm[1]);
  646.               AvState := 0;
  647.               End;
  648.            3: Begin                         {^V^L}
  649.               TextAttr := AnsiParm[1];
  650.               InitializeScrnRegion(WhereX, WhereY, WhereX + AnsiParm[3],
  651.                 WhereY + AnsiParm[2], ' ');
  652.               AvState := 0;
  653.               End;
  654.            4: Begin                         {^V^M}
  655.               TextAttr := AnsiParm[1];
  656.               InitializeScrnRegion(WhereX, WhereY, WhereX + AnsiParm[4],
  657.                 WhereY + AnsiParm[3], Chr(AnsiParm[2]));
  658.               AvState := 0;
  659.               End;
  660.            5: Begin                         {Have num chars swith to 6}
  661.               RemainingParms := Ord(Ch) + 2;
  662.               CommandType := 6;
  663.               End;
  664.            6: Begin                         {^V^Y}
  665.               RepCount := AnsiParm[AnsiParmNo - 1];
  666.               While RepCount > 0 Do
  667.                 Begin
  668.                 AnsiParmNo := 2;
  669.                 While AnsiParmNo < (AnsiParm[1]+ 3) Do
  670.                   Begin
  671.                   Write(Chr(AnsiParm[AnsiParmNo]));
  672.                   Inc(AnsiParmNo);
  673.                   End;
  674.                 Dec(RepCount);
  675.                 End;
  676.               AvState := 0;
  677.               End;
  678.            End;
  679.          End;
  680.        End;
  681.     12:Begin {"ansi" music}
  682.        Case ch of
  683.          'F': AvState := 13;
  684.          'B': AvState := 13;
  685.          Else
  686.            Begin
  687.            AvState := 13;
  688.            MusicChar(UpCase(ch));
  689.            End;
  690.          End;
  691.        End;
  692.     13:Begin {"Ansi" music after F/B}
  693.        MusicChar(UpCase(ch));
  694.        End;
  695.     End;
  696.   End;
  697.  
  698.  
  699.  
  700. Begin
  701. AvInit;
  702. End.
  703.  
  704.  
  705.