{$S-,R-,I-,V-,B-}

  {*********************************************************}
  {*                   TPOLDIFC.PAS 4.03                   *}
  {*        Copyright (c) TurboPower Software 1987.        *}
  {* Portions copyright (c) Sunny Hill Software 1985, 1986 *}
  {*     and used under license to TurboPower Software     *}
  {*                 All rights reserved.                  *}
  {*********************************************************}

unit TpOldIfc;
  {-Standard interface calls for Turbo Professional 1.x/2.x TSR's and TaskView}

interface

uses
  Dos;

const
  IFCVersionGlb = 0;
  IFCVec1Glb : Byte = $6F;
  IFCVec2Glb : Byte = $7F;
type
  Asciiz = array[0..255] of Char;
  ModuleIdentRecGlb = record
                        JumpInstr1 : Byte;
                        JumpPtr1 : Pointer;
                        JumpInstr2 : Byte;
                        JumpPtr2 : Pointer;
                        NamePtr : ^Asciiz;
                        IFCVersion : Integer;
                        CmdEntryPtr : Pointer;
                      end;
  ModuleIdentRecPtr = ^ModuleIdentRecGlb;

  function ModuleInstalled(ModuleName : string) : Integer;
    {-Returns 0 if ModuleName is not installed, else its number.}

  function ModuleCmdEntry(ModuleName : string) : Pointer;
    {-Returns the command entry pointer of the named module.}

  function ModuleNameStr(ModNumber : Integer) : string;
    {-Returns the module name of the ModNumber module. Module numbers are
      determined by the order of loading, the last loaded being number one.}

  function HowManyModules : Byte;
    {-Returns number of modules using the interface.}

  {==========================================================================}

implementation

  function StringFromAsciiz(var AsciizStr; MaxLen : Byte) : string;
    {-Turns an ASCIIZ string into a Turbo compatible string. It trims long
      strings to a maximum of MaxLen characters.}
  var
    CharArr : Asciiz absolute AsciizStr;
    TStr : string;
  begin
    TStr := '';
    while (TStr[0] < Chr(MaxLen)) and (CharArr[Ord(TStr[0])] <> #0) do
      TStr := TStr+CharArr[Ord(TStr[0])];
    StringFromAsciiz := TStr;
  end;

  function NextModulePtr(P1, P2 : Pointer) : ModuleIdentRecPtr;
    {-Returns a pointer to the next module as determined by the two pointers.}
  begin
    if (Byte(P1^) = $EA) and (Mem[Seg(P1^):Ofs(P1^)+5] = $EA) then
      NextModulePtr := @P1^
    else
      if (Byte(P2^) = $EA) and (Mem[Seg(P2^):Ofs(P2^)-5] = $EA) then
        NextModulePtr := Ptr(Seg(P2^), (Ofs(P2^)-5))
      else
        NextModulePtr := nil;
  end;

  function HowManyModules : Byte;
    {-Returns number of modules using the interface.}
  var
    Count : Word;
    MP : ModuleIdentRecPtr;
    P1, P2 : Pointer;
  begin
    Count := 0;
    GetIntVec(IFCVec1Glb, P1);
    GetIntVec(IFCVec2Glb, P2);
    MP := NextModulePtr(P1, P2);
    while (MP <> nil) do begin
      Inc(Count);
      with MP^ do
        MP := NextModulePtr(JumpPtr1, JumpPtr2);
    end;
    HowManyModules := Count;
  end;

  function ModulePtrByName(var ModuleName : string) : ModuleIdentRecPtr;
    {-Returns a pointer to the module header or Nil.}
  var
    TPtr : ModuleIdentRecPtr;
    P1, P2 : Pointer;
    Found : Boolean;
  begin
    GetIntVec(IFCVec1Glb, P1);
    GetIntVec(IFCVec2Glb, P2);

    Found := False;
    TPtr := NextModulePtr(P1, P2);
    while (TPtr <> nil) and not Found do
      with TPtr^ do
        if StringFromAsciiz(NamePtr^, Ord(ModuleName[0])) = ModuleName then
          Found := True
        else
          TPtr := NextModulePtr(JumpPtr1, JumpPtr2);
    if Found then
      ModulePtrByName := TPtr
    else
      ModulePtrByName := nil;
  end;

  function ModuleCmdEntry(ModuleName : string) : Pointer;
    {-Returns the command entry pointer of the named module.}
  var
    TPtr : ModuleIdentRecPtr;
  begin
    TPtr := ModulePtrByName(ModuleName);
    if TPtr <> nil then
      ModuleCmdEntry := TPtr^.CmdEntryPtr
    else
      ModuleCmdEntry := nil;
  end;

  function ModuleNameStr(ModNumber : Integer) : string;
    {-Returns the module name of the ModNumber module. Module numbers are
      determined by the order of loading, the last loaded being number one.}
  var
    Count : Integer;
    TPtr : ModuleIdentRecPtr;
    P1, P2 : Pointer;
  begin
    Count := 0;
    GetIntVec(IFCVec1Glb, P1);
    GetIntVec(IFCVec2Glb, P2);
    repeat
      TPtr := NextModulePtr(P1, P2);
      Inc(Count);
      P1 := TPtr^.JumpPtr1;
      P2 := TPtr^.JumpPtr2;
    until (TPtr = nil) or (Count = ModNumber);
    if TPtr <> nil then
      ModuleNameStr := StringFromAsciiz(TPtr^.NamePtr^, 255)
    else
      ModuleNameStr := '';
  end;

  function ModuleInstalled(ModuleName : string) : Integer;
    {-Returns 0 if ModuleName is not installed, else its number.}
  var
    I, Max : Byte;
  begin
    {assume failure}
    ModuleInstalled := 0;

    {search for the module}
    Max := HowManyModules;
    for I := 1 to Max do
      if Pos(ModuleName, ModuleNameStr(I)) = 1 then begin
        ModuleInstalled := I;
        Exit;
      end;
  end;

{begin}
end.
