{$IFDEF MSDOS}
{$F+,O+}
{$ENDIF}

Unit tWin;

{*********************************************************}
{*                      TWIN.PAS                         *}
{*                                                       *}
{*  Copyright (c) Alex Radzishevskiy, 1995-96,           *}
{*  Copyright (c) Konstantin Klyagin, 1995-98,           *}
{*                exspecially for Tornado BBS System     *}
{*                                                       *}
{*********************************************************}

Interface

Uses
{$IFNDEF WIN32}
  DOS,
{$ELSE}
  Windows,
  Classes,
  SysUtils,
{$IFNDEF NOT_TOR}
  AwUser,
{$ENDIF}

{$ENDIF}

{$IFDEF OS2}
  Os2Base,
{$ENDIF}

{$IFNDEF NOT_TOR}
{$IFNDEF WIN32}
  ApCom,
{$ENDIF}
{$ENDIF}

  TimeTask,
  Objects,
  tMisc,
  TGlob,
  OpCrt;

Type
  PBoxRec = ^TBoxRec;
  TBoxRec = Record
    X1, Y1, X2, Y2,               { координаты окна           }
    FrameType,                    { тип линий (см. ниже)      }
    Color,                        { цвет окна                 }
    DelayTime,                    { задержка зумминга         }
    TitleAttr      : Byte;        { цвет заголовка            }
    Title          : String [40]; { заголовок окошка          }
    Covers         : Pointer;     { ссылка на сохраненный фон }
  End;

  PMarkItem = ^TMarkItem;
  TMarkItem = Record
    Text    : String
            {$IFDEF MSDOS}
              [ 78]
            {$ELSE}
              [100]
            {$ENDIF};
    Marked  : Boolean;
  End;

  GetItemFunc = Function (N: LongInt): String;
  tInfoProc = Procedure (S: String);

Const
  ScrX      : Byte = 80;
  ScrY      : Byte = 24;
  ZoomSpeed : Byte = 5;

Procedure TWinInit;

{Устанавливает заданные параметры в запись}
Procedure InitWindow (Var Box: PBoxRec; CX1, CY1, CX2, CY2, CFrameType,
                   Clr: Byte; CTitle: String; TitleAtt: Byte; CDelayTime:
                   Byte; Center: Boolean);

{Рисует окно с зуммингом}
Procedure DrawWindow (Var Box: PBoxRec);

Procedure TitleColor (W: PBoxRec; Num, Attr: Byte);

{Unzoom заданной области экрана. Запоминает текущие координаты курсора}
Procedure CloseWindow (Var Box: PBoxRec);

{Рисует трехмерную кнопочку}
Procedure Key (X, Y, TxtClr, Background: Byte; Txt: String);

{Рисует нажатую трехмерную кнопочку}
Procedure PressedKey (X, Y, TxtClr, BkgClr: Byte; Txt: String);

{Рисует рамочку, в ней пишет текст. Рисует 3х мерную кнопочку OK и ждет}
{нажатия любой клавиши после чего зуммится обратно                     }
Procedure CenterTempBox (Color, KeyColor: Byte; cFrameType: Byte; cTitle:
                         String; cDelayTime: Byte; WindowTitle: String);

{Тоже что и предыдущ., но не с кнопочкой а ждет заданное кол-во времени}
Procedure CenterDelayTempBox (Color, TxtColor, cFrameType: Byte;
                              cTitle: String; cDelayTime: Byte;
                              WindowTitle: String);

Procedure DoneTempBox;

Procedure Rotate (X, Y: Byte; Color: Word);

Procedure ScrollTextWindow (X1, Y1, X2, Y2, TxtClr, TxtBkg, SNormalClr,
          SNormalBkg, SLightClr, SLightBkg: Byte; TextBody: PNotSortedCollection);
 { - Рисует окно с заданными координатами и скроллит в нем текст }

Function tWinMenu (X1, Y1, X2, Y2, CLightColor, CDarkColor: Byte;
                   Var StartDisp: LongInt; StartItem: LongInt; Items:
                   PNotSortedCollection; Checks: Boolean;
                   LightWords: String; InfoProc: tInfoProc): LongInt;

Function tCustomWinMenu (X1, Y1, X2, Y2, CLightColor, CDarkColor: Byte;
                         Var StartDisp: LongInt; StartItem: LongInt;
                         Items: PNotSortedCollection; fGetItem: GetItemFunc;
                         Total: LongInt; Checks: Boolean; LightWords: String): LongInt;

Function SelectBox (Choices: String; WAttr, BSAttr, TAttr, Delay: Byte;
         Text: String): Byte;

Procedure ScrollLightLine (X1, Y1, X2, Y2, TxtClr, BkgClr, DelayTime: Byte;
          RandomClr: Boolean);
 { - Пробегает полосочкой по заданной области экрана заданным цветом }

Function NewMarkItem (Const S: tMarkItem): PMarkItem;
Procedure DisposeMarkItem (P: PMarkItem);

{$IFNDEF NOT_TOR}
Function WaitForKey (Var C: Char): Boolean;
{$ENDIF}

Implementation

