0% found this document useful (0 votes)
10 views22 pages

Tools

The document outlines the Turbo Vision File Manager Demo, detailing various utility procedures and object definitions for file management tasks such as copying, deleting, renaming, and viewing files. It includes methods for handling file attributes, executing files, and displaying status messages. Additionally, it provides functions for string manipulation and configuration management.

Uploaded by

lazaruspascalth
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views22 pages

Tools

The document outlines the Turbo Vision File Manager Demo, detailing various utility procedures and object definitions for file management tasks such as copying, deleting, renaming, and viewing files. It includes methods for handling file attributes, executing files, and displaying status messages. Additionally, it provides functions for string manipulation and configuration management.

Uploaded by

lazaruspascalth
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 22

{************************************************}

{ }
{ Turbo Vision File Manager Demo }
{ Copyright (c) 1992 by Borland International }
{ }
{************************************************}

unit Tools;

{$X+,V-}

interface

uses Drivers, Objects, Views, Dialogs, Memory, App, MsgBox,


Globals, FileCopy, Gauges, Dos;

type
String2 = String[2];
String4 = String[4];
TConfigHeader = String[24];

{ Used to display status messages }


PStatusBox = ^TStatusBox;
TStatusBox = object(TDialog)
procedure HandleEvent(var Event: TEvent); virtual;
end;

{ buffered file copy object }


PCopier = ^TCopier;
TCopier = object(TFileCopy)
procedure ReadMsg(const FName: FNameStr; Progress: Longint); virtual;
procedure WriteMsg(const FName: FNameStr; Progress: Longint); virtual;
function IOError(const FName: FNameStr; ECode:Integer) : erAction; virtual;
end;

{ generate a cmOK if double clicked }


POkListBox = ^TOkListBox;
TOkListBox = object(TListBox)
procedure SelectItem(Item: Integer); virtual;
end;

{ ShowStatusBox displays a status dialog, using StatusMsg as the string }


{ to display. The status box responds to the cmStatusUpdate command by }
{ redrawing the text. }
procedure ShowStatusBox;

{ KillStatusBox removes the status box from the screen }


procedure KillStatusBox;

{ Return True if the passed list contains any tagged files }


function HasTaggedFiles(P: PFileList) : Boolean;

{ Return the path and filename (no extension) of the exe }


function GetExeBaseName: String;

{ Convert strings to upper and lower case }


procedure UpperCase(var s: String);
procedure LowerCase(var s: String);
{ Return a right justified number (in an 8 character field) }
function RJustNum(L: Longint): String;

{ Pad right end of string to Len bytes }


function Pad(s: String; Len: Byte): String;

{ Return a fully trimmed copy of Original }


function FullTrim(const Original: String): String;

{ Return string value of W, optionally with leading zero if Pad=True }


function TwoDigit(W: Word; Pad: Boolean): String2;

{ Return 4 digit string representation of W }


function FourDigit(W: Word): String4;

{ Return a string version of the Date/Time longint. Opts=$01 adds the }


{ date portion. Opts=$02 adds time, Opts=$03 adds both }
function FormatDateTime(DT: Longint; Opts: Word): String;

{ Return the 4 character string representation of the attribute word }


function FormatAttr(Attr: Word): String4;

{ Return True if file is a .BAT, .COM, or .EXE }


function IsExecutable(const FileName: FNameStr): Boolean;

{ Execute the passed file, asks for parameters }


procedure ExecuteFile(FileName: FNameStr);

{ View passed file as Hex, Text, or with Custom Viewer }


procedure ViewAsHex(const FileName: FNameStr);
procedure ViewAsText(const FileName: FNameStr);
procedure ViewCustom(const FileName: FNameStr);

{ Return True if the passed drive letter is valid }


function DriveValid(Drive: Char): Boolean;

{ Return a selected drive letter from listbox of valid drives }


function SelectDrive: Char;

{ Invalidate the passed directory by issuing a cmInvalidDir broadcast }


procedure InvalidateDir(Path: FNameStr);

{ Copy either tagged or current file to a destination path }


procedure HandleFileCopy(const Path: FNameStr; P: PFileList; Current: Integer);

{ Delete file if user confirms the deletion, return error code }


function SafeDelete(FileName: FNameStr): Integer;

{ Handle deleting one or multiple files from a file list }


