unit GvRedir;

{ Application-level abstract network redirector
  Copr. 1998 Matthias K"oeppe
}

interface

uses {$ifdef Windows} WinDos, {$endif} Dos, Objects;

type
  PFileSystem = ^TFileSystem;

  PRedirSearchRec = ^TRedirSearchRec;
  TRedirSearchRec = record
    Fill: array[1..21] of Byte;
    Attr: Byte;
    Time: Longint;
    Size: Longint;
    Name: string[12];
    User: LongInt;
    System: PFileSystem;
  end;

  TFileSystem = object(TObject)
    function GetFAttr(const Name: string): Word; virtual;
    procedure SetFAttr(const Name: string; Attr: Word); virtual;
    procedure Rename(const Name, NewName: string); virtual;
    procedure Delete(const Name: string); virtual;
    function GetDriveType(const Name: string): Word; virtual;
    procedure FindFirst(const Path: string; Attr: Word;
			var SR: TRedirSearchRec); virtual;
    procedure FindNext(var SR: TRedirSearchRec);
    procedure FindEnd(var SR: TRedirSearchRec);
    procedure DoFindNext(var SR: TRedirSearchRec); virtual;
    procedure DoFindEnd(var SR: TRedirSearchRec); virtual;
    procedure FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr;
      var Ext: ExtStr); virtual;
    function FExpand(Path: PathStr): PathStr; virtual;
    function CopyFile(const SourceName, TargetName: string): Boolean; virtual;
  end;

type
  PLocalFileSystem = ^TLocalFileSystem;
  TLocalFileSystem = object(TFileSystem)
    function GetFAttr(const Name: string): Word; virtual;
    procedure SetFAttr(const Name: string; Attr: Word); virtual;
    procedure Rename(const Name, NewName: string); virtual;
    procedure Delete(const Name: string); virtual;
    function GetDriveType(const Name: string): Word; virtual;
    procedure FindFirst(const Path: string; Attr: Word;
			var SR: TRedirSearchRec); virtual;
    procedure DoFindNext(var SR: TRedirSearchRec); virtual;
    procedure DoFindEnd(var SR: TRedirSearchRec); virtual;
    procedure FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr;
      var Ext: ExtStr); virtual;
    function FExpand(Path: PathStr): PathStr; virtual;
  end;

var
  FileSystem: PFileSystem;
  FileSystemError: Integer;

implementation

uses Misc;

type
  PSearchRec = ^SearchRec;

function TFileSystem.GetFAttr(const Name: string): Word; begin Abstract end;
procedure TFileSystem.SetFAttr(const Name: string; Attr: Word); begin Abstract end;
procedure TFileSystem.Rename(const Name, NewName: string); begin Abstract end;
procedure TFileSystem.Delete(const Name: string); begin Abstract end;
function TFileSystem.GetDriveType(const Name: string): Word; begin Abstract end;
procedure TFileSystem.FindFirst(const Path: string; Attr: Word;
		    var SR: TRedirSearchRec); begin Abstract end;
procedure TFileSystem.DoFindNext(var SR: TRedirSearchRec); begin Abstract end;
procedure TFileSystem.DoFindEnd(var SR: TRedirSearchRec); begin Abstract end;
procedure TFileSystem.FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr;
  var Ext: ExtStr); begin Abstract end;
function TFileSystem.FExpand(Path: PathStr): PathStr; begin Abstract end;
function TFileSystem.CopyFile(const SourceName, TargetName: string): Boolean;
begin CopyFile := false end;

procedure TFileSystem.FindNext(var SR: TRedirSearchRec);
begin
  SR.System^.DoFindNext(SR)
end;

procedure TFileSystem.FindEnd(var SR: TRedirSearchRec);
begin
  SR.System^.DoFindEnd(SR)
end;

function TLocalFileSystem.GetFAttr(const Name: string): Word;
var
  F: File;
  Attr: Word;
begin
  Assign(F, Name);
  {$ifdef Windows}WinDos{$else}Dos{$endif}.GetFAttr(F, Attr);
  GetFAttr := Attr;
  FileSystemError := DosError;
end; { TLocalFileSystem.GetFAttr }

procedure TLocalFileSystem.SetFAttr(const Name: string; Attr: Word);
var
  F: File;
begin
  Assign(F, Name);
  {$ifdef Windows}WinDos{$else}Dos{$endif}.SetFAttr(F, Attr);
  FileSystemError := DosError;
end; { TLocalFileSystem.SetFAttr }

procedure TLocalFileSystem.Rename(const Name, NewName: string);
var
  F: File;
begin
  Assign(F, Name);
  {$i-}
  System.Rename(F, NewName);
  {$i+}
  FileSystemError := IoResult
end; { TLocalFileSystem.Rename }

procedure TLocalFileSystem.Delete(const Name: string);
var
  F: File;
begin
  Assign(F, Name);
  {$i-}
  System.Erase(F);
  {$i+}
  FileSystemError := IoResult;
end; { TLocalFileSystem.Delete }

{from gvstddlg.pas}
function DriveValid(Drive: Char): Boolean; near; assembler;
asm
	MOV	AH,19H          { Save the current drive in BL }
        INT	21H
        MOV	BL,AL
 	MOV	DL,Drive	{ Select the given drive }
        SUB	DL,'A'
        MOV	AH,0EH
        INT	21H
        MOV	AH,19H		{ Retrieve what DOS thinks is current }
        INT	21H
        MOV	CX,0		{ Assume false }
        CMP	AL,DL		{ Is the current drive the given drive? }
	JNE	@@1
        MOV	CX,1		{ It is, so the drive is valid }
	MOV	DL,BL		{ Restore the old drive }
        MOV	AH,0EH
        INT	21H
@@1:	XCHG	AX,CX		{ Put the return value into AX }
end;

function TLocalFileSystem.GetDriveType(const Name: string): Word;
begin
  If ((Upcase(Name[1]) < 'C') and (Misc.GetDriveType(Name[1]) <> dtInvalid)) or DriveValid(Name[1])
  then GetDriveType := Misc.GetDriveType(Name[1])
  else GetDriveType := dtInvalid;
  FileSystemError := 0;
end; { TLocalFileSystem.GetDriveType }

procedure TLocalFileSystem.FindFirst(const Path: string; Attr: Word;
				     var SR: TRedirSearchRec);
begin
  Dos.FindFirst(Path, Attr, PSearchRec(@SR)^);
  SR.User := 0;
  SR.System := @Self;
  FileSystemError := DosError;
end; { TLocalFileSystem.FindFirst }

procedure TLocalFileSystem.DoFindNext(var SR: TRedirSearchRec);
begin
  Dos.FindNext(PSearchRec(@SR)^);
  FileSystemError := DosError;
end; { TLocalFileSystem.FindNext }

procedure TLocalFileSystem.DoFindEnd(var SR: TRedirSearchRec);
begin
  { We need not finish the search in a DOS file system explicitly. }
  FileSystemError := 0
end;

procedure TLocalFileSystem.FSplit(Path: PathStr; var Dir: DirStr; var Name: NameStr;
  var Ext: ExtStr);
begin
  Dos.FSplit(Path, Dir, Name, Ext)
end;

function TLocalFileSystem.FExpand(Path: PathStr): PathStr;
begin
  FExpand := Dos.FExpand(Path)
end;

begin
  FileSystem := New(PLocalFileSystem, Init)
end.