Const
  RotState     : Byte = 1;
  RotNum       = 4;
  RotBar       : Array [1..RotNum] Of Char = ('|', '/', '─', '\');

Function NewMarkItem (Const S: tMarkItem): PMarkItem;
Var
  P     : PMarkItem;

Begin
  GetMem (P, SizeOf (S));
  P^ := S;
  NewMarkItem := P;
End;

Procedure DisposeMarkItem (P: PMarkItem);
Begin
  If P <> nil Then FreeMem (P, SizeOf (P^));
End;

Var
  MyBox   : PBoxRec;

{$IFNDEF NOT_TOR}
Function WaitForKey (Var C: Char): Boolean;
Begin
  WaitForKey := False;
  C := #0;
  While Not KeyPressed Do
  Begin
    If Not Local Then
    If (Not {$IFNDEF WIN32} CheckDCD (P) {$ELSE} P. DCD {$ENDIF} )
            {$IFDEF OS2} Or NeedThreadClose {$ENDIF} Then
    Begin
{$IFDEF OS2}
      If NeedThreadClose Then Exit;
{$ENDIF}
      {$IFDEF OS2} DosSleep {$ELSE} Sleep {$ENDIF} (Cnf. CDLostDelay);
      If Not {$IFNDEF WIN32} CheckDCD (P) {$ELSE} P. DCD {$ENDIF} Then Exit;
    End;
    TimeSlice;
  End;
  C := ReadKey;
  WaitForKey := True;
End;
{$ENDIF}

Procedure ChangeFrameChars (T: Byte);
Begin
  Case T Of
    1 : OpCrt. FrameChars := '┌└┐┘──││';
    2 : OpCrt. FrameChars := '╔╚╗╝══║║';
    3 : OpCrt. FrameChars := '        ';
    4 : OpCrt. FrameChars := '╒╘╕╛══││';
    5 : OpCrt. FrameChars := '┌└┐┘──││';
  End;
End;

Procedure InitWindow (Var Box: PBoxRec; CX1, CY1, CX2, CY2, CFrameType,
                   Clr: Byte; CTitle: String; TitleAtt: Byte; CDelayTime:
                   Byte; Center: Boolean);
Begin
  GetMem (Box, SizeOf (TBoxRec));
  With Box^ Do
  Begin
    If Not Center Then
    Begin
      X1 := cX1; Y1 := cY1;
      X2 := cX2; Y2 := cY2;
    End Else
    Begin
      X1 := Round (ScrX/2)-Trunc ((cX2-cX1)/2);
      X2 := X1+cX2-cX1;
      Y1 := Round (ScrY/2)-Round ((cY2-cY1)/2);
      Y2 := Y1+cY2-cY1;
    End;

    FrameType := CFrameType;
    Color := Clr;
    Title := CTitle;
    DelayTime := CDelayTime;
    TitleAttr := TitleAtt;
  End;
End;

Procedure Shadow (X1, Y1, X2, Y2: Byte);
Var
  i       : Byte;

Begin
  If X2 < ScrX Then
    For i := Y1+1 To Y2+1 Do
      ChangeAttribute (2, i, X2+1, $08)

  Else If X2 = ScrX-1 Then
    For i := Y1+1 To Y2+1 Do
      ChangeAttribute (1, i, X2+1, $08);

  If X2 = ScrX Then Dec (X2, 2);
  If X2 = ScrX-1 Then Dec (X2);

  If Y2 < ScrY Then
    For i := X1+2 To X2+1 Do
      ChangeAttribute (2, Y2+1, i, $08);
End;

Procedure DrawWindow (Var Box: PBoxRec);
Var
  i, j, ie, je, HeaderLen, Width : Byte;
  Update                         : Boolean;

Begin
  With Box^ Do
  Begin
    If (X2 <> ScrX) and (Y2 <> ScrY) and (X1 > 0) and (X2 < ScrX) Then
    Begin
      i := X1;
      If i = 1 Then i := 2;
      SaveWindow (i-1, Y1, X2+2, Y2+1, True, Covers);
    End Else
      SaveWindow (X1, Y1, X2, Y2, True, Covers);

    ChangeFrameChars (FrameType);

  {$IFNDEF WIN32}
    If DelayTime <> 0 Then
    Begin
      i := Y1 + Trunc ((Y2-Y1+1)/2); j := X1 + Trunc ((X2-X1+1)/2);
      ie := Y1 + Trunc ((Y2-Y1+1)/2); je := X1 + Trunc ((X2-X1+1)/2);
      ClearWindow (j, i, je, ie, ' ', Color);

      While (i <> Y1) Or (j <> X1) Or (ie <> Y2) Or (je <> X2) Do
      Begin
        If i > Y1 Then Dec (i) Else i := Y1;
        If ie < Y2 Then Inc (ie) Else ie := Y2;
        If j > X1 Then Dec (j) Else j := X1;
        If je < X2 Then Inc (je) Else je := X2;

        Update := Not Update;

        If Update Or ((i=Y1) And (ie=Y2) And (j=X1) And (je=X2)) Then
        Begin
          ClearWindow (j+1, i+1, je-1, ie-1, ' ', Color);
          FrameWindow (j, i, je, ie, Color, TitleAttr, '');
          If (X2 < ScrX) and (Y2 < ScrY) Then Shadow (j, i, je, ie);
          Delay (DelayTime);
        End;

      End;

      HeaderLen := Length (Title);
      If X2 <= X1 Then Width := 0 Else Width := X2-X1-1;

      If HeaderLen > 0 Then
      Begin
        If HeaderLen > Width Then HeaderLen := Width;
        Title [0] := Chr (HeaderLen);
        HeaderLen := Round ((Width-HeaderLen)/2);
        FastWrite (Title, Y1, X1+HeaderLen+1, TitleAttr);
      End;

    End Else
  {$ENDIF}
    Begin
      ClearWindow (X1, Y1, X2, Y2, ' ', Color);
      FrameWindow (X1, Y1, X2, Y2, Color, TitleAttr, Title);
      If (X2 < ScrX) and (Y2 < ScrY) Then Shadow (X1, Y1, X2, Y2);
    End;

    If Title [1] in [#176..#223] Then
    Begin
      ChangeAttribute (2, Y1, X1 + (((X2 - X1) - Length (Title)) Div 2), Color);
      ChangeAttribute (2, Y1, X1 + (((X2 - X1) - Length (Title)) Div 2) + Length (Title) - 1, Color);
    End;

  End;
End;

Procedure TitleColor (W: PBoxRec; Num, Attr: Byte);
Begin
  With W^ Do
  ChangeAttribute (Length (Title) - Num * 2 + 1, Y1,
  X1 + (((X2 - X1) - Length (Title)) Div 2) + Num, Attr)
End;

Procedure Key (X, Y, TxtClr, Background: Byte; Txt: String);
Begin
  FastWrite (Txt, Y, X, TxtClr);
  FastWrite (Replicate ('▀', Length (Txt)), Y + 1, X + 1, Background);
  FastWrite ('▄', Y, X + Length (Txt), Background);
End;

Procedure PressedKey (X, Y, TxtClr, BkgClr: Byte; Txt: String);
Begin
  FastWrite (' ', Y, X, BkgClr);
  FastWrite (Txt, Y, X + 1, TxtClr);
  FastWrite (Replicate (' ', Length (Txt)), Y + 1, X + 1, BkgClr);
End;

Procedure CloseWindow (Var Box: PBoxRec);
Begin
  With Box^ Do
  If (X2 <> ScrX) and (Y2 <> ScrY) and (X1 > 0) and (X2 < ScrX) Then
  Begin
    If X1 = 1 Then Inc (X1);
    RestoreWindow (X1-1, Y1, X2+2, Y2+1, True, Covers);
  End Else
    RestoreWindow (X1, Y1, X2, Y2, True, Covers);

  If Box <> Nil Then FreeMem (Box, SizeOf (TBoxRec));
End;

Procedure CenterTempBox (Color, KeyColor: Byte; cFrameType: Byte;
          cTitle: String; cDelayTime: Byte; WindowTitle: String);
Var
  MyBox               : PBoxRec;
  i, Counter, HowMany : Byte;
  C                   : Char;
  TitleStr            : Array [1..10] Of String [70];

Label
  1, ShutDown;

Begin
  If KeyPressed Then
  While KeyPressed Do ReadKey;

  FillChar (TitleStr, SizeOf (TitleStr), #0);
  HowMany := WordCount (cTitle, ['|']);

  For i := 1 To HowMany Do TitleStr [i] := ExtractWord (i, cTitle, ['|']);

  If ((HowMany) Mod 2) = 0 Then
  Begin
    Inc (HowMany);
    TitleStr [HowMany] := ' ';
  End;

  Counter := Length (TitleStr [1]);

  For i := 1 To HowMany Do
  If Length (TitleStr [i]) > Counter Then Counter := Length (TitleStr [i]);

  InitWindow (MyBox, 1, 1, Counter + 6, HowMany + 6,
  cFrameType, Color, WindowTitle, Color, cDelayTime, True);

  DrawWindow (MyBox);

  With MyBox^ Do
  Begin
    For i := 1 To (HowMany) Do
    FastWrite (TitleStr [i], Y1 + 1 + i, X1 + (X2 - X1)
    Div 2 - Length (TitleStr [i]) Div 2, Color);

    Key (36, Y2 - 2, KeyColor, Hi4 (Color) * 16,  '   Ok   ');

    1:
  {$IFNDEF NOT_TOR}
    If Not WaitForKey (C) Then GoTo ShutDown;
  {$ELSE}
    C := ReadKey;
  {$ENDIF}

    If Not (C In ['O', 'o', 'K', 'k', #27, #13, #32]) Then GoTo 1;
    PressedKey (36, Y2 - 2, KeyColor, Hi4 (Color) * 16, '   Ok   ');
    Pause (200);

    Key (36, Y2 - 2, KeyColor, Hi4 (Color) * 16, '   Ok   ');
    Pause (50);
  End;

  ShutDown:
  CloseWindow (MyBox);

  If KeyPressed Then
  While KeyPressed Do ReadKey;
End;

Procedure CenterDelayTempBox (Color, TxtColor, cFrameType: Byte;
                              cTitle: String; cDelayTime: Byte;
                              WindowTitle: String);
Var
  Delta, i, Counter, Which, HowMany       : Byte;
  TitleStr                                : Array [1..10] Of String [70];

Begin
  If KeyPressed Then
  While KeyPressed Do ReadKey;

  HowMany := WordCount (cTitle, ['|']);
  FillChar (TitleStr, SizeOf (TitleStr), #0);

  For i := 1 To HowMany Do TitleStr [i] := ExtractWord (i, cTitle, ['|']);

  If ((HowMany) Mod 2) = 0 Then
  Begin
    HowMany := HowMany + 1;
    TitleStr [HowMany] := ' ';
    Delta := 2;
  End Else
    Delta := 4;

  Counter := Length (TitleStr [1]);
  Which := 1;

  For i := 1 To HowMany Do
  If Length (TitleStr [i]) > Counter Then
  Begin
    Counter := Length (TitleStr [i]);
    Which := i;
  End;

  If (Length (TitleStr [Which]) Mod 2) = 0 Then
  TitleStr [Which] := TitleStr [Which] + ' ';

  InitWindow (MyBox, 1, 1, Counter + 6, HowMany + Delta, cFrameType, Color, WindowTitle, Color,
             cDelayTime, True);

  DrawWindow (MyBox);

  With MyBox^ Do
  Begin
    For i := 1 To (HowMany) Do
      FastWrite (TitleStr [i], Y1 + 1 + i, X1 + (X2 - X1) Div 2 - Length
                (TitleStr [i] ) Div 2, TxtColor);
  End;
End;

Procedure DoneTempBox;
Begin
  CloseWindow (MyBox);
End;

Procedure ScrollLightLine (X1, Y1, X2, Y2, TxtClr, BkgClr, DelayTime: Byte; RandomClr: Boolean);
{$IFDEF MSDOS}
  Var TempInt, TempInt1: Byte;
    NewAttr: Word;
    PredAttr: Array [1..25] Of Word;
    PredAttr1: Array [1..25] Of Word;
    Box: PBoxRec;
    counter: Byte;
  Begin;

    NewAttr := BkgClr * 16 + TxtClr;
    Counter := 0;

    For TempInt := 1 - (Y2 - Y1) To (X2 - X1) {+(Y2-Y1)} Do Begin;
      For TempInt1 := 1 To (Y2 - Y1) + 1 Do Begin;
        If ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) >= X1 - 1) And
           ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) <= X2 - 3) Then Begin;
          Move (Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 + TempInt +
               (Y2 - Y1 - TempInt1) - 1) * 2 + 1], PredAttr [TempInt1], 1);
          Move (Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 + TempInt +
               (Y2 - Y1 - TempInt1) - 1 + 1) * 2 + 1], PredAttr1 [TempInt1], 1);
          Counter := Counter + 1;
          If Counter = 2 Then Break;
        End;
      End;
    End;

    For TempInt := 1 - (Y2 - Y1) To (X2 - X1) {+(Y2-Y1)} Do Begin;
      If RandomClr = True Then NewAttr := (BkgClr ShL 4) + (8 + Round (Random (8) ) );
      For TempInt1 := 1 To (Y2 - Y1) + 1 Do Begin;
        If ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) >= X1 - 1) And
           ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) <= X2 - 2) Then Begin;
          Move (PredAttr [TempInt1], Mem [VideoSegment: (Y1 + TempInt1 - 2) *
                160 + (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) * 2 + 1], 1);
          Move (PredAttr1 [TempInt1], Mem [VideoSegment: (Y1 + TempInt1 - 2) *
                160 + (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1 + 1) * 2 + 1], 1);
        End;
        If ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) >= X1 - 2) And
           ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) <= X2 - 3) Then Begin;
          Move (Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 + TempInt +
               (Y2 - Y1 - TempInt1) - 1) * 2 + 1], PredAttr [TempInt1], 1);
          Move (Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 + TempInt +
               (Y2 - Y1 - TempInt1) - 1 + 1) * 2 + 1], PredAttr1 [TempInt1], 1);
          Move (NewAttr, Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 +
                TempInt + (Y2 - Y1 - TempInt1) - 1) * 2 + 1], 1);
          Move (NewAttr, Mem [VideoSegment: (Y1 + TempInt1 - 2) * 160 + (X1 +
                TempInt + (Y2 - Y1 - TempInt1) - 1 + 1) * 2 + 1], 1);
        End;
      End;
      Delay (DelayTime);
    End; {for TempInt}
    For TempInt := (X2 - X1) - 2 To X2 - X1  Do Begin;
      For TempInt1 := 1 To (Y2 - Y1) + 1 Do Begin;
        If ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) >= X1 - 2) And
           ( (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 - 1) <= X2 - 3) Then Begin;
          Move (PredAttr [tempint1], Mem [VideoSegment: (Y1 + TempInt1 - 2) *
                160 + (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1) * 2 + 1], 1);
          Move (PredAttr1 [TempInt1], Mem [VideoSegment: (Y1 + TempInt1 - 2) *
                160 + (X1 + TempInt + (Y2 - Y1 - TempInt1) - 1 + 1) * 2 + 1], 1);
        End;
      End;
    End;
{$ELSE}
Begin
{$ENDIF}
  End; {procedure}

