home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
h
/
htmix20.zip
/
MISC.ZIP
/
TCD.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-07-13
|
15KB
|
534 lines
program TCD;
{┌──────────────────────────────── INFO ────────────────────────────────────┐}
{│ File : TCD.PAS │}
{│ Author : Harald Thunem │}
{│ Purpose : Graphically change directory. │}
{│ Updated : July 10 1992 │}
{└──────────────────────────────────────────────────────────────────────────┘}
{────────────────────────── Compiler directives ─────────────────────────────}
{$A+ Word align data }
{$B- Short-circuit Boolean expression evaluation }
{$E- Disable linking with 8087-emulating run-time library }
{$G+ Enable 80286 code generation }
{$R- Disable generation of range-checking code }
{$S- Disable generation of stack-overflow checking code }
{$V- String variable checking }
{$X- Disable Turbo Pascal's extended syntax }
{$N+ 80x87 code generation }
{$D- Disable generation of debug information }
{────────────────────────────────────────────────────────────────────────────}
uses Dos,
Screen,
Common,
Keyboard;
const MaxDirs = 1000;
MainAttr = White+BlueBG;
TopAttr = Blue+LightWhiteBG;
BottomAttr1= Yellow+CyanBG;
BottomAttr2= White+CyanBG;
ScanAttr = White+CyanBG;
type PDirItem = ^TDirItem;
TDirItem = record
ShortName: String[14];
LongName : DirStr;
Level : byte;
end;
var DirList : array[1..MaxDirs] of PDirItem;
LastList : array[1..MaxDirs] of boolean;
DriveList : array[1..26] of char;
DriveNum,
NumDrives : byte;
NumDirs : 0..MaxDirs;
MainDir : DirStr;
MainSize : word;
MainScr : pointer;
SearchStr : string;
MaxLevel,
ScanRow,
ScanCol,
CDRow,
CDCol,
CDRows,
CDCols : byte;
CDFile : File of TDirItem;
procedure GetDrives;
var i,w: byte;
begin
NumDrives := 1;
Port[$70] := $14;
w := Port[$71];
w := w and $C0;
DriveList[NumDrives] := 'A';
if w=$40 then
begin
Inc(NumDrives);
DriveList[NumDrives] := 'B';
end;
for i := 3 to 26 do
if DiskSize(i)>-1 then
begin
Inc(NumDrives);
DriveList[NumDrives] := Chr(i+64);
end;
end;
procedure GetFirst(MainDir: DirStr);
begin
NumDirs := 1;
GetMem(DirList[1],SizeOf(TDirItem));
DirList[1]^.ShortName := MainDir+'\';
DirList[1]^.LongName := MainDir+'\';
DirList[1]^.Level := 0;
end;
procedure ScanDirs(Dir: DirStr; Level: byte);
var S: SearchRec;
begin
FindFirst(Dir+'\*.*',AnyFile,S);
while DosError=0 do
if ((S.Attr and Directory)=Directory) and (S.Name<>'.') and (S.Name<>'..') then
begin
Inc(NumDirs);
GetMem(DirList[NumDirs],SizeOf(TDirItem));
DirList[NumDirs]^.ShortName := ' '+S.Name+' ';
DirList[NumDirs]^.LongName := Dir+'\'+S.Name;
DirList[NumDirs]^.Level := Level;
WriteStr(ScanRow,ScanCol,ScanAttr,' ');
WriteC(ScanRow,ScanCol+6,ScanAttr,S.Name);
ScanDirs(Dir+'\'+S.Name,Level+1);
FindNext(S);
end
else FindNext(S);
end;
procedure SaveToFile(MainDir: DirStr);
var i: word;
begin
{$I-}
Assign(CDFile,MainDir+'\TREEINFO.TCD');
ReWrite(CDFile);
{$I+}
if IOResult = 0 then
begin
for i := 1 to NumDirs do
Write(CDFile,DirList[i]^);
Close(CDFile);
end
else MessageBox('Error saving info to file!');
end;
function ReadFromFile(MainDir: DirStr): boolean;
var i: word;
begin
{$I-}
Assign(CDFile,MainDir+'\TREEINFO.TCD');
ReSet(CDFile);
{$I+}
if IOResult=0 then
begin
NumDirs := 0;
while not Eof(CDFile) do
begin
Inc(NumDirs);
GetMem(DirList[NumDirs],SizeOf(TDirItem));
Read(CDFile,DirList[NumDirs]^);
end;
Close(CDFile);
ReadFromFile := true;
Exit;
end;
ReadFromFile := false;
end;
procedure FindLast;
var i,j: word;
begin
MaxLevel := 0;
for i := 1 to NumDirs do
if DirList[i]^.Level > MaxLevel then
MaxLevel := DirList[i]^.Level;
for i := 1 to NumDirs do
LastList[i] := true;
for i := 1 to NumDirs-1 do
begin
for j := i+1 to NumDirs do
if DirList[j]^.Level = DirList[i]^.Level then LastList[i] := false;
end;
LastList[NumDirs] := true;
end;
procedure BackGround;
var i: byte;
begin
CDRow := 3;
CDRows := CRTRows-5;
CDCols := 19+5*MaxLevel;
CDCol := 40-(CDCols div 2);
Fill(CDRow,CDCol,CDRows,CDCols,MainAttr,' ');
AddShadow(CDRow,CDCol,CDRows,CDCols);
for i := 1 to CDRows-1 do
begin
WriteStr(CDRow+i,CDCol,MainAttr,'█');
WriteStr(CDRow+i,CDCol+CDCols-1,MainAttr,'█');
end;
Fill(CDRow+CDRows-1,CDCol,1,CDCols,MainAttr,'█');
WriteStr(CDRow+1,CDCol+CDCols-2,White+BlackBG,#24);
WriteStr(CDRow+CDRows-2,CDCol+CDCols-2,White+BlackBG,#25);
for i := CDRow+2 to (CDRow+CDRows-3) do
WriteStr(i,CDCol+CDCols-2,White+BlackBG,'░');
Fill(CDRow,CDCol,1,CDCols,TopAttr,' ');
WriteC(CDRow,CDCol+(CDCols div 2),TopAttr,'TCDir 2.0');
Fill(CRTRows,1,1,80,BottomAttr2,' ');
WriteStr(CRTRows,3,BottomAttr1,'F2');
WriteEos(BottomAttr2,' - ReScan ');
WriteEos(BottomAttr1,'F3');
WriteEos(BottomAttr2,' - Drive ');
WriteEos(BottomAttr1,'Return');
WriteEos(BottomAttr2,' - Goto ');
WriteEos(BottomAttr1,'Esc');
WriteEos(BottomAttr2,' - Quit');
end;
procedure EraseDirs;
var i: word;
begin
for i := 1 to NumDirs do
FreeMem(DirList[i],SizeOf(TDirItem));
end;
procedure ReScan(ForceScan: boolean);
begin
SearchStr := '';
if ForceScan then
begin
Box(ScanRow-3,ScanCol-12,6,38,ScanAttr,SingleBorder,' ');
AddShadow(ScanRow-3,ScanCol-12,6,38);
WriteC(ScanRow-1,ScanCol+6,ScanAttr,'Scanning directory-structure');
GetFirst(MainDir);
ScanDirs(MainDir,1);
SaveToFile(MainDir);
end
else
if not ReadFromFile(MainDir) then
begin
Box(ScanRow-3,ScanCol-12,6,38,ScanAttr,SingleBorder,' ');
AddShadow(ScanRow-3,ScanCol-12,6,38);
WriteC(ScanRow-1,ScanCol+6,ScanAttr,'Scanning directory-structure');
GetFirst(MainDir);
ScanDirs(MainDir,1);
SaveToFile(MainDir);
end;
StoreToScr(1,1,CRTRows,80,MainScr^);
FindLast;
end;
procedure ChangeDrive(var DriveNum: byte; var MainDir: DirStr);
var
i,
Current,
DN,
Start,
Row,
Col,
Rows,
Cols: byte;
begin
GetDrives;
Cols := 11;
Rows := 8;
Row := (CRTRows div 2)-4;
Col := 38-(Cols div 2);
Box(Row+1,Col,Rows-2,Cols-2,White+LightBlackBG,SingleBorder,' ');
AddShadow(Row,Col,Rows-1,Cols-2);
Fill(Row,Col,1,Cols-2,Magenta+LightWhiteBG,' ');
WriteC(Row,Col+4,SameAttr,'Drive');
for i := 1 to NumDrives do
if i < 5 then
WriteStr(Row+1+i,Col+4,SameAttr,DriveList[i]);
Start := 1;
while DriveNum>(Start+3) do
begin
Inc(Start);
ScrollUp(Row+2,Col+2,Rows-4,Cols-6,White+LightBlackBG);
WriteStr(Row+5,Col+4,SameAttr,DriveList[Start+3]);
end;
Current:=0;
repeat
Inc(Current)
until DriveList[Current] = MainDir[1];
WriteStr(Row+2+Current-Start,Col+2,Blue+LightWhiteBG,' '+DriveList[Current]+' ');
repeat
Inkey(Ch,Key);
WriteStr(Row+2+Current-Start,Col+2,White+LightBlackBG,' '+DriveList[Current]+' ');
case Key of
UpArrow : if Current>1 then Dec(Current);
DownArrow: if Current<NumDrives then Inc(Current);
end;
if Current<Start then
begin
ScrollDown(Row+2,Col+2,Rows-4,Cols-6,White+LightBlackBG);
Dec(Start);
end;
if Current>(Start+3) then
begin
ScrollUp(Row+2,Col+2,Rows-4,Cols-6,White+LightBlackBG);
Inc(Start);
end;
WriteStr(Row+2+Current-Start,Col+2,Blue+LightWhiteBG,' '+DriveList[Current]+' ');
until Key in [Return,Escape];
if (Key=Return) then
begin
DN := Ord(DriveList[Current])-64;
if DiskSize(DN)>-1 then
begin
MainDir := DriveList[Current]+':';
DriveNum := Ord(MainDir[1])-64;
end
else MessageBox('No disk in drive!');
end;
Key := NullKey;
end;
procedure ScrollDirs;
const CurrentAttr = White+RedBG;
var Start,Current: integer;
OldDriveNum: byte;
OldMainDir: DirStr;
s: string;
procedure WriteLine(Current,Start,Attr: word);
var i,j,OldL,NewL: integer;
Last: boolean;
s: string;
C: char;
begin
Last := true;
s := '';
if Current=NumDirs then
begin
s:='└────';
with DirList[Current]^ do
if Level>1 then
for i := 2 to Level do
s := ' '+s;
end
else
begin
OldL := DirList[Current]^.Level;
i := Current;
repeat
Inc(i);
NewL := DirList[i]^.Level;
until (NewL<=OldL) or (i=NumDirs);
if NewL>=OldL then
s := '├────'
else s:='└────';
OldL := DirList[Current]^.Level;
i := Current;
repeat
Inc(i);
NewL := DirList[i]^.Level;
if NewL=DirList[Current]^.Level then
Last := false;
if OldL > NewL then
begin
if OldL-NewL>1 then
for j := 2 to (OldL-NewL) do
s := ' ' + s;
s := '│ ' + s;
OldL := NewL;
end;
until (i=NumDirs) or (NewL=1);
if NewL>1 then
for i := 2 to NewL do
s := ' ' + s;
if DirList[Current]^.Level=1 then
if Last then
s := '└────'
else s := '├────';
end;
if DirList[Current]^.Level=0 then
s:='';
with DirList[Current]^ do
begin
WriteStr(CDRow+Current-Start+1,CDCol+2,MainAttr,s);
WriteStr(CDRow+Current-Start+1,CDCol+2+5*Level,Attr,ShortName);
end;
end;
procedure WritePage(Start: word);
var i: word;
begin
Fill(CDRow+1,CDCol+1,CDRows-2,CDCols-3,MainAttr,' ');
for i := 1 to CDRows-2 do
if (i+Start-1)<=NumDirs then
WriteLine(i+Start-1,Start,MainAttr);
end;
procedure WriteFraction(Current: word);
var i,Fraction: byte;
begin
for i := CDRow+2 to (CDRow+CDRows-3) do
WriteStr(i,CDCol+CDCols-2,White+BlackBG,'░');
Fraction := Trunc((CDRows-5)*(Current/NumDirs));
i := CDRow+2+Fraction;
WriteStr(i,CDCol+CDCols-2,White+BlackBG,'█');
end;
procedure CheckPosition;
begin
Start := 1;
Current := 1;
GetDir(DriveNum,OldMainDir);
repeat
Inc(Current);
until (DirList[Current]^.LongName=OldMainDir) or (Current>=NumDirs);
if DirList[Current]^.LongName<>OldMainDir then
Current := 1;
end;
begin
CheckPosition;
BackGround;
Start := Current-(CDRows div 2)+2;
if Start<1 then Start:=1;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
repeat
InKey(Ch,Key);
WriteLine(Current,Start,MainAttr);
case Key of
UpArrow : Dec(Current);
DownArrow : Inc(Current);
PgUp : begin
Dec(Current,CDRows-3);
Dec(Start,CDRows-3);
if Start<1 then Start:=1;
if Current<1 then Current:=1;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
end;
PgDn : begin
Inc(Current,CDRows-3);
Inc(Start,CDRows-3);
if Start>(NumDirs-CDRows+3) then Start:=NumDirs-CDRows+3;
if Current>NumDirs then Current:=NumDirs;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
end;
F2 : if Confirm('Re-scan drive '+MainDir,true) then
begin
EraseDirs;
ReScan(true);
CheckPosition;
BackGround;
Start := Current-(CDRows div 2)+2;
if Start<1 then Start:=1;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
end;
F3 : begin
OldDriveNum := DriveNum;
ChangeDrive(DriveNum,MainDir);
if DriveNum<>OldDriveNum then
begin
EraseDirs;
ReScan(false);
CheckPosition;
BackGround;
Start := Current-(CDRows div 2)+2;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
end
else begin
BackGround;
WritePage(Start);
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
end;
end;
end;
if Current < 1 then Current := 1;
if Current > NumDirs then Current := NumDirs;
if Current < Start then
begin
ScrollDown(CDRow+1,CDCol+1,CDRows-2,CDCols-3,MainAttr);
Dec(Start);
end;
if Current >= Start+(CDRows-2) then
begin
ScrollUp(CDRow+1,CDCol+1,CDRows-2,CDCols-3,MainAttr);
Inc(Start);
end;
WriteLine(Current,Start,CurrentAttr);
WriteFraction(Current);
until Key in [Return,Escape];
if Key=Return then
begin
{$I-}
ChDir(DirList[Current]^.LongName);
{$I+}
if IOResult<>0 then
MessageBox('Could not find directory '+DirList[Current]^.LongName+'. Quitting...');
end;
end;
begin
Write('TCD 2.0 Written by H.Thunem');
GetDir(0,MainDir);
MainDir := Copy(MainDir,1,2);
DriveNum := Ord(MainDir[1])-64;
if ParamCount=1 then
begin
MainDir := ParamStr(1);
MainDir[1] := Upcase(MainDir[1]);
DriveNum := Ord(MainDir[1])-64;
if Pos(':',MainDir)=0 then
MainDir := MainDir+':';
if DiskSize(DriveNum)=-1 then
begin
WriteLn('Drive ',MainDir,' does not respond !');
Halt(1);
end;
end;
MainSize := 2*CRTRows*80;
GetMem(MainScr,MainSize);
StoreToMem(1,1,CRTRows,80,MainScr^);
SetCursor(CursorOff);
SetIntens;
ScanRow := (CRTRows div 2);
ScanCol := 34;
ReScan(false);
ScrollDirs;
EraseDirs;
SetBlink;
StoreToScr(1,1,CRTRows,80,MainScr^);
FreeMem(MainScr,MainSize);
SetCursor(CursorUnderline);
end.