home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
MBUG
/
MBUG094.ARC
/
NMANGR1.PRO
< prev
next >
Wrap
Text File
|
1979-12-31
|
14KB
|
465 lines
Var
DriveStr:char;
x,recrd,Block,SavedDrive,DriveSelected,DirCount,
Index,Loop,Loop2,OffSet,RecNo,Track,Sector,ExtNo:integer;
RecNoF,OffSetF,TrackF,SectorF,ExtNoF:integer;
CurSector,CurTrack,CurDrive:integer; {Current sector in DMA}
UserNF :Byte;
DMA : array[0..511] of Byte; {this needs to be large
I don't know why but if
small causes crash on exit
from program}
SectorData:SectorBuff absolute DMA;
DirIndex: Array [0..MaxDirSize] of integer; {Points to posns in Directory
where FIRST extents
of files are}
WorkSpaceDirStart:integer; {Points to posn in DirIndex where files IN a
WorkSpace are found}
WorkSpaceDirEnd:integer;
DirCounter:Integer; {used to load Directory}
Directory: Array [0..MaxDirSize] of DirName; {Points to disk location
of directory entries
(extents)}
{File managing routines to directly access records in a file
need to obtain the Directory entry first}
var
DPH,SPT,DSM,DPB,OFF,DRM:Integer;
SkewTrans:Boolean;
BSH,BLM:byte;
Procedure GetDriveInfo(Drive:integer);
Const
SelDsk=8;
GetDPB=31;
Procedure DefaultDrive(Drive:integer);
Begin
bdos(13);{Reset drives causes disk allocation table to be built}
bdos(14,Drive);Mem[4]:=Drive; {Select Drive }
{Bdos(13); Dont. It sets back to A} {Reset Drives}
end;
Begin
DefaultDrive(Drive);
DPH:=BiosHL(SelDsk,Drive);
If DPH=0 then Begin write('DPH error'); Halt end;
SkewTrans:=( (Mem[DPH]+Mem[DPH+1])<>0 );
DPB:=BdosHL(GetDPB);
DSM:=Mem[DPB+5]+256*Mem[DPB+6];
BLM:=Mem[DPB+3];
BSH:=Mem[DPB+2];
SPT:=Mem[DPB]+256*Mem[DPB+1];
OFF:=Mem[DPB+$0D]+256*Mem[DPB+$0D+1];
DRM:=Mem[DPB+$07]+256*Mem[DPB+$07+1];
end;
Procedure LocateRecord(Var Blocks:BlockData;
Var RecordInExtent,Track,Sector:Integer;
BigDrv:Boolean);
{Find track and sector within track
*** only operates on blocks covered by extent
must obtain drive info first}
Var
X1,RemX1,Block,BlockNo,RecordInBlock:Integer;
Begin
RecordInBlock:= RecordInExtent AND BLM;
BlockNo:= RecordInExtent shr BSH;
If BigDrv then
Block:= Blocks[BlockNo shl 1] + (Blocks[(BlockNo shl 1) +1] shl 8)
else
Block:= Blocks[BlockNo];
If (Block<0) or (Block>DSM) then begin write('Block too big');Halt end;
x1:= (Block div SPT) SHL BSH;
RemX1 := (Block mod SPT) SHL BSH;
Track := X1 + ((RemX1 + RecordinBlock) div SPT)+OFF;
Sector:= (RemX1+RecordinBlock) mod SPT; {Sector within track}
end;
Procedure GetRecord( Drive,Track,Sector:integer);
{Record placed in DMA}
Var Error :Byte;
Const
SelDsk=8;
GetDPB=31;
SetTrk=9;
SetSec=10;
SecTran=15;
Read=12;
Set_DMA=26;
Begin
{ GotoXY(20,23);Write(' ');} {******}
If (Drive<>CurDrive) or (Track<>CurTrack) or (Sector<>CurSector)
then
begin
{GotoXY(20,23);Write('Reading ',Drive,' ',Track,' ',Sector);} {******}
BDos(Set_DMA,Addr(DMA));
If (Drive<>CurDrive) then Bios(SelDsk,Drive);
If (Drive<>CurDrive) or (Track<>CurTrack) then Bios(SetTrk,Track);
If SkewTrans then Sector:=BiosHL(SecTran,Sector);
Bios(SetSec,Sector);
Error:=Bios(Read);
If Error<>0 then begin write('I/O error = ',Error);Halt end;
CurDrive:=Drive;
CurTrack:=Track;
CurSector:=Sector;
end
end;
Procedure DeleteFile( Var Index:Integer);
Var
Ch:Char;
Oname:FileName;
DirIx:Integer;
Procedure WriteSector(Drive,Track,Sector:integer);
Var Error :Byte;
Const
SelDsk=8;
GetDPB=31;
SetTrk=9;
SetSec=10;
SecTran=15;
Write=13;
Set_DMA=26;
Begin
BDos(Set_DMA,Addr(DMA));
Bios(SelDsk,Drive);
Bios(SetTrk,Track);
If SkewTrans then Sector:=BiosHL(SecTran,Sector);
Bios(SetSec,Sector);
{Write('***',Track,' ',Sector,' ',Offset,'***');}
Error:=Bios(Write);
If Error<>0 then begin write('I/O error = ',Error);Halt end;
end;
Begin
GotoXY(1,23);
DirIx:=DirIndex[Index];
OName:=Directory[DirIx].Dname;
Write('Do you want to delete ',Oname,' (Y/N) ? ');
Repeat
Read(Kbd,Ch);
Ch:=Upcase(Ch);
until Ch in ['Y','N'];
WriteLn(Ch);
If Ch='Y' then
begin
GoToXY(1,23);DelLine;
Repeat
with Directory[DirIx] do
begin
OName:=Dname;
GetRecord(DriveSelected,Dtrack,Dsector);
DMA[Doffset]:=$E5;
writesector(DriveSelected,Dtrack,Dsector)
end;
DirIx:=DirIx+1
until OName<>Directory[DirIx].DName;
WorkSpaceDirEnd:=WorkSpaceDirEnd-1;
For x:=Index to WorkSpaceDirEND do DirIndex[x]:=DirIndex[X+1];
If Index<WorkSpaceDirStart then
begin
WorkSpaceDirStart:=WorkSpaceDirStart-1;
If Index=WorkSpaceDirStart then Index:=WorkSpaceDirStart-1
end;
If Index>WorkSpaceDirEnd then Index:=WorkSpaceDirEnd;
end
end;
Procedure GetNextFileName( DirSize:integer;
BigDrv :Boolean;
Var RecNo,Track,Sector,Offset,ExtNo:Integer;
Var UserNo:byte;
UserMax,UserMin:Byte;
Var DirBlocks:BlockData; {array 0 to 15 int}
Var EndDir:Boolean;
Var Name:FileName); {str[12]}
begin
Repeat
Offset:=Offset+32;
if offSet>127 then begin
Offset:=0;
RecNo:=RecNo+1
end;
EndDir:= RecNo>DirSize;
If Not(EndDir) then begin
LocateRecord(DirBlocks,RecNo,Track,Sector,BigDrv);
GetRecord(DriveSelected,Track,Sector); {DriveSelected a global integer}
Loop:=0;
Repeat
Loop:=Loop+1
until (DMA[Offset+Loop]<>$E5) or (loop>16);
If Loop>16 then EndDir:=TRUE
end
Until EndDir or ((DMA[OffSet]<=UserMax) and (DMA[Offset]>=UserMin) {and
((DMA[Offset+$C] shr 1)=0)} ); {First Entry TEMP**}
If Not(EndDir) then begin
UserNo:=DMA[Offset];
Name:=' ';
For Loop :=1 to 8 do Name[Loop]:=Char(DMA[OffSet+Loop] AND $7F);
Name[9]:='.';
For Loop :=9 to 11 do Name[Loop+1]:=Char(DMA[OffSet+Loop] AND $7F);
ExtNo:=DMA[Offset+$0C]
end;
end;
Var
DirBlocks,MainDirBlks:BlockData; {array 0 to 15 int}
EndDirWSP,EndDirFLS:Boolean;
Name:FileName;
EndOfDirectory,DirSize,EndWSPDirPtr:integer; {Pointer to Directory}
Ch :Char;
OName:FileName;
Const
MainDirBlksL:BlockData=(0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0);
MainDirBlksS:BlockData=(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
Procedure GetWSPFiles;
begin
DirCounter:=EndWSPDirPtr+1;
RecNoF:=0;OffSetF:=-32;
Repeat
GetNextFileName( 59,(DSM>$FF),RecNoF,TrackF,SectorF,OffsetF,ExtNoF,
UserNF,
$F,$0, {UserMax,UserMin}
DirBlocks,
EndDirFLS,
Name);
If not(EndDirFLS) then begin
with Directory[DirCounter] do begin
DName:=Name;
DTrack:=TrackF;
DSector:=SectorF;
DOffset:=OffsetF;
DExtNo :=ExtNoF;
DUser :=UserNF
end;
DirCounter:=DirCounter+1;
end
until EndDirFLS or (DirCounter>MaxDirSize);
EndOfDirectory:=DirCounter-1;
end;
Procedure GetWSpaces;
begin
DirCounter:=0;
DirSize:=DRM shr 2;
RecNo:=0;Offset:=-32;
If DSM>$FF then MainDirBlks:=MainDirBlksL else MainDirBlks:=MainDirBlksS;
repeat
GetNextFileName(DirSize,(DSM>$FF),RecNo,Track,Sector,Offset,ExtNo,UserNF,
$20,$20, {UserMax,UserMin}
MainDirBlks,
EndDirWSP,
Name);
If not(EndDirWSP) then begin
with Directory[DirCounter] do begin
DName:=Name;
DTrack:=Track;
DSector:=Sector;
DOffset:=Offset;
DExtNo :=ExtNo;
DUser :=UserNF;
end;
DirCounter:=DirCounter+1;
end
until EndDirWSP or (DirCounter>(MaxDirSize-10));
EndWSPDirPtr:=DirCounter-1;
end;
Procedure ShellSort(Start,Enddata:integer);
Var
ListMax,Indx,Jndx,Inc:Integer;
Temp:DirName;
Swap:Boolean;
Function DoSwap(Pos1,Pos2:DirName):Boolean;
begin
If Pos1.DUser>Pos2.DUser
Then DoSwap:=True
else if (Pos1.DUser=Pos2.DUser) and (Pos1.Dname>Pos2.Dname)
then DoSwap:=True
else If (Pos1.DUser=Pos2.DUser) and (Pos1.Dname=Pos2.Dname) and (Pos1.DExtNo>Pos2.DExtNo)
then DoSwap:=True
else DoSwap:=False
end;
Function Index(Indx:integer):Integer;
Begin
Index:=Indx+Start-1
end;
Begin
ListMax:=EndData-Start+1;
Inc:=1;
Repeat
Inc := 3*Inc+1
until Inc>ListMax;
Repeat
Inc := Inc div 3;
For Indx := Inc+1 to ListMax do begin
Temp := Directory[Index(Indx)];
Jndx := Indx;
Swap:= DoSwap(Directory[Index(Jndx-Inc)],Temp);
while swap do begin
Directory[Index(Jndx)] := Directory[Index(Jndx-Inc)];
Jndx := Jndx-Inc;
If Jndx>Inc then Swap:= DoSwap(Directory[Index(Jndx-Inc)],Temp)
else Swap:=False
end;
Directory[Index(Jndx)] := Temp
end
until Inc = 1;
end;
Procedure FillIndex(StartInx,StartDir,EndDir:Integer; Var IdxCounter:integer);
Var
Oname :FileName;
OUser :byte;
Begin
Oname:='';
IdxCounter:=StartInx;
For DirCounter:=StartDir to EndDir do
If (Oname<>Directory[DirCounter].Dname) or (OUser<>Directory[DirCounter].DUser) then begin
Oname:= Directory[DirCounter].Dname;
OUser:=Directory[DirCounter].DUser;
DirIndex[IdxCounter]:=DirCounter;
IdxCounter:=IdxCounter+1
end
end;
Procedure Select( Var ScreenStart:integer; IndexStart,IndexEnd:integer; Var Index,Response:integer);
Var OIndex:integer;
Const
LineStart=4;
Cmd=22;
PageSize=85;
Function ScrX(Index:integer):integer;
Var Scr:integer;
begin
Scr:=(Index-ScreenStart) mod 5;
ScrX:= Scr*16+1; {80 div 5}
end;
Function ScrY(Index:integer):integer;
begin
ScrY:=((Index-ScreenStart) div 5) +lineStart
end;
Procedure HighL(index:integer);
Begin
GotoXY(ScrX(index),ScrY(index));
LowVideo;
Write(Directory[DirIndex[Index]].Dname);
NormVideo
end;
Procedure LowL(index:integer);
Begin
GotoXY(ScrX(index),ScrY(index));
NormVideo;
Write(Directory[DirIndex[Index]].Dname)
end;
Procedure PutOnScreenIndex;
begin
If Index>ScreenStart+PageSize-1 then
begin
GotoXY(1,LineStart);
DelLine;
ScreenStart:=ScreenStart+5;
Loop:=ScreenStart+PageSize-5;
Repeat
GotoXY(ScrX(Loop),ScrY(loop));
with Directory[DirIndex[Loop]] do write(DName,' ');
Loop:=Loop+1
until (Loop>IndexEnd) or (loop>ScreenStart+PageSize-1);
WriteLn;
InsLine;
end;
If Index<ScreenStart then
begin
GotoXY(1,LineStart);
InsLine;
ScreenStart:=ScreenStart-5;
For Loop:=ScreenStart to ScreenStart+4 do
begin
GotoXY(ScrX(Loop),ScrY(loop));
with Directory[DirIndex[Loop]] do write(DName,' ')
end;
GotoXY(1,ScrY(ScreenStart+PageSize-1)+1);
DelLine;
end;
If (Index>IndexEnd) or (Index<IndexStart) then
begin
Writeln(**** error out of page bounds ****);
Halt
end;
end;
begin
GotoXY(1,LineStart);
Loop:=ScreenStart;
While (Loop<=IndexEnd) and (loop<=ScreenStart+PageSize-1) do
begin
with Directory[DirIndex[Loop]] do write(DName,' ');
Loop:=Loop+1
end;
WriteLn;
If IndexEnd<IndexStart then begin
WriteLn('No files');
Delay(1000);
Ch:=#27
end
else
begin
GotoXY(1,Cmd);
WriteLn('Commands => RETURN , DEL, ^E, ^X, ^S, ^D, (arrows), P, ESC ');
Repeat
PutOnScreenIndex;
Oindex:=Index;
GotoXY(1,Cmd+1);
Write('UserArea= ',Directory[DirIndex[Index]].DUser);
HighL(Index);
Read(Kbd,Ch);
Case ch of
'P','p':ScreenDump;
#5 : If Index-5>=IndexStart then Index:=Index-5;
#24 : If Index+5<=IndexEnd then Index:=Index+5;
#19 : If Index-1>=IndexStart then Index:=Index-1;
#4 : If Index+1<=IndexEnd then Index:=Index+1
end;
If OIndex<>Index then LowL(OIndex);
until Ch in [#13,#127,#27];
end;
Response:=Ord(Ch);
end;