procedure HandleFileDelete(const Path: FNameStr; List: PFileList;
Current: Integer);

{ Present the Rename file dialog }


procedure RenameFile(const Path: FNameStr; F: PFileRec);

{ Present the Change Attribute dialog }


procedure ChangeAttr(const Path: FNameStr; F:PFileRec);

{ Allow user to specify what viewer program to use }


procedure InstallViewer;

{ Allow user to specify the display options }


procedure SetDisplayPrefs;

{ Save and load the configuration file }


procedure SaveConfig;
procedure ReadConfig;

{ Execute the passed string literally }


procedure RunDosCommand(Command: String);

{ Return a TFileNameRec built from the passed filespec. This structure }


{ allows for easier comparisons by other procedures }
function NewFileNameRec(const Path: FNameStr): PFileNameRec;

{ Perform a drag & drop copy }


procedure DragDropCopy(Mover: PFileMover; Dest: PathStr);

{ return true if this name matches the wildcard }


function WildCardMatch(const Name, Card: FNameStr): Boolean;

const
StatusMsg : String = '';

implementation

uses ViewHex, ViewText, Strings, Equ, Assoc;

const
StatusBox : PStatusBox = nil;
StatusPMsg : PString = @StatusMsg;

ConfigHeader : TConfigHeader = 'TVFM Configuration File'#26;

{ General utility procedures }

procedure ShowStatusBox;
var
R: TRect;
P: PView;
begin
if StatusBox <> nil then exit;
R.Assign(0,0,40,5);
StatusBox := New(PStatusBox, Init(R, 'Status'));
with StatusBox^ do
begin
Options := Options or ofCentered;
Options := Options and (not ofBuffered);
Flags := Flags and (not wfClose) and (not wfMove);
R.Assign(2,2,38,3);
P := New(PParamText, Init(R, ^C'%s', 1));
Insert(P);
end;
StatusMsg := '';
StatusPMsg := @StatusMsg;
StatusBox^.SetData(StatusPMsg);
Desktop^.Insert(StatusBox);
end;
procedure ShowCopyStatusBox(MaxSize: Longint);
var
R: TRect;
P: PView;
begin
if StatusBox <> nil then exit;
R.Assign(0,0,40,7);
StatusBox := New(PStatusBox, Init(R, 'Status'));
with StatusBox^ do
begin
Options := Options or ofCentered;
Options := Options and (not ofBuffered);
Flags := Flags and (not wfClose) and (not wfMove);
R.Assign(2,2,38,3);
P := New(PParamText, Init(R, ^C'%s', 1));
Insert(P);
R.Assign(5,4,34,5);
Insert(New(PBarGauge, Init(R, MaxSize)));
R.Assign(2,4,4,5);
Insert(New(PStaticText, Init(R, '0%')));
R.Assign(35,4,39,5);
Insert(New(PStaticText, Init(R, '100%')));
end;
StatusMsg := '';
StatusPMsg := @StatusMsg;
StatusBox^.SetData(StatusPMsg);
Desktop^.Insert(StatusBox);
end;

procedure KillStatusBox;
begin
if StatusBox <> nil then
begin
Dispose(StatusBox, Done);
StatusBox := nil;
end;
end;

{ Return TRUE if the passed list has tagged files in it }


function HasTaggedFiles(P: PFileList) : Boolean;
var
Has: Boolean;
i: Integer;
begin
Has := False;
i := 0;
while (i < P^.Count) and (not Has) do
begin
Has := PFileRec(P^.At(i))^.Tagged;
Inc(i);
end;
HasTaggedFiles := Has;
end;

function GetExeBaseName : String;


var
ExeFileName: FNameStr;
D: DirStr;
N: NameStr;
E: ExtStr;
begin
ExeFileName := ParamStr(0);
if ExeFileName = '' then
ExeFileName := FSearch(EXEName, GetEnv('PATH'));
ExeFileName := FExpand(ExeFileName);
FSplit(ExeFileName, D, N, E);
GetExeBaseName := D + N;
end;

procedure UpperCase(var s:string);


var
i : Integer;
begin
for i := 1 to Length(s) do
s[i] := Upcase(s[i]);
end;

procedure LowerCase(var s:string);


var
i : Integer;
begin
for i := 1 to Length(s) do
if s[i] in ['A'..'Z'] then Inc(s[i], 32);
end;

function RJustNum(L: Longint): String;


