home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
turbopas
/
sfmsrc.arc
/
SFMVARS.INC
< prev
Wrap
Text File
|
1987-11-15
|
16KB
|
427 lines
{ Super File Manager
SFMVARS.INC
by David Steiner
2035 J Apt. 6
Lincoln, NE
This include file is for declaring the majority of the program's
global variables, constants and types. Also included are a
couple of routines that need to come before all of the others,
and don't fit in the second include file.
}
CONST
version = 'v1.01';
MaxFiles = 512;
MinStack = 512; { Set aside to insure against heap/stack collision }
KiloByte = 1024.0; { Formal definition, maybe you'd rather it was 1000 }
WindowLen = 17;
DelChar = #229; { DOS character to signal deleted file }
NulChar = #000;
PtrChar = #175; { Pointer character in directory windows }
horzlin = #205; { These characters make up the window }
vertlin = #179; { borders. }
int1 = #209;
int2 = #216;
int3 = #207;
corn1 = #213;
corn2 = #184;
corn3 = #212;
corn4 = #190;
tleft = #198;
trght = #181;
lbrk = #219 {#181};
rbrk = #219 {#198};
Rbit = $01; { These are masks for the bits in the file's }
Hbit = $02; { attribute byte: read-only, hidden, sys, }
Sbit = $04; { volume label, directory and archive. }
Vbit = $08;
Dbit = $10;
Abit = $20;
MakeNoise : boolean = true; { Typed constant so Int10 can access flag }
cursornum : integer = $0607; { Default CGA cursor }
TYPE
{
This 'variant record' allows accessing full and half registers
without two separate variable declarations.
}
Reg_T = record case boolean of
true : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : integer);
false : (AL,AH,BL,BH,CL,CH,DL,DH : byte);
end;
{
The archaic DOS File Control Block.
}
FCB_T = record
Drive : byte;
Name : array[1..8] of char;
Ext : array[1..3] of char;
BlockNum,
RecSize : integer;
Size : array[0..1] of integer;
Date : integer;
Reserved2 : array[0..9] of byte;
SeqNum : byte;
RandomNum : array[0..3] of byte;
end;
{
DOS Extended File Control Block.
}
ExtFCB_T = record
ExtFlag : byte;
Reserved : array[0..4] of byte;
FileAttr,
Drive : byte;
Name : array[1..8] of char;
Ext : array[1..3] of char;
BlockNum,
RecSize : integer;
Size : array[0..1] of integer;
Date : integer;
Reserved2 : array[0..9] of byte;
SeqNum : byte;
RandomNum : array[0..3] of byte;
end;
{
The entries in a directory follow the specifications of the
following record. By using this record we can read from disk
into a memory area reserved for an array of Entry_T.
}
Entry_T = record
Name : array[1..8] of char;
Ext : array[1..3] of char;
Attr : byte;
Reserved : array[0..9] of byte;
Time,
Date,
Cluster : integer;
Size : array[0..1] of integer;
end;
{
This record outlines the table at an address returned by DOS function
request $32. This is a non-documented function, but is supported
from DOS v2.0 through v3.2 and seems very reliable.
}
DskTbl_T= record
DRIVE1,
DRIVE2 : byte;
SECTORSIZE : integer;
CLUSTERSIZE,
NHEADS : byte;
BOOTSIZE : integer;
NFATS : byte;
ROOTENTRIES,
DATASECTOR,
MAXCLUSTER : integer;
FATSIZE : byte;
ROOTSECTOR : integer;
DEVDRIVER : array[0..1] of integer;
FATATTR : byte;
end;
{
String types for use in procedure declarations.
}
str4 = string[ 4];
str6 = string[ 6];
str10 = string[10];
str11 = string[11];
str80 = string[80];
{
Types for passing addresses between procedures.
}
Addr_T = ^integer;
DskTblptr = ^DskTbl_T;
EntryArr_T = array[1..MaxFiles] of Entry_T;
MarkedArr_T = array[1..MaxFiles] of boolean;
VAR
SavedPath : str80;
{
Coordinates for specifying the current window
}
X1, X2, Y1, Y2 : integer;
{
Colors to be used by program, they are set in procedure Colors.
}
PATTR, NATTR, HATTR, HATTR2, BNATTR, BHATTR : integer;
MATTR : array[1..2] of integer;
Color,
ShowAll,
FATsaved,
FuncKey : boolean;
FATptr,
HeapStart : Addr_T;
DiskTable : array[1..2] of ^DskTbl_T;
Path : array[1..2] of str80;
HelpScreen,
Loaded,
Saved,
NoSave : array[1..2] of boolean;
Drive : array[1..2] of integer;
TopEntry,
CurLin,
CurEntry,
MaxEntry : array[1..2] of integer;
DiskFree,
DirSize,
FATbytes : array[1..2] of real;
Entry : array[1..2] of EntryArr_T;
Marked : array[1..2] of MarkedArr_T;
{
Store the directory mask as entered and as converted by DOS.
}
Mask,
ConvMask : array[1..2] of string[12];
procedure Noise( freq, dur : integer );
begin
if MakeNoise then
begin
Sound( freq );
Delay( dur );
end;
NoSound;
end;
{
The following section takes over BIOS interrupt $10, function
request $0E (Write Character as TeleType). This is done
in order to prevent DOS from destroying our screen when it
prints the message for changing disks on a one floppy
system. The interrupt handler basically just forces the
function request to conform to the current window settings.
After Int10 is turned on calls to interrupt 10 will be directed
to these routines rather than the BIOS.
Don't forget to make sure the original interrupt handler is restored
before the program exits. See procedures AbortProgram and
AbortOnError in the sfmSCRN.inc file.
}
const
DataSeg : integer = 0;
Int10char : char = #0; { Temporary storage for character to print }
OldInt10 : array[0..1] of integer = (0,0);
procedure Int10;
{
The beep code below is not my own, I converted it from a sample
program from 'The Complete Guide to IBM PC AT Assembly Language'
by Harley Hahn. If you are looking for a good Assembly reference
I've been pretty happy with this one (I don't have an AT either).
The beep emulates the above Noise procedure by putting the
frequency in CX and the duration (in milleseconds) in BX.
OUTLINE OF INT10:
Check if interrupt call was for 'Write Character as Teletype'
if not
(
call the normal BIOS
exit
)
otherwise
(
if the character to be printed is
a Linefeed : make a short beep
a Carriage Return : print a Space instead
anything else : print the character using Turbo's Write
exit
)
}
begin
{ ; These lines are not entered by us, they
PUSH BP ; are placed at the start of every subroutine
MOV BP, SP ; by Turbo Pascal. You must therefore account
PUSH SP ; for them before executing an IRET instruction.
}
Inline(
$80/$FC/$0E { CMP AH, $0E }
/$74/$0A { JE gotit }
{ ; }
/$9C { PUSHF }
/$2E/$FF/$1E/>OLDINT10 {CS: CALL FAR [>OldInt10] ; Call BIOS }
{ ; }
/$89/$EC { MOV SP, BP ; Code to exit }
/$5D { POP BP }
/$CF { IRET }
{ ; }
{ ; Only enter here if BIOS function }
{ ; request was $0E, otherwise we }
{ ; let the BIOS procede normally }
{ ; with the above PUSHF and CALL. }
{ ; }
/$50 {gotit: PUSH AX ; Save all registers }
/$53 { PUSH BX ; so we can use Turbo }
/$51 { PUSH CX ; code below. }
/$52 { PUSH DX }
/$57 { PUSH DI }
/$56 { PUSH SI }
/$06 { PUSH ES }
/$1E { PUSH DS }
{ ; }
/$2E/$A2/>INT10CHAR {CS: MOV [>Int10char], AL ; Get char }
{ ; }
{ ; Now we replace linefeed characters }
{ ; with a short beep if the }
{ ; MakeNoise flag is set. }
{ ; }
/$3C/$0A { CMP AL, 10 }
/$75/$36 { JNE nobeep }
/$2E/$A0/>MAKENOISE {CS: MOV AL, [>MakeNoise] }
/$3C/$00 { CMP AL, $00 }
/$74/$2E { JE nobeep }
{ ; }
/$B9/$E8/$03 { MOV CX, 1000 ; Frequency }
/$BB/$64/$00 { MOV BX, 100 ; Duration (millsecs)}
{ ; }
/$B0/$B6 { MOV AL, $B6 ; Prepare timer }
/$E6/$43 { OUT $43, AL }
{ ; }
/$BA/$12/$00 { MOV DX, $0012 ; Calculate freq. }
/$B8/$DC/$34 { MOV AX, $34DC }
/$F7/$F1 { DIV CX }
{ ; }
/$E6/$42 { OUT $42, AL ; Send freq to timer }
/$EB/$00 { JMP SHORT j1 }
/$88/$E0 {j1: MOV AL, AH }
/$E6/$42 { OUT $42, AL }
{ ; }
/$E4/$61 { IN AL, $61 ; Save current timer }
/$88/$C4 { MOV AH, AL ; setting }
{ ; }
/$0C/$03 { OR AL, $03 ; Turn on speaker }
/$E6/$61 { OUT $61, AL }
{ ; }
/$B9/$D4/$01 {l1: MOV CX, 468 ; Delay }
/$E2/$FE {l2: LOOP l2 }
/$4B { DEC BX }
/$75/$F8 { JNZ l1 }
{ ; }
/$88/$E0 { MOV AL, AH ; Turn off speaker }
/$E6/$61 { OUT $61, AL }
{nobeep: }
{ ; }
{ ; The following two lines set the }
{ ; data segment to allow access to }
{ ; variables in the common area of }
{ ; the program. }
{ ; }
/$2E/$A1/>DATASEG {CS: MOV AX, [>DataSeg] }
/$8E/$D8 { MOV DS, AX }
);
case Int10char of { Not much here, but it does the job }
#10 : { Already beeped };
#13 : write( ' ' );
else write( Int10char );
end;
InLine(
$1F { POP DS ; Restore all registers }
/$07 { POP ES }
/$5E { POP SI }
/$5F { POP DI }
/$5A { POP DX }
/$59 { POP CX }
/$5B { POP BX }
/$58 { POP AX }
{ ; }
/$89/$EC { MOV SP, BP ; Code to exit }
/$5D { POP BP }
/$CF { IRET }
);
end;
procedure Int10ON;
{
Direct interrupt 10 calls through our procedure, Int10.
}
var
Regs : reg_T;
begin
DataSeg := Dseg;
with Regs do
begin
AH := $35; { DOS function $35 - Get Interrupt Vector Address }
AL := $10; { getting $10 - BIOS Video interrupt }
MsDos( Regs );
OldInt10[1] := ES;
OldInt10[0] := BX;
AH := $25; { DOS function $25 - Set Interrupt Vector Address }
AL := $10; { setting $10 - BIOS Video interrupt }
DS := Cseg;
DX := ofs( Int10 );
MsDos( Regs );
end;
end;
procedure Int10OFF;
{
Restores the original address for interrupt 10.
}
var
Regs : reg_T;
begin
with Regs do
begin
AH := $25; { DOS function $25 - Set Interrupt Vector Address }
AL := $10; { setting $10 - BIOS Video interrupt }
DS := OldInt10[1];
DX := OldInt10[0];
MsDos( Regs );
end;
end;
function HexStr( num : integer ) : str4;
{
Convert integer to its four character hex representation
(padded with zeros).
}
var
tstr : string[4];
i, j : integer;
begin
tstr[0] := #4;
for i := 0 to 3 do
begin
j := ord('0') + ( (num SHR (4*i)) AND $0F );
if j < 58 then
tstr[4-i] := chr( j )
else
tstr[4-i] := chr( j + 7 );
end;
HexStr := tstr;
end;