Program MenuEditor;
Uses Dos,Crt,Extense,Records,GenStr;
{$M 65520,0,65535}

Type
 MenuCommandRec = Record
                   Description  : String[35];
                   Access       : ACS;
                   CMDKey       : String[80];
                   Operation    : String[90];
                   Password     : String[20];
                   PString      : String[50];
                   CMDType      : Byte; {1=Normal,2=First,3=Every,4=Pullbar }
                   PullbarX     : Byte;
                   PullbarY     : Byte;
                   UnLitText    : String[80];
                   LitText      : String[80];
                  End;

(* Menu Record *)
 MenuRec = Record
            Name        : String[8];
            Description : String[50];
            Access      : String[80];
            Helpfile    : String[12];
            Tutorial    : String[12];
            Hotkeys     : Boolean;
            Useprompt   : Boolean;
            Pullbar     : Boolean;
            ClearScreen : Boolean;
            Prompt      : Array[1..2] of String[50];
            Fileconf    : Byte;
            MsgConf     : Byte;
            NumCommands : Byte;
            Command     : Array[1..50] of MenuCommandRec;
           End;

Procedure MenuTop; External;{$L MENUTOP.OBJ}
Procedure MenuEnd; External;{$L MENUEND.OBJ}
Procedure CmdTop;  External;{$L CMDTOP.OBJ}
Procedure CmdEdit; External;{$L CMDEDIT.OBJ}
Procedure MenuEdit;External;{$L MENUEDIT.OBJ}

Type Str12 = String[12];

Var Menu       : MenuRec;
    Dirinfo    : SearchRec;
    X,Y,Z      : Word;
    Active     : Byte;
    Top        : Byte;
    Highest    : Word;
    CH         : Char;
    Filename   : Array[1..30] of String[12];
    Descrip    : Array[1..30] of String[20];
    Access     : Array[1..30] of String[50];
    Active_Two : Byte;

Procedure Print(S : String);
Var X,Code : Byte;
    Error  : Integer;
    Total : Byte;
Begin
Total := Length(S);
For X := 1 to Total do
 Begin
  If S[X] <> '|' then Write(S[X])

   Else
         if s[x+1]='B' then begin
                          textbackground(valu(s[x+2]));
                          inc(x,2);
                          end
                          else
 Begin
         Val(Copy(S,X + 1,2),Code,Error);
         If Error>0 then Write(S[X])
                     Else Begin
                            If Code<16 then Textcolor(Code)
                             Else Textbackground(Code-16);
                            If X + 2 > total then Inc(X,1) else Inc(X,2);
                           End;
        End;
 End;
End;

Procedure Read_Menu(Filename : String);
Var MenuFile : Text;
    X : Word;
   TempChar : Char;
Begin
 Assign(MenuFile,Filename);
 Reset(MenuFile);
 Readln(menufile,menu.Name);
 Readln(menufile,menu.Description);
 Readln(menufile,MENU.Access);
 Readln(menufile,MENU.HelpFile);
 Readln(menufile,MENU.Tutorial);
 Readln(menufile,tempchar);MENU.Hotkeys     := (Upcase(TempChar) = 'T');
 Readln(menufile,tempchar);MENU.UsePrompt   := (Upcase(TempChar) = 'T');
 Readln(menufile,tempchar);MENU.Pullbar     := (Upcase(TempChar) = 'T');
 Readln(menufile,tempchar);MENU.ClearScreen := (Upcase(TempChar) = 'T');
 Readln(menufile,MENU.prompt[1]);
 Readln(menufile,MENU.prompt[2]);
 Readln(menufile,MENU.fileconf);
 Readln(menufile,MENU.msgconf);
 X := 0;
 while not (eof(menufile)) do
  begin
   Inc(X);
   readln(menufile,MENU.Command[X].description);
   readln(menufile,MENU.Command[X].CMDKey);
   readln(menufile,MENU.Command[X].Access);
   Readln(menufile,MENU.Command[X].CMDType);
   readln(menufile,MENU.Command[X].Operation);
   readln(menufile,MENU.Command[X].PString);
   readln(menufile,MENU.Command[X].PullbarX);
   readln(menufile,MENU.Command[X].PullbarY);
   readln(menufile,MENU.Command[X].LitText);
   readln(menufile,MENU.Command[X].UnlitText);
  end;
 MENU.Numcommands := X;
 Close(MenuFile);
End;

Procedure Write_Menu(Filename : String);
Var MenuFile : Text;
    X : Word;
   TempChar : Char;
