SUBS1.PAS

21.6 KB c7f9cdbc242c2f8f…
{$I DIRECT.INC}

UNIT Subs1;

INTERFACE

Uses Crt, Dos, MkAvatar, GenSubs, GenTypes,
     StatRet, ConfigRt, Modem, SwapUnit, DosMem;

Const MultiTasking : Boolean = TRUE;

Type StrRec = Record
       C : Array[1..15] of String[2];
       S : Array[1..15] of Lstr;
       T : Array[1..15] of Byte;
     End;

Var FirstVariable,
    Tasker,
    Usebottom : Byte;

    Local,
    Online,
    ChatMode,
    Disconnected : Boolean;

    Unum,
    Ulvl : Integer;
    Baudrate : Longint;
    Unam : Mstr;
    BaudStr : Mstr;
    Urec : UserRec;

    LogonTime,
    LogoffTime,
    LogonUnum : Integer;
    Laston : Longint;

    Dots,
    Nochain,
    Break,
    XPressed,
    Requestchat,
    RequestCom,
    RequestBreak,
    ReqSpecial,
    ForceHangup,
    Modeminlock,
    Modemoutlock,
    Timelock,
    TempSysop,
    SplitMode,
    Texttrap,
    PrinterEcho,
    UseLineFeeds,
    UseCapsonly,
    DontStop,
    NoBreak,
    WordWrap,
    BeginWithSpacesOK,
    SysNext,
    InGetStr,
    No_Local_Output : Boolean;

    RegularLevel,
    NumUsers,
    CurBoardnum,
    Lasty,
    LineCount,
    Curattrib,
    Firstfree,
    LockedTime,
    IoCode,
    Buflen : integer;
    CurSection : Configtype;
    CurboardName : Sstr;

    Inpt,
    Chainstr : Anystr;

    Chatreason,
    Lastprompt,
    Errorparam,
    ErrorProc : Lstr;

    Curboard : Boardrec;

    Mes : Message;

    Syslogdat : Array [0..maxsyslogdat] of syslogdatrec;

    NumSysLogDat : Integer;
    ReturnTo     : Char;
    ConnectBaud  : Longint;
    OkForTitle   : Boolean;
    UnReadNewMsgs,
    ReplyNum     : Integer;
    MCStrLength  : Byte;
    LastMsgConf,
    LastFileConf,
    MsgConf,
    FileConf     : ShortInt;
    LastMenu     : SStr;
    IOErrors     : Array[1..48] of Mstr;
    LastVariable : Byte;

    Sr           : StrRec;
    Non_Stop,
    CheckPageLength : Boolean;
    Theme            : ThemeRec;

Const Numsysfiles = 20;

Var TextFile : File of Lstr;
    MailFile : File of MailPtrRec;
    UFile    : File of UserRec;
    MFile    : File of MailRec;
    UDFile   : File of UDRec;
    UDIndex  : File of UDIndexREC;
    AFile    : File of Arearec;
    BFile    : File of Bulrec;
    BDFile   : File of Boardrec;
    BiFile   : File of Sstr;
    ScanFile : File of NewScanRec;
    DDFile   : File of Baserec;
    EFile    : File of entryrec;
    GFile    : File of GroupRec;
    Logfile  : File of Logrec;
    USDile   : File of UserSpecsRec;
    RFile    : File of RumorRec;
    MNIFile  : File Of Node_Message;
    ThemeFile  : File of ThemeRec;

    SysFiles : Array [1..NumSysFiles] of File Absolute Textfile;

    TTFile : Text;