Function SelectBox (Choices: String; WAttr, BSAttr, TAttr, Delay: Byte; Text: String): Byte;
Var
  Width, WC, MaxLen, i  : Byte;
  Y, ActiveItem         : LongInt;
  TxtArr                : Array [1..10] Of String [70];
  S                     : String [70];
  Items                 : PNotSortedCollection;

Begin
  Width := Length (Text);
  FillChar (TxtArr, SizeOf (TxtArr), #0);
  Items := New (PNotSortedCollection, Init (5, 1));

  WC := WordCount (Text, ['|']);
  For i := 1 To WC Do TxtArr [i] := ExtractWord (i, Text, ['|']);

  MaxLen := Length (TxtArr [1]);
  For i := 2 To WC Do
  If Length (TxtArr [i]) > MaxLen Then MaxLen := Length (TxtArr [i]);

  Inc (MaxLen, 2);
  ActiveItem := 0;
  WC := WordCount (Choices, ['|']);

  For i := 1 To WC Do
  Begin
    S := ' ' + ExtractWord (i, Choices, ['|']);

    If S [2] = '~' Then
    Begin
      ActiveItem := i-1;
      S := ' ' + Copy (S, 3, 255);
    End;

    If Length (S) + 1 > MaxLen Then MaxLen := Length (S) + 1;

    Items^. Insert (NewStr (S));
  End;

  InitWindow (MyBox, 1, 1, MaxLen + 2, WordCount (Text, ['|']) + WordCount
             (Choices, ['|']) + 3, 1, WAttr, '', TAttr,
             Delay, True);

  DrawWindow (MyBox);

  FastWrite (Replicate ('─', MaxLen), MyBox^. Y1 + WordCount (Text, ['|']) + 1, MyBox^. X1 + 1, WAttr);
  For i := 1 To WC Do FastWrite (TxtArr [i], MyBox^. Y1 + i, MyBox^. X1 + 2, TAttr);

  If ActiveItem > 0 Then Y := Items^. Count-ActiveItem+1 Else Y := 0;
  If Items^. Count-1 = ActiveItem Then Dec (Y);

  SelectBox := tWinMenu (MyBox^. X1+1, MyBox^. Y1+WordCount (Text, ['|'])+2,
               MyBox^. X2, MyBox^. Y2-1, BSAttr, WAttr, Y, ActiveItem, Items,
               False, '', nil);

  CloseWindow (MyBox);
  Dispose (Items, Done);
End;

Procedure ScrollTextWindow;
Var
  TempInt, Offs, XOffs,
  TempKey, i, MaxLen,
  Koefficient           : Byte;
  HorScroll             : Boolean;
  C                     : Char;

Label
  ShutDown;

Begin
  Offs := 0;
  XOffs := 0;

  If TextBody^. Count <= Y2 - Y1 Then {если весь текст на экране помещается}
  Begin
    For TempInt := 0 To TextBody^. Count - 1
    Do FastWrite (Copy (PString (TextBody^. At (TempInt))^ + Replicate
                 (' ', 78), 1, X2 - X1), Y1 + TempInt, X1, TxtBkg * 16 + TxtClr);

    Repeat
      {$IFNDEF NOT_TOR}
      If Not WaitForKey (C) Then Exit;
      {$ELSE}
      C := ReadKey;
      {$ENDIF}
      TempKey := Ord (C);
      If TempKey in [27, 13, 32] Then Exit;
    Until True = False;

    Exit;
  End;

  MaxLen := 0;
  For i := 0 To TextBody^. Count-1 Do
  If Length (PString (TextBody^. At (i))^) > MaxLen
     Then MaxLen := Length (PString (TextBody^. At (i))^);

  If MaxLen > X2-X1-2 Then HorScroll := True
                      Else HorScroll := False;

  {теперь если требуется скроллер}
  {V}  For TempInt := 1 To Y2 - Y1 - 2 Do
           FastWrite (Chr (177), Y1 + TempInt, X2, SNormalBkg * 16 + SNormalClr);

  {e}  FastWrite (#30, Y1, X2, SlightBkg * 16 + SLightClr);
  {r}  FastWrite (#31, Y2 - 1, X2, SlightBkg * 16 + SLightClr);
  {t}  FastWrite ('■', Round (Y1 + (Y2 - Y1) * (100 * Offs /
                  TextBody^. Count) / 100) + 1, X2,
                  SlightBkg * 16 + SLightClr);

  If HorScroll Then
  Begin
  { }  For TempInt := 1 To X2 - X1 - 2 Do
           FastWrite ('▒', Y2, X1 + TempInt, SNormalBkg *
                      16 + SNormalClr);
  {H}  FastWrite (Chr (17), Y2, X1, SlightBkg * 16 + SLightClr);
  {o}  FastWrite (Chr (16), Y2, X2 - 1, SlightBkg * 16 + SLightClr);
  {r}  FastWrite ('■', Y2, Round (X1 + (X2 - X1) * (100 * XOffs /
                  255) / 100) + 1, SlightBkg * 16 + SLightClr);
  End;

  While True Do
  Begin
    For TempInt := 1 To Y2 - Y1 Do
      FastWrite (Copy (PString (TextBody^. At (TempInt - 1 + offs))^ + Replicate (' ', 80),
                XOffs, X2 - X1), Y1 + TempInt - 1, X1, TxtBkg * 16 + TxtClr);

    For TempInt := 1 To Y2 - Y1 - 2 Do
    FastWrite ('▒', Y1 + TempInt, X2, SNormalBkg * 16 + SNormalClr);

    TempInt := Y1 + Round ((Y2-Y1-3) * Offs / (TextBody^. Count-(Y2-Y1)));

    FastWrite ('■', TempInt + 1, X2, SlightBkg * 16 + SLightClr);

    If HorScroll Then
    Begin
      For TempInt := 1 To X2 - X1 - 2 Do
      FastWrite (Chr (177), Y2, X1 + TempInt, SNormalBkg * 16 + SNormalClr);
      FastWrite ('■', Y2, X1 + Round ( (X2 - X1 - 3) * XOffs /
                (255 - (X2 - X1) ) ) + 1, SlightBkg * 16 + SLightClr);
    End;

    {$IFNDEF NOT_TOR}
    If Not WaitForKey (C) Then Exit;
    {$ELSE}
    C := ReadKey;
    {$ENDIF}

    TempKey := Ord (C);
    If TempKey in [27, 13, 32] Then Exit;
    If TempKey = 0 Then
    Begin
      TempKey := Ord (ReadKey);
      Case TempKey Of
        80: {Down} If Offs + (Y2 - Y1) + 1 <= TextBody^. Count Then Inc (Offs);
        72: {Up} If Offs > 0 Then Dec (Offs);
        73: {PgUp} If Offs - (Y2 - Y1) > 0 Then Offs := Offs - Y2 + Y1 Else Offs := 0;
        81: {PgDown} Begin
              If Offs + Y2 - Y1 >= TextBody^. Count -
                 (Y2 - Y1) Then Offs := (TextBody^.
                 Count - (Y2 - Y1))
              Else Offs := Offs + Y2 - Y1;
            End;
        79: {End} Offs := TextBody^. Count - (Y2 - Y1);
        71: {Home} Offs := 0;
        77: If HorScroll Then
            Begin {right}
              If XOffs + X2 - X1 < 255 Then Inc (XOffs);
            End;
        75: If HorScroll Then
            Begin {left}
              If XOffs > 1 Then Dec (XOffs);
            End;
      End;
    End;
  End;
End;

Function tWinMenu (X1, Y1, X2, Y2, CLightColor, CDarkColor: Byte;
                   Var StartDisp: LongInt; StartItem: LongInt; Items:
                   PNotSortedCollection; Checks: Boolean;
                   LightWords: String; InfoProc: tInfoProc): LongInt;
Var
  i, Key, MaxLen, Height, sX, sY  : LongInt;
  Finished, DecCur                : Boolean;
  SaveWind                        : Pointer;
  sPos                            : LongInt;

  LightNum, WC                    : Word;
  LightStrs                       : Array [1..10] Of String [50];
  LightAttrs                      : Array [1..10] Of Word;

Const
  Current  : LongInt = 0;
  oCur     : LongInt = 0;
  Delta    : Byte    = 0;
  Mark     : Array [Boolean] Of String [3] = ('  ', '√ ');

Procedure DrawItem (S: String; Y, X: Byte);
Var
  i   : Byte;

Begin
  FastWrite (PadCh (Copy (S, 1, MaxLen), ' ', MaxLen), Y, X, cDarkColor);

  If LightWords <> '' Then
  For i := 1 To LightNum Do
  If Pos (LightStrs [i], S) <> 0
  Then ChangeAttribute (Length (LightStrs [i]), Y, X+Pos (LightStrs [i], S)-1, LightAttrs [i]);
End;

Procedure DispMenuItems (Top, Bottom: LongInt);
Var
  i     : LongInt;

Begin
  For i := Top To Bottom Do
  If Y1+i-Current <= Y2 Then
  If Not Checks
  Then
    DrawItem (PString (Items^. At (i))^, Y1+i-Current, X1)
  Else
    DrawItem (Mark [PMarkItem (Items^. At (i))^. Marked] + PMarkItem (Items^. At
             (i))^. Text, Y1+i-Current, X1);
End;

Label
  Down,
  Check;

Begin
  sX := WhereX;
  sY := WhereY;

  Current := 0;
  oCur := 0;
  Delta := 0;

  MaxLen := X2-X1;
  Height := Y2-Y1;

  If ((Y2-Y1 > Items ^. Count) and (StartDisp = 0) and (StartItem > 0))
  Then StartDisp := StartItem;

  If ((Y2-Y1 <= Items ^. Count) and
      (Items ^. Count-StartItem <= Y2-Y1))
  Then StartDisp := Y2-Y1-(Items ^. Count-StartItem)+1;

  If (Y2-Y1 = Items ^. Count) and (StartDisp > 0)
  Then Dec (StartDisp);

  If Y2-Y1 = Items ^. Count
  Then Dec (Height);

  If Height > Items^. Count Then
  Begin
    Height := Items^. Count-1;
    Y2 := Items^. Count+Y1-1;
  End;

  If LightWords <> '' Then
  Begin
    WC := WordCount (LightWords, ['|']);

    For LightNum := 1 To WC Do
    If (LightNum/2) = Trunc (LightNum/2)
    Then LightAttrs [Trunc (LightNum/2)] := Hex2Word (ExtractWord (LightNum, LightWords, ['|']))
    Else LightStrs [LightNum] := ExtractWord (LightNum, LightWords, ['|']);

    LightNum := Trunc (LightNum/2);
  End;

  SaveWindow (X1, Y1, X1 + MaxLen - 1, Y2, True, SaveWind);
  ClearWindow (X1, Y1, X1 + MaxLen - 1, Y2, ' ', CDarkColor);

  If StartItem < Items^. Count Then Current := StartItem Else Current := 0;
  sPos := Current-StartDisp;
  If sPos < 0 Then
  Begin
    sPos := 1;
    StartDisp := 0;
    Delta := 1;
  End;

  For i := sPos To sPos+Height Do
  If i <= Items^. Count-1 Then
  If Not Checks Then
    DrawItem (PString (Items^. At (i))^, Y1+i-sPos+Delta, X1)
  Else
    DrawItem (Mark [PMarkItem (Items^. At (i))^. Marked] +
    PMarkItem (Items^. At (i))^. Text, Y1+i-sPos+Delta, X1);

  GoToXY (X1, Y1+StartDisp);

  If Not Checks
  Then
    FastWrite (PadCh (PString (Items^. At (Current))^, ' ', MaxLen), WhereY, X1, cLightColor)
  Else
    FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current))^. Marked] + PMarkItem
    (Items^. At (Current))^. Text, ' ', MaxLen), WhereY, X1, cLightColor);

  Finished := False;
  If Assigned (InfoProc) Then InfoProc (PString (Items^. At (Current))^);

  While Not Finished Do
  Begin
    Key := Ord (ReadKey);

    If Key = 0 Then
    Begin
      Key := Ord (ReadKey);

      If Key in [71..73, 75, 77, 79..82] Then
      Begin
        Case Key Of
         75, 72 : If Current > 0 Then                 { .Up.    }
                  If (WhereY > Y1) and (WhereY <= Y2) Then
                  Begin
                    If Checks Then
                      DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                      PString (Items^. At (Current))^, WhereY, X1)
                    Else
                      DrawItem (PString (Items^. At (Current))^, WhereY, X1);

                    ChangeAttribute (MaxLen, WhereY-1, X1, CLightColor);
                    Dec (Current);
                    GoToXY (X1, WhereY-1);
                  End Else
                  Begin
                    ScrollWindowDown (X1, Y1, X2-1, Y2, 1);
                    If Checks Then
                      DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                      PString (Items^. At (Current))^, WhereY+1, X1)
                    Else
                      DrawItem (PString (Items^. At (Current))^, WhereY+1, X1);

                    If Not Checks Then
                      FastWrite (Copy (PString (Items^. At (Current-1))^, 1,
                      MaxLen), Y1, X1, cLightColor)
                    Else
                      FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current-1))^. Marked] +
                      PMarkItem (Items^. At (Current-1))^. Text, ' ', MaxLen), Y1, X1, cLightColor);

                    Dec (Current);
                  End;

         77, 80 : Down:
                  If Current < Items^. Count-1 Then   { .Down.  }
                  If (WhereY >= Y1) and (WhereY < Y2) Then
                  Begin
                    If Checks Then
                      DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                      PString (Items^. At (Current))^, WhereY, X1)
                    Else
                      DrawItem (PString (Items^. At (Current))^, WhereY, X1);

                    ChangeAttribute (MaxLen, WhereY+1, X1, CLightColor);
                    Inc (Current);
                    GoToXY (X1, WhereY+1);
                  End Else
                  Begin
                    ScrollWindowUp (X1, Y1, X2-1, Y2, 1);
                    If Checks Then
                      DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                      PString (Items^. At (Current))^, WhereY-1, X1)
                    Else
                      DrawItem (PString (Items^. At (Current))^, WhereY-1, X1);

                    If Not Checks Then
                      FastWrite (Copy (PString (Items^. At (Current+1))^, 1, MaxLen), Y2, X1, cLightColor)
                    Else
                      FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current+1))^. Marked] +
                      PMarkItem (Items^. At (Current+1))^. Text, ' ', MaxLen), Y2, X1, cLightColor);

                    Inc (Current);
                  End;

             73 : Begin                               { .PgUp.  }
                    If Current = 0 Then Continue;

                    If WhereY = Y1 Then
                    Begin
                      If Current-Y2+Y1 >= 0 Then
                      Begin
                        Key := Current;
                        Dec (Current, Y2-Y1);
                      End Else
                      Begin
                        Current := 0;
                        Key := Height;
                      End;
                      DispMenuItems (Current, Key);
                    End Else
                    Begin
                      If Checks Then
                        DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                        PString (Items^. At (Current))^, WhereY, X1)
                      Else
                        DrawItem (PString (Items^. At (Current))^, WhereY, X1);
                      Current := Current-WhereY+Y1;
                    End;

                    ChangeAttribute (MaxLen, Y1, X1, CLightColor);
                    GoToXY (X1, Y1);
                  End;

             81 : Begin                               { .PgDn.  }
                    If Current = Items^. Count-1 Then Continue;

                    If WhereY = Y2 Then
                    Begin
                      DecCur := False;

                      If Current+Height > Items ^. Count-1 Then
                      Begin
                        Key := Items^. Count-1;
                        Current := Key-Height;
                      End Else
                      Begin
                        Key := Current+Height;
                        DecCur := True;
                      End;
                      DispMenuItems (Current, Key);
                      Current := Key;
                    End Else
                    Begin
                      If Checks Then
                        DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                        PString (Items^. At (Current))^, WhereY, X1)
                      Else
                        DrawItem (PString (Items^. At (Current))^, WhereY, X1);

                      Current := Current+Y2-WhereY;
                      If Current > Items ^. Count-1 Then Current := Items ^. Count-1;
                    End;

                    ChangeAttribute (MaxLen, Y1+Height, X1, CLightColor);
                    GoToXY (X1, Y1+Height);
                  End;

             71 : If Current <> 0 Then { Home }
                  Begin
                    Current := 0;
                    DispMenuItems (Current, Height);
                    ChangeAttribute (MaxLen, Y1, X1, CLightColor);
                    GoToXY (X1, Y1);
                  End;

             79 : If Current <> Items^. Count-1 Then { End }
                  Begin
                    Key := Items^. Count-1;
                    Current := Key-Height;
                    If Current < 0 Then Current := 0;
                    DispMenuItems (Current, Key);
                    ChangeAttribute (MaxLen, Y1+Height, X1, CLightColor);
                    GoToXY (X1, Y1+Height);
                    Current := Items^. Count-1;
                  End;

             82 : Check:
                  If Checks Then
                  Begin
                    PMarkItem (Items^. At (Current))^. Marked := Not PMarkItem (Items^. At (Current))^. Marked;
                    FastWrite (Mark [PMarkItem (Items^. At (Current))^. Marked], WhereY, WhereX, cLightColor);
                    GoTo Down;
                  End;
        End;

        If Assigned (InfoProc) Then InfoProc (PString (Items^. At (Current))^);
      End;
    End Else
    Case Key Of
      13 : Begin                               { .Enter. }
             Finished := True;
             tWinMenu := Current + 1;
           End;
      27 : Begin                               { .Esc.   }
             Finished := True;
             tWinMenu := 0;
           End;
      32 : GoTo Check;
    End;
  End;

  StartDisp := WhereY-Y1;
  RestoreWindow (X1, Y1, X1+MaxLen-1, Y2, True, SaveWind);
  GoToXY (sX, sY);