Begin
 Assign(Menufile,MENU.Name+'.MNU');
 Rewrite(Menufile);
 WriteLn(menufile,MENU.Name);
 WriteLn(menufile,MENU.Description);
 WriteLn(menufile,MENU.Access);
 WriteLn(menufile,MENU.HelpFile);
 Writeln(menufile,MENU.Tutorial);
 If MENU.Hotkeys then Writeln(Menufile,'T') else Writeln(Menufile,'F');
 If MENU.UsePrompt then Writeln(Menufile,'T') else Writeln(MenuFile,'F');
 If MENU.Pullbar then Writeln(Menufile,'T') else Writeln(Menufile,'F');
 If MENU.ClearScreen then Writeln(Menufile,'T') else Writeln(Menufile,'F');
 Writeln(menufile,MENU.prompt[1]);
 Writeln(menufile,MENU.prompt[2]);
 Writeln(menufile,MENU.fileconf);
 Writeln(menufile,MENU.msgconf);
 For X := 1 to MENU.Numcommands do
  Begin
   Writeln(menufile,MENU.Command[X].description);
   Writeln(menufile,MENU.Command[X].CMDKey);
   Writeln(menufile,MENU.Command[X].Access);
   Writeln(menufile,MENU.Command[X].CMDType);
   Writeln(menufile,MENU.Command[X].Operation);
   Writeln(menufile,MENU.Command[X].PString);
   Writeln(menufile,MENU.Command[X].PullbarX);
   Writeln(menufile,MENU.Command[X].PullbarY);
   Writeln(menufile,MENU.Command[X].LitText);
   Writeln(menufile,MENU.Command[X].UnlitText);
  End;
 Close(Menufile);
End;

Procedure Simulation;
Var Key : Char;
    Pullbars : Array[1..100] of MenuCommandRec;
    Y : Byte;
    Select : Byte;