var
s: String;
begin
FormatStr(s, '%8d', L);
RJustNum := s;
end;

function Pad(s: String; Len: Byte): String;


begin
if Length(s) < Len then
FillChar(s[Succ(Length(s))], Len-Length(s), ' ');
s[0] := Char(Len);
Pad := s;
end;

function FullTrim(const Original: String): String;


var
S: String;
begin
S := Original;
while (S[0] > #0) and (S[Length(S)] = #32) do Dec(S[0]); { trim left }
while (S[0] > #0) and (S[1] = #32) do
begin
Move(S[2], S[1], Pred(Length(S)));
Dec(S[0]);
end;
FullTrim := S;
end;

function TwoDigit(W: Word; Pad: Boolean) : String2;


var
s: String2;
begin
Str(W:2, s);
if Pad and (s[1] = ' ') then s[1] := '0';
TwoDigit := s;
end;

function FourDigit(W: Word) : String4;


var
s: String4;
begin
Str(W:4, s);
FourDigit := s;
end;

function FormatDateTime(DT: Longint; Opts: Word): String;


var
s: String;
t: DateTime;
begin
UnpackTime(DT, t);
s := '';
if (Opts and 1) <> 0 then { add the date }
begin
s := s + TwoDigit(t.Month, False) + '-' + TwoDigit(t.Day, True);
s := s + '-' + Copy(FourDigit(t.Year),3,2);
end;
if (Opts and 2) <> 0 then { add the time }
begin
if s <> '' then s := s + ' ';
s := s + TwoDigit(t.Hour, True) + ':' + TwoDigit(t.Min, True) + ':' +
TwoDigit(t.Sec, True);
end;
FormatDateTime := s;
end;

function FormatAttr(Attr: Word): String4;


var
s: String4;
begin
s := '����';
if Attr and Archive = Archive then s[1] := 'A';
if Attr and ReadOnly = ReadOnly then s[2] := 'R';
if Attr and SysFile = SysFile then s[3] := 'S';
if Attr and Hidden = Hidden then s[4] := 'H';
FormatAttr := s;
end;

function IsExecutable(const FileName: FNameStr): Boolean;


var
D: DirStr;
N: NameStr;
E: ExtStr;
begin
FSplit(FExpand(FileName), D, N, E);
IsExecutable := (E = '.EXE') or (E = '.COM') or (E = '.BAT');
end;

procedure ExecuteFile(FileName: FNameStr);


var
D: PDialog;
R: TRect;
P: PView;
Dir: DirStr;
Name: FNameStr;
E: ExtStr;
Event: TEvent;
Params: string[80];
Command: string[80];
L: array[0..2] of Longint;
ParamPos: Integer;
Association: PAssociation;
begin
FSplit(FExpand(FileName), Dir, Name, E);
Name := Name + E;
Association := nil;

Command := '';
Params := '';
{ Does an association exist for this file? }
if not IsExecutable(FileName) then
begin
Association := GetAssociatedCommand(E);
if Association <> nil then Command := Association^.Cmd^;
if Command = '' then
begin
L[0] := Longint(@FileName);
MessageBox(RezStrings^.Get(sNoAssociation), @L, mfError +
mfOKButton);
Exit;
end
else
begin
ParamPos := Pos(' ', Command);
if ParamPos > 0 then
begin
Params := Copy(Command, ParamPos + 1, $FF);
Delete(Command, ParamPos, $FF);
Params := Params + ' ' + FileName;
end
else
Params := FileName;
end;
end
else
begin
Command := FileName;
Params := '';
end;

R.Assign(0,0,50,8);
D:= New(PDialog, Init(R, 'Execute Program'));
with D^ do
begin
Options := Options or ofCentered;
R.Assign(2,2,15,3);
Insert(New(PStaticText, Init(R, ' Executing:')));
R.Assign(15,2,48,3);
Insert(New(PStaticText, Init(R, Command)));

R.Assign(15,3,48,4);
P := New(PInputLine, Init(R, 80));
Insert(P);
R.Assign(2,3,15,4);
Insert(New(PLabel, Init(R, '~P~arameters', P)));

R.Assign(12,5,24,7);
Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
R.Move(14,0);
Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
SelectNext(False);
end;

if ( (Association <> nil) and (not Association^.Prompt)) or


(Application^.ExecuteDialog(D, @Params) = cmOK) then
begin
DoneSysError;
DoneEvents;
DoneVideo;
DoneDosMem;
SwapVectors;

if E = '.BAT' then
begin
Command := GetEnv('COMSPEC');
Params := '/c ' + FileName + Params;
end;

Exec(Command, Params);
SwapVectors;

PrintStr(RezStrings^.Get(sPressAnyKey));
Event.What := evNothing;
repeat
GetKeyEvent(Event);
until Event.What <> evNothing;

InitDosMem;
InitVideo;
InitEvents;
InitSysError;
Application^.Redraw;

if DosError <> 0 then


begin
L[0] := DosError;
L[1] := Longint(@Command);
MessageBox(RezStrings^.Get(sExecErr), @L, mfError + mfOKButton);
end else
begin
L[0] := DosExitCode and $FF;
if L[0] <> 0 then
MessageBox(RezStrings^.Get(sExecRetCode), @L,
mfInformation + mfOKButton);
end;
end;
end;
{ view file procedures }
procedure ViewAsHex(const FileName: FNameStr);
var
H: PHexWindow;
R: TRect;
begin
R.Assign(0,0,72,15);
H := New(PHexWindow, Init(R, FileName));
H^.Options := H^.Options or ofCentered;
Desktop^.Insert(H);
end;

procedure ViewAsText(const FileName: FNameStr);


var
T: PTextWindow;
R: TRect;
begin
R.Assign(0,0,72,15);
T := New(PTextWindow, Init(R, FileName));
T^.Options := T^.Options or ofCentered;
Desktop^.Insert(T);
end;

procedure ViewCustom(const FileName: FNameStr);


var
Params : FNameStr;
Command : FNameStr;
D: DirStr;
N: NameStr;
E: ExtStr;
L : array[0..1] of Longint;
Msg: String;
PS: PString;
begin
{ create the program name }

if FullTrim(Viewer) = '' then


begin
MessageBox(RezStrings^.Get(sNoViewerErr), nil, mfError + mfOKButton);
Exit;
end;

FSplit(Viewer, D, N, E);

DoneSysError;
DoneEvents;
DoneVideo;
DoneDosMem;
SwapVectors;

if E = '.BAT' then
begin
Command := GetEnv('COMSPEC');
Params := '/c ' + Viewer + ' ' + FileName;
end
else
begin
Command := Viewer;
Params := FileName;
end;

Exec(Command, Params);
SwapVectors;

InitDosMem;
InitVideo;
InitEvents;
InitSysError;
Application^.Redraw;

if DosError <> 0 then


begin
L[0] := DosError;
L[1] := Longint( @Viewer );
MessageBox(RezStrings^.Get(sInvokeErr), @L, mfError + mfOKButton);
end;

end;

function DriveValid(Drive: Char): Boolean; 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;

{ Return a redirected device entry into the specified buffers }


function GetRedirEntry(Entry: Word; Local, Net: Pointer): Boolean; assembler;
asm
PUSH DS
LDS SI,Local
LES DI,Net
MOV AX,5F02h
MOV BX,Entry
INT 21h
POP DS
SBB AL,AL
INC AL
end;

{ return a list of redirected devices (drives only) }


function RedirDeviceList: PDeviceCollection;
var
List: PDeviceCollection;
Device: PDeviceRec;
P: PChar;
I: Word;
LocalName: array[0..15] of char;
NetworkName: array[0..127] of char;
begin
List := nil;

{$IFNDEF DPMI}
List := New(PDeviceCollection, Init(10,10));
for I := 0 to 99 do
begin
if GetRedirEntry(I, @LocalName, @NetworkName) then
begin
if (LocalName[0] in ['D'..'Z']) and (LocalName[1] = ':') then
begin
New(Device);
Device^.LocalName := LocalName[0];
P := @NetworkName[2];
Device^.NetworkName := NewStr( StrPas(P) );
List^.Insert(Device);
end;
end
else Break;
end;

if List^.Count = 0 then
begin
Dispose(List, Done);
List := nil;
end;
{$ENDIF}

RedirDeviceList := List;
end;

function ValidDriveList: PStringCollection;


var
DriveList: PStringCollection;
DeviceList: PDeviceCollection;
Drive: Char;
Device: PDeviceRec;
S: String;

function DriveMatch(P: PDeviceRec): Boolean; far;


begin
DriveMatch := Drive = P^.LocalName;
end;

begin
DriveList := New(PStringCollection, Init(26,0));
DeviceList := RedirDeviceList;
for Drive := 'A' to 'Z' do
begin
if DriveValid(Drive) then
begin
S := Drive + ':';
if DeviceList <> nil then
begin
Device := DeviceList^.FirstThat(@DriveMatch);
if Device <> nil then S := S + ' ' + Device^.NetworkName^;
end;
DriveList^.Insert(NewStr(S));
end;
end;
if DriveList^.Count = 0 then
begin
Dispose(DriveList, Done);
DriveList := nil;
end;
ValidDriveList := DriveList;
if DeviceList <> nil then Dispose(DeviceList, Done);
end;

function SelectDrive : Char;


var
R: TRect;
D: PDialog;
LB: PListBox;
SB: PScrollBar;
P: PString;
DriveList: PStringCollection;
CurDir: String;

function IsCurrentDirectory(Dir: PString): Boolean; far;


begin
IsCurrentDirectory := Dir^[1] = CurDir[1];
end;

begin
GetDir(0, CurDir); { save this value }
SelectDrive := ' ';
DriveList := ValidDriveList;

if DriveList = nil then


begin
MessageBox(RezStrings^.Get(sNoDrivesErr), nil, mfError + mfOKButton);
Exit;
end;

R.Assign(0, 0, 53, 13);


D := New(PDialog, Init(R, 'Select Drive'));
with D^ do
begin
Options := Options or ofCentered;
R.Assign(50, 3, 51, 9);
SB := New(PScrollBar, Init(R));
Insert(SB);
R.Assign(2, 3, 50, 9);
LB := New(POkListBox, Init(R, 1, SB));
Insert(LB);
LB^.NewList(DriveList);
R.Assign(2, 2, 19, 3);
Insert(New(PLabel, Init(R, '~D~rives', LB)));
R.Assign(12, 10, 24, 12);
Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
R.Move(16, 0);
Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
SelectNext(False);
end;

P := DriveList^.FirstThat(@IsCurrentDirectory);
if P <> nil then
LB^.FocusItem(DriveList^.IndexOf(P));

if Desktop^.ExecView(D) = cmOK then


begin
P := DriveList^.At(LB^.Focused);
if P <> nil then SelectDrive := P^[1];
end;
Dispose(DriveList, Done);
Dispose(D, Done);
end;

procedure InvalidateDir(Path: FNameStr);


begin
Message(Desktop, evBroadcast, cmInvalidDir, @Path);
end;

procedure HandleFileCopy(const Path: FNameStr; P: PFileList; Current: Integer);


var
Dest, S, D: string[80];
C: TCopier;
Dlg: PDialog;
TotalSize: Longint;

procedure CopyTagged(F: PFileRec); far;


begin
if F^.Tagged then
begin
S := Path + '\' + F^.Name + F^.Ext;
D := Dest + F^.Name + F^.Ext;
C.CopyFile(S, D, coNormal);
end;
end;

procedure AddSizes(F: PFileRec); far;


begin
if F^.Tagged then Inc(TotalSize, F^.Size);
end;

procedure CopySingle(F: PFileRec);


begin
S := Path + '\' + F^.Name + F^.Ext;
D := Dest + F^.Name + F^.Ext;
C.CopyFile(S, D, coNormal);
end;

begin
Dest := '';
Dlg := PDialog( RezFile.Get('CopyDialog') );
Application^.ExecuteDialog(Dlg, @Dest);
if Dest = '' then Exit;
Dest := FExpand(Dest);
if (Dest[Length(Dest)] <> '\') and (Dest[Length(Dest)] <> ':') then
Dest := Dest + '\';

C.Init(20);

TotalSize := 0;
if HasTaggedFiles(P) then P^.ForEach(@AddSizes)
else TotalSize := PFileRec(P^.At(Current))^.Size;
ShowCopyStatusBox(TotalSize);

if HasTaggedFiles(P) then P^.ForEach(@CopyTagged)


else CopySingle( PFileRec( P^.At(Current) ) );

C.Done;
KillStatusBox;

if Dest[Length(Dest)] = '\' then Dec(Dest[0]);


InvalidateDir(Dest);
end;

function SafeDelete(FileName: FNameStr): Integer;


var
R: Word;
F: File;
C: Word;
L: Longint;
D: PDialog;
Params: array[0..1] of Pointer;
Name : FNameStr;
Msg : String;
Attr: Word;
begin
SafeDelete := -1;
C := cmYes; { default value }
Assign(F, FileName);
GetFAttr(F, Attr);
if DosError <> 0 then
begin
Params[0] := Pointer(L);
Params[1] := @FileName;
MessageBox(RezStrings^.Get(sAccessErr), @Params, mfError + mfOKButton);
SafeDelete := L;
Exit;
end;

if (Attr and ReadOnly) <> 0 then Msg := RezStrings^.Get(sFileIsReadOnly)


else Msg := '';
Params[0] := @FileName;
Params[1] := @Msg;

if ConfirmDelete then
begin
D := PDialog( RezFile.Get('ConfirmDelete') );
C := Application^.ExecuteDialog(D, @Params);
end;

if C = cmYes then
begin
{ if file was read-only, clear that attribute }
if (Attr and ReadOnly) <> 0 then
begin
SetFAttr(F, Attr and (not ReadOnly));
if DosError <> 0 then
begin
L := DosError;
Params[0] := @Msg;
Params[1] := Pointer(L);
MessageBox(RezStrings^.Get(sSetAttrErr), @Params, mfError+mfOKButton);
SafeDelete := DosError;
Exit;
end;
end;

{ delete the file }


{$I-}
Erase(F);
{$I+}
L := IOResult;
if L <> 0 then
begin
Params[0] := @Msg;
Params[1] := Pointer(L);
MessageBox(RezStrings^.Get(sDeleteErr), @Params, mfError+mfOKButton);
SafeDelete := L;
Exit;
end
else
SafeDelete := 0;
end;
end;

function RemoveDeadFiles(P: PFileList): Integer;


var
F : PFileRec;
i : Integer;
Count: Integer;
begin
Count := 0;
i := 0;
while i < P^.Count do
begin
F := P^.At(i);
if F^.Name[1] = #0 then
begin
if F^.Tagged then
begin
F^.Toggle;
Message(Desktop, evBroadcast, cmTagChanged, F);
end;
Inc(Count);
P^.AtFree(i);
end
else inc(i);
end;
RemoveDeadFiles := Count;
end;
function DeleteMultFiles(Path: FNameStr; List: PFileList): Boolean;
var
F: PFileRec;
N: FNameStr;

procedure DeleteIfTagged(F: PFileRec); far;


begin
if F^.Tagged then
begin
N := Path + '\' + F^.Name + F^.Ext;
StatusMsg := RezStrings^.Get(sDeleting) + N;
Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
if SafeDelete(N) = 0 then F^.Name[1] := #0; { mark as deleted }
end;
end;

begin
ConfirmDelete := False;

StatusMsg := '';
ShowStatusBox;
List^.ForEach(@DeleteIfTagged);
KillStatusBox;

DeleteMultFiles := RemoveDeadFiles(List) > 0;

ConfirmDelete := True;
end;

procedure HandleFileDelete(const Path: FNameStr; List: PFileList;


Current: Integer);
var
D: PDialog;
Command: Word;
F: PFileRec;
begin

F := List^.At(Current);
Command := cmNo; { default to only deleting current file }

if HasTaggedFiles(List) then
begin
D := PDialog( RezFile.Get('DeleteWhich') );
Command := Application^.ExecuteDialog(D, nil);
end;

if Command = cmNo then { only delete the current file }


begin
F := List^.At(Current);
if SafeDelete(Path + '\' + F^.Name + F^.Ext) = 0 then
InvalidateDir(Path);
end
else if Command = cmYes then { delete all marked files }
begin
if DeleteMultFiles(Path, List) then
InvalidateDir(Path);
end;

end;
procedure RenameFile(const Path: FNameStr; F: PFileRec);
var
D: PRenameDialog;
Dir: DirStr;
N: NameStr;
E: ExtStr;
begin
D := New(PRenameDialog, Init(Path + '\' + F^.Name + F^.Ext));
if D <> nil then
begin
if Application^.ExecuteDialog(D, nil) = cmOK then
begin
FSplit(D^.NewName, Dir, N, E);
F^.Name := N;
F^.Ext := E;
InvalidateDir(Path);
end;
end;
end;

procedure ChangeAttr(const Path: FNameStr; F: PFileRec);


var
D: PAttrDialog;
begin
D := New(PAttrDialog, Init(Path + '\' + F^.Name + F^.Ext));
if D <> nil then
begin
if Application^.ExecuteDialog(D, nil) = cmOK then
begin
F^.Attr := D^.NewAttr;
InvalidateDir(Path);
end;
end
else
MessageBox(RezStrings^.Get(sReadAttrErr), nil,
mfError + mfOKButton);
end;

procedure InstallViewer;
var
VPath: FNameStr;
Valid, Done: Boolean;
L: Longint;
begin
VPath := Viewer;
Valid := False;
Done := False;
while (not Valid) and (not Done) do
begin
if InputBox(RezStrings^.Get(sCustomViewer), RezStrings^.Get(sPathAndName),
VPath, SizeOf(FNameStr) - 1) = cmOK then
begin
UpperCase(VPath);
VPath := FSearch(VPath, GetEnv('PATH'));
if VPath = '' then
begin
MessageBox(RezStrings^.Get(sCantLocateOnPath), nil,
mfError + mfOKButton);
end
else if not IsExecutable(VPath) then
begin
L := Longint(@VPath);
MessageBox(RezStrings^.Get(sFileNotAnExe), @L, mfError+mfOKButton);
end
else Valid := True;
end
else Done := True;
end;
if Valid then Viewer := VPath;
end;

procedure SetDisplayPrefs;
var
D: PDialog;
SaveMask: string[12];
begin
D := PDialog( RezFile.Get('DisplayPref') );

SaveMask := ConfigRec.FileMask;
if Application^.ExecuteDialog(D, @ConfigRec) = cmOK then
begin
Uppercase(ConfigRec.FileMask);

if ConfigRec.ShowHidden > 0 then


UnwantedFiles := VolumeID or Directory
else
UnwantedFiles := VolumeID or Directory or SysFile or Hidden;

if ConfigRec.FileMask <> SaveMask then


Message(Desktop, evBroadcast, cmRescan, nil)
else
Message(Desktop, evBroadcast, cmRefreshDisplay, nil);
end;
end;

procedure SaveConfig;
var
Result: Longint;
F: PDosStream;
Pal: PString;
begin
F := New(PDosStream, Init(GetExeBaseName + CFGExt, stCreate));
Result := F^.Status;
if Result <> 0 then
begin
MessageBox(RezStrings^.Get(sWriteCfgErr), @Result, mfError+mfOKButton);
Exit;
end;
F^.Write(ConfigHeader[1], SizeOf(TConfigHeader) - 1);
F^.Write(ConfigRec, SizeOf(TConfigRec));
F^.Write(Viewer, SizeOf(FNameStr));
Pal := @Application^.GetPalette^;
F^.WriteStr(Pal);
WriteAssociationList(F^);
Dispose(F, Done);
end;
procedure ReadConfig;
var
Result: Longint;
F: PDosStream;
Header: TConfigHeader;
Pal: PString;
begin
F := New(PDosStream, Init(GetExeBaseName + CFGExt, stOpenRead));
Result := F^.Status;
if Result <> 0 then Exit;
F^.Read(Header[1], SizeOf(TConfigHeader) - 1);
Header[0] := Char( SizeOf(TConfigHeader) -1 );
if Header <> ConfigHeader then
begin
MessageBox(RezStrings^.Get(sInvalidCfgErr), nil, mfError + mfOKButton);
Exit;
end;
F^.Read(ConfigRec, SizeOf(TConfigRec));
F^.Read(Viewer, SizeOf(FNameStr));
Pal := F^.ReadStr;
if Pal <> nil then
begin
Application^.GetPalette^ := Pal^;
DoneMemory;
Application^.ReDraw;
DisposeStr(Pal);
end;
ReadAssociationList(F^);
Dispose(F, Done);
end;

procedure RunDosCommand(Command: String);


var
D: PDialog;
Event: TEvent;
begin
D := PDialog( RezFile.Get('RunDialog') );
if (Application^.ExecuteDialog(D, @Command) = cmOK) and
(FullTrim(Command) <> '') then
begin
DoneSysError;
DoneEvents;
DoneVideo;
DoneDosMem;

SwapVectors;
Exec(GetEnv('COMSPEC'), '/C' + Command);
SwapVectors;

PrintStr(RezStrings^.Get(sPressAnyKey));
repeat
GetKeyEvent(Event);
until Event.What <> evNothing;

InitDosMem;
InitVideo;
InitEvents;
InitSysError;
Application^.Redraw;
end;
end;

function NewFileNameRec(const Path: FNameStr): PFileNameRec;


var
D: DirStr;
N: NameStr;
E: ExtStr;
P: PFileNameRec;
begin
FSplit(Path, D, N, E);
New(P);
P^.Dir := D;
P^.Name := N;
P^.Ext := E;
NewFileNameRec := P;
end;

procedure DragDropCopy(Mover: PFileMover; Dest: PathStr);


var
C: TCopier;
TotalSize: Longint;

procedure AddSizes(F: PFileRec); far;


begin
Inc(TotalSize, F^.Size);
end;

procedure CopyFiles(F: PFileRec); far;


begin
C.CopyFile(Mover^.Dir + '\' + F^.Name + F^.Ext,
Dest + '\' + F^.Name + F^.Ext, coNormal);
end;

begin
if Mover^.Dir = Dest then
begin
MessageBox('Files cannot be copied to same directory.',nil,
mfError + mfOKButton);
Exit;
end;

if MessageBox('Copy files to ' + Dest, nil, mfConfirmation +


mfOKCancel) <> cmOK then Exit;

C.Init(20);
TotalSize := 0;
Mover^.Items^.ForEach(@AddSizes);

ShowCopyStatusBox(TotalSize);
Mover^.Items^.ForEach(@CopyFiles);

C.Done;
KillStatusBox;

InvalidateDir(Dest);
end;
function WildCardMatch(const Name, Card: FNameStr): Boolean;
var
I, J: Integer;
begin
WildCardMatch := False;
J := 1;
I := 1;
while J <= Length(Card) do
case Card[J] of
'*':
begin
while (J <= Length(Card)) and (Card[J] <> '.') do Inc(J);
while (I <= Length(Name)) and (Name[I] <> '.') do Inc(I);
end;
'?':
begin
Inc(J);
Inc(I);
end;
'.':
begin
if I <= Length(Name) then
if Name[I] <> '.' then
Exit
else
Inc(I);
Inc(J);
end;
else
if (I > Length(Name)) or (Card[J] <> Name[I]) then Exit;
Inc(I);
Inc(J);
end;
WildCardMatch := (I > Length(Name)) and (J > Length(Card));
end;

{ TStatusBox }
procedure TStatusBox.HandleEvent(var Event:TEvent);
begin
inherited HandleEvent(Event);
if (Event.What=evBroadcast) and (Event.Command = cmStatusUpdate) then
DrawView;
end;

{ TCopier }
procedure TCopier.ReadMsg(const FName: FNameStr; Progress: Longint);
begin
StatusMsg := RezStrings^.Get(sReading) + FName;
Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
Message(StatusBox, evBroadcast, cmAddGauge, Pointer(Progress div 2));
end;

procedure TCopier.WriteMsg(const FName: FNameStr; Progress: Longint);


begin
StatusMsg := RezStrings^.Get(sWriting) + FName;
Message(StatusBox, evBroadcast, cmStatusUpdate, nil);
Message(StatusBox, evBroadcast, cmAddGauge, Pointer(Progress div 2));
end;
function TCopier.IOError(const FName: FNameStr; ECode: Integer) : erAction;
var
Msg: String;
D: PDialog;
R: TRect;
P: PView;
begin
Msg := ErrorMsg(ECode);

R.Assign(0,0,55,7);
D := New(PDialog, Init(R, FName));
with D^ do
begin
Options := Options or ofCentered;
R.Assign(2,2,52,3);
Insert(New(PStaticText, Init(R, Msg)));
R.Assign(20,4,32,6);
Insert(New(PButton, Init(R, '~R~etry', cmOK, bfDefault)));
R.Move(14,0);
Insert(New(PButton, Init(R, '~A~bort', cmCancel, bfNormal)));
SelectNext(False);
end;
if Application^.ExecuteDialog(D, nil) = cmOK then IOError := erRetry
else IOError := erAbort;
end;

{ TOkListBox }

procedure TOkListBox.SelectItem(Item: Integer);


var
E: TEvent;
begin
inherited SelectItem(Item);
with E do
begin
What := evCommand;
Command := cmOk;
InfoPtr := nil;
end;
PutEvent(E);
end;

end.

You might also like