home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / RADOOR30.ZIP / DRIVER.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-04-10  |  19.4 KB  |  672 lines

  1. {╔═════════════════════════════════════════════════════════════════════════╗
  2.  ║                                                                         ║
  3.  ║                   (c) CopyRight LiveSystems 1990, 1994                  ║
  4.  ║                                                                         ║
  5.  ║ Author    : Gerhard Hoogterp                                            ║
  6.  ║ FidoNet   : 2:282/100.5   2:283/7.33                                    ║
  7.  ║ BitNet    : GERHARD@LOIPON.WLINK.NL                                     ║
  8.  ║                                                                         ║
  9.  ║ SnailMail : Kremersmaten 108                                            ║
  10.  ║             7511 LC Enschede                                            ║
  11.  ║             The Netherlands                                             ║
  12.  ║                                                                         ║
  13.  ║        This module is part of the RADoor BBS doorwriters toolbox.       ║
  14.  ║                                                                         ║
  15.  ╚═════════════════════════════════════════════════════════════════════════╝}
  16. { Current problems/bugs:
  17.  
  18. * The AVATAR ^V^Y routine doesn't work recursive. Well, this is a problem
  19.   seen with more AVT/0+ implementation. Still working on a decent way to
  20.   implement this sequence the right way. (The Status variable is the killer,
  21.   Since it's a globaly define variable so the status is remembered between
  22.   calls.. It's a disadvantage of the stream-like way of implementing..)
  23.  
  24. - 2 aug 91
  25.    Added support for special ANSI codes. With these you can use this unit for
  26.    an special door-terminal and let the doorgame send codes for loading
  27.    backdrops, moving object coordinates or REAL music..
  28.    F.e.:
  29.           <ESC>[<BackdropNr>b   (Note the SMALL 'b'!)
  30.             Load backdrop no. <BackDropNr>
  31.  
  32.           <Esc>[<VOCname>V
  33.             Play VOC file
  34.  
  35.           Etc.
  36.   Make sure that the ANSI-indentifier isn't in use yet. The original ANSI
  37.   codes are checked first!
  38.  
  39.   b.t.w. Don't use sequences longer than a string, including the <ESC>[
  40.   and the trailing indentifier!
  41.  
  42.   An other tip.. If you want to send text (which is not possible normaly
  43.   because it usualy contains ANSI indentifiers!) set the 8th bit and reset it
  44.   after receiving. ANSI doesn't use Character above the 128 anyhow...
  45.  
  46. * Added an compiler directive EatCursorReq. If Not selected, the normal
  47.   Ansi detection doesn't detect the <ESQ>[6n cursor position request
  48.   anymore. This way you can implement it as an special ANSI code, and
  49.   send back the cursor position. This system is often used for
  50.   detecting if a terminal has ANSI support. (This one is also for
  51.   special terminal use..)
  52.  
  53. - 12 Feb 92: Release
  54.  
  55.  
  56. }
  57.  
  58. { Define Debug       } { Turn on AVATAR debugging                           }
  59. {$Define UseMusic    } { Just eat music if un-selected                      }
  60. { Define normalBeep  } { Use the normal #7 beep                             }
  61.  
  62. Unit Driver;
  63. Interface
  64. Uses {$IfDef UseMusic}
  65.         AnsiMus,
  66.      {$EndIf}
  67.       CRT;
  68.  
  69. Const AddedSet : String[64] = '';  { Implement extra, special ANSI codes }
  70.  
  71. Type  DoAddedANSIType = Procedure(Buf : String);
  72.                            { The procedure to process the special ANSI codes }
  73.                            { you can use this in a special game-terminal to  }
  74.                            { Load backgrounds from the local HD or to play   }
  75.                            { REAL (Soundblaster? ADLib?) music during the    }
  76.                            { game.. Many possibilites! See DrvDemo.Pas for   }
  77.                            { an simple example..                             }
  78.  
  79. Var  NoColor   : Boolean;  { Replaces the old Monochrome variable  }
  80.      BeQuiet   : Boolean;  { Don't beep at the local screen        }
  81.      RACode    : Boolean;  { True when the character isn't part of }
  82.                            { an ansi/avatar sequence.              }
  83.      AnsiDetect: Boolean;  { Is set to true when a ^]]x;yR is      }
  84.                            { received                              }
  85.  
  86.      DoAddedANSI : DoAddedANSIType;
  87.  
  88. { Comment: (Mon  02-04-1991, 23:07:27)
  89. |-----------------------------------------------------------------------------|
  90.   Just throw characters into the driver and ansi/avatar sequences will be
  91.   inpretered correctly. Character not recognised go to the local screen.
  92. |-----------------------------------------------------------------------------|
  93. }
  94.  
  95. Procedure ScreenDriver(C : Char);
  96. Procedure InitDriver;
  97.  
  98.  
  99. Function StatusResult:String;
  100. Function GotRequest:Boolean;
  101.  
  102. {$IfDef Debug}
  103. Procedure DebugIt(Line : String);
  104. Procedure FlushDebug;
  105. {$EndIf} {Debug}
  106.  
  107. Implementation
  108.  
  109.  
  110. {$IfDef Debug}
  111. Type DebugArray = Array[1..100] Of String[20];
  112. Var  Debug : DebugArray;
  113.      DPtr  : Byte;
  114.  
  115. Procedure DebugIt(Line : String);
  116. Const HexChar : Array[0..$F] of Char = '0123456789ABCDEF';
  117. Var Out : Text;
  118.     C   : Byte;
  119.     Log : String[80];
  120. Begin
  121. Log:='^'+Chr(Ord(Line[1])+64);
  122. If Length(Line)>1
  123.    Then Log:=Log+' ^'+Chr(Ord(Line[2])+64);
  124. For C:=3 To Length(Line) Do
  125.  Log:=Log+' #'+HexChar[(Ord(Line[C]) And $F0) Shr 4]+HexChar[Ord(Line[C]) And $0F];
  126. Inc(DPtr);
  127. If DPtr>100
  128.    Then Begin
  129.         Assign(Out,'AVATAR.LOG');
  130.         Append(Out);
  131.         If IoResult<>0
  132.            Then Rewrite(Out);
  133.         For C:=1 to 100 Do
  134.          WriteLn(Out,Debug[C]);
  135.         Close(Out);
  136.         DPtr:=1;
  137.         End;
  138. Debug[DPtr]:=Log;
  139. End;
  140.  
  141. Procedure FlushDebug;
  142. Var Out : Text;
  143.     C   : Byte;
  144. Begin
  145. Assign(Out,'AVATAR.LOG');
  146. Append(Out);
  147. If IoResult<>0
  148.    Then Rewrite(Out);
  149. For C:=1 to 100 Do
  150.  WriteLn(Out,Debug[C]);
  151. Close(Out);
  152. End;
  153. {$EndIf} {Debug}
  154.  
  155.  
  156.  
  157. Procedure NiceBeep;
  158. Var Nice : Longint;
  159. Begin
  160. NoSound;
  161. For Nice:=1000 to 3000 Do
  162.  Sound(Nice);
  163. NoSound;
  164. End;
  165.  
  166. Const AnsiSet          = 'mABCDsufHhJKlnR'#14;
  167.  
  168. Type DrvStat = (Normal,Ansi,Avatar,Music);
  169.  
  170. Const Status : DrvStat = Normal;
  171.       DefaultColor : Byte =$03;
  172.       CurrentColor : Byte =$03;
  173.  
  174. Var   Buf        : String;
  175.       AvMX,AvMy  : Byte;
  176.       AnMx,AnMy  : Byte;
  177.       AnsiWrap   : Boolean;
  178.       HiColor    : Boolean;
  179.       LastCol    : Byte;
  180.  
  181.       AVTIns     : Boolean;
  182.       RepLen     : Byte;
  183.  
  184.       SendBack   : String;
  185.       GotReq     : Boolean;
  186.  
  187. Function Str2Nr(S : String):Word;
  188. Var Temp : Word;
  189.     Err  : Word;
  190. Begin
  191. Val(S,Temp,Err);
  192. If Err<>0
  193.    Then Str2Nr:=0
  194.    Else Str2Nr:=Temp;
  195. End;
  196.  
  197. Type Str3 = String[3];
  198.  
  199. Function Nr2Str(N : Byte):Str3;
  200. Var Temp : Str3;
  201. Begin
  202. Str(N,Temp);
  203. Nr2Str:=Temp;
  204. End;
  205.  
  206. Procedure InitDriver;
  207. Begin
  208. Window(1,1,80,24);
  209. RACode:=False;
  210. BeQuiet:=False;
  211. NoColor:=False;
  212.  
  213. AnsiDetect:=False;
  214. GotReq:=False;
  215. SendBack:='';
  216.  
  217. Buf:='';
  218. AnsiWrap:=True;
  219. HiColor:=False;
  220. LastCol:=7;
  221.  
  222. AVTIns:=False;
  223. End;
  224.  
  225. Function StatusResult:String;
  226. Begin
  227. StatusResult:=SendBack;
  228. GotReq:=False;
  229. End;
  230.  
  231. Function GotRequest:Boolean;
  232. Begin
  233. GotRequest:=GotReq;
  234. End;
  235.  
  236.  
  237. Procedure Clip(I: Char; X,Y : Byte);
  238. Begin
  239. Case I Of
  240.  'A' : Begin
  241.        If WhereY<=Y
  242.           Then GotoXy(WhereX,1)
  243.           Else GotoXy(WhereX,WhereY-Y);
  244.        End;
  245.  'B' : Begin
  246.        If (WhereY+Y)>25
  247.           Then GotoXy(WhereX,24)
  248.           Else GotoXy(WhereX,WhereY+Y);
  249.        End;
  250.  'C' : Begin
  251.        If (WhereX+X)>80
  252.           Then GotoXy(80,WhereY)
  253.           Else GotoXy(WhereX+X,WhereY);
  254.        End;
  255.  'D' : Begin
  256.        If (WhereX<=X)
  257.           Then GotoXy(1,WhereY)
  258.           Else GotoXy(WhereX-X,WhereY);
  259.        End;
  260. End; {Case}
  261. End;
  262.  
  263. Procedure DoColor(Color : Byte);
  264. Const LForColors  : Array[0..7] Of Byte = (0,4,2,6,1,5,3,7);
  265.       HForColors  : Array[0..7] Of Byte = (8,12,10,14,9,13,11,15);
  266.       BackColors  : Array[0..7] Of Byte = (0,4,2,6,1,5,3,7);
  267. Begin
  268. If Color <= 8
  269.    Then Begin
  270.         Case Color Of
  271.           0 : Begin
  272.               HiColor:=False;
  273.               TextAttr:=$0F;
  274.               End;
  275.           1 : Begin
  276.               HiColor:=True;
  277.               TextColor(HForColors[LastCol]);
  278.               End;
  279.           5 : TextAttr:=TextAttr Or $80;
  280.         End;
  281.         Exit
  282.         End;
  283. If (Color In [30..37]) And
  284.    (Not NoColor)
  285.    Then Begin
  286.         Dec(Color,30);
  287.         LastCol:=Color;
  288.         TextAttr:=TextAttr And $F0;
  289.         If HiColor
  290.            Then TextAttr:=TextAttr+HForColors[Color]
  291.            Else TextAttr:=TextAttr+LForColors[Color];
  292.         Exit;
  293.         End;
  294. If (Color In [40..47]) And
  295.    (Not NoColor)
  296.    Then Begin
  297.         TextAttr:=TextAttr And $8F;
  298.         TextAttr:=TextAttr+(BackColors[Color-40] Shl 4);
  299.         End;
  300. End;
  301.  
  302. Procedure DoAnsi(S : String);
  303. Var Indent : Char;
  304.     X,Y    : Byte;
  305.     TStr   : String[10];
  306.     Color  : Byte;
  307.     DPos   : Byte;
  308.     Err    : Integer;
  309.  
  310. Begin
  311. Delete(S,1,2);
  312. Indent:=S[Length(S)];
  313. Dec(Byte(S[0]));
  314. Case Indent Of
  315.  'm'   : Begin
  316.          While S<>'' Do
  317.           Begin
  318.           DPos:=Pos(';',S);
  319.           If DPos>0
  320.              Then Begin
  321.                   TStr:=Copy(S,1,DPos-1);
  322.                   Delete(S,1,DPos);
  323.                   End
  324.              Else Begin
  325.                   TStr:=S;
  326.                   S[0]:=#00;
  327.                   End;
  328.           VAL(TStr,Color,Err);
  329.           DoColor(Color);
  330.           End;
  331.          End;
  332.  'A',
  333.  'B',
  334.  'C',
  335.  'D'   : Begin
  336.          If S=''
  337.             Then Begin
  338.                  X:=1;
  339.                  Y:=1;
  340.                  End
  341.             Else Begin
  342.                  X:=Str2Nr(S);
  343.                  Y:=X;
  344.                  End;
  345.          Clip(Indent,X,Y);
  346.          End;
  347.  's'   : Begin
  348.          AnMx:=WhereX;
  349.          AnMy:=WhereY;
  350.          End;
  351.  'n'   : Begin
  352.          GotReq:=True;
  353.          SendBack:=#27'['+Nr2Str(WhereY)+';'+Nr2Str(WhereX)+'R';
  354.          End;
  355.  'u'   : GotoXy(AnMx,AnMy);
  356.  'f',
  357.  'H'   : Begin
  358.          If Length(S)=0
  359.             Then GotoXy(1,1)
  360.             Else Begin
  361.                  DPos:=Pos(';',S);
  362.                  TStr:=Copy(S,1,DPos-1);
  363.                  If TStr=''
  364.                     Then Begin
  365.                          If DPos=0
  366.                             Then Begin
  367.                                  Val(S,Y,Err);
  368.                                  S[0]:=#00;
  369.                                  End
  370.                             Else Begin
  371.                                  Y:=1;
  372.                                  Delete(S,1,1);
  373.                                  End;
  374.                          End
  375.                     Else Begin
  376.                          Val(TStr,Y,Err);
  377.                          Delete(S,1,DPos);
  378.                          End;
  379.                  If S=''
  380.                     Then X:=1
  381.                     Else Val(S,X,Err);
  382.                  GotoXy(X,Y);
  383.                  End;
  384.          End;
  385.  'J'   : If S='2'
  386.             Then CRt.ClrScr;
  387.  'l'   : If S='=7'
  388.             Then AnsiWrap:=True;
  389.  'K'   : If S=''
  390.             Then CRT.ClrEol;
  391.  'R'   : AnsiDetect:=True;
  392. End; {Case}
  393. End;
  394.  
  395. Procedure DoAvatar(S : String);
  396. Var Count : Byte;
  397.     X,Y   : Byte;
  398.     RepStr: String;
  399.     MWMin,
  400.     MWMax : Word;
  401.  
  402. Begin
  403. {$IfDef Debug}
  404.   DebugIt(S);
  405. {$EndIf} {Debug}
  406.  
  407. Case S[1] Of
  408.  ^Y : Begin
  409.       For Count:=1 To Ord(S[3]) Do
  410.          Write(S[2]);
  411.       End;
  412.  ^V : Begin
  413.         Case S[2] Of
  414.           ^A  : If Not NoColor
  415.                    Then CurrentColor:=Ord(S[3]);
  416.           ^B  : If Not NoColor
  417.                    Then CurrentColor:=CurrentColor Or $80;
  418.           ^C  : If WhereY>1
  419.                    Then GotoXy(WhereX,WhereY-1);
  420.           ^D  : If WhereY<25
  421.                    Then GotoXy(WhereX,WhereY+1);
  422.           ^E  : If WhereX>1
  423.                    Then GotoXy(WhereX-1,WhereY);
  424.           ^F  : If WhereX<80
  425.                    Then GotoXy(WhereX+1,WhereY);
  426.           ^G  : Crt.ClrEol;
  427.           ^H  : GotoXy(Ord(S[4]),Ord(S[3]));
  428.           ^J  : Begin
  429.                 AvMX:=WhereX; AvMY:=WhereY;
  430.                 MWMin:=WindMin;
  431.                 MWMAx:=WindMax;
  432.                 Window(Ord(S[5]),Ord(S[4]),Ord(S[7]),Ord(S[6]));
  433.                 For Count:=1 To Ord(S[3]) Do
  434.                  DelLine;
  435.                 WindMin:=MWMin;
  436.                 WindMAx:=MWMax;
  437.                 GotoXy(AvMX,AvMY);
  438.                 End;
  439.           ^K  : Begin
  440.                 AvMX:=WhereX; AvMY:=WhereY;
  441.                 MWMin:=WindMin;
  442.                 MWMAx:=WindMax;
  443.                 Window(Ord(S[5]),Ord(S[4]),Ord(S[7]),Ord(S[6]));
  444.                 For Count:=1 To Ord(S[3]) Do
  445.                  InsLine;
  446.                 WindMin:=MWMin;
  447.                 WindMAx:=MWMax;
  448.                 GotoXy(AvMX,AvMY);
  449.                 End;
  450.           ^L  : Begin
  451.                 AvMX:=WhereX;AvMY:=WhereY;
  452.                 MWMin:=WindMin;
  453.                 MWMAx:=WindMax;
  454.                 Window(AvMX,AvMY,AvMx+Ord(S[5]),AvMY+Ord(S[4]));
  455.                 TextAttr:=(Ord(S[3]) And $7F);
  456.                 ClrScr;
  457.                 WindMin:=MWMin;
  458.                 WindMAx:=MWMax;
  459.                 GotoXy(AvMX,AvMy);
  460.                 CurrentColor:=TextAttr;
  461.                 End;
  462.           ^M  : Begin
  463.                 AvMX:=WhereX;AvMY:=WhereY;
  464.                 If (Ord(S[3]) And $80)=$80
  465.                    Then Begin
  466.                         CurrentColor:=Ord(S[3]) AND $7F;
  467.                         TextAttr:=Ord(S[3]);
  468.                         End
  469.                    Else TextAttr:=(Ord(S[3]) Or $7F);
  470.                 RepStr:='';
  471.                 For X:= AVMx To AvMX+Ord(S[6])-1 Do
  472.                   RepStr:=RepStr+S[4];
  473.                 For Y:= AVMy To AvMY+Ord(S[5])-1 Do
  474.                   Begin
  475.                   GotoXy(AvMX,Y);
  476.                   Write(RepStr);
  477.                   End;
  478.                 GotoXy(AvMX,AvMy);
  479.                 End;
  480.           ^Y  : Begin
  481.                 RepStr:=S;
  482.                 Delete(RepStr,1,3);
  483.                 Dec(RepStr[0]);
  484.                 For X:=1 To Ord(S[Length(S)]) Do
  485.                  Write(RepStr);
  486.                 End;
  487.          End; {Case}
  488.         End; { ^V }
  489. End; {Case}
  490. TextAttr:=CurrentColor;
  491. End;
  492.  
  493. Procedure ScreenDriver(C : Char);
  494. Var Buffed : Boolean;
  495. Begin
  496. Repeat
  497.  Buffed:=False;
  498.  Case Status Of
  499.   Normal : Begin
  500.            Case C of
  501.             #00  :;
  502.             #27  : Begin
  503.                    Status:=Ansi;
  504.                    Buf:=C;
  505.                    End;
  506.             #09  : Write('        ');
  507.             ^L   : Begin
  508.                    DefaultColor :=$03;
  509.                    CurrentColor :=$03;
  510.                    TextAttr:=CurrentColor;
  511.                    CRT.ClrScr;
  512.                    AVTIns:=False;
  513.                    End;
  514.             ^Y,
  515.             ^V   : Begin
  516.                    Status:=Avatar;
  517.                    Buf:=C;
  518.                    RepLen:=0;
  519.                    End;
  520.            Else    Begin
  521.                    If (C=#7) And (Not BeQuiet)
  522.                       Then {$IfDef NormalBeeb}
  523.                              Write(#7);
  524.                            {$Else}
  525.                              NiceBeep;
  526.                            {$EndIf}
  527.                    If (C<>#7)
  528.                       Then Write(C);
  529.                    End;
  530.           End; {Case}
  531.           End;
  532.  
  533.   Ansi   : Begin
  534.            If (Buf=#27'[M') And
  535.               (Upcase(C) In ['F','B'])
  536.               Then Begin
  537.                    NoSound;
  538.                    Status:=Music;
  539.                    End
  540.               Else Begin
  541.                    Buf:=Buf+C;
  542.                    If Pos(C,AnsiSet)>0
  543.                       Then Begin
  544.                            Status:=Normal;
  545.                            DoAnsi(Buf);
  546.                            End;
  547.  
  548.                    If (AddedSet<>'') And       { 2/8/91, special ANSI support }
  549.                       (Pos(C,AddedSet)>0)
  550.                       Then Begin
  551.                            Status:=Normal;
  552.                            DoAddedANSI(Buf);
  553.                            End;
  554.                    End;
  555.            End;
  556.    Music : Begin
  557.            If C <#32
  558.               Then Begin
  559.                    If (C<>#14) And
  560.                       (C<>#13)
  561.                       Then Buffed:=True;
  562.                    Status:=Normal;
  563.                    NoSound;
  564.                    {$IfDef UseMusic}
  565.                     ResetMusic;
  566.                    {$EndIf}
  567.                    End
  568.               Else Begin
  569.                    {$IfDef UseMusic}
  570.                      If Not BeQuiet
  571.                         Then AnsiMusic(Upcase(C));
  572.                    {$EndIf}
  573.                    End;
  574.            End;
  575.   Avatar : Begin
  576.            Buf:=Buf+C;
  577.            Case Buf[1] Of
  578.             ^V  : Begin
  579.                   If Buf[2]<>^Y
  580.                      Then AVTIns:=False;
  581.                   Case Buf[2] Of
  582.                    ^A : Begin
  583.                         If Length(Buf)=3
  584.                            Then Begin
  585.                                 Status:=Normal;
  586.                                 DoAvatar(Buf);
  587.                                 End;
  588.                         End;
  589.                    ^B,
  590.                    ^C,
  591.                    ^D,
  592.                    ^E,
  593.                    ^F,
  594.                    ^G  : Begin
  595.                          Status:=Normal;
  596.                          DoAvatar(Buf);
  597.                          End;
  598.                    ^H  : Begin
  599.                          If Length(Buf)=4
  600.                             Then Begin
  601.                                  Status:=Normal;
  602.                                  DoAvatar(Buf);
  603.                                  End;
  604.                          End;
  605.                    ^I  : AVTIns:=True;
  606.                    ^J,
  607.                    ^K  : Begin
  608.                          If Length(Buf)=7
  609.                             Then Begin
  610.                                  Status:=Normal;
  611.                                  DoAvatar(Buf);
  612.                                  End;
  613.                          End;
  614.                    ^L  : Begin
  615.                          If Length(Buf)=5
  616.                             Then Begin
  617.                                  Status:=Normal;
  618.                                  DoAvatar(Buf);
  619.                                  End;
  620.                          End;
  621.                    ^M  : Begin
  622.                          If Length(Buf)=6
  623.                             Then Begin
  624.                                  Status:=Normal;
  625.                                  DoAvatar(Buf);
  626.                                  End;
  627.                          End;
  628.                    ^Y  : Begin
  629.                          Case Length(Buf) Of
  630.                           3   : RepLen:=Ord(C)+4;
  631.                           Else Begin
  632.                                If Length(Buf)=RepLen
  633.                                   Then Begin
  634.                                        Status:=Normal;
  635.                                        DoAvatar(Buf);
  636.                                        End;
  637.                                End;
  638.                          End; {Case}
  639.                          End;
  640.                   End; { Case }
  641.                   End;  { Case ^V }
  642.             ^Y  : Begin
  643.                   If Length(Buf)=3
  644.                      Then Begin
  645.                           Status:=Normal;
  646.                           DoAvatar(Buf);
  647.                           End;
  648.                   End;
  649.            End; {Case}
  650.            End;
  651.  End; {Case}
  652. Until Not Buffed;
  653. RACode:=Status=Normal;
  654. End;
  655.  
  656. {$F+}
  657. Procedure NoAddedAnsi(Buf : String);
  658. {$F-}
  659. Begin
  660. End;
  661.  
  662. Begin
  663. DirectVideo:=False;
  664. InitDriver;
  665.  
  666. {$IfDef Debug}
  667.  DPtr:=0;
  668. {$EndIf} {Debug}
  669.  
  670. DoAddedANSI:=NoAddedANSI; { Init a dummy special ansi driver. }
  671. End.
  672.