Begin
 {DisplayAnsi(MENU.Helpfile,True);}
 Y := 0;
 Select := 1;
 For X := 1 to MENU.Numcommands do
   Begin
    If MENU.Command[X].CMDType = 4 then
     Begin
      Inc(Y);
      Pullbars[Y].Description := MENU.Command[X].Description;
      Pullbars[Y].PullBarX    := MENU.Command[X].PullbarX;
      Pullbars[Y].PullBarY    := MENU.Command[X].PullbarY;
      Pullbars[Y].UnlitText   := MENU.Command[X].UnlitText;
      Pullbars[Y].LitText     := MENU.Command[X].LitText;
     End;
   End;
 Repeat
  For X := 1 to Y do
   Begin
    GoXY(Pullbars[X].PullBarX,Pullbars[X].PullbarY);
    If Select = X then print(Pullbars[X].LitText) else
                       print(Pullbars[X].UnlitText);
   End;
  Key := Readkey;If Key = #0 then Key := Readkey;
  Case Key of
   #72 : If Select > 1 then Dec(Select) else Select := Y;
   #80 : If Select < Y then Inc(Select) else Select := 1;
  End;
 Until Key in[#13,#27];
End;

Procedure InputLn(var Lne : String;Chars:Byte;Caps:Boolean;Allcaps:Boolean);
Var
 StartedX,Counter,OldAttr : Byte;
 CH   : Char;
 P    : String;
 Done : boolean;
 X : Byte;
 Marker : Byte;
 C1,C2 : Char;
Begin
 OldAttr  := Textattr;
 StartedX := WhereX;
 P        := '';
 Counter  := 0;
 asm mov ah,1; mov ch,6; mov cl,7;int 10h; end; {Yes Cursor}
 Done := False;
 GotoXy(StartedX,WhereY);
 For X := 1 to Chars+1 do Write(' ');
 GotoXy(StartedX,WhereY);
 Marker := Counter;
Repeat
 MemW[$0000:$041C] := MemW[$0000:$041A];
 Qwrite(StartedX,
        WhereY,
        Padstring(P,Chars),
        7,
        0,
        80);
 GotoXy(StartedX+Marker,WhereY);
 C1 := #0;C2 := #0;
 C1 := Readkey;If C1 = #0 then C2 := Readkey;
 Case C1 of
 #13 : Done := True;
 #27 : Begin
        P := 'Aborted';
        Done := True;
       End;
  #8 : If (Marker > 0) and (Counter > 0) then
        Begin
         Delete(P,Marker,1);
         Dec(Counter);
         Dec(Marker);
        End;
 #32..#126 : If Counter < Chars then
              Begin
               Inc(Counter);
               Inc(Marker);
               If Caps then If (P[Counter-1] = #0) or (P[Counter-1]=#32) then C1 := Upcase(C1);
               If Allcaps then C1 := Upcase(C1);
               Insert(C1,P,Marker);
              End;
   End;
 Case C2 of
 #75 : Begin
        If Marker > 1 then Dec(Marker);
       End;
 #77 : Begin
        If Marker < Counter then Inc(Marker);
       End;
    End;
 Until Done = True;
 Lne := P;
 GotoXy(StartedX,WhereY);
 Textattr := 7;For X := 1 to Chars do Write(' ');
 If Lne <> 'Aborted' then Begin
                            GotoXy(StartedX,WhereY);
                            Write(Lne);
                          End;
 Textattr := OldAttr;
End;

Procedure Input_Adder(var Lne : String;Chars:Byte;Caps:Boolean;Allcaps:Boolean;Adder : String);
Var
 StartedX,Counter,OldAttr : Byte;
 CH   : Char;
 P    : String;
 Done : boolean;
 X : Byte;
 Marker : Byte;
 C1,C2 : Char;
Begin
 OldAttr  := Textattr;
 StartedX := WhereX;
 P        := Adder;
 Counter  := Length(Adder);
 asm mov ah,1; mov ch,6; mov cl,7;int 10h; end; {Yes Cursor}
 Done := False;
 GotoXy(StartedX,WhereY);
 For X := 1 to Chars+1 do Write(' ');
 GotoXy(StartedX,WhereY);
 Marker := Counter;
Repeat
{ MemW[$0000:$041C] := MemW[$0000:$041A];}
 Qwrite(StartedX,WhereY,Padstring(P,Chars),7,0,80);
 GotoXy(StartedX+Marker,WhereY);
 C1 := #0;C2 := #0;
 C1 := Readkey;If C1 = #0 then C2 := Readkey;
 Case C1 of
 #13 : Done := True;
 #27 : Begin
        P := 'Aborted';
        Done := True;
       End;
  #8 : If (Marker > 0) and (Counter > 0) then
        Begin
         Delete(P,Marker,1);
         Dec(Counter);
         Dec(Marker);
        End;
 #32..#255{126} : If Counter < Chars then
              Begin
               Inc(Counter);
               Inc(Marker);
               If Caps then If (P[Counter-1] = #0) or (P[Counter-1]=#32) then C1 := Upcase(C1);
               If Allcaps then C1 := Upcase(C1);
               Insert(C1,P,Marker);
              End;
   End;
  Case C2 of
   #75 : If Marker > 0 then Dec(Marker);
   #77 : If Marker < Counter then Inc(Marker);
  End;
 Until Done = True;
 Lne := P;
 GotoXy(StartedX,WhereY);
 Textattr := 7;For X := 1 to Chars do Write(' ');
 If Lne <> 'Aborted' then Begin
                            GotoXy(StartedX,WhereY);
                            Write(Lne);
                           End;
 Textattr := OldAttr;
End;

Procedure LoadMenus;
Var MenuFile : Text;
Begin
 Fillchar(Filename,Sizeof(Filename),#0);
 Fillchar(Descrip,Sizeof(Descrip),#0);
 Fillchar(Access,Sizeof(Access),#0);
 FindFirst('*.MNU',Archive,Dirinfo);
 X := 0;
 While (Doserror = 0) and (X < 1000) do
  Begin
   Inc(X);
   FileName[X] := Dirinfo.Name;
   FindNext(Dirinfo);
  End;
 Highest := X;
 For X := 1 to Highest do
  Begin
   Assign(MenuFile,Filename[X]);
   Reset(MenuFile);
   readln(menufile,MENU.Name);
   readln(menufile,MENU.Description);
   readln(menufile,MENU.Access);
   Descrip[X] := MENU.Description;
   Access[X] := MENU.Access;
   Close(Menufile);
  End;
End;

Procedure EditCommands(CmdNumber : Byte;Add : Boolean);
Const Opts : Array[1..11] of String[17] =
(' Description     ',' Access          ',' Command Key     ',' Operation       ',
 ' PString         ',' Command Type    ',' Password        ',' X Location      ',
 ' Y Location      ',' Pullbar Unlit   ',' Pullbar Lit     ');
Var Select : Byte;

Procedure DrawOptions;
var gg:byte;
Begin
 Qwrite(33,8,Padstring(Copy(MENU.Command[CmdNumber].Description,1,36),36),7,0,80);
 Qwrite(33,9,Padstring(Copy(MENU.Command[CmdNumber].Access,1,36),36),7,0,80);
 Qwrite(33,10,Padstring(MENU.Command[CmdNumber].CmdKey,1),7,0,80);
{ Qwrite(33,11,Padstring(MENU.Command[CmdNumber].Operation,2),7,0,80);}
 gotoxy(33,11);
 write(MENU.Command[CmdNumber].Operation);
 Qwrite(33,12,Padstring(Copy(MENU.Command[CmdNumber].PString,1,36),50),7,0,80);
 Case MENU.Command[CmdNumber].CmdType of
  1 : Qwrite(33,13,'Normal ',7,0,80);
  2 : Qwrite(33,13,'First  ',7,0,80);
  3 : Qwrite(33,13,'Every  ',7,0,80);
  4 : Qwrite(33,13,'Pullbar',7,0,80);
 End;
 Qwrite(33,14,Padstring(MENU.Command[CmdNumber].Password,20),7,0,80);
 Qwrite(33,15,Padstring(Strr(MENU.Command[CmdNumber].PullbarX),2),7,0,80);
 Qwrite(33,16,Padstring(Strr(MENU.Command[CmdNumber].PullbarY),2),7,0,80);
 Textattr := 7;
 WaitRetrace;
 GotoXy(33,17);For X := 1 to 36 do Write(' ');
 GotoXy(33,17);Pipewrite(MENU.Command[CmdNumber].UnlitText,True);
 Textattr := 7;
 GotoXy(33,18);For X := 1 to 36 do Write(' ');
 GotoXy(33,18);Pipewrite(MENU.Command[CmdNumber].litText,True);
 Textattr := 7;
End;

Var Temp : String;

Begin
 Textattr := 7;
 Fillchar(Mem[$b800:0000],4000,#0);
 If Add then
 Begin
  If CmdNumber > MENU.Numcommands then MENU.Numcommands := CmdNumber;
  With Menu do
    Begin
     Command[CmdNumber].Description := 'New Command';
     Command[CmdNumber].Access   := '';
     Command[CmdNumber].CMDKey   := '';
     Command[CmdNumber].Operation := '';
     Command[CmdNumber].Password := '';
     Command[CmdNumber].PString  := '';
     Command[CmdNumber].CmdType  := 1;
     Command[CmdNumber].PullbarX := 0;
     Command[CmdNumber].PullbarY := 0;
     Command[CmdNumber].UnlitText := '';
     Command[CmdNumber].LitText := '';
    End;
  End;
 Select := 1;
 Move(@CmdEdit^,Mem[$b800:0000],160*19);
 Repeat
  For X := 1 to 11 do If X = Select then Qwrite(13,7+X,Opts[X],15,1,80)
                                    else Qwrite(13,7+X,Opts[X],7,0,80);
  DrawOptions;
  CH := #0;
  If Keypressed then Getkeys(CH,CH);
  Case CH of
   #73 : {PageUp} Begin If CmdNumber > 1 then Dec(CmdNumber); End;
   #81 : {PageDn} Begin If CmdNumber < MENU.Numcommands then Inc(CmdNumber) End;
   #72 : If Select > 1 then Dec(Select);
   #80 : If Select < 11 then Inc(Select);
   #13 : Begin
          GotoXy(33,Select+7);
          Case Select of
           1 : Begin { Title }
                Input_Adder(Temp,36,False,False,MENU.Command[CmdNumber].Description);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].Description := Temp;
               End;
           2 : Begin { Access }
                Input_Adder(Temp,36,False,False,MENU.Command[CmdNumber].Access);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].Access := Temp;
               End;
           3 : Begin { CMD Key }
                Input_Adder(Temp,1,True,True,MENU.Command[CmdNumber].Cmdkey);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].Cmdkey := Temp;
               End;
           4 : Begin { Operation }
                Input_Adder(Temp,20,True,True,MENU.Command[CmdNumber].Operation);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].Operation := Temp;
               End;
           5 : Begin { PString }
                Input_Adder(Temp,36,False,False,MENU.Command[CmdNumber].PString);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].PString := Temp;
               End;
           6 : If MENU.Command[CmdNumber].CMDType < 4 then Inc(MENU.Command[CmdNumber].CMDType)
                                                          else MENU.Command[CmdNumber].CMDType := 1;
           7 : Begin {Password}
                Input_Adder(Temp,20,True,True,MENU.Command[CmdNumber].Password);
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].Password := Temp;
               End;
           8 : Begin { Pullbar X }
                InputNums(Temp,2,True);
                If Temp = '' then Temp := '0';
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].PullbarX := Valu(Temp);
               End;
           9 : Begin { Pullbar Y }
                InputNums(Temp,2,True);
                If Temp = '' then Temp := '0';
                If (Temp <> 'Aborted') then MENU.Command[CmdNumber].PullbarY := Valu(Temp);
               End;
           10 : Begin { Pullbar Unlit }
                 Textattr := 7;
                 Input_Adder(Temp,36,False,False,MENU.Command[CmdNumber].UnlitText);
                 If (Temp <> 'Aborted') then MENU.Command[CmdNumber].UnlitText := Temp;
                End;
           11 : Begin
                 Textattr := 7;
                 Input_Adder(Temp,36,False,False,MENU.Command[CmdNumber].litText);
                 If (Temp <> 'Aborted') then MENU.Command[CmdNumber].litText := Temp;
                End;
          End;
         NoCursor;
         End;
   #27 : Begin
          ClearScreen;
          Exit;
         End;
  End;
 Until 1 = 0;
