Program Exec;

Uses crt, pr_exec, pr_defs, progdefs, strings, console, fkscr;

Var  i,j,lc,err   : Integer;
     func         : LongInt;
     c            : Char;
     fn           : PChar;
     update,
     quitflag     : Boolean;
     realtime     : LongInt Absolute $40:$6C;

{--------CONSOLE COMMANDS:}
Procedure cmd_quit;
Begin
  Halt(0);
End;

Procedure cmd_help;
Var i : integer;
Begin
  Con_WriteLn('Available console commands:');
  For i := 0 to numcmds - 1 do begin
    Con_Write('  ');
    Con_Write(cmds[i].name);
    Con_Write(' ');
    Con_WriteLn(cmds[i].help);
  End;
End;

Procedure cmd_func_list;
Var i : integer;
Begin
  Con_WriteLn('Available functions:');
  For i := 1 To progs^.numfunctions - 1 Do Begin
    If Integer(pr_functions^[i].first_statement) >= 0 Then Begin
      Con_Write('  ');
      Con_Write(StrPas(@pr_strings^[pr_functions^[i].s_name]));
      Con_WriteLn('();');
    End;
  End;
End;

Var oldcmd : PChar;
    crp    : PChar;
    displock : Boolean;
    displine : LongInt;

Begin
  CursorHide;
  TextColor(7); TextBackground(0);
  con_clear;
  AddCmd('exec', '<func> - execute a function', {$IFNDEF TP}@{$ENDIF}cmd_exec);
  AddCmd('func_list', '- list all functions', {$IFNDEF TP}@{$ENDIF}cmd_func_list);
  AddCmd('help', '- see this list', {$IFNDEF TP}@{$ENDIF}cmd_help);
  AddCmd('clear', '- clear the console', con_clear);
  AddCmd('quit', '- quit program', {$IFNDEF TP}@{$ENDIF}cmd_quit);

  If ParamCount = 0 Then err := PR_LoadBPC('bm.bpc')
  Else err := PR_LoadBPC(ParamStr(1));

  If err <> 0 Then Begin
    Con_WriteLn('There was an error loading the file.');
    Halt(0);
  End;

  GetMem(cmd, 256); oldcmd := cmd; lc := 0;
  For i := 0 To 255 do cmd[i] := #0;
  update := True;
  cmd_help; displock := True;
  Repeat
    ClrScr;
    If KeyPressed Then Begin
      c := ReadKey;
      Case c Of
        #32..#127: Begin cmd[lc] := c; Inc(lc); End;
        #0: Case ReadKey Of
              #75: Dec(lc);
              #77: Inc(lc);
              #73: Begin
                     If displock Then displine := lacc - 23;
                     displock := False;
                     displine := displine - 1;
                   End;
              #81: Begin
                     displock := False;
                     displine := displine + 1;
                     If displine >= (lacc - 23) Then Begin
                       displock := True; displine := lacc - 23;
                     End;
                   End;
            End;
        #8: Begin
              If lc > 0 Then Begin
                For i := lc To 255 do cmd[i-1] := cmd[i];
                Dec(lc);
              End;
            End;
        #13: Begin
               {Skip to next line:}
               fn := GetToken; update := False;
               For i := 0 To numcmds - 1 Do
                 If StrIComp(fn, StrPCopy(crp, cmds[i].name)) = 0 Then Begin
                   cmds[i].func; update := True;
                 End;
               If (update = False) Then Begin
                 Con_Write('Unknown command "');
                 Con_Write(StrPas(fn));
                 Con_WriteLn('"');
               End;
               {Reset the pointer.}
               cmd := oldcmd;
               For i := 0 To lc do cmd[i] := #0;
               lc := 0;
             End;
        #27: quitflag := true;
      End;
    End;
    If displock Then Begin
      GotoXY(1, 1);
      For i := lacc - 23 To lacc Do
        If (i >= 0) And Assigned(lines[i]) Then Begin
          WriteLn(StrPas(lines[i]));
        End Else Begin
          WriteLn('');
        End;
    End Else Begin
      GotoXY(1, 1);
      If displine < 0 Then displine := 0;
      If displine > (lacc-23) Then Begin
        displock := True;
        displine := lacc - 23;
      End;
      For i := displine To displine + 22 Do
        If (i >= 0) And Assigned(lines[i]) Then Begin
          WriteLn(StrPas(lines[i]));
        End Else Begin
          WriteLn('');
        End;
    End;
    GotoXY(1, 24); Write(']'); Write(StrPas(cmd)); clreol;
    GotoXY(lc+2, 24);
    If (realtime And 4) = 0 Then Write('Û') Else Write(' ');
    VRet;
    CopyScreen;
  Until (quitflag = true);
End.
