(* Menuing.  They are pretty good.  Could be even better *)

Unit Menu;

interface
uses Dos,FILEAREA,linklist,pullbar,Records,UserStuf,timeing,nodechat,
     crt,DataArea,msgarea,barinfo,filehandle,detector;

Type

 MenuCommandRec = Record
                   Description  : String[35];
                   Access       : ACS;
                   CMDKey       : String[80];
                   Operation    : String[60];
                   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];
           keys        : string[50];
           Hotkeys     : Boolean;
           Useprompt   : Boolean;
           Pullbar     : Boolean;
           ClearScreen : Boolean;
           Prompt      : Array[1..2] of String[80];
           Fileconf    : 0..999;
           MsgConf     : 0..999;
           NumCommands : 0..999;
          End;

  cmds=string;

  MSTR=STRING[8];

var
    Menur      : Menurec;
    MaxCmd     : 1..50;
    cmdlist    : pdllobj;
    oldmenu    : string[12];
    tempchar   : char;
    menuchange : boolean;
    ds         : boolean;
    didhelp    : boolean;
    PB         : Pullmoderec;
    passwordit : boolean;
  Procedure First_Menu;
  Procedure RunMenu(A:MSTR);
  Function  ACS(S:string):Boolean;
  Procedure Process_Menu_Command(command:Menucommandrec;a:cmds);
  procedure clearit;
Implementation

uses io,protcomm,genstr;

Function ACS(S:string):boolean;
Begin
End;

procedure clearit;
var x:byte;
begin
for x:=1 to maxbars do pb.bar[x]:=false;
end;

Procedure Process_Menu_Command(command:Menucommandrec;a:cmds);
Var cmd1,cmd2 : char;
    cmd3      : string;
    Year,
    Month,
    Day,
    DOW       : Word;
    DT        : DateTime;
    MSec      : Word;
    Counter   : integer;
    Divs      : Array[1..5] Of Byte;
    z,X       : Integer;
    D         : INTEGER;
    temps     : string[40];
    MENU      : MSTR;
    userx     : longint;
    dyn       : boolean;
    loadmenu  : string;