End;

Procedure CommandEdit;
Const Options : Array[1..7] of String[8] =
 (' Insert ','  New  ',' Delete ','  Edit  ','  View  ','  Help  ','  Exit  ');
      OptX    : Array[1..7] of Byte = (4,16,26,37,48,59,70);

Var T_Active, T_Top, X, O_Active : Byte;
    CH : Char;

Procedure Display;
Var X : Byte;
Begin
  For X := 1 to 10 do
  Begin
   If X > MENU.Numcommands then Break;
   Qwrite(01,X+3,'³',8,0,80);
   Qwrite(05,X+3,'³',8,0,80);
   Qwrite(23,X+3,'³',8,0,80);
   Qwrite(36,X+3,'³',8,0,80);
   Qwrite(40,X+3,'³',8,0,80);
   Qwrite(45,X+3,'³',8,0,80);
   Qwrite(80,X+3,'³',8,0,80);
   If X = T_Active then
    Begin
     Qwrite(2,X+3,Padstring(' '+Strr(X+T_Top-1),3),15,1,80);
     Qwrite(6,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].Description,1,15)+' ',17),15,1,80);
     Qwrite(24,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].Access,1,10)+' ',12),15,1,80);
     Qwrite(37,X+3,Padstring(' '+MENU.Command[X+T_Top-1].CMDKey+' ',3),15,1,80);
     gotoxy(41,x+3);
     write(menu.Command[X+T_Top-1].Operation[1],menu.Command[X+T_Top-1].Operation[2]);

     Qwrite(46,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].PString,1,32)+' ',34),15,1,80);
    End else
    Begin
     Qwrite(2 ,X+3,Padstring(' '+Strr(X+T_Top-1),3),7,0,80);
     Qwrite(6 ,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].Description,1,15)+' ',17),7,0,80);
     Qwrite(24,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].Access,1,10)+' ',12),7,0,80);
     Qwrite(37,X+3,Padstring(' '+MENU.Command[X+T_Top-1].CMDKey+' ',3),7,0,80);
     gotoxy(41,x+3);
     write(menu.Command[X+T_Top-1].Operation[1],menu.Command[X+T_Top-1].Operation[2]);
{     Qwrite(41,X+3,menu.Command[X+T_Top-1].Operation,7,0,2);}
     Qwrite(46,X+3,Padstring(' '+Copy(MENU.Command[X+T_Top-1].PString,1,32)+' ',34),7,0,80);
    End;
  End;