End;

Function tCustomWinMenu (X1, Y1, X2, Y2, CLightColor, CDarkColor: Byte;
                         Var StartDisp: LongInt; StartItem: LongInt;
                         Items: PNotSortedCollection; fGetItem: GetItemFunc;
                         Total: LongInt; Checks: Boolean; LightWords: String): LongInt;
Var
  i, Key, MaxLen, Height, sX, sY  : LongInt;
  Finished, DecCur                : Boolean;
  SaveWind                        : Pointer;
  sPos                            : LongInt;

  LightNum, WC                    : Word;
  LightStrs                       : Array [1..10] Of String [50];
  LightAttrs                      : Array [1..10] Of Word;

Const
  Current  : LongInt = 0;
  oCur     : LongInt = 0;
  Delta    : Byte    = 0;
  Mark     : Array [Boolean] Of String [2] = ('  ', '√ ');

Function GetItem (N: LongInt): String;
Begin
  If Not Checks Then
  Begin
    If (Items^. At (N-1) = Nil) Or (PString (Items^. At (N-1))^ = '')
    Then Items^. AtPut (N-1, NewStr (fGetItem (N)));
    GetItem := PString (Items^. At (N-1))^
  End Else
  Begin
    If PMarkItem (Items^. At (N-1))^. Text = ''
    Then PMarkItem (Items^. At (N-1))^. Text := fGetItem (N);
    GetItem := PMarkItem (Items^. At (N-1))^. Text;
  End;
