home *** CD-ROM | disk | FTP | other *** search
- unit GS_DBASE;
-
- { GS_DBASE Copyright (c) Richard F. Griffin
-
- 8 January 1990
-
- 102 Molded Stone Pl
- Warner Robins, GA 31088
-
- -------------------------------------------------------------
- This unit handles the objects for all dBase III file (.DBF)
- operations.
-
- SHAREWARE -- COMMERCIAL USE RESTRICTED
- }
-
-
- interface
- uses dos, GS_DB_IX;
-
- const
- GS_dBase_MaxRecBytes = 4000; { dBASE III record limit }
- GS_dBase_MaxRecField = 128; { dBASE III field limit }
-
- Next_Record = -1;
- Prev_Record = -2;
- Top_Record = -3;
- Bttm_Record = -4;
-
- GS_dBase_UnDltChr = 32; {Character for Undeleted Record}
- GS_dBase_DltChr = 42; {Character for Deleted Record}
-
- type
- GS_dBase_Status = (NotOpen, NotUpdated, Updated);
- GS_dBase_dRec = ^GS_dBase_DataRecord;
- GS_dBase_DataRecord = ARRAY[0..GS_dBase_MaxRecBytes] OF Byte;
-
- GS_dBase_Head = Record
- DBType : Byte;
- Year : Byte;
- Month : Byte;
- Day : Byte;
- RecCount : LongInt;
- Location : Integer;
- RecordLen : Integer;
- Reserved : Array[1..20] of Byte;
- end;
-
- GS_dBase_Field = Record
- FieldName : Array[1..11] of Char;
- FieldType : Char;
- FieldAddress : LongInt;
- FieldLen : Byte;
- FieldDec : Byte;
- Reserved : Array[1..14] of Char;
- end;
-
- GS_dBase_dFld = ^GS_dBase_DataField;
- GS_dBase_DataField = ARRAY[1..GS_dBase_MaxRecField] OF GS_dBase_Field;
-
- GS_dBase_DB = object
- FileName : string[64];
- dFile : file;
- mFile : file;
- HeadProlog : GS_dBase_Head;
- dStatus : GS_dBase_Status;
- WithMemo : Boolean;
- DateOfUpdate : string[8];
- NumRecs : LongInt;
- HeadLen : Integer;
- RecLen : Integer;
- NumFields : Integer;
- Fields : GS_dBase_dFld;
- RecNumber : LongInt;
- CurRecord : GS_dBase_dRec;
- DelFlag : boolean;
- dbfError : Integer;
- dbfOK : Boolean;
- File_EOF : boolean;
- Found : boolean;
- dbfNdxTbl : array [1..16] of GS_Indx_LPtr;
- dbfNdxActv : boolean;
- PROCEDURE Append;
- PROCEDURE Close;
- PROCEDURE Create(FName : string; Flds : GS_dBase_dFld; FCnt : integer);
- PROCEDURE Delete;
- PROCEDURE Find(st : string);
- PROCEDURE GetRec(RecNum: LongInt);
- PROCEDURE Index(IName : String);
- PROCEDURE Init(FName : string);
- PROCEDURE Open;
- PROCEDURE Pack;
- PROCEDURE PutRec(RecNum : LongInt);
- PROCEDURE UnDelete;
- end;
-
-
-
- implementation
-
- CONST
- DB3File = 3;
- DB3WithMemo = $83;
-
- PROCEDURE GS_dBase_DB.GetRec(RecNum : LongInt);
- VAR
- Result : Integer;
- RNum : LongInt;
- BEGIN
- RNum := RecNum;
- if (dbfNdxActv) and (RecNum < 0) then
- RNum := dbfNdxTbl[1]^.KeyRead(RecNum);
- case RNum of
- Next_Record : begin
- RNum := RecNumber + 1;
- if RNum > NumRecs then RNum := NumRecs;
- end;
- Prev_Record : begin
- RNum := RecNumber - 1;
- if RNum < 1 then RNum := 1;
- end;
- Top_Record : RNum := 1;
- Bttm_Record : RNum := NumRecs;
- end;
- if (RNum < 1) or (RNum > NumRecs) then
- begin
- dbfOK := false;
- dbfError := 100 {Disk read beyond EOF};
- exit;
- end;
- {$I-} Seek(dFile, HeadLen+(RNum-1) * RecLen); {$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockRead(dFile, CurRecord^, RecLen, Result); {$I+}
- dbfError := IOResult;
- IF (dbfError = 0) AND (Result < RecLen) THEN
- dbfError := 100; {Partial read only}
- RecNumber := RNum;
- if CurRecord^[0] = GS_dBase_UnDltChr then DelFlag := false
- else DelFlag := true;
- END;
- dbfOK := (dbfError = 0);
- if (dbfNdxActv) and (RecNum < 0) then
- File_EOF := dbfNdxTbl[1]^.KeyEOF
- else if RecNumber = NumRecs then File_EOF := true else File_EOF := false;
- END; {GetRec}
-
- Procedure GS_dBase_DB.Find(st : string);
- var
- RNum : longint;
- begin
- if (dbfNdxActv) then
- RNum := dbfNdxTbl[1]^.KeyFind(st);
- if RNum > 0 then GetRec(RNum);
- end;
-
-
- PROCEDURE GS_dBase_DB.PutRec(RecNum : LongInt);
- VAR
- Result : Integer;
- RNum : LongInt;
- BEGIN
- RNum := RecNum;
- IF (RNum > NumRecs) or (RNum < 1) then
- begin
- inc(NumRecs);
- RNum := NumRecs;
- end;
- {$I-} Seek(dFile, HeadLen + (RNum-1) * RecLen); {$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, CurRecord^, RecLen, Result); {$I+}
- dbfError := IOResult;
- RecNumber := RNum;
- dStatus := Updated;
- end;
- dbfOK := (dbfError = 0);
- END; {PutRec}
-
- PROCEDURE GS_dBase_DB.Append;
- BEGIN
- PutRec(0);
- END;
-
- PROCEDURE GS_dBase_DB.Delete;
- begin
- DelFlag := true;
- CurRecord^[0] := GS_dBase_DltChr;
- PutRec(RecNumber);
- end;
-
- PROCEDURE GS_dBase_DB.UnDelete;
- begin
- DelFlag := false;
- CurRecord^[0] := GS_dBase_UnDltChr;
- PutRec(RecNumber);
- end;
-
- PROCEDURE GS_dBase_DB.Close;
- CONST
- EofMark : Byte = $1A;
- var
- yy, mm, dd, wd : word;
-
- procedure UpDate_File;
- BEGIN
- GetDate (yy,mm,dd,wd);
- HeadProlog.year := yy-1900; {Year}
- HeadProlog.month := mm; {Month}
- HeadProlog.day := dd; {Day}
- HeadProlog.RecCount := NumRecs;
- {$I-}Seek(dFile, 0);{$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, HeadProlog, 8); {$I+}
- dbfError := IOResult;
- END;
- dbfOK := (dbfError = 0);
- IF dbfError = 0 THEN
- BEGIN
- {$I-} Seek(dFile, HeadLen+NumRecs*RecLen); {$I+}
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, EofMark, 1); {$I+} {Put EOF marker }
- dbfError := IOResult;
- END;
- END; { IF Updated }
-
- begin
- dbfError := 0;
- IF dStatus = NotOpen THEN exit;
- IF dStatus = Updated THEN UpDate_File;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} System.Close(dFile); {$I+}
- if WithMemo then System.Close(mFile);
- dbfError := IOResult;
- dStatus := NotOpen;
- END;
- dbfOK := (dbfError = 0);
- END; { GS_dBase_Close }
-
- PROCEDURE GS_dBase_DB.Open;
- BEGIN { GS_dBase_Open }
- if dStatus = NotOpen then
- begin
- Assign(dFile, FileName);
- {$I-} Reset(dFile, 1); {$I+}
- dbfError := IOResult;
- dbfOK := (dbfError = 0);
- dStatus := NotUpdated;
- if WithMemo then Reset(mFile,512);
- RecNumber := 0;
- end;
- END; { GS_dBase_Open }
-
- PROCEDURE GS_dBase_DB.Init(FName : string);
- var
- i : integer;
-
- PROCEDURE ProcessHeader;
- VAR
- Result : integer;
- o, i : Integer;
- m,dy,y : string[2];
- BEGIN {ProcessHeader}
- CASE HeadProlog.DBType OF
- DB3File : WithMemo := False;
- DB3WithMemo : WithMemo := True;
- ELSE
- BEGIN
- dbfError := 157; {Not dBase file (Unknown Media)}
- System.Close(dFile);
- Exit;
- END;
- END; {CASE}
- Str(HeadProlog.month,m);
- if length(m) = 1 then m := '0'+m;
- Str(HeadProlog.day,dy);
- if length(dy) = 1 then dy := '0'+dy;
- Str(HeadProlog.year,y);
- if length(y) = 1 then y := '0'+y;
- DateOfUpdate := m + '/' + dy + '/' + y;
- NumRecs := HeadProlog.RecCount;
- HeadLen := HeadProlog.Location;
- RecLen := HeadProlog.RecordLen;
- RecNumber := 0;
- File_EOF := false;
- GetMem(Fields, HeadLen-33); { Allocate memory for a buffer }
- NumFields := (HeadLen - 33) div 32;
- {$I-} BlockRead(dFile, Fields^,HeadLen-33, Result); {$I+}
- END; {ProcessHeader}
-
- PROCEDURE GetHeader;
- VAR
- Result : Integer;
- BEGIN { GetHeader }
- {$I-} BlockRead(dFile, HeadProlog, 32, Result); {$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN ProcessHeader;
- END; { GetHeader }
-
- begin
- Filename := FName+'.DBF';
- Assign(dFile, FileName);
- {$I-} Reset(dFile, 1); {$I+}
- dbfError := IOResult;
- dbfOK := (dbfError = 0);
- if dbfOK then
- begin
- GetHeader;
- System.Close(dFile);
- GetMem(CurRecord, RecLen); { Allocate memory for a buffer }
- end;
- dStatus := NotOpen;
- dbfNdxActv := false;
- for i := 1 to 16 do dbfNdxTbl[i] := nil;
- if WithMemo then assign(mFile, FName+'.DBT');
- end;
-
- PROCEDURE GS_dBase_DB.Create(FName : string; Flds: GS_dBase_dFld;
- FCnt : integer);
- CONST
- EofMark : Byte = $1A;
- EohMark : Byte = $0D;
- var
- yy, mm, dd, wd : word;
- i, rl : integer;
-
- procedure Make_GS_Head;
- VAR
- m,dy,y : string[2];
- begin
- Str(mm,m);
- if length(m) = 1 then m := '0'+m;
- Str(dd,dy);
- if length(dy) = 1 then dy := '0'+dy;
- Str(yy,y);
- if length(y) = 1 then y := '0'+y;
- DateOfUpdate := m + '/' + dy + '/' + y;
- NumRecs := 0;
- HeadLen := HeadProlog.Location;
- RecLen := rl;
- RecNumber := 0;
- NumFields := FCnt;
- end;
-
- procedure MakeHeader;
- var
- i : integer;
- BEGIN
- HeadProlog.DBType := DB3File;
- GetDate (yy,mm,dd,wd);
- HeadProlog.year := yy-1900; {Year}
- HeadProlog.month := mm; {Month}
- HeadProlog.day := dd; {Day}
- HeadProlog.RecCount := 0;
- HeadProlog.Location := (FCnt*32) + 33;
- rl := 1;
- for i := 1 to FCnt do rl := rl + Flds^[i].FieldLen;
- HeadProlog.RecordLen := rl;
- FillChar(HeadProlog.Reserved,20,#0);
- {$I-}Seek(dFile, 0);{$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, HeadProlog, 32); {$I+}
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, Flds^, FCnt*32); {$I+}
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, EohMark, 1); {$I+} {Put EOH marker }
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(dFile, EofMark, 1); {$I+} {Put EOF marker }
- dbfError := IOResult;
- END;
- dbfOK := (dbfError = 0);
- END; { IF Updated }
-
- begin
- Filename := FName+'.DBF';
- Assign(dFile, FileName);
- {$I-} Rewrite(dFile, 1); {$I+}
- dbfError := IOResult;
- dbfOK := (dbfError = 0);
- if dbfOK then
- begin
- MakeHeader;
- Make_GS_Head;
- Fields := Flds;
- System.Close(dFile);
- GetMem(CurRecord, RecLen); { Allocate memory for a buffer }
- end;
- dStatus := NotOpen;
- END; { GS_dBase_Create }
-
- PROCEDURE GS_dBase_DB.PACK;
- CONST
- EofMark : Byte = $1A;
- EohMark : Byte = $0D;
- ZroMark : Byte = $00;
-
- var
- df : file;
-
- Procedure Copy_Recs;
- var
- i, j : longint;
- begin
- j := 0;
- for i := 1 to NumRecs do
- begin
- GetRec(i);
- if not DelFlag then
- begin
- {$I-} BlockWrite(df, CurRecord^, RecLen); {$I+}
- dbfError := IOResult;
- inc(j);
- end;
- end;
- NumRecs := j;
- {$I-} BlockWrite(df, EofMark, 1); {$I+} {Put EOF marker }
- dbfError := IOResult;
- end;
-
- Procedure Copy_Head;
- var
- delta : integer;
- begin
- {$I-}Seek(df, 0);{$I+}
- dbfError := IOResult;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(df, HeadProlog, 32); {$I+}
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(df, Fields^, NumFields*32); {$I+}
- dbfError := IOResult;
- END;
- IF dbfError = 0 THEN
- BEGIN
- {$I-} BlockWrite(df, EohMark, 1); {$I+} {Put EOH marker }
- dbfError := IOResult;
- END;
- delta := (NumFields*32) + 33;
- while delta <> HeadProlog.Location do
- begin
- {$I-} BlockWrite(df, ZroMark, 1); {$I+} {Put Zero }
- inc(delta);
- end;
- dbfOK := (dbfError = 0);
- end;
-
- begin
- Assign(df, 'DB$$$.DB$');
- {$I-} Rewrite(df, 1); {$I+}
- dbfError := IOResult;
- dbfOK := (dbfError = 0);
- if dbfOK then
- begin
- Copy_Head;
- Copy_Recs;
- end;
- dStatus := UpDated;
- System.Close(dFile);
- System.Close(df);
- Erase(dFile);
- Rename(df, Filename);
- Assign(dFile, FileName);
- {$I-} Reset(dFile, 1); {$I+}
- Close;
- Open;
- END; { GS_dBase_Pack }
-
- Procedure GS_dBase_DB.Index (IName : String);
- var
- i,j : integer;
- st : String[64];
- begin
- i := 1;
- while dbfNdxTbl[i] <> nil do
- begin
- System.Close(dbfNdxTbl[i]^.Ndx_File);
- Dispose(dbfNdxTbl[i]);
- dbfNdxTbl[i] := nil;
- inc(i);
- end;
- i := 0;
- j := 1;
- st := '';
- while j <= length(IName) do
- begin
- if (IName[j] <> ' ') and (IName[j] <> ',') then
- st := st + IName[j]
- else
- begin
- inc(i);
- if st <> '' then
- begin
- New(dbfNdxTbl[i]);
- dbfNdxTbl[i]^.Init(st);
- end;
- st := '';
- end;
- inc(j);
- end;
- inc(i);
- if st <> '' then
- begin
- New(dbfNdxTbl[i]);
- dbfNdxTbl[i]^.Init(st);
- end;
- if i > 0 then dbfNdxActv := true;
- end;
-
-
- end.