End;

Begin
 ClrScr;
 T_Active := 1;
 T_Top := 1;
 O_Active := 1;
 FastMove(@CmdTop^,Mem[$b800:0000],160*3);
 GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
 If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                           else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
 Repeat
  Display;
  For X := 1 to 7 do
   Begin
    If MENU.Numcommands < 10 then
    If O_Active = X then Qwrite(OptX[X],MENU.NumCommands+5,Options[X],15,1,80)
                      else Qwrite(OptX[X],MENU.NumCommands+5,Options[X],7,0,80);
    If MENU.Numcommands >= 10 then
    If O_Active = X then Qwrite(OptX[X],15,Options[X],15,1,80) else Qwrite(OptX[X],15,Options[X],7,0,80);
   End;
  CH := #0;
  If Keypressed then Getkeys(CH,CH);
  Case CH of
   #80 : Begin
          If MENU.Numcommands > 10 then
           Begin
            If T_Active < 10 then Inc(T_Active) else If T_Top+9 < MENU.Numcommands then Inc(T_Top);
           End else If T_Active < MENU.Numcommands then Inc(T_Active);
         End;
   #72 : If T_Active > 1 then Dec(T_Active) else If T_Top > 1 then Dec(T_Top);
   #75 : If O_Active > 1 then Dec(O_Active);
   #77 : If O_Active < 7 then Inc(O_Active);
   #27 : Begin
           ClearScreen;
           Clear_Keyboard_Buffer;
           Exit;
         End;
   #13 : Begin
          Case O_Active of
           1 : Begin  {Insert}
                For X := MENU.Numcommands+1 downto T_Active+T_Top do
                 Begin
                  MENU.Command[X].Description  := MENU.Command[X-1].Description;
                  MENU.Command[X].Access       := MENU.Command[X-1].Access;
                  MENU.Command[X].CMDKey       := MENU.Command[X-1].CMDKey;
                  MENU.Command[X].Operation    := MENU.Command[X-1].Operation;
                  MENU.Command[X].Password     := MENU.Command[X-1].Password;
                  MENU.Command[X].PString      := MENU.Command[X-1].PString;
                  MENU.Command[X].CMDType      := MENU.Command[X-1].CMDType;
                  MENU.Command[X].PullbarX     := MENU.Command[X-1].PullBarX;
                  MENU.Command[X].PullbarY     := MENU.Command[X-1].PullBarY;
                  MENU.Command[X].UnLitText    := MENU.Command[X-1].UnlitText;
                  MENU.Command[X].LitText      := MENU.Command[X-1].LitText;
                 End;
                Inc(MENU.NumCommands);
                EditCommands(T_Active+T_Top-1,True);
                FastMove(@CmdTop^,Mem[$b800:0000],160*3);
               GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
                If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                           else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
               End;
           2 : Begin { Add }
                Inc(MENU.NumCommands);
                EditCommands(MENU.Numcommands,True);
                FastMove(@CmdTop^,Mem[$b800:0000],160*3);
                GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
                If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                           else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
               End;
           3 : Begin { Delete Command }
                For X := T_Active+T_Top-1 to MENU.NumCommands-1 do
                 Begin
                  MENU.Command[X].Description  := MENU.Command[X+1].Description;
                  MENU.Command[X].Access       := MENU.Command[X+1].Access;
                  MENU.Command[X].CMDKey       := MENU.Command[X+1].CMDKey;
                  MENU.Command[X].Operation    := MENU.Command[X+1].Operation;
                  MENU.Command[X].Password     := MENU.Command[X+1].Password;
                  MENU.Command[X].PString      := MENU.Command[X+1].PString;
                  MENU.Command[X].CMDType      := MENU.Command[X+1].CMDType;
                  MENU.Command[X].PullbarX     := MENU.Command[X+1].PullBarX;
                  MENU.Command[X].PullbarY     := MENU.Command[X+1].PullBarY;
                  MENU.Command[X].UnLitText    := MENU.Command[X+1].UnlitText;
                  MENU.Command[X].LitText      := MENU.Command[X+1].LitText;
                 End;
                Dec(MENU.NumCommands);
                ClearScreen;
                FastMove(@CmdTop^,Mem[$b800:0000],160*3);
                GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
                If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                           else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
                If T_Active+T_Top-1 > MENU.NumCommands then
                 Begin
                  If T_Active > 1 then Dec(T_Active) else If T_Top > 1 then Dec(T_Top);
                 End;
               End;
           4 : Begin { Edit }
                EditCommands(T_Active+T_Top-1,False);
                FastMove(@CmdTop^,Mem[$b800:0000],160*3);
                GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
                If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                           else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
               End;
           5 : Begin
                ClearScreen;
                Clear_Keyboard_Buffer;
                Simulation;
                ClearScreen;
                Clear_Keyboard_Buffer;
                FastMove(@CmdTop^,Mem[$b800:0000],160*3);
                GotoXy(3,1);PipeWrite('|08[|07'+MENU.Name+'.MNU|08]',True);
                If MENU.NumCommands <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(MENU.Numcommands+3)*160],160)
                            else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
               End;
           7 : Begin
                ClearScreen;
                Clear_Keyboard_Buffer;
                Exit;
               End;
          End;
         End;
  End;
 Until 0 = 1;