End;

Procedure DrawItem (S: String; Y, X: Byte);
Var
  i   : Byte;

Begin
  FastWrite (PadCh (Copy (S, 1, MaxLen), ' ', MaxLen), Y, X, cDarkColor);

  If LightWords <> '' Then
  For i := 1 To LightNum Do
  If Pos (LightStrs [i], S) <> 0
  Then ChangeAttribute (Length (LightStrs [i]), Y, X+Pos (LightStrs [i], S)-1, LightAttrs [i]);
End;

Procedure DispMenuItems (Top, Bottom: LongInt);
Var
  i     : LongInt;

Begin
  For i := Top To Bottom Do
  If Y1+i-Current <= Y2 Then
  If Not Checks
  Then
    DrawItem (GetItem (i+1), Y1+i-Current, X1)
  Else
    DrawItem (Mark [PMarkItem (Items^. At (i))^. Marked] + GetItem (i+1), Y1+i-Current, X1);
End;

Label
  Down,
  Check;

Begin
  sX := WhereX; sY := WhereY;
  MaxLen := X2-X1;
  Height := Y2-Y1;

  If ((Y2-Y1 > Total) and (StartDisp = 0) and (StartItem > 0))
  Then StartDisp := StartItem;

  If ((Y2-Y1 <= Total) and (Total-StartItem <= Y2-Y1))
  Then StartDisp := Y2-Y1-(Total-StartItem)+1;

  If (Y2-Y1 = Total) and (StartDisp > 0) Then Dec (StartDisp);
  If Y2-Y1 = Total Then Dec (Height);

  If Height > Total Then
  Begin
    Height := Total-1;
    Y2 := Total+Y1-1;
  End;

  If LightWords <> '' Then
  Begin
    WC := WordCount (LightWords, ['|']);

    For LightNum := 1 To WC Do
    If (LightNum/2) = Trunc (LightNum/2)
    Then LightAttrs [Trunc (LightNum/2)] := Hex2Word (ExtractWord (LightNum, LightWords, ['|']))
    Else LightStrs [LightNum] := ExtractWord (LightNum, LightWords, ['|']);

    LightNum := Trunc (LightNum/2);
  End;

  SaveWindow (X1, Y1, X1 + MaxLen - 1, Y2, True, SaveWind);
  ClearWindow (X1, Y1, X1 + MaxLen - 1, Y2, ' ', CDarkColor);

  If StartItem < Total Then Current := StartItem Else Current := 0;
  sPos := Current-StartDisp;
  If sPos < 0 Then
  Begin
    sPos := 1;
    StartDisp := 0;
    Delta := 1;
  End;

  For i := sPos To sPos+Height Do
  If i <= Total-1 Then
  If Not Checks Then
    DrawItem (GetItem (i+1), Y1+i-sPos+Delta, X1)
  Else
    DrawItem (Mark [PMarkItem (Items^. At (i))^. Marked] + GetItem (i+1), Y1+i-sPos+Delta, X1);

  GoToXY (X1, Y1+StartDisp);

  If Not Checks
  Then
    FastWrite (PadCh (GetItem (Current+1), ' ', MaxLen), WhereY, X1, cLightColor)
  Else
    FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current))^. Marked] + GetItem
              (Current+1), ' ', MaxLen), WhereY, X1, cLightColor);

  Finished := False;

  While Not Finished Do
  Begin
    Key := Ord (ReadKey);

    If Key = 0 Then
    Begin
    Key := Ord (ReadKey);
    Case Key Of

  75, 72 : If Current > 0 Then                 { .Up.    }
           If (WhereY > Y1) and (WhereY <= Y2) Then
           Begin
             If Checks Then
               DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
               GetItem (Current+1), WhereY, X1)
             Else
               DrawItem (GetItem (Current+1), WhereY, X1);

             ChangeAttribute (MaxLen, WhereY-1, X1, CLightColor);
             Dec (Current);
             GoToXY (X1, WhereY-1);
           End Else
           Begin
             ScrollWindowDown (X1, Y1, X2-1, Y2, 1);
             If Checks
             Then DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                  GetItem (Current+1), WhereY+1, X1)
             Else DrawItem (GetItem (Current+1), WhereY+1, X1);

             If Not Checks
             Then
               FastWrite (Copy (GetItem (Current), 1, MaxLen), Y1, X1, cLightColor)
             Else
               FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current-1))^. Marked] +
               GetItem (Current), ' ', MaxLen), Y1, X1, cLightColor);

             Dec (Current);
           End;

  77, 80 : Down:
           If Current < Total-1 Then   { .Down.  }
           If (WhereY >= Y1) and (WhereY < Y2) Then
           Begin
             If Checks
             Then DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                  GetItem (Current+1), WhereY, X1)
             Else DrawItem (GetItem (Current+1), WhereY, X1);

             ChangeAttribute (MaxLen, WhereY+1, X1, CLightColor);
             Inc (Current);
             GoToXY (X1, WhereY+1);
           End Else
           Begin
             ScrollWindowUp (X1, Y1, X2-1, Y2, 1);
             If Checks
             Then DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                  GetItem (Current+1), WhereY-1, X1)
             Else DrawItem (GetItem (Current+1), WhereY-1, X1);

             If Not Checks
             Then
               FastWrite (Copy (GetItem (Current+2), 1, MaxLen), Y2, X1, cLightColor)
             Else
               FastWrite (PadCh (Mark [PMarkItem (Items^. At (Current+1))^. Marked] +
               GetItem (Current+2), ' ', MaxLen), Y2, X1, cLightColor);

             Inc (Current);
           End;

      73 : Begin                               { .PgUp.  }
             If Current = 0 Then Continue;

             If WhereY = Y1 Then
             Begin
               If Current-Y2+Y1 >= 0 Then
               Begin
                 Key := Current;
                 Dec (Current, Y2-Y1);
               End Else
               Begin
                 Current := 0;
                 Key := Height;
               End;
               DispMenuItems (Current, Key);
             End Else
             Begin
               If Checks
               Then DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                    GetItem (Current+1), WhereY, X1)
               Else DrawItem (GetItem (Current+1), WhereY, X1);
               Current := Current-WhereY+Y1;
             End;

             ChangeAttribute (MaxLen, Y1, X1, CLightColor);
             GoToXY (X1, Y1);
           End;

      81 : Begin                               { .PgDn.  }
             If Current = Total-1 Then Continue;

             If WhereY = Y2 Then
             Begin
               DecCur := False;

               If Current+Height > Total-1 Then
               Begin
                 Key := Total-1;
                 Current := Key-Height;
               End Else
               Begin
                 Key := Current+Height;
                 DecCur := True;
               End;
               DispMenuItems (Current, Key);
               Current := Key;
             End Else
             Begin
               If Checks
               Then DrawItem (Mark [PMarkItem (Items^. At (Current))^. Marked] +
                    GetItem (Current+1), WhereY, X1)
               Else DrawItem (GetItem (Current+1), WhereY, X1);

               Current := Current+Y2-WhereY;
               If Current > Total-1 Then Current := Total-1;
             End;

             ChangeAttribute (MaxLen, Y1+Height, X1, CLightColor);
             GoToXY (X1, Y1+Height);
           End;

      71 : If Current <> 0 Then { Home }
           Begin
             Current := 0;

             DispMenuItems (Current, Height);

             ChangeAttribute (MaxLen, Y1, X1, CLightColor);
             GoToXY (X1, Y1);
           End;

      79 : If Current <> Total-1 Then { End }
           Begin
             Key := Total-1;
             Current := Key-Height;
             If Current < 0 Then Current := 0;
             DispMenuItems (Current, Key);
             ChangeAttribute (MaxLen, Y1+Height, X1, CLightColor);
             GoToXY (X1, Y1+Height);
             Current := Total-1;
           End;

      82 : Check:
           If Checks Then
           Begin
             PMarkItem (Items^. At (Current))^. Marked := Not
             PMarkItem (Items^. At (Current))^. Marked;

             FastWrite (Mark [PMarkItem (Items^. At (Current))^. Marked],
             WhereY, WhereX, cLightColor);

             GoTo Down;
           End;

    End;
    End Else
    Case Key Of

      13 : Begin                               { .Enter. }
             Finished := True;
             tCustomWinMenu := Current + 1;
           End;

      27 : Begin                               { .Esc.   }
             Finished := True;
             tCustomWinMenu := 0;
           End;

      32 : GoTo Check;

    End;
  End;

  StartDisp := WhereY-Y1;
  RestoreWindow (X1, Y1, X1+MaxLen-1, Y2, True, SaveWind);
  GoToXY (sX, sY);
End;

Procedure Rotate (X, Y: Byte; Color: Word);
Begin
  FastWrite (RotBar [RotState], Y, X, Color);
  Inc (RotState); If RotState > RotNum Then RotState := 1;
End;

Procedure TWinInit;
Begin
  ScrX := {Lo (WindMax)} 79;
  ScrY := Hi (WindMax);
End;

End.