begin
 TimeSlice;
 cmd1 := a[1];
 cmd2 := a[2];
 cmd3:='';
 cmd3:=a;
 delete(cmd3,1,2);
 D:=VALU(CMD3[1]);
 MENU:=CMD3;
 x:=1;
 z:=1;
 textattr:=7;
 doyn:=false;
 case cmd1 of
  'R': Case cmd2 of
        'A':printrandom(Config.Textfile_Dir+CMD3,basicmci,false);
       END;
  '*': Case Cmd2 of
        'T':Enter:=True;
        'F':Enter:=false;
       End;
  'B': CASE CMD2 OF
        'L': batchlist;
       End;
  'D': CASE CMD2 OF
        'A': Runadd(D);
        'R': Runadd2(D);
        'L': Runit (D);
        'P': randompick(D);
       End;
  '^': Case cmd2 of
        'L' : UserList;
       End;
  'F':CASE CMD2 OF
       'M':ADDFILEAREA;
       'A':AREALIST;
       'U':UPLOAD;
       'D':DOWNLOAD;
       'F':LISTFILES;
       'E':fileareaedit;
       END;
  'M':case cmd2 of
       'P':POSTit(false,0);
       'A':Message_Area_List;
       'R':read_messages(true);
      end;
  '-':Case cmd2 of {-x = General BBS Commands}

       '!': begin {this is for password}
            infobar(currentbar,command.password);
            printfile(CONFIG.TEXTFILE_DIR+cmd3,basicmci,true);
            infobar(currentbar,'');
            if uppercase(basicmci[23].str)=uppercase(command.password) then
            passwordit:=true else passwordit:=false;
            basicmci[23].str:='';
            end;

       '^': Begin {-^ - Goto menu}
             ds:=false;
             savedx:=1;
             savedy:=1;
             cmdlist^.emptylist;
             menuchange:=true;
             menustack[currentmenu]:=cmd3;
            End;
       '/':;
       '\':;
       'G': Begin
             cmdlist^.emptylist;
             release(cmdlist);
             loggedoff:=true;
             Exit;
            End;
{       'S': printrandom(CONFIG.TEXTFILE_DIR+cmd3,basicmci,false);}
       'F': printfile(CONFIG.TEXTFILE_DIR+cmd3,basicmci,false);
       'P': Animated_HoldScreen;
       'L': AnsiClr;
       'X': asm xor user.xpermode,1 end;
      End;
      'S':case cmd2 of
           'O':begin
               scroller.filename:=cmd3;
               scrolltext(1);
               end;
           'F':scrolltext(3);
          end;
      'N':case cmd2 of
           'C': multichat;
           end;
      'X':Case cmd2 of {Xx = Matrix Commands}
           'A': Apply;
           'L': Begin
                 user.time:=10;
                 timeleft:=10;
                 logontime:=timer;
                 If GetUser=FALSE then Exit;
                 logontime:=timer;
                 InfoBar(CurrentBar,'');
                 cmdlist^.emptylist;
{                 menuchange:=true;
{                 menustack[currentmenu]:='Startup';}
                 UnpackTime(User.Lastcall,DT);
                 GetDate(Year,Month,Day,DOW);
                 If (Year <> DT.Year) or (Month <> DT.Month) or (Day <> DT.Day)
                 then User.Time := User.Timeperday;
                 GetTime(DT.Hour,DT.Min,DT.Sec,MSec);
                 PackTime(DT,User.Lastcall);
                 InfoBar(CurrentBar,'');
                 addtolog('|B0|08Ä--> |15'+user.alias+' |08logged on at |15'+time+' |08on |15'+
                           Date+' |15at |08'+STRR(CONNECTBAUD)+' |15baud');
                End;
              end;
          else print('|12Command Error!!');
          End ;
End;

function checkcmd(s:String):boolean; {this checks for certain letters}
var x:byte;
begin
if MENUR.KEYS='' then begin
                      checkcmd:=true;
                      exit;
                      end;
for x:=1 to LENGTH(MENUR.KEYS) do
if upcase(s[1])=upcase(menur.keys[x]) then
                          begin
                          checkcmd:=true;
                          exit;
                          end;
checkcmd:=false;
end;

procedure parseit(cmd:menucommandrec);
        var cmdstr   : cmds;
            counter  : byte;
            pp       : string;

begin
 cmdstr:='';
 FOR counter:=1 TO length(cmd.operation) do
 begin
 if cmd.operation[counter]<>';' then cmdstr:=cmdstr+cmd.operation[counter];
 if (cmd.operation[counter]=';') or (counter=length(cmd.operation)) then
    begin
    passwordit:=true;
    Process_Menu_Command(cmd,cmdstr);
    if passwordit=false then counter:=length(cmd.operation);
    cmdstr:='';
    end;
 end;
end;


Procedure Run_Config_Pullbars;
Var X,Count : 1..50;
    Cmd     : Menucommandrec;
    Result  : Byte;
    Key     : String[80];
Begin
 Count := 1;
 For X := 1 to MaxCmd do
  Begin
   Cmdlist^.Getnodedata(cmdlist^.nodeptr(x),cmd);
   If Cmd.CmdType = 3 then parseit(cmd) else
   if cmd.cmdtype = 4 then
    Begin
     Pb.Onstring[Count]   := Cmd.LitText;
     Pb.Offstring[Count]  := cmd.UnlitText;

     if pb.bar[count]=false then begin
     Pb.X[Count]          := Cmd.Pullbarx;
     Pb.Y[Count]          := Cmd.Pullbary;
     end;

     Pb.Choices           := Count;
{    pb.chars[count]      := cmd.cmdkey[1];}
     Pb.Pointercmd[Count] := X;
     Pb.Firstoption       := 1;
     Inc(Count);
    End;
  End;
  Result := Pullbars(Pb);
  Cmdlist^.Getnodedata(cmdlist^.nodeptr(pb.pointercmd[Result]),cmd);
  Key := Cmd.CMDKey;
  For X := 1 to maxCmd do
  Begin
   If (not carrier) and (not localon) then Exit;
   Fillchar(Cmd,SizeOf(Cmd),0);
   Cmd.Operation[1] := #0;
   Cmd.Operation[2] := #0;
   Cmdlist^.Getnodedata(cmdlist^.nodeptr(X),cmd);
   If Cmd.CMDKey = Key then parseit(cmd);
   if menuchange then exit;
  End;
End;


Procedure Run_Input;
Var X     : Byte;
    Cmd   : Menucommandrec;
    Input : String;
    ss    : cmds;
    y     : byte;
    xx    : byte;
    pp    : string;
    yn    : boolean;
Begin
 yn:=false;
 if loggedoff then exit;
 if menuchange then exit;
 Fillchar(cmd,sizeof(cmd),#0);
 Input := '';
 For X := 1 to MaxCmd do
  Begin
   Fillchar(cmd,sizeof(cmd),#0);
   Cmdlist^.Getnodedata(cmdlist^.Nodeptr(x),Cmd);
   If Cmd.CmdType = 3 then If Acs(Cmd.Access) then parseit(cmd);
  End;

 If Menur.UsePrompt then
  Begin
   if (menur.prompt[1]='') and (menur.prompt[2]='') then showprompt(didhelp) else
     begin
     print(Menur.prompt[1]);
     If Menur.Prompt[2]<>'' Then print(#10#13+Menur.prompt[2]);
     end;
  END;
  didhelp:=false;
  if doyn  =true  then
  IF tempyn=true  then INPUT:='Y' else
  IF tempyn=false then INPUT:='N';
  if doyn  =false then

  BEGIN
  buflen:=30;
  if enter=false then
  repeat
  if (user .hotkey=false) then sreadln(input) else Input := SReadkey;
  until (input<>#13) OR ((Not Carrier) AND (Not Localon)) or (hungup) or (loggedoff) else

  repeat
  if (user .hotkey=false) then sreadln(input) else Input := SReadkey;
  until (INPUT<>#13) OR ((Not Carrier) AND (Not Localon)) or (hungup) or (loggedoff);;
  END;

 if input='?' then begin

                   PRINTrandom(Config.Textfile_Dir+Menur.Helpfile,BASICMCI,False);
                   didhelp:=true;
                   end
 else If Length(Input) > 0 then
 Begin
  For X := 1 to MaxCmd do
   if checkcmd(input) then
   Begin
    Fillchar(cmd,sizeof(cmd),#0);
    Cmdlist^.Getnodedata(cmdlist^.Nodeptr(x),Cmd);
    If Menur.Hotkeys then
     Begin
     If Upcase(Input[1]) = UpCase(Cmd.CmdKey[1]) then
     If ACS(Cmd.Access) then parseit(cmd);
     if loggedoff then exit;
     if menuchange then exit;
     End else
     Begin
      If uppercase(input) = uppercase(cmd.CMDkey) then
      if acs(cmd.access) then parseit(cmd);
      if loggedoff then exit;
      if menuchange then exit;
     End;
   End;
 End;
 Swriteln('');
End;

Procedure RunMenu(A:MSTR);
Var X : Byte;
  Cmd : MenuCommandRec;
  menufile:file;
  ss:cmds;
  y:byte;
  xx: byte;
 pp :string;
 S:STRING[12];
begin
 S:='';
 S:=A+'.MNU';
 menuchange := False;
 assign(menufile,config.menu_dir+S);
 fillchar(pb,sizeof(pb),#0);
 {$I-} reset (menufile,1); {$I+}
 if ioresult<>0 then
  begin
   writeln('Menu Does Not Exist Falling Back');
   Assign(menufile,config.menu_dir+oldmenu);
   {$I-} Reset (menufile,1); {$I+}
   if ioresult<>0 then
    begin
     writeln('Fallback Menu Does Not Exist Halting Operations!');
     halt(1);
    end;
  end;
 nread(menufile,menur,sizeof(menur));
  while not (eof (menufile)) do
  begin
    with cmd do
        begin
        nread(menufile,cmd,sizeof(cmd));
        Case Cmd.CMDType of
          1,4 : CMDList^.Add(Cmd,SizeOf(Cmd)); { normal / pullbar }
          2   : parseit(cmd);                  { first }
          3   : Begin                          { every }
                parseit(cmd);
                CMDList^.Add(Cmd,SizeOf(Cmd));
                End;
        end;
 end;
 Maxcmd:=cmdlist^.totalnodes;
end;

 close(menufile);
 Infobar(CurrentBar,'');
 menuname:=menur.description;
 Repeat
  if loggedoff  then exit;
  If menuchange then exit;
  If Menur.Clearscreen then if user.xpermode=false then AnsiClr;
  If Menur.Pullbar then begin;
                        PRINTrandom(Config.Textfile_Dir+Menur.Helpfile,BASICMCI,False);
                        end
  else If not User.XPerMode then PRINTrandom(Config.Textfile_Dir+Menur.HelpFile,baSICMCI,False);
  OldMenu := S;

  For X := 1 to MaxCmd do { this does everys }
   Begin
    Fillchar(Cmd,sizeof(cmd),#0);
    Cmdlist^.Getnodedata(cmdlist^.Nodeptr(x),Cmd);
    If Cmd.CmdType = 2 then parseit(cmd);
   End;

 If Menur.Pullbar Then Run_Config_Pullbars else Run_Input;
 if loggedoff then exit;
 IF MENUCHANGE THEN EXIT;
 Until (not carrier and not localon) or (hungup) or (loggedoff);
End;



Procedure First_Menu;
 var userx:longint;
 Begin
  fillchar(menustack,sizeof(menustack),#0);
  currentmenu:=1;
  oldmenu:='';
  fillchar(currentndx,sizeof(currentndx),#0);
  read_base('MSGCONF1',1,CurrentBASE);
  new(cmdlist,init);
  menustack[currentmenu]:='matrix';
  menuchange:=false;
  repeat
  runmenu(menustack[currentmenu]);
  until ((not carrier) and (not localon)) or (loggedoff) or (hungup);
 End;

end.