End;

Procedure EditMenu(Filename : Str12;Add : Boolean);
Const Opts : Array[1..14] of String[17] =
(' Description     ',' Menu Access     ',' Menu Tutorial   ',' Help File       ',
 ' Hot Keys        ',' Use Prompt      ',' Clear Screen    ',
 ' Prompt Line 1   ',' Prompt Line 2   ',' Force File Conf ',' Force Msg Conf  ',
 ' Menu Filename   ',' Pullbar Menu    ',' Command Editor  ');

Var Select : Byte;
    CH     : Char;
    X,Y,Z  : Byte;
    Temp : String;
    MenuFile : Text;
    TempChar : Char;
    Cmd : MenuCommandRec;

Procedure DrawOptions;
Begin
 Qwrite(26,7,Padstring(MENU.Description,36),7,0,80);
 Qwrite(26,8,Padstring(Copy(MENU.Access,1,36),50),7,0,80);
 Qwrite(26,9,Padstring(MENU.Tutorial,12),7,0,80);
 Qwrite(26,10,Padstring(MENU.HelpFile,12),7,0,80);
 If MENU.Hotkeys then Qwrite(26,11,'Yes ',7,0,80) else Qwrite(26,11,'Nope',7,0,80);
 If MENU.UsePrompt then Qwrite(26,12,'Yes ',7,0,80) else Qwrite(26,12,'Nope',7,0,80);
 If MENU.ClearScreen then Qwrite(26,13,'Yes ',7,0,80) else Qwrite(26,13,'Nope',7,0,80);
 GoXy(26,14);PipeWrite(Padstring(Copy(MENU.Prompt[1],1,36),36),True);
 GoXy(26,15);PipeWrite(Padstring(Copy(MENU.Prompt[2],1,36),36),True);
 Textattr := 7;
 Qwrite(26,16,Padstring(Strr(MENU.FileConf),2),7,0,80);
 Qwrite(26,17,Padstring(Strr(MENU.MsgConf),2),7,0,80);
 Qwrite(26,18,Padstring(MENU.Name,8),7,0,80);
 If MENU.Pullbar then Qwrite(26,19,'Yes ',7,0,80) else Qwrite(26,19,'Nope',7,0,80);
End;


Begin
 Local := True;
 Textattr := 7;
 Fillchar(Mem[$b800:0000],4000,#0);
 If Add then
  Begin
   Fillchar(Menu,Sizeof(Menu),#0);
   With Menu do
    Begin
     Name        := 'NEWMENU';
     Description := 'New Menu';
     Access      := '';
     Tutorial    := '';
     HelpFile    := Name+'.ANS';
     Hotkeys     := True;
     UsePrompt   := True;
     ClearScreen := True;
     Prompt[1]   := Name+' Menu - |TL Left';
     Prompt[2]   := 'Enter Command :';
     Fileconf    := 1;
     Msgconf     := 1;
     Numcommands := 1;
     Pullbar     := False;
     Command[1].Description := 'New Command';
     Command[1].Access   := '';
     Command[1].CMDKey   := '';
     Command[1].Operation := '-';
     Command[1].PString  := 'MAIN';
     Command[1].CmdType  := 1;
     Command[1].PullbarX := 0;
     Command[1].PullbarY := 0;
     Command[1].UnlitText := '';
     Command[1].LitText := '';
    End;
  End else
  Begin
   Fillchar(Menu,SizeOf(Menu),#0);
   Read_Menu(Filename);
  End;
 Select := 1;
 Move(@Menuedit^,Mem[$b800:0000],4000);
 Repeat
  For X := 1 to 14 do If X = Select then Qwrite(6,6+X,Opts[X],15,1,80)
                                    else Qwrite(6,6+X,Opts[X],7,0,80);
  DrawOptions;
  CH := #0;
  If Keypressed then Getkeys(CH,CH);
  Case CH of
   #72 : If Select > 1 then Dec(Select);
   #80 : If Select < 14 then Inc(Select);
   #27 : Begin
          GoXy(1,22);PipeWrite('|07Save Changes to |08"|15'+MENU.Name+'.MNU|08"|07? ',True);
          If Yesno($07,$1F) then Write_Menu(MENU.Name);
          Break;
         End;
   #13 : Begin
          GotoXy(26,Select+6);
          Case Select of
           1 : Begin { Title }
                Input_Adder(Temp,36,False,False,MENU.Description);
                If (Temp <> 'Aborted') then MENU.Description := Temp;
               End;
           2 : Begin { Access }
                Input_Adder(Temp,36,False,False,MENU.Access);
                If (Temp <> 'Aborted') then MENU.Access := Temp;
               End;
           3 : Begin { Tutorial }
                Input_Adder(Temp,12,True,True,MENU.Tutorial);
                If (Temp <> 'Aborted') then MENU.Tutorial := Temp;
               End;
           4 : Begin { Help File }
                Input_Adder(Temp,12,True,True,MENU.HelpFile);
                If (Temp <> 'Aborted') then MENU.Helpfile := Temp;
               End;
           5 : {asm xor MENU.hotkeys,1 end;} IF MENU.HOTKEYS=TRUE THEN MENU.HOTKEYS:=FALSE ELSE MENU.HOTKEYS:=TRUE;
           6 : {asm xor MENU.useprompt,1 end;}
               IF MENU.USEPROMPT=TRUE THEN MENU.USEPROMPT:=FALSE ELSE MENU.USEPROMPT:=TRUE;
           7 : {asm xor MENU.clearscreen,1 end;}
           IF MENU.CLEARSCREEN=TRUE THEN MENU.CLEARSCREEN:=FALSE ELSE MENU.CLEARSCREEN:=TRUE;
           8 : Begin
                 Input_Adder(Temp,36,False,False,MENU.Prompt[1]);
                 If (Temp <> 'Aborted') then MENU.Prompt[1] := Temp;
                End;
           9 : Begin
                 Input_Adder(Temp,36,False,False,MENU.Prompt[2]);
                 If (Temp <> 'Aborted') then MENU.Prompt[2] := Temp;
                End;
           10 : Begin
                InputNums(Temp,2,True);
                If Temp = '' then Temp := '1';
                If (Temp <> 'Aborted') then MENU.FileConf := Valu(Temp);
               End;
           11 : Begin
                 InputNums(Temp,2,True);
                 If Temp = '' then Temp := '1';
                 If (Temp <> 'Aborted') then MENU.MsgConf := Valu(Temp);
                End;
           12 : Begin
                 Input_Adder(Temp,12,true,True,MENU.Name);
                 If (Temp <> 'Aborted') and (Temp <> '') then MENU.Name := Temp;
                End;
           13 : {asm xor MENU.pullbar,1 end;}
             IF MENU.PULLBAR=TRUE THEN MENU.PULLBAR:=FALSE ELSE MENU.PULLBAR:=TRUE;
           14 : Begin
                 ClrScr;
                 CommandEdit;
                 Move(@Menuedit^,Mem[$b800:0000],4000);
                End;
          End;
         NoCursor;
        End;
  End;
 Until 1 = 0;
 ClrScr;
 Fastmove(@Menutop^,Mem[$b800:0000],480);
 If Highest <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(Highest+3)*160],160)
                 else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
End;

Procedure Display;
Const Options : Array[1..5] of String[8] =
 (' Insert ',' Delete ','  Edit  ','  Help  ','  Exit  ');
      OptX    : Array[1..5] of Byte = (8,23,38,51,64);
Begin
 For X := 1 to 10 do
  Begin
   If X > Highest then Break;
   Qwrite(23,X+3,'³',8,0,80);
   Qwrite(38,X+3,'³',8,0,80);
   Qwrite(01,X+3,'³',8,0,80);
   Qwrite(80,X+3,'³',8,0,80);
   If Active = X then
    Begin
     Qwrite(02,X+3,' '+Padstring(Descrip[X+Top-1],20),15,1,80);
     Qwrite(24,X+3,' '+Padstring(Filename[X+Top-1],13),15,1,80);
     Qwrite(39,X+3,' '+Padstring(Access[X+Top-1],40),15,1,80);
    End else
    Begin
     Qwrite(02,X+3,' ' + Padstring(Descrip[X+Top-1],20),7,0,80);
     Qwrite(24,X+3,' '+ Padstring(Filename[X+Top-1],13),7,0,80);
     Qwrite(39,X+3,' '+ Padstring(Access[X+Top-1],40),7,0,80);
    End;
  End;
 For X := 1 to 5 do
  Begin
   If Highest < 10 then
   If Active_Two = X then Qwrite(OptX[X],Highest+5,Options[X],15,1,80)
                     else Qwrite(OptX[X],Highest+5,Options[X],7,0,80);
   If Highest >= 10 then
   If Active_Two = X then Qwrite(OptX[X],15,Options[X],15,1,80) else Qwrite(OptX[X],15,Options[X],7,0,80);
  End;
End;

Begin
 LoadMenus;
 Active := 1;
 Active_Two := 1;
 Top    := 1;
 asm mov ax,3; int 10h; end;
 Nocursor;
 Fastmove(@Menutop^,Mem[$b800:0000],480);
 If Highest <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(Highest+3)*160],160)
                 else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
 Repeat
  Display;
  CH := #0;
  If Keypressed then Getkeys(CH,CH);
  Case CH of
   #72 : If Active > 1 then Dec(Active) else If Top > 1 then Dec(Top);
   #75 : If Active_Two > 1 then Dec(Active_Two);
   #77 : If Active_Two < 5 then Inc(Active_Two);
   #27 : Begin
          asm mov ax,3; int 10h; end;
          Halt(0);
         End;
   #80 : Begin
          If Highest > 10 then
           Begin
            If Active < 10 then Inc(Active) else If Top+9 < Highest then Inc(Top);
           End else If Active < Highest then Inc(Active);
         End;
   #13 : Begin
          Case Active_Two of
            1 : Begin
                 EditMenu('',True);
                 LoadMenus;
                 WaitRetrace;
                 ClrScr;
                 Fastmove(@Menutop^,Mem[$b800:0000],480);
                 If Highest <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(Highest+3)*160],160)
                                  else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
                End;
            2 : Begin
                 DeleteFile(Filename[Active+Top-1]);
                 LoadMenus;
                 Active := 1;
                 Top := 1;
                 WaitRetrace;
                 ClrScr;
                 Fastmove(@Menutop^,Mem[$b800:0000],480);
                 If Highest <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(Highest+3)*160],160)
                                  else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
                End;
            3 : Begin
                 EditMenu(Filename[Active+Top-1],False);
                 LoadMenus;
                 WaitRetrace;
                 ClrScr;
                 Fastmove(@Menutop^,Mem[$b800:0000],480);
                 If Highest <= 10 then Fastmove(@MenuEnd^,Mem[$b800:(Highest+3)*160],160)
                  else Fastmove(@MenuEnd^,Mem[$b800:13*160],160);
                End;
            5 : Begin
                 asm mov ax,3; int 10h; end;
                 Halt(0);
                End;
          End;
         End;
  End;
 Until 0 = 1;
End.