Procedure UnCrunch (var Addr1,Addr2; BlkLen:Integer);
Function B_(X:Byte):Sstr;
FUNCTION Hex2Byte (HexByte : STRING) : BYTE;
Function DiskSpace(Path:lstr; Total:boolean):LongInt;
Procedure MultiColor(M:String);
procedure writelog (m,s:integer; prm:lstr);
procedure files30;
function ioerrorstr (num:integer):lstr;
procedure error (errorstr,proc,param:lstr);
procedure fileerror (procname,filename:mstr);
procedure che;
function timeleft:integer;
function timetillevent:integer;
procedure settimeleft (tl:integer);
procedure tab (n:anystr; np:integer);
function yes:boolean;
function yesno (b:boolean):sstr;
function timeontoday:integer;
function isopen (var ff):boolean;
procedure textclose (var f:text);
procedure close (var ff);
function withintime (t1,t2:sstr):boolean;
Procedure TimeSlice;
function hungupon:boolean;
function sysopisavail:boolean;
function sysopavailstr:sstr;
function singularplural (n:integer; m1,m2:mstr):mstr;
function s (n:integer):sstr;
function numthings (n:integer; m1,m2:mstr):lstr;
procedure thereisare (n:integer);
procedure thereare (n:integer; m1,m2:mstr);
procedure assignbdfile;
procedure openbdfile;
procedure formatbdfile;
procedure closebdfile;
procedure opentempbdfile;
procedure closetempbdfile;
function keyhit:boolean;
procedure readline (var xx);
Procedure ShutDownSystem;
procedure close_them_all(var ff);
Function RandomFile(FileName : String) : String;
procedure clearbreak;
procedure ansicolor (attrib:byte);
procedure ansireset;
procedure specialmsg (q:anystr);
function bars_ok : boolean;
Procedure Color(Foreground,Background : Byte);
Function Percentage(A,B:Integer) : Real;
Procedure executewithswap(ProgName : LStr; CommandLine : AnyStr; Force:Boolean);
function lget_ms: longint;
procedure delay(ms: longint);
Procedure SendStr(S:String);
Procedure SendLn(S : String);
Procedure SendFull(S:String);
Procedure SendCr(S : String);

implementation

uses userret,archive,subsovr, subs2, windows;

Function RandomFile(FileName : String) : String;
Var S : SearchRec;
    N : Byte;
Begin
  N := 0;
  FindFirst(FileName+'.*', AnyFile, S);
  While DosError = 0 Do
  Begin
    Inc(N);
    FindNext(S);
  End;
  Randomize;
  RandomFile := FileName + '.' + Strr(Random(N) + 1);
End;


Procedure UnCrunch (var Addr1,Addr2; BlkLen:Integer);
Begin
  InLine ($1E/$C5/$B6/Addr1/$C4/$BE/Addr2/$8B/$8E/BlkLen/$8B/$D7/
          $B4/$00/$AC/$3C/$10/$73/$07/$80/$E4/$F0/$0A/$E0/$EB/$44/
	  $3C/$18/$74/$13/$73/$19/$2C/$10/$02/$C0/$02/$C0/$02/$C0/
	  $02/$C0/$80/$E4/$0F/$0A/$E0/$EB/$2D/$81/$C2/$A0/$00/$8B/
	  $FA/$EB/$25/$3C/$1A/$75/$0B/$AC/$49/$51/$32/$ED/$8A/$C8/
	  $AC/$EB/$0D/$90/$3C/$19/$75/$11/$AC/$51/$32/$ED/$8A/$C8/
	  $B0/$20/$0B/$C9/$74/$03/$AB/$E2/$FD/$59/$49/$AB/$0B/$C9/
	  $74/$02/$E2/$AA/$1F);
End;


Function B_(X:Byte) : SStr;
Begin
  B_ := #27'[' + Strr(X) + 'D';
End;

Function DiskSpace(Path:lstr; Total:boolean) : LongInt;
Begin
  If Total Then
    DiskSpace := DiskSize(Byte(UpCase(Path[1]))-64) Else
    DiskSpace := DiskFree(Byte(UpCase(path[1]))-64);
End;

Procedure SendStr(S:String);
Var X: Byte;
Begin
  For X := 1 to Byte(S[0]) do DirectOutChar(S[X]);
End;

Procedure SendLn(S : String);
Begin
  SendStr(S + #13#10);
End;

Procedure SendFull(S:String);
Var X: Byte;
Begin
  For X:=1 to Byte(S[0]) do WriteChar(S[X]);
End;

Procedure SendCr(S : String);
Begin
  SendFull(S + #13#10);
End;

Procedure AnsiColor (Attrib : Byte);
Var TC : Integer;
    W  : Byte;
Const ColorID : Array [0..7] of Byte = (30,34,32,36,31,35,33,37);
Begin
  If CurAttrib = Attrib Then Exit Else CurAttrib := Attrib;
  If Avatar in Urec.Config Then
  Begin
    SendStr(^V^A+Char(Attrib));
    Exit;
  End;
  If Attrib = 0 Then TextAttr := 7 Else TextAttr := Attrib;
  If Not (AnsiGraphics in Urec.Config) Or (Attrib = 0) Or (UseCapsOnly)
     Or Break Then Exit;
  SendStr(#27'[0');
  TC := Attrib AND 7;
  If TC <> 7 Then SendStr(';'+Strr(ColorID[TC]));
  TC := (Attrib SHR 4) AND 7;
  If TC <> 0 Then SendStr(';'+Strr(colorid[tc]+10));
  if (attrib and 8)=8 then SendStr(';1');
  if (attrib and 128)=128 then SendStr(';5');
  DirectOutChar('m');
End;

FUNCTION Hex2Byte (HexByte : STRING) : BYTE;
ASSEMBLER;
ASM
  LES     DI, [HexByte]
  MOV     AX, ES:[DI+1]
  SUB     AX, 3030h
  CMP     AL, 9
  JLE     @Done1
  SUB     AL, 7

@DONE1:
  SHL     AL, 4
  CMP     AH, 9
  JLE     @Done2
  SUB     AH, 7

@DONE2:
  OR      AL, AH
END;

Procedure Color(Foreground,Background : Byte);
Begin
  AnsiColor(ForeGround OR (BackGround SHL 4));
End;

Procedure MultiColor (M : String);
Var X,
    Z,
    ForeGround,
    BackGround : Byte;
    A : String[2];
    SChar : Char;
Begin
  ClearBreak;
  McStrLength := 0;
  BackGround := 0;
  ForeGround := Urec.Color1;
  If Pos('@USER@', UpString(M)) > 0 Then
  Begin
    X := Pos('@USER@', UpString(M));
    Delete(M, X, 6);
    Insert(Unam, M, X);
  End;
  X := 1;
  While X <= Length(M) Do
  Begin
    Case M[X] Of
      '@' : If X <= (Length(M) - 3) Then
            Begin
              Inc(X);
              If (M[X] = 'X') Then
              Begin
                A := M[X + 1] + M[X + 2];
                Inc(X,3);
                AnsiColor(Hex2Byte(A));
              End
              Else SendFull('@');
            End
            Else
            Begin
              SendFull(M[X]);
              Inc(X);
            End;
      '$' : Begin
              Inc(X);
              Case M[X] Of
                'a':ansicolor(0);
                'b':ansicolor(1);
                'g':ansicolor(2);
                'c':ansicolor(3);
                'r':ansicolor(4);
                'p':ansicolor(5);
                'y':ansicolor(6);
                'w':ansicolor(7);
                'A':ansicolor(8);
                'B':ansicolor(9);
                'G':Ansicolor(10);
                'C':Ansicolor(11);
                'R':ansicolor(12);
                'P':ansicolor(13);
                'Y':ansicolor(14);
                'W':ansicolor(15);
                Else SendFull('$' + M[X]);
              End;
              Inc(X);
            End;
      '|' : Begin
              A := UpString(M[X + 1] + M[X + 2]);
              Inc(X, 2);
              If A[1] = '@' Then
              Begin
                SChar := A[2];
                A[0]:=#0;
                Inc(X);
                While (Length(A)<3) and (M[X] in ['0'..'9']) Do
                Begin
                  A := A + M[X];
                  Inc(X);
                End;
                Dec(X);
                For Z := 1 To Valu(A) Do DirectOutChar(SChar);
              End
              Else
              If A = 'C1' then AnsiColor(Urec.Color1)
              Else
              If A = 'C2' then AnsiColor(Urec.Color2)
              Else
              If A = 'C3' then AnsiColor(Urec.Color3)
              Else
              If A = 'C4' Then AnsiColor(Urec.Color4)
              Else
              If A = 'C5' Then AnsiColor(Urec.Color5)
              Else
              If A = 'C6' Then Ansicolor(Urec.Color6)
              Else
              If A = 'C7' Then ansiColor(Urec.Color7)
              Else
              If A = 'TL' then SendFull(strr(timeleft))
              Else
              if A = 'TN' then SendFull(timestr(now))
              Else
              if A = 'UH' then SendFull(urec.handle)
              Else
              if A = 'CL' then ansiCls
              else
              if A = 'GO' then
                begin
                goXY(stoi(copy(m,x+1,2)),stoi(copy(m,x+3,2)));
                inc(x,4);
                end else
              if A = 'CR' then SendCr('')
              Else
              if A = Sr.C[1] Then
                If (Sr.C[1]<>'OR') and (Sr.C[1]<>'MN')
                Then SendFull(Sr.S[1])
                Else MultiColor(Sr.S[1])
              Else
              If A = Sr.C[2] then SendFull(Sr.S[2])
              Else
              If A = Sr.C[3] then SendFull(Sr.S[3])
              Else
              If (A[1]='B') and (A[2] in ['0'..'7']) Then
              Begin
                AnsiColor((Valu(A[2]) SHL 4) OR ForeGround);
                BackGround := Valu(A[2]);
              End
              Else
              If (Valu(A) in [0..15]) Then
              Begin
                AnsiColor((BackGround SHL 4) OR Valu(A));
                ForeGround := Valu(A);
              End
              Else SendFull('|'+A);
              Inc(X);
            End;
      #0..
      #255: Begin
              Inc(McStrLength);
              SendStr(M[X]);
              Inc(X);
            End;
    End;
  End;
End;

Procedure WriteLog (M, S : Integer; Prm : LStr);
Var N : Integer;
    L : LogRec;
Begin
  With L Do
  Begin
    Menu := M;
    SubCommand := S;
    When := Now;
    Param := Copy(Prm,1,41)
  End;
  If Not isopen(logfile) then
    begin
      assign (logfile,cfg.DATADir+'SYSLOG');
      reset (logfile);
      if ioresult<>0 then begin
        rewrite (logfile);
        if ioresult<>0 then begin
          WriteLn('system error: cannot write to log');
          exit
        end
      end
    end;
  seek (logfile,filesize(logfile));
  Write(logfile,l)
end;

procedure files30;
begin
  coolwrite('filez','error - must have files=30 in config.sys@!#|CR');
  exit;
end;

function ioerrorstr (num:integer):lstr;
var tmp:lstr; ok:boolean;
    x:string[3];
    n,s:integer;
begin
  If Num=243 then files30;
  ok:=false;
  For n:=1 to 50 Do Begin
    X:=Copy(Ioerrors[N],1,3);
    S:=Valu(X);
    If S=Num then Begin
      ok:=true;
      Tmp:=Copy(Ioerrors[N],5,40);
      IoErrorStr:=^R'('^S'ERROR'^A': '^S+Strr(Num)+' - '+Tmp+^R')';
    End;
  End;
  If Not ok then ioerrorstr:='ERROR: Cannot be identified!';
end;

procedure error (errorstr,proc,param:lstr);
var p,n:integer;
    pk:char;
    tf:text;
begin
  n:=ioresult;
  repeat
    p:=pos('%',errorstr);
    if p<>0 then begin
      pk:=errorstr[p+1];
      delete (errorstr,p,2);
      case upcase(pk) of
        '1':insert (param,errorstr,p);
        'P':insert (proc,errorstr,p);
        'I':insert (ioerrorstr(iocode),errorstr,p)
      end
    end
  until p=0;
  assign (tf,Cfg.DATADIR+'ErrLog');
  append (tf);
  if ioresult<>0
    then
      begin
        textclose (tf);
        rewrite (tf)
      end;
  WriteLn(tf,#27+'[1;33m'+DateStr(now)+' - '+TimeStr(Now)+#27+'[1;37m: '+#27+'[1;36m'+unam+' was Online When'+#27+'[0;36m:');
  WriteLn(tf,#27+'[1;32m'+errorstr);
  WriteLn(tf);
  textclose (tf);
  n:=ioresult;
  writelog (0,4,errorstr);
  SendCr(errorstr)
end;

procedure fileerror (procname,filename:mstr);
begin
  error ('%I accessing %1 in %P',procname,filename)
end;

procedure che;
var i:integer;
begin
  i:=ioresult;
  case i of
    0:;
    4:files30;
    else
      begin
        iocode:=i;
        error ('','','')
      end
  end
end;

function timeleft:integer;
var timeon:integer;
begin
  timeon:=timer-logontime;
  if timeon<0 then timeon:=timeon+1440;
  timeleft:=urec.timetoday-timeon
end;

function timetillevent:integer;
var n:integer;
begin
  if (length(Cfg.eventtime)=0) or (length(Cfg.eventbatch)=0) or
    (status.eventdone = datestr(now))
    then n:=1440
    else n:=timeval(Cfg.eventtime)-timer;
  if n < 0 then n:=n+1440;
  timetillevent:=n
end;

procedure settimeleft (tl:integer);
begin
  urec.timetoday:=timer+tl-logontime
end;

procedure tab (n:anystr; np:integer);
var cnt:integer;
begin
  SendFull(n);
  for cnt:=length(n) to np-1 do SendFull(' ')
end;

function yes:boolean;
begin
  if length(inpt)=0
    then yes:=false
    else yes:=upcase(inpt[1])='Y'
end;

function yesno (b:boolean):sstr;
begin
  if b
    then yesno := ' Yup '
    else yesno := ' Nope '
end;

function timeontoday:integer;
var timeon:integer;
begin
  timeon:=timer-logontime;
  if timeon<0 then timeon:=timeon+1440;
  timeontoday:=timeon
end;

function isopen (var ff):boolean;
var fi : fib absolute ff;
begin
  isopen := fi.handle <> 0
end;

procedure textclose (var f:text);
var n:integer;
    fi:fib absolute f;
begin
  if isopen(f)
    then system.close (f);
  fi.handle:=0;
  n:=ioresult
end;

procedure close (var ff);
var f:file absolute ff;
    fi:fib absolute ff;
    n:integer;
begin
  if isopen(f)
    then system.close (f);
  fi.handle:=0;
  n:=ioresult
end;

function withintime (t1,t2:sstr):boolean;
var t,a,u:integer;
begin
  t:=timer;
  If ((t1='') or (t2='')) then begin
    withintime:=false;
    exit;
  end;
  a:=timeval(t1);
  u:=timeval(t2);
  if a<=u
    then withintime:=(t>=a) and (t<=u)
    else withintime:=(t>=a) or (t<=u)
end;

function hungupon:boolean;
begin
  hungupon:=forcehangup or
  (online and not (carrier or modeminlock or modemoutlock))
end;

function sysopisavail:boolean;
begin
  case status.sysopavail of
    0 : sysopisavail:=true;
    2 : sysopisavail:=false;
    1 : sysopisavail:=withintime (Cfg.availtime,Cfg.unavailtime)
  end
end;

function sysopavailstr:sstr;
const strs:array [0..2] of string[9]=
        ('On      ','Time=','Off     ');
var tstr:sstr;
    tmp : byte;
begin
  tstr:=strs[status.sysopavail];
  if status.sysopavail=1
    then
      begin
        if sysopisavail
          then tmp:=0
          else tmp:=2;
        tstr:=tstr+strs[tmp]
      end;
  sysopavailstr:=tstr
end;

function singularplural (n:integer; m1,m2:mstr):mstr;
begin
  if n=1
    then singularplural:=m1
    else singularplural:=m2
end;

function s (n:integer):sstr;
begin
  s:=singularplural (n,'','s')
end;

function numthings (n:integer; m1,m2:mstr):lstr;
begin
  numthings:=strr(n)+' '+singularplural (n,m1,m2)
end;

procedure thereisare (n:integer);
begin
  SendFull(^R'There ');
  if N = 1
    then SendFull('is '^A'1 '^R)
    else
      begin
        SendFull('are ');
        if n=0
          then SendFull(^A' no '^R)
          else SendFull(^A+strr(n)+' '^R)
       end
end;

procedure thereare (n:integer; m1,m2:mstr);
begin
  thereisare (n);
  if n=1
    then SendFull(m1)
    else SendFull(m2);
  SendCr('.')
end;

procedure assignbdfile;
begin
  assign (bdfile,Cfg.boarddir+'BOARDDIR.'+Strr(MsgConf));
  assign (bifile,Cfg.boarddir+'BDINDEX.'+Strr(MsgConf))
end;

procedure openbdfile;
var i:integer;
begin
  closebdfile;
  assignbdfile;
  reset (bdfile);
  i:=ioresult;
  reset (bifile);
  i:=i or ioresult;
  if i<>0 then formatbdfile
end;

procedure formatbdfile;
begin
  close (bdfile);
  close (bifile);
  assignbdfile;
  rewrite (bdfile);
  rewrite (bifile)
end;

procedure closebdfile;
begin
  close (bdfile);
  close (bifile)
end;

var wasopen:boolean;

procedure opentempbdfile;
begin
  wasopen:=isopen(bdfile);
  if not wasopen then openbdfile
end;

procedure closetempbdfile;
begin
  if not wasopen then closebdfile
end;

Function KeyHit : Boolean; Assembler;
Asm
  mov ah, 01h
  int 16h
  mov ax, 00h
  jz @1
  inc ax
  @1:
end;

procedure readline (var xx);
var a:anystr absolute xx;
    l:byte absolute xx;
    k:char;

  procedure backspace;
  begin
    if l>0 then begin
      Write(^H,' ',^H);
      l:=l-1
    end
  end;

  procedure eraseall;
  begin
    while l > 0 do backspace
  end;

  procedure addchar (k:char);
  begin
    if l<buflen then begin
      l:=l+1;
      a[l]:=k;
      Write(k)
    end
  end;

begin
  l:=0;
  repeat
    k:=bioskey;
    case k of
      #8:backspace;
      #27:eraseall;
      #32..#254 : addchar(k)
    end
  until k=#13;
  WriteLn('')
end;

Procedure ShutDownSystem;
Var Cnt : Byte;
Begin
  StopTimer (status.minutesidle);
  stoptimer (status.minutesused);
  WriteStatus;
  TextClose (TTFile);
  Cnt := IOResult;
  DeleteFiles;
  for cnt:=1 to numsysfiles do close (sysfiles[cnt]);
End;

procedure close_them_all(var ff);    { close most open files EXCEPT ff }
var cnt, i : integer;
begin
  i := ioresult;
  for cnt := 6 to numsysfiles do begin
    if ofs(ff) <> ofs(sysfiles[cnt])
      then begin
        if filerec(sysfiles[cnt]).handle <> 0
          then close(sysfiles[cnt]);
        i := ioresult;
      end
  end
end;

procedure clearbreak;
begin
  break:=false;
  xpressed:=false;
  dontstop:=false;
  nobreak:=false
end;

procedure ansireset;
begin
  textattr := urec.color1;
  if usecapsonly then exit;
  if urec.color1<>0 then begin
    ansicolor (urec.color1);
    exit
  end;
  if (not (ansigraphics in urec.config)) or (curattrib=0) or break then exit;
  SendStr(#27'[0m');
  curattrib:=0
end;

procedure specialmsg (q:anystr);
begin
  textattr:=9;
  WriteLn(q);
end;

Procedure TimeSlice; Assembler;
Asm
    CMP   TASKER, 0
    JE    @GIVEDOS
    CMP   TASKER, 1
    JE    @GIVEDVX
    CMP   TASKER, 2
    JE    @GOS2WIN
    CMP   TASKER, 3
    JE    @GOS2WIN
    MOV   BX,$000A
    INT   $7A
    JMP   @DONE
@GIVEDOS:
    INT   $28
    JMP   @DONE
@GIVEDVX:
    MOV   AX, $1000
    INT   $15
    JMP   @DONE
@GOS2WIN:
    MOV   AX, $1680
    INT   $2F
@DONE:
End;

function bars_ok : boolean;
begin
  bars_ok := (usebars in urec.config) AND theme.allowbars;
end;

Function Percentage(A,B:Integer):Real;
Begin
  If (A>0) and (B>0)
    Then Percentage := (A/B) * 100
    Else percentage := 0;
End;

Procedure ExecuteWithSwap( ProgName : Lstr; Commandline : AnyStr; Force:Boolean);
{Const SwapLoc : Array[Boolean] of String[7]=('on disk','in EMS');}
Const SWAPFILE = 'INFSWAP.$$$';
Var W : Integer;
    S : AnyStr;
Begin

  If ProgName <> '' Then Begin
    S := '/C ' + ProgName;
    If CommandLine <> ''
      Then S := S + #32 + CommandLine;
  End Else S := '';

  If (Not Cfg.MaxDosShell) And (Not Force) Then Begin
    SwapVectors;
    Dos.Exec(GetEnv('COMSPEC'),S);
    SwapVectors;
    Exit;
  End;

  Dos_FreeMem(Strng);
  W := SwapExec(GetEnv('COMSPEC'),S,SwapFile,SwapToAny);
  Dos_GetMem(Strng,SizeOf(Strng^) + 1);
  ReadStrings;

   Case Hi(W) Of
    1 : Writeln('DOS Memory Chain Error');
    2 : Writeln('Unable to Swap Out iNFUSiON');
    3 : Case Lo(W) Of
          2 : Writeln('Unable to find/execute '+Progname);
          5 : Writeln('Couldn''t open '+Progname);
          8 : Writeln('Insufficient memory to run '+Progname);
        End;
  End;
End;

function lget_ms: longint;
var
   h,m,s,s1: word;
begin
   GetTime(h,m,s,s1);
   lget_ms  := longint(s1) * longint(10) +      {seconds/100}
               longint(s)  * longint(1000) +    {seconds}
               longint(m)  * longint(60000) +   {minutes}
               longint(h)  * longint(3600000);  {hours}
end;

Procedure delay(ms: longint);
var
   finish:  longint;
   start:   longint;
   now:     longint;

begin
   start := lget_ms;
   finish := start + ms;

   repeat
      timeslice;
      now := lget_ms;
   until (now > finish) or    {time elapsed}
         (now < start);       {midnight rolover!}
end;

End.