home *** CD-ROM | disk | FTP | other *** search
- {$A+,B-,D+,E+,F+,I+,L+,N-,O+,R-,S+,V-}
- {$M 16384,0,655360}
-
- Unit TPDB;
-
- {This version is Version 3.11 September, 1989}
-
-
- (***********************************)
- (* Object -Oriented *)
- (* Turbo Pascal 5.5 Unit *)
- (* for Accessing dBASE III *)
- (* files. *)
- (* Copyright 1989 *)
- (* Brian Corll *)
- (* All Rights Reserved *)
- (* dBASE is a registered *)
- (* trademark of Ashton-Tate, Inc. *)
- (* Version 3.11 September 1989 *)
- (***********************************)
- (* Portions Copyright 1984,1989 *)
- (* Borland International Corp. *)
- (***********************************)
-
-
- INTERFACE
-
- Uses CRT,Dos,TPDBINDX,TPDBDate,TPDBScrn,TPDBStr;
-
-
- (******************************)
- (* Global VARiables *)
- (******************************)
-
- CONST
-
- (**************************************************************************)
- MaxInds = 10; {Maximum number of indexes per file. Change this as needed.}
- (**************************************************************************)
-
- AutoWrap : Boolean = FALSE;
- CursorDown = ^X;
- CursorEND = ^F;
- CursorHome = ^A;
- CursorLeft = ^S;
- CursorRight = ^D;
- CursorUp = ^E;
- DelKey = ^G;
- Duplicates = 1;
- Escape = ^[;
-
- ExtKey : Boolean = FALSE;
- Filler : Char = #32;
- MaxLong = 2147483647;
- MaxReal = 3.4E37;
- MinLong = -2147483647;
- MinReal = 1.5E-45;
- NoDuplicates = 0;
- PageDown = ^C;
- PageUp = ^R;
- Return = ^M;
- TabKey = #9;
- UpperCase : Boolean = FALSE;
-
- {Date format constants}
- {Used by SetDateFormat procedure}
- French = 1; {dd/mm/yy}
- German = 2; {dd.mm.yy}
- Italian = 3; {dd-mm-yy}
- American = 4; {mm/dd/yy}
- British = 5; {dd/mm/yy}
- Ansi = 99;{yy.mm.dd}
-
-
-
- Type
- Str2 = String[2];
- Str4 = String[4];
- Str5 = String[5];
- Str6 = String[6];
- Str8 = String[8];
- Str10 = String[10];
- Str15 = String[15];
- Str20 = String[20];
- Str30 = String[30];
- Str60 = String[60];
- Str80 = String[80];
- Str132 = String[132];
- Str254 = String[254];
- CharSet = Set of Char;
- ByteSet = Set of Byte;
-
- FileName = String[66];
- DBRecPtr = ^DBType;
- DBType = Array[1..4000] of Char;
-
- DBHeader = RECORD
- DBType : Byte;
- Year : Byte;
- Month : Byte;
- Day : Byte;
- RecCount : LongInt;
- Location : Integer;
- RecordLen : Integer;
- Reserved : Array[1..20] of Byte;
- Terminator : Char;
- END;
-
- DBField = Record
- FieldName : Array[1..11] of Char;
- FieldType : Byte;
- FieldAddress : LongInt;
- FieldLen : Byte;
- FieldDec : Byte;
- Reserved : Array[1..14] of Char;
- END;
-
- HeadPtr = ^DBHeader;
- PosPtr = ^DBEditArray;
- FieldPtr = ^FieldArray;
- DBEditArray = Array[1..2,1..128] of Integer;
- FieldArray = Array[1..128] of DBField;
- DBIndex = RECORD
- Ndx : IndexFile;
- NdxID : BYTE;
- NdxName : FileName;
- Open : BOOLEAN;
- END;
-
- NdxArray = ARRAY[1..MaxInds] OF DBIndex;
- NdxPtr = ^NdxArray;
-
- (*****************************************************************************)
- (* Database File Object Declaration *)
- (*****************************************************************************)
-
- DataObject = ^DBF;
-
- DBF = OBJECT
- DBFName : FileName;
- DBFile : File;
- Header : HeadPtr;
- Fields : FieldPtr;
- Positions : ^DBEditArray;
- DBFOpen : BOOLEAN;
- IndsOpen : BOOLEAN;
- Indexes : NdxPtr;
- DBRecord : ^DBType;
- DBRecNum : LONGINT;
- TotalRecs : LONGINT;
- NumFields : BYTE;
- MAlloc : BOOLEAN;
- Start,Stop : INTEGER;
- FUNCTION Add(Field1,Field2 : Byte):string;VIRTUAL;
- PROCEDURE AddDBKey(NdxID : BYTE;KeyStr : DBKey);VIRTUAL;
- PROCEDURE AddDBRec;VIRTUAL;
- FUNCTION Allocated : BOOLEAN;
- PROCEDURE AppendBlank;VIRTUAL;
- PROCEDURE BailOut;VIRTUAL;
- FUNCTION BinSearch(FieldNo : BYTE;
- Position : Integer;SearchKey : DBKey) : LONGINT;
- FUNCTION BOF : Boolean;VIRTUAL;
- PROCEDURE CloseDBIndex(NdxID : BYTE);VIRTUAL;
- PROCEDURE DBReset;VIRTUAL;
- PROCEDURE DelDBKey(KeyStr : DBKey;NdxID : BYTE);VIRTUAL;
- FUNCTION Deleted : Boolean;VIRTUAL;
- PROCEDURE Display;VIRTUAL;
- FUNCTION Divide(Field1,Field2 : Byte):string;VIRTUAL;
- DESTRUCTOR Done;VIRTUAL;
- FUNCTION DBEOF : BOOLEAN;VIRTUAL;
- FUNCTION Field(FNo : Byte) : string;VIRTUAL;
- PROCEDURE FillRecs(NumRecs : LongInt);VIRTUAL;
- PROCEDURE Find(NdxID : BYTE;SearchStr : string);VIRTUAL;
- PROCEDURE FlushDB;VIRTUAL;
- PROCEDURE Get(FNo,X,Y : Byte);VIRTUAL;
- PROCEDURE GetDBRec(RecordNumber : LongInt);VIRTUAL;
- FUNCTION GetField(RecordNo : LongInt;FNo : Byte) : String;VIRTUAL;
- PROCEDURE GoBottom;VIRTUAL;
- PROCEDURE GoTop;VIRTUAL;
- FUNCTION IIF(BoolVAR : Boolean;IfTRUE,IfFALSE : String) : String;VIRTUAL;
- PROCEDURE IndexOn(NdxID : BYTE;NdxName : FileName;
- NdxField : BYTE;DupFlag : BYTE);
- CONSTRUCTOR Init(DBName : FileName);
- FUNCTION Locate(FieldNo : BYTE;SearchStr : String) : BOOLEAN;
- PROCEDURE LookUp(SearchStr : string;NdxID : BYTE);VIRTUAL;
- PROCEDURE MakeDBIndex(NdxID : BYTE;DBIndexName : FileName;KeyLen,Status : Integer);VIRTUAL;
- PROCEDURE Mark;VIRTUAL;
- FUNCTION Mul(Field1,Field2 : Byte):string;VIRTUAL;
- PROCEDURE NextDBKey(NdxID : BYTE;KeyStr : DBKey);VIRTUAL;
- PROCEDURE NewDBRec;VIRTUAL;
- PROCEDURE NextRec;VIRTUAL;
- PROCEDURE OpenDBIndex(NdxID : BYTE;DBIndexName : FileName;KeyLen,Status : Integer);VIRTUAL;
- PROCEDURE Pack;VIRTUAL;
- PROCEDURE PrevDBKey(NdxID : BYTE;KeyStr : DBKey);VIRTUAL;
- PROCEDURE PrevRec;VIRTUAL;
- PROCEDURE PutDBRec(RecordNumber : LongInt);VIRTUAL;
- PROCEDURE ReadDBHeader;VIRTUAL;
- PROCEDURE Recall;VIRTUAL;
- FUNCTION RecCount : LONGINT;VIRTUAL;
- FUNCTION RecNo : LONGINT;VIRTUAL;
- PROCEDURE Repl(FNo : Byte;InStr : string);VIRTUAL;
- PROCEDURE ReplEach(FNo : Byte;InStr : String);VIRTUAL;
- PROCEDURE Save;VIRTUAL;
- PROCEDURE Say(FNo,Row,Col : Byte);VIRTUAL;
- PROCEDURE ShowStatus;VIRTUAL;
- PROCEDURE Skip;VIRTUAL;
- FUNCTION Sub(Field1,Field2 : Byte) : string;VIRTUAL;
- FUNCTION Sum(FNo : Byte) : Real;VIRTUAL;
- PROCEDURE WriteDBHeader;VIRTUAL;
- PROCEDURE Zap;VIRTUAL;
- END;
-
- (****************************************************************************)
- (* END Object Declaration *)
- (****************************************************************************)
-
- Const
-
- Up : CharSet = [CursorUp];
- Down : CharSet = [CursorDown,Return];
- Next : CharSet = [Escape];
-
- VAR
- FilesOpen : BYTE;
- UCKey : BOOLEAN;
- ErrCode : INTEGER;
- Found : BOOLEAN;
- Ch,BC : CHAR;
- Normal,Reverse : BYTE;
- Decimals : Byte;
- TempFile : File;
- K : Byte;
- NumLen : Byte;
- Y,M,D,DW : WORD;
- FromPack : BOOLEAN;
- DateFormat : BYTE;
-
- (**********************************)
- (* PROCEDUREs and FUNCTIONs *)
- (**********************************)
-
- PROCEDURE Beep;
- {Sound a couple of tones.}
-
- FUNCTION BoolToStr(Param : Byte;IfTRUE,IfFALSE : Char): String;
-
-
- PROCEDURE CheckScreen(VAR CurrPos:Byte;BC:Char;Up,Down:CharSet;Low,High:Byte);
- {Used in full screen editing.}
-
- PROCEDURE CopyFile(Source,Dest : FileName);
-
- PROCEDURE FlashFill(Row,Col,Rows,Cols,Attr : Byte;Ch : Char);
- {Fill a region of the screen with a specified color and character.}
-
- FUNCTION GetBoolean(VAR Param:Byte;IfTRUE,IfFALSE:Char;X,Y:Byte):Char;
-
- FUNCTION GetByte(VAR Param:Byte;LowLim,UpLim,Len,X,Y:Byte):Char;
-
- FUNCTION GetInteger(VAR Param:Integer;LowLim,UpLim:Integer;Len,X,Y:Byte):Char;
- {Input an integer.}
-
- FUNCTION GetLongInt(VAR Param:LongInt;LowLim,UpLim:LongInt;Len,X,Y:Byte):Char;
- {Input a long integer.}
-
- FUNCTION GetReal(VAR Param : Real; LowLim, UpLim : Real; Len, X, Y : Word) : Char;
- {Input a real number.}
-
- FUNCTION GetString(VAR Param : String; Len, X, Y : Byte) : Char;
- {Input a string.}
-
- FUNCTION Input(VAR S:String;Term:CharSet;L,X,Y:Byte;VAR BC:Char):String;
-
- FUNCTION IntToStr(Number : LongInt): String;
-
- FUNCTION Max(N1,N2 : Integer) : Integer;
-
- FUNCTION Min(N1,N2 : Integer) : Integer;
-
- PROCEDURE Prompt(Row,Col : Byte;PromptStr : Str80);
- {Display a prompt at a specified row and column.}
-
- FUNCTION ReadChar : Char;
-
- PROCEDURE ReadKB (VAR ExtKey: Boolean; VAR Ch: Char);
-
- FUNCTION RealToStr(Number : Real): String;
-
- PROCEDURE SetDateFormat(Format : BYTE);
-
- PROCEDURE SetDBColor(FG,BG : Byte);
- {Set initial foreground and background colors.}
-
- PROCEDURE Wait;
- {Wait for a key press and display a message.}
-
-
- IMPLEMENTATION
-
- FUNCTION DBF.Add(Field1,Field2 : Byte):string;
- (* Adds two fields and returns the string of the sum. *)
- VAR
- T1,T2,T3 : String;
- A1,A2,A3 : Real;
- ErrCode : Integer;
- BEGIN
- T1 := RTrim(Field(Field1));
- T2 := RTrim(Field(Field2));
- Val(T1,A1,ErrCode);
- Val(T2,A2,ErrCode);
- A3 := A1+A2;
- Str(A3 : Max(Fields^[Field1].FieldLen,Fields^[Field2].FieldLen) :
- Max(Fields^[Field1].FieldDec,Fields^[Field2].FieldDec),T3);
- Add := LTrim(T3);
- END;
-
- PROCEDURE DBF.AddDBKey(NdxID : BYTE;KeyStr : DBKey);
- BEGIN
- If UCKey then KeyStr := Upper(KeyStr);
- AddKey(Indexes^[NdxID].Ndx,DBRecNum,KeyStr);
- END;
-
- PROCEDURE DBF.AddDBRec; {Add new record, no index open.}
- VAR
- RecordNumber : LongInt;
- BEGIN
- TotalRecs := TotalRecs + 1;
- RecordNumber := TotalRecs;
- DBRecNum := RecordNumber;
- RecordNumber := (RecordNumber - 1) * Header^.RecordLen + Header^.Location;
- Seek(DBFile,RecordNumber);
- BlockWrite(DBFile,DBRecord^,Header^.RecordLen,ErrCode);
- Dispose(DBRecord);
- END;
-
- FUNCTION DBF.Allocated : BOOLEAN;
- BEGIN
- Allocated := (DBRecord <> NIL);
- END;
-
- PROCEDURE DBF.AppendBlank;
- VAR
- RecordNumber : LONGINT;
- BEGIN
- NewDBRec;
- TotalRecs := TotalRecs + 1;
- RecordNumber := TotalRecs;
- DBRecNum := RecordNumber;
- RecordNumber := (RecordNumber - 1) * Header^.RecordLen + Header^.Location;
- Seek(DBFile,RecordNumber);
- BlockWrite(DBFile,DBRecord^,Header^.RecordLen,ErrCode);
- END;
-
-
- PROCEDURE DBF.BailOut;
- VAR
- Message : String[80];
- Number : string;
- ID : BYTE;
- BEGIN
- GotOne := TRUE;
- FOR ID := 1 TO MaxInds DO
- IF Indexes^[ID].Open THEN
- CloseDBIndex(ID);
- IndsOpen := FALSE;
- SetDBColor(White,Blue);
- ClrScr;
- Case TPDBErr of
- 1 : Message := 'Invalid DOS FUNCTION code !';
- 2 : Message := 'File not found ! '+
- IIF(Length(RTrim(LTrim(TErrorName)))<>0,' -- > '+Upper(TErrorName),'');
- 3 : Message := 'Path not found !';
- 4 : Message := 'Too many open files !';
- 5 : Message := 'File access denied !';
- 6 : Message := 'Invalid file handle !';
- 8 : Message := 'Not enough memory !';
- 9 : Message := 'Too many open indexes !';
- 12 : Message := 'Invalid file access code !';
- 15 : Message := 'Invalid drive number !';
- 16 : Message := 'Cannot remove current directory !';
- 17 : Message := 'Cannot rename across drives !';
- 100 : Message := 'Disk read error !';
- 101 : Message := 'Disk write error !';
- 102 : Message := 'File not assigned !';
- 103 : Message := 'File not open !';
- 104 : Message := 'File not open for input !';
- 105 : Message := 'File not open for output !';
- 106 : Message := 'Invalid numeric format !';
- 200 : Message := 'Division by zero !';
- 201 : Message := 'Range check error !';
- 202 : Message := 'Stack overflow error !';
- 203 : Message := 'Heap overflow error !';
- 204 : Message := 'Invalid pointer operation !';
- 1000 : Message := 'Record size is greater than 4000 chars !';
- 1002 : Message := 'Specified Index Key Length is greater than 254 chars !';
- 1003 : Message := 'Invalid DBF File structure !';
- 1004 : Message := 'Index File created with different key size !';
- 1005 : Message := 'Not enough memory for index page stack !';
- END;
- Beep;Beep;
- FlashC(8,White+BlueBG,'TPDB Version 3.11');
- FlashC(10,Yellow+BlueBG,'ERROR !');
- FlashC(12,White+RedBG,Message);
- CursorOff;
- FlashC(14,LightRed+BlueBG,'Press any key to halt program....');
- FlashC(16,LightCyan+BlueBG,'Copyright 1989 Brian Corll');
- Repeat Until KeyPressed;
- TErrorName := '';
- TPDBErr := 0;
- SetDBColor(White,Black);
- ClrScr;
- Halt(1);
- END;
-
- PROCEDURE Beep;
- BEGIN
- Sound(1500); Delay(50);
- Sound(1000); Delay(50);
- NoSound;
- END;
-
- FUNCTION DBF.BinSearch(FieldNo : BYTE;Position : Integer;SearchKey : DBKey) : LONGINT;
- {Implements a binary search for sorted files of unique elements }
-
- VAR
- Width : Integer;
- J,Low,High,Result : LONGINT;
- BEGIN
- Width := Length(SearchKey);
- IF Width < 1 THEN EXIT;
- Low := 1;
- High := TotalRecs;
- WHILE High >= Low DO
- BEGIN
- J := (Low + High) DIV 2;
- GetDBRec(J);
- IF SearchKey < Copy(Field(FieldNo),Position,Width) THEN
- High := J-1
- ELSE
- IF SearchKey > Copy(Field(FieldNo),Position,Width) then
- Low := J + 1
- ELSE
- BEGIN
- BinSearch := J;
- EXIT
- END
- END;
- BinSearch := 0;
- END;
-
-
- FUNCTION DBF.BOF : Boolean;
- BEGIN
- If DBRecNum = 1 then
- BOF := TRUE
- else BOF := FALSE;
- END;
-
- FUNCTION BoolToStr(Param : Byte;IfTRUE,IfFALSE : Char): String;
- VAR
- Temp : String;
- BEGIN
- Case Param of
- 0: Temp := Filler;
- 1: Temp := IfTRUE;
- 2: Temp := IfFALSE;
- END;
- BoolToStr:=Temp;
- END;
-
-
-
- PROCEDURE CheckScreen(VAR CurrPos:Byte;BC:Char;Up,Down:CharSet;Low,High:Byte);
-
- BEGIN
- If (BC In Down) Then
- If CurrPos = High Then CurrPos := Low
- Else Inc(CurrPos)
- Else
- If (BC In Up) Then
- If CurrPos = Low Then CurrPos := High
- Else Dec(CurrPos)
- END;
-
-
- DESTRUCTOR DBF.Done;
- VAR
- EOFMarker : Byte;
- Z : BYTE;
- BEGIN
- WriteDBHeader;
- EOFMarker := $1A;
- Seek(DBFile,Header^.Location+(Header^.RecCount*Header^.RecordLen));
- BlockWrite(DBFile,EOFMarker,1);
- Close(DBFile);
- Dec(FilesOpen);
- If not MAlloc then
- BEGIN
- Dispose(Header);
- Dispose(Fields);
- Dispose(Positions);
- END;
- IF Allocated THEN
- BEGIN
- DISPOSE(DBRecord);
- END;
- DBFOpen := FALSE;
- FOR Z := 1 to MaxInds DO
- BEGIN
- IF Indexes^[Z].Open THEN
- BEGIN
- CloseDBIndex(Z);
- Indexes^[Z].Open := FALSE;
- END;
- END;
- IF FromPack THEN
- FromPack := FALSE
- ELSE
- Dispose(Indexes);
- END;
-
- PROCEDURE DBF.CloseDBIndex(NdxID : BYTE);
- BEGIN
- IF Indexes^[NdxID].Open THEN
- BEGIN
- CloseIndex(Indexes^[NdxID].Ndx);
- Indexes^[NdxID].Open := FALSE;
- END;
- DEC(FilesOpen);
- END;
-
- PROCEDURE CopyFile(Source,Dest : FileName);
- { Copies a .DBF file to another .DBF file }
- TYPE
- FileBuffer = ARRAY[1..65521] OF BYTE;
- VAR
- Buffer : ^BYTE;
- InFile,OutFile : File;
- ErrorCode,
- BlocksRead,
- BlocksWritten : WORD;
- Time : LONGINT;
- BufferSize : WORD;
- Begin
- BufferSize := SizeOf(FileBuffer);
- IF (BufferSize > MaxAvail) THEN BufferSize := MaxAvail;
- GetMem(Buffer,BufferSize);
- Assign(InFile,Source);
- Reset(InFile,1);
- ErrorCode := IOResult;
- GetFTime(InFile,Time);
- If ErrorCode = 0 then
- Begin
- Assign(OutFile,Dest);
- Rewrite(OutFile,1);
- ErrorCode := IOResult;
- If ErrorCode = 0 Then
- Begin
- Repeat
- BlockRead(InFile,Buffer^,BufferSize,BlocksRead);
- BlockWrite(OutFile,Buffer^,BlocksRead,BlocksWritten);
- If BlocksWritten < BlocksRead Then ErrorCode := 81;
- Until ((ErrorCode <> 0) OR (BlocksRead < BufferSize));
- SetFTime(OutFile,Time);
- Close(OutFile);
- If ErrorCode <> 0 Then Erase(OutFile);
- End;
- Close(InFile);
- End;
- FreeMem(Buffer,BufferSize);
- End; { CopyFile }
-
-
- PROCEDURE DBF.DBReset; {Reset dBASE file.}
- BEGIN
- {$I-} Reset(DBFile,1); {$I+}
- If TPDBErr=0 then TPDBErr := IOResult;
- If (TPDBErr<>0) and (not GotOne) then
- BEGIN
- TErrorName := DBFName;
- BailOut;
- END;
- END;
-
- PROCEDURE DBF.DelDBKey(KeyStr : DBKey;NdxID : BYTE);
- BEGIN
- If UCKey then KeyStr := Upper(KeyStr);
- DeleteKey(Indexes^[NdxID].Ndx,DBRecNum,KeyStr);
- END;
-
- FUNCTION DBF.Deleted : Boolean;
- BEGIN
- If DBRecord^[1] = Chr(Ord($2A)) then
- Deleted := TRUE
- else
- Deleted := FALSE;
- END;
-
- PROCEDURE DBF.Display;
- VAR
- FNo : Byte;
- K : Integer;
-
- BEGIN
- ClrScr;
- For FNo := 1 to NumFields do
- BEGIN
- For K := 1 to 11 do
- Write(Fields^[FNo].FieldName[K]);
- Write(': ');
- If Chr(Ord(Fields^[FNo].FieldType)) = 'D' then
- Write(FormDate(Field(FNo)))
- else Write(Field(FNo));
- Writeln;
- If FNo mod 23 = 0 then
- BEGIN
- Wait;
- ClrScr;
- END;
- END;
- END;
-
- FUNCTION DBF.Divide(Field1,Field2 : Byte):string;
- (* Divide field1 BY field 2 *)
- VAR
- T1,T2,T3 : String;
- D1,D2,D3 : Real;
- BEGIN
- T1 := RTrim(Field(Field1));
- T2 := RTrim(Field(Field2));
- Val(T1,D1,ErrCode);
- Val(T2,D2,ErrCode);
- D3 := D1/D2;
- Str(D3 : Max(Fields^[Field1].FieldLen,Fields^[Field2].FieldLen) :
- Max(Fields^[Field1].FieldDec,Fields^[Field2].FieldDec),T3);
- Divide := LTrim(T3);
- END;
-
- FUNCTION DBF.DBEOF : BOOLEAN;
- BEGIN
- If DBRecNum >= TotalRecs then
- DBEOF := TRUE
- else DBEOF := FALSE;
- END;
-
- FUNCTION DBF.Field(FNo : Byte) : string;
- VAR
- Temp : String;
- BEGIN
- Temp[0] := Chr(Ord(Fields^[FNo].FieldLen));
- Move(DBRecord^[Positions^[1,FNo]],Temp[1],Fields^[FNo].FieldLen);
- Temp := PadR(Temp,Fields^[FNo].FieldLen);
- Field := Temp;
- END;
-
- PROCEDURE DBF.FillRecs(NumRecs : LongInt);
- VAR
- J : LongInt;
- BEGIN
- If TotalRecs>0 then GoBottom;
- For J := 1 to NumRecs do
- BEGIN
- NewDBRec;
- AddDBRec;
- END;
- END;
-
- PROCEDURE DBF.Find(NdxID : BYTE;SearchStr : string);
- BEGIN
- FindKey(Indexes^[NdxID].Ndx,DBRecNum,SearchStr);
- If OK then
- BEGIN
- GetDBRec(DBRecNum);
- Found := TRUE;
- END
- else
- Found := FALSE;
- END;
-
- PROCEDURE FlashFill(Row,Col,Rows,Cols,Attr : Byte;Ch : Char);
- VAR
- Z : Byte;
- Temp : String;
- BEGIN
- Temp := Replicate(Ch,Cols);
- For Z := Row to Row + Rows-1 do
- Flash(Z,Col,Attr,Temp);
- END;
-
-
-
- PROCEDURE DBF.FlushDB;
- BEGIN
- MAlloc := TRUE;
- Done;
- MAlloc := FALSE;
- DBReset;
- END;
-
- PROCEDURE DBF.Get(FNo,X,Y : Byte);
- VAR
- TempStr1 : string;
-
- PROCEDURE Character;
- BEGIN
- TempStr1 := Field(FNo);
- BC := GetString(TempStr1,Fields^[FNo].FieldLen,Y,X);
- Repl(FNo,TempStr1);
- TempStr1 := PadR(TempStr1,Fields^[FNo].FieldLen);
- Flash(X,Y,Normal,Tempstr1);
- END; {PROCEDURE Character}
-
- PROCEDURE Numeric;
- VAR
- NumLen : Byte;
- TempInt : LongInt;
- TempReal : Real;
- RealStr,IntStr : String;
- BEGIN
- NumLen := Fields^[FNo].FieldLen;
- Decimals := Fields^[FNo].FieldDec;
- {If field is a real number}
- If Decimals>0 then
- BEGIN
- RealStr := '';
- TempReal := 0;
- RealStr := Field(FNo);
- Val(RealStr,TempReal,ErrCode);
- BC := GetReal(TempReal,MinReal,MaxReal,NumLen,Y,X);
- Str(TempReal : NumLen : Decimals,RealStr);
- Repl(FNo,RealStr);
- Flash(X,Y,Normal,RealStr);
- END
- else
- {Otherwise, it's an integer value}
- BEGIN
- IntStr := '';
- TempInt := 0;
- IntStr := Field(FNo);
- Val(IntStr,TempInt,ErrCode);
- BC := GetLongInt(TempInt,MinLong,MaxLong,NumLen,Y,X);
- Str(TempInt : NumLen,IntStr);
- Repl(FNo,IntStr);
- Flash(X,Y,Normal,IntStr);
- END;
- END; {PROCEDURE Numeric}
-
- PROCEDURE Dates;
- VAR
- TempDate,TmpDat2 : String[8];
- MM,DD,DC : Byte;
- YY,GG : Integer;
- TM,TD,TY,Month,Day : String[2];
- Year : String[4];
- BEGIN
- TempDate := '';
- TempDate := Field(FNo);
- Repeat
- Year := Copy(TempDate,1,4);
- Month := Copy(TempDate,5,2);
- Day := Copy(TempDate,7,2);
- Val(Year,YY,ErrCode);
- Val(Month,MM,ErrCode);
- Val(Day,DD,ErrCode);
- If YY>=1900 then YY := YY-1900;
- Case DateFormat of
- American : BEGIN
- BC := GetByte(MM,0,12,2,Y,X);
- BC := GetByte(DD,0,31,2,Y+3,X);
- BC := GetInteger(YY,0,99,2,Y+6,X);
- END;
- French : BEGIN
- BC := GetByte(DD,0,31,2,Y,X);
- BC := GetByte(MM,0,12,2,Y+3,X);
- BC := GetInteger(YY,0,99,2,Y+6,X);
- END;
- Italian : BEGIN
- BC := GetByte(DD,0,31,2,Y,X);
- BC := GetByte(MM,0,12,2,Y+3,X);
- BC := GetInteger(YY,0,99,2,Y+6,X);
- END;
- German : BEGIN
- BC := GetByte(DD,0,31,2,Y,X);
- BC := GetByte(MM,0,12,2,Y+3,X);
- BC := GetInteger(YY,0,99,2,Y+6,X);
- END;
- Ansi : BEGIN
- BC := GetInteger(YY,0,99,2,Y,X);
- BC := GetByte(MM,0,12,2,Y+3,X);
- BC := GetByte(DD,0,31,2,Y+6,X);
- END;
- British : BEGIN
- BC := GetByte(DD,0,31,2,Y,X);
- BC := GetByte(MM,0,12,2,Y+3,X);
- BC := GetInteger(YY,0,99,2,Y+6,X);
- END;
- END;
- Str(MM,Month);
- Str(DD,Day);
- YY := YY + 1900;
- Str(YY:4,Year);
- If DD<10 then Day := '0'+Day;
- If MM<10 then Month := '0'+Month;
- TempDate :=Year+Month+Day;
- If not ValidDate(TempDate) then Beep;
- Case DateFormat of
- American : BEGIN
- TmpDat2 := Copy(TempDate,5,2)+'/'+Copy(TempDate,7,2)+'/'+
- Copy(TempDate,3,2);
- END;
- French : BEGIN
- TmpDat2 := Copy(TempDate,7,2)+'/'+Copy(TempDate,5,2)+
- '/'+Copy(TempDate,3,2)
- END;
- Italian : BEGIN
- TmpDat2 := Copy(TempDate,7,2)+'-'+Copy(TempDate,5,2)+
- '-'+Copy(TempDate,3,2)
- END;
- German : BEGIN
- TmpDat2 := Copy(TempDate,7,2)+'.'+Copy(TempDate,5,2)+
- '.'+Copy(TempDate,3,2)
- END;
- Ansi : BEGIN
- TmpDat2 := Copy(TempDate,3,2)+'.'+Copy(TempDate,5,2)+
- '.'+Copy(TempDate,7,2)
- END;
- British : BEGIN
- TmpDat2 := Copy(TempDate,7,2)+'/'+Copy(TempDate,5,2)+
- '/'+Copy(TempDate,3,2)
- END;
-
- END;
- Flash(X,Y,Normal,TmpDat2);
- Until ValidDate(TempDate);
- Repl(FNo,TempDate);
- END; {PROCEDURE Dates}
-
- PROCEDURE Logical;
- VAR
- BoolVAR : Byte;
- TF : String[1];
- BEGIN
- Case DBRecord^[Positions^[1,FNo]] of
- 'Y' : BoolVAR := 1;
- 'N' : BoolVAR := 2
- else BoolVAR := 0;
- END;
- BC := GetBoolean(BoolVAR,'Y','N',Y,X);
- TF := BoolToStr(BoolVAR,'Y','N');
- DBRecord^[Positions^[1,FNo]] := TF[1];
- Flash(X,Y,Normal,TF);
- END;
-
- VAR
- Z : Byte;
-
- BEGIN {PROCEDURE Get}
- Case Chr(Ord(Fields^[FNo].FieldType)) of
- 'C' : Character;
- 'L' : Logical;
- 'N' : Numeric;
- 'D' : Dates;
- END;
- END;{PROCEDURE Get}
-
-
- FUNCTION GetBoolean(VAR Param:Byte;IfTRUE,IfFALSE:Char;X,Y:Byte):Char;
- VAR
- BC : Char;
- Temp : String;
- Value : Byte;
- BEGIN
- Value := Param;
- Temp := BoolToStr(Value,IfTRUE,IfFALSE);
- UpperCase := TRUE;
- Temp := Input(Temp,[IfTRUE,IfFALSE],1,X,Y,BC);
- If Length(Temp) = 0 Then
- BEGIN
- Param := 0;
- Flash(Y,X,Normal,BoolToStr(Param,IfTRUE,IfFALSE));
- END
- Else
- BEGIN
- If Temp = Filler Then Param := 0;
- If Temp = IfTRUE Then Param := 1;
- If Temp = IfFALSE Then Param := 2;
- END;
- UpperCase := FALSE;
- GetBoolean := BC;
- END;
-
- FUNCTION GetByte(VAR Param:Byte;LowLim,UpLim,Len,X,Y:Byte):Char;
- VAR
- BC : Char;
- WW,WL,WH : LongInt;
- BEGIN
- WW := LongInt(Param);
- WL := LongInt(LowLim);
- WH := LongInt(UpLim);
- BC := GetLongInt(WW,WL,WH,Len,X,Y);
- Param := Byte(WW);
- GetByte := BC;
- END;
-
- PROCEDURE DBF.GetDBRec(RecordNumber : LongInt);
- BEGIN
- If not Allocated then
- BEGIN
- New(DBRecord);
- END
- else
- BEGIN
- Dispose(DBRecord);
- New(DBRecord);
- END;
- DBRecNum := RecordNumber;
- RecordNumber := (RecordNumber - 1) * Header^.RecordLen + Header^.Location;
- Seek(DBFile,RecordNumber);
- BlockRead(DBFile,DBRecord^,Header^.RecordLen,ErrCode);
- END;
-
- FUNCTION DBF.GetField(RecordNo : LongInt;FNo : Byte) : String;
-
- Type
- FldArray = Array[1..254] of Char;
-
- VAR
- TempArray : FldArray;
-
- FldAddr,RecordNumber : LongInt;
- Temp : String[254];
- K : Byte;
-
- BEGIN
- If FNo = 1 then FldAddr := 1
- else
- BEGIN
- FldAddr := 1;
- For K := 1 to FNo-1 do
- FldAddr := FldAddr+Fields^[K].FieldLen;
- END;
- RecordNumber := (RecordNo - 1) * Header^.RecordLen + Header^.Location+FldAddr;
- Seek(DBFile,RecordNumber);
- BlockRead(DBFile,TempArray,Fields^[FNo].FieldLen,ErrCode);
- Temp := '';
- For K := 1 to Fields^[FNo].FieldLen do
- Temp := Temp+TempArray[K];
- GetField := Temp;
- END;
-
-
- FUNCTION GetInteger(VAR Param:Integer;LowLim,UpLim:Integer;Len,X,Y:Byte):Char;
- VAR
- BC : Char;
- WW,WL,WH : LongInt;
- BEGIN
- WW := LongInt(Param);
- WL := LongInt(LowLim);
- WH := LongInt(UpLim);
- BC := GetLongInt(WW,WL,WH,Len,X,Y);
- Param := Integer(WW);
- GetInteger := BC;
- END;
-
- FUNCTION GetLongInt(VAR Param:LongInt;LowLim,UpLim:LongInt;Len,X,Y:Byte):Char;
- VAR
- Temp : String;
- P, Value : LongInt;
- I : Integer;
- Err : Boolean;
- BC : Char;
- BEGIN
- Repeat
- Err := FALSE;
- Str(Param, Temp);
- Temp := Input(Temp, ['0'..'9'], Len, X, Y, BC);
- Val(Temp, P, I);
- If length(Temp) = 0 Then Value := 0
- Else If I = 0 Then Value := P
- Else
- BEGIN
- Value := Param;
- Beep;
- Err := TRUE;
- END;
- If (Not((Value >= LowLim) And (Value <= UpLim))) Then Beep;
- Until (Value >= LowLim) And (Value <= UpLim) And (Not(Err));
- Param := Value;
- GetLongInt := BC;
- END;
-
-
- FUNCTION GetReal(VAR Param : Real; LowLim, UpLim : Real; Len, X, Y : Word) : Char;
- VAR
- Temp : String;
- P, Value : Real;
- I : Word;
- Err : Boolean;
- BC : Char;
- BEGIN
- Repeat
- Err := FALSE;
- Temp := RealToStr(Param);
- Temp := Input(Temp, ['0'..'9', '.','-'], Len, X, Y, BC);
- Val(Temp, P, I);
- If Length(Temp) = 0 Then Value := 0.0
- Else If I = 0 Then Value := P
- Else
- BEGIN
- Value := Param;
- Beep;
- Err := TRUE;
- END;
- If (Not((Value >= LowLim) And (Value <= UpLim))) Then Beep;
- Until (Value >= LowLim) And (Value <= UpLim) And (Not(Err));
- Param := Value;
- GetReal := BC;
- END;
-
- FUNCTION GetString(VAR Param : String; Len, X, Y : Byte) : Char;
- VAR
- Temp : String;
- BC : Char;
- BEGIN
- Temp := Param;
- Temp := Input(Temp, [#32..#126], Len, X, Y, BC);
- Param := Temp;
- GetString := BC;
- END;
-
- FUNCTION GetWord(VAR Param:Word;LowLim,UpLim:Word;Len,X,Y:Byte):Char;
- VAR
- BC : Char;
- WW,WL,WH : LongInt;
- BEGIN
- WW := LongInt(Param);
- WL := LongInt(LowLim);
- WH := LongInt(UpLim);
- BC := GetLongInt(WW,WL,WH,Len,X,Y);
- Param := Word(WW);
- GetWord := BC;
- END;
-
- PROCEDURE DBF.GoBottom;
- BEGIN
- GetDBRec(Header^.RecCount);
- END;
-
- PROCEDURE DBF.GoTop;
- BEGIN
- GetDBRec(1);
- END;
-
- FUNCTION DBF.IIF(BoolVAR : Boolean;IfTRUE,IfFALSE : String) : String;
- BEGIN
- If BoolVAR then IIF := IfTRUE
- else IIF := IfFALSE;
- END;
-
- PROCEDURE DBF.IndexOn(NdxID : BYTE;NdxName : FileName;NdxField : BYTE;DupFlag : BYTE);
- VAR
- RecNumber : LONGINT;
- BEGIN
- MakeDBIndex(NdxID,NdxName,Fields^[NdxField].FieldLen,DupFlag);
- OpenDBIndex(NdxID,NdxName,Fields^[NdxField].FieldLen,DupFlag);
- FOR RecNumber := 1 TO TotalRecs DO
- BEGIN
- GetDBRec(RecNo);
- AddDBKey(NdxID,Field(NdxField));
- END;
- END;
-
- CONSTRUCTOR DBF.Init(DBName : FileName);
- VAR
- NdxID : BYTE;
- BEGIN
- NEW(DBRecord);
- Inc(FilesOpen);
- New(Header);
- New(Fields);
- New(Positions);
- NEW(Indexes);
- DBFName := RTrim(LTrim(DBName));
- Assign(DBFile,DBFName);
- {$I-} Reset(DBFile,1); {$I+}
- TPDBErr := IOResult;
- If (TPDBErr<>0) and (not GotOne) then
- BEGIN
- TErrorName := DBName;
- BailOut;
- END;
- DBFOpen := TRUE;
- DBRecNum := 1;
- FOR NdxID := 1 TO MaxInds DO
- BEGIN
- Indexes^[NdxID].NdxName := '';
- Indexes^[NdxID].Open := FALSE;
- Indexes^[NdxID].NdxID := 0;
- END;
- ReadDBHeader;
- END;
-
-
- FUNCTION Input(VAR S:String;Term:CharSet;L,X,Y:Byte;VAR BC:Char):String;
- Const
- Next : CharSet = [Return,CursorUp,CursorDown,PageUp,PageDown,Escape];
- VAR
- P : Byte;
- Ch : Char;
- Temp : String;
- BEGIN
- CursorOn;
- If S = '0' Then S[0] := #0;
- Temp:= Replicate(Filler,L-Length(S));
- Temp := Concat(S,Temp);
- Flash(Y,X,Reverse,Temp);
- P := 0;
- Repeat
- GoToXY(X+P,Y);
- Ch := ReadChar;
- If UpperCase Then CH := UpCase(CH);
- If (CH In Term) Then
- BEGIN
- If P < L Then
- BEGIN
- If Length(S) = L Then Delete(S, L, 1);
- Inc(P);
- Insert(CH, S, P);
- Write(Copy(S, P, L));
- If AutoWrap AND (P = L) Then Ch := Return;
- END
- Else If Not(AutoWrap) Then Beep;
- END
- Else
- Case CH Of
- ^H, #127 : If P > 0 Then
- BEGIN
- Delete(S, P, 1);
- Write(^H, Copy(S, P, L), Filler);
- Dec(P);
- END
- Else Beep;
- DelKey : If P < Length(S) Then
- BEGIN
- Delete(S, Succ(P), 1);
- Write(Copy(S, Succ(P), L), Filler);
- END;
- CursorLeft : If P > 0 Then Dec(P)
- Else Beep;
- CursorRight: If P < Length(S) Then Inc(P)
- Else Beep;
- CursorHome : P := 0;
- CursorEND : P := Length(S);
- ^Y : BEGIN
- Write(Replicate(Filler, Length(S)-P));
- Delete(S, Succ(P), L);
- END;
- END;
- Until CH In Next;
- P := Length(S);
- Input := S;
- BC := CH;
- CursorOff;
- END;
-
-
- FUNCTION IntToStr(Number : LongInt): String;
- VAR
- Temp : String;
- BEGIN
- Str(Number,Temp);
- IntToStr := RTrim(LTrim(Temp));
- END;
-
- FUNCTION DBF.Locate(FieldNo : BYTE;SearchStr : String) : BOOLEAN;
- VAR
- RecNumber : LONGINT;
- BEGIN
- DBReset;
- RecNumber := 1;
- WHILE RecNumber <= TotalRecs DO
- BEGIN
- GetDBRec(RecNumber);
- IF Pos(SearchStr,IIF(UCKey,Upper(Field(FieldNo)),Field(FieldNo))) > 0 THEN
- BEGIN
- Locate := TRUE;
- EXIT;
- END;
- RecNumber := RecNumber + 1;
- END;
- Locate := FALSE;
- END;
-
-
- PROCEDURE DBF.LookUp(SearchStr : string;NdxID : BYTE);
- BEGIN
- SearchKey(Indexes^[NdxID].Ndx,DBRecNum,SearchStr);
- If OK then
- BEGIN
- GetDBRec(DBRecNum);
- Found := TRUE;
- END
- else
- Found := FALSE;
- END;
-
- PROCEDURE DBF.MakeDBIndex(NdxID : BYTE;DBIndexName : FileName;KeyLen,Status : Integer);
- BEGIN
- MakeIndex(Indexes^[NdxID].Ndx,DBIndexName,KeyLen,Status);
- Indexes^[NdxID].NdxName := DBIndexName;
- Indexes^[NdxID].NdxID := NdxID;
- Indexes^[NdxID].Open := TRUE;
- CloseDBIndex(NdxID);
- END;
-
- PROCEDURE DBF.Mark;
- BEGIN
- DBRecord^[1] := Chr(Ord($2A));
- END;{Mark}
-
- FUNCTION Max(N1,N2 : Integer) : Integer;
- BEGIN
- If N1>N2 then Max := N1
- else Max := N2;
- END;{Max}
-
- FUNCTION Min(N1,N2 : Integer) : Integer;
- BEGIN
- If N1<N2 then Min := N1
- else Min := N2;
- END;{Min}
-
- FUNCTION DBF.Mul(Field1,Field2 : Byte):string;
- (* Multiply field 1 and field2 *)
- VAR
- T1,T2,T3 : String;
- M1,M2,M3 : Real;
- ErrCode : Integer;
- BEGIN
- T1 := RTrim(Field(Field1));
- T2 := RTrim(Field(Field2));
- Val(T1,M1,ErrCode);
- Val(T2,M2,ErrCode);
- M3 := M1*M2;
- Str(M3 : Max(Fields^[Field1].FieldLen,Fields^[Field2].FieldLen) :
- Max(Fields^[Field1].FieldDec,Fields^[Field2].FieldDec),T3);
- Mul := LTrim(T3);
- END;{Mul}
-
- PROCEDURE DBF.NewDBRec;
- BEGIN
- If not Allocated then
- BEGIN
- New(DBRecord);
- END
- else
- BEGIN
- Dispose(DBRecord);
- New(DBRecord);
- END;
- FillChar(DBRecord^,SizeOf(DBRecord^),#32);
- DBRecNum := TotalRecs + 1;
- END;{NewDBRec}
-
- PROCEDURE DBF.NextDBKey(NdxID : BYTE;KeyStr : DBKey);
- BEGIN
- If UCKey then KeyStr := Upper(KeyStr);
- NextKey(Indexes^[NdxID].Ndx,DBRecNum,KeyStr);
- GetDBRec(DBRecNum);
- END;{NextDBKey}
-
- PROCEDURE DBF.NextRec;
- BEGIN
- GetDBRec(DBRecNum+1);
- END;{NextRec}
-
-
- PROCEDURE DBF.OpenDBIndex(NdxID : BYTE;DBIndexName : FileName;KeyLen,Status : Integer);
- BEGIN
- OpenIndex(Indexes^[NdxID].Ndx,DBIndexName,KeyLen,Status);
- Indexes^[NdxId].NdxName := DBIndexName;
- Indexes^[NdxID].NdxID := NdxId;
- Indexes^[NdxID].Open := TRUE;
- INC(FilesOpen);
- END;{OpenDBIndex}
-
- PROCEDURE DBF.Pack;
- VAR
- FNo : Byte;
- J,TRec : LongInt;
-
- PROCEDURE PutTempRec(RecordNumber : LongInt); {Add new record, no index open.}
- BEGIN
- DBRecNum := RecordNumber;
- RecordNumber := (RecordNumber - 1) * Header^.RecordLen + Header^.Location;
- Seek(TempFile,RecordNumber);
- BlockWrite(TempFile,DBRecord^,Header^.RecordLen,ErrCode);
- END;
-
- BEGIN
- MAlloc := TRUE;
- Done;
- Malloc := FALSE;
- FromPack := TRUE;
- DBReset;
- ReadDBHeader;
- Assign(TempFile,'temp.$$$');
- ReWrite(TempFile,1);
- BlockWrite(TempFile,Header^,32,ErrCode);
- For FNo := 1 to NumFields do
- BEGIN
- BlockWrite(TempFile,Fields^[FNo],32,ErrCode);
- END;
- Header^.Terminator := Chr(Ord($0D));
- BlockWrite(TempFile,Header^.Terminator,1,ErrCode);
- TRec := 1;
- For J := 1 to TotalRecs do
- BEGIN
- GetDBRec(J);
- If not Deleted then
- BEGIN
- PutTempRec(TRec);
- TRec := TRec + 1;
- END;
- END;
- Done;
- Close(TempFile);
- Erase(DBFile);
- Rename(TempFile,DBFName);
- Init(DBFName);
- TotalRecs := TRec-1;
- WriteDBHeader;
- END;{Pack}
-
- PROCEDURE DBF.PrevDBKey(NdxID : BYTE;KeyStr : DBKey);
- BEGIN
- If UCKey then KeyStr := Upper(KeyStr);
- PrevKey(Indexes^[NdxID].Ndx,DBRecNum,KeyStr);
- GetDBRec(DBRecNum);
- END;{PrevDBKey}
-
- PROCEDURE DBF.PrevRec;
- BEGIN
- GetDBRec(DBRecNum-1);
- END;{PrevRec}
-
- PROCEDURE Prompt(Row,Col : Byte;PromptStr : Str80);
- BEGIN
- Flash(Row,Col,Normal,PromptStr);
- END;{Prompt}
-
- PROCEDURE DBF.PutDBRec(RecordNumber : LongInt);
- BEGIN
- DBRecNum := RecordNumber;
- RecordNumber := (RecordNumber - 1) * Header^.RecordLen + Header^.Location;
- Seek(DBFile,RecordNumber);
- BlockWrite(DBFile,DBRecord^,Header^.RecordLen,ErrCode);
- Dispose(DBRecord);
- END;{PutDBRec}
-
- FUNCTION ReadChar : Char;
- VAR
- CH : Char;
- BEGIN
- ReadKb(ExtKey, CH);
- If ExtKey Then
- BEGIN
- Case CH Of
- #75 : CH := CursorLeft;
- #77 : CH := CursorRight;
- #72 : CH := CursorUp;
- #80 : CH := CursorDown;
- #73 : CH := PageUp;
- #81 : CH := PageDown;
- #71 : CH := CursorHome;
- #79 : CH := CursorEND;
- #83 : CH := DelKey;
- Else CH := #0;
- END;
- If CH = #9 Then CH := TabKey;
- END;
- ReadChar := CH;
- END;{ReadChar}
-
- PROCEDURE DBF.ReadDBHeader;
- {Read .DBF header.}
- VAR
- FNo : Byte;
- BEGIN
- BlockRead(DBFile,Header^,32,ErrCode);
- TotalRecs := Header^.RecCount;
- NumFields := (Header^.Location - 33) div 32;
- For FNo := 1 to NumFields do
- BEGIN
- BlockRead(DBFile,Fields^[FNo],32,ErrCode);
- END;
- For K := 1 to NumFields do
- BEGIN
- Positions^[1,K] := 0;
- Positions^[2,K] := 0;
- END;
- Start := 2;
- For FNo := 1 to NumFields do
- BEGIN
- Stop := Start+Fields^[FNo].FieldLen-1;
- Positions^[1,FNo] := Start;
- Positions^[2,FNo] := Stop;
- Start := Stop+1;
- END;
- END;{ReadDBHeader}
-
- PROCEDURE ReadKB (VAR ExtKey: Boolean; VAR Ch: Char);
- BEGIN
- ExtKey := FALSE;
- Ch := ReadKey;
- If Ch = #0 Then
- BEGIN
- ExtKey := TRUE;
- Ch := ReadKey;
- END;
- END;{ReadKB}
-
- FUNCTION RealToStr(Number : Real): String;
- VAR
- Temp : String;
- I : Word;
- BEGIN
- Str(Number:NumLen:Decimals, Temp);
- Temp := LTrim(Temp);
- I := Length(Temp);
- While Temp[I] = '0' Do Dec(I);
- If Temp[I] = '.' Then Dec(I);
- RealToStr := Copy(Temp, 1, I);
- END;{RealToStr}
-
-
- PROCEDURE DBF.Recall;
- BEGIN
- DBRecord^[1] := Chr(Ord($20));
- END;{Recall}
-
- FUNCTION DBF.RecCount : LONGINT;
- BEGIN
- RecCount := TotalRecs;
- END;
-
- FUNCTION DBF.RecNo : LONGINT;
- BEGIN
- RecNo := DBRecNum;
- END;
-
- PROCEDURE DBF.Repl(FNo : Byte;InStr : string);
- VAR
- Temp : String;
- BEGIN
- Temp := PadR(InStr,Fields^[FNo].FieldLen);
- Move(Temp[1],DBRecord^[Positions^[1,FNo]],Fields^[FNo].FieldLen);
- END;{Repl}
-
- PROCEDURE DBF.ReplEach(FNo : Byte;InStr : String);
- VAR
- J : LongInt;
-
- BEGIN
- DBReset;
- For J := 1 to TotalRecs do
- BEGIN
- GetDBrec(J);
- Repl(FNo,InStr);
- PutDBRec(J);
- END;
- END;{ReplEach}
-
-
- PROCEDURE DBF.Save;
- BEGIN
- PutDBRec(DBRecNum);
- END;{Save}
-
-
- PROCEDURE DBF.Say(FNo,Row,Col : Byte);
- VAR
- GG : Integer;
- TempStr : String;
- Bool : Char;
- TempDate : String[8];
- Month,Day,Year : String[2];
- YY : Integer;
- MM,DD : Byte;
- Slush : String[8];
- BEGIN
- Case Chr(Ord(Fields^[FNo].FieldType)) of
- 'C','N' : BEGIN
- TempStr :='';
- For GG := Positions^[1,FNo] to Positions^[2,FNo] do
- TempStr := TempStr+DBRecord^[GG];
- Flash(Row,Col,Normal,TempStr);
- END;
- 'L' : BEGIN
- Bool := DBRecord^[Positions^[1,FNo]];
- Flash(Row,Col,Normal,Bool);
- END;
- 'D' : BEGIN
- TempDate := '';
- Slush := '';
- Case DateFormat of
- American : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,5,2)+'/'+Copy(Slush,7,2)+
- '/'+Copy(Slush,3,2);
- END;
- Ansi : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,3,2)+'.'+Copy(Slush,5,2)+
- '.'+Copy(Slush,7,2);
- END;
- British : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,7,2)+'/'+Copy(Slush,5,2)+
- '/'+Copy(Slush,3,2);
- END;
- French : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,7,2)+'/'+Copy(Slush,5,2)+
- '/'+Copy(Slush,3,2);
- END;
- German : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,7,2)+'.'+Copy(Slush,5,2)+
- '.'+Copy(Slush,3,2);
- END;
- Italian : BEGIN
- Slush := Field(FNo);
- TempDate := Copy(Slush,7,2)+'-'+Copy(Slush,5,2)+
- '-'+Copy(Slush,3,2);
- END;
- END;
- Flash(Row,Col,Normal,TempDate);
- END;
- END;
- END;{Say}
-
-
- PROCEDURE SetDateFormat(Format : BYTE);
- BEGIN
- DateFormat := Format;
- END;
-
-
- PROCEDURE SetDBColor(FG,BG : Byte);
- BEGIN
- TextColor(FG);
- TextBackGround(BG);
- END;{SetDBColor}
-
- PROCEDURE DBF.ShowStatus; {Display .DBF status.}
- VAR
- FNo,K : Byte;
- BEGIN
- ClrScr;
- WriteLn('File name is ',Upper(DBFName),'.');
- WriteLn('Last update was on ',Header^.Month,'/',Header^.Day,'/',Header^.Year,'.');
- WriteLn('Number of records is ',Header^.RecCount,'.');
- WriteLn('Data starts at byte # ',Header^.Location,'.');
- WriteLn('Record length is ',Header^.RecordLen,' bytes.');
- WriteLn('There are ',NumFields,' fields.');
- Wait;
- For FNo := 1 to NumFields do
- BEGIN
- Write('Field # ',FNo:2,': ');
- For K := 1 to 11 do
- Write(Fields^[FNo].FieldName[K]);
- Write(' Type: ',Chr(Fields^[FNo].FieldType));
- Write(' Length: ',Fields^[FNo].FieldLen:3);
- If Chr(Ord(Fields^[FNo].FieldType))='N' then
- Write(' Decimals: ',Fields^[FNo].FieldDec:2);
- WriteLn;
- If FNo mod 20 = 0 then Wait;
- END;
- Wait;
- DBReset;
- END;{ShowStatus}
-
- PROCEDURE DBF.Skip;
- BEGIN
- GetDBRec(DBRecNum+1);
- END;{Skip}
-
-
- FUNCTION DBF.Sub(Field1,Field2 : Byte) : string;
- (* Subtract field 2 FROM field 1 *)
- VAR
- T1,T2,T3 : String;
- S1,S2,S3 : Real;
- ErrCode : Integer;
- BEGIN
- T1 := RTrim(Field(Field1));
- T2 := RTrim(Field(Field2));
- Val(T1,S1,ErrCode);
- Val(T2,S2,ErrCode);
- S3 := S1-S2;
- Str(S3 : Max(Fields^[Field1].FieldLen,Fields^[Field2].FieldLen) :
- Max(Fields^[Field1].FieldDec,Fields^[Field2].FieldDec),T3);
- Sub := LTrim(T3);
- END;{Sub}
-
- FUNCTION DBF.Sum(FNo : Byte) : Real;
- {Sums a numeric field. If specified field is not numeric returns 0.}
- VAR
- J : LongInt;
- TempStr : String;
- TempReal : Real;
- EC : Integer;
- TotalSum : Real;
- BEGIN
- If Chr(Ord(Fields^[FNo].FieldType))<>'N' then
- BEGIN
- Sum := 0;
- Exit;
- END
- else
- BEGIN
- DBReset;
- TotalSum := 0;
- For J := 1 to TotalRecs do
- BEGIN
- GetDBRec(J);
- TempStr := RTrim(LTrim(Field(FNo)));
- Val(TempStr,TempReal,EC);
- TotalSum := TotalSum + TempReal;
- END;
- END;
- Sum := TotalSum;
- END;{Sum}
-
- PROCEDURE Wait;
- BEGIN
- Writeln('Press any key to continue...');
- Ch := ReadKey;
- END;{Wait}
-
-
- PROCEDURE DBF.WriteDBHeader;
- {Update .DBF header.}
- BEGIN
- DBReset;
- GetDate(Y,M,D,DW);
- Y := Y-1900;
- Header^.Year := Y;
- Header^.Month := M;
- Header^.Day := D;
- Header^.RecCount := TotalRecs;
- BlockWrite(DBFile,Header^,32,ErrCode);
- END;{WriteDBHeader}
-
- PROCEDURE DBF.Zap;
- VAR
- FNo : Byte;
- BEGIN
- ReWrite(DBFile,1);
- TotalRecs := 0;
- Header^.RecCount := 0;
- BlockWrite(DBFile,Header^,32,ErrCode);
- For FNo := 1 to NumFields do
- BEGIN
- BlockWrite(DBFile,Fields^[FNo],32,ErrCode);
- END;
- Header^.Terminator := Chr(Ord($0D));
- BlockWrite(DBFile,Header^.Terminator,1,ErrCode);
- DBReset;
- END;{Zap}
-
- BEGIN {TPDB}
- SetDateFormat(American);
- FromPack := FALSE;
- TAErrorProc := @DBF.BailOut;
- TErrorName := '';
- TPDBErr := 0;
- FilesOpen := 0;
- END. {TPDB}
-
- {END of Source Code - TPDB.pas Version 3.11 Copyright 1989 Brian Corll }
-
- CHANGES and ADDITIONS in this version -
- Version 3.2 {September 1989}
- - Procedure SetColor changed to SetDBColor to prevent conflicts
- when the Graph unit is used.
-
- - Procedure SetDateFormat was added to allow use of foreign date formats.
-
- Supported date formats are as follows:
- CONST
- French = 1; {dd/mm/yy}
- German = 2; {dd.mm.yy}
- Italian = 3; {dd-mm-yy}
- American = 4; {mm/dd/yy}
- British = 5; {dd/mm/yy}
- Ansi = 99;{yy.mm.dd}
-
- - Added procedures ChAttr and ChAllAttr to change displayed screen
- attributes.
-
- - Added RecNo and RecCount functions.
-
- - Added SaveScreen and RestoreScreen procedures. Moved most screen-handling
- code to TPDBScrn.tpu.
-
- - Added sorting routines, creating TPDBSort.pas.
-
- - Added BinSearch routine, for searching sorted files of unique keys.
-
- - Moved all string functions into TPDBStr.